From 04d84a17b01e99601e176f954d802fea0297b121 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Jul 2015 12:58:53 +0200 Subject: [PATCH] Allow uploading of effects without starting them right away. --- ffbdevice.cpp | 138 +++++++++++++++++++++++++++---------------------- ffbdevice.h | 4 +- ffbeffect.h | 2 +- mainwindow.cpp | 27 ++++++++-- mainwindow.h | 3 +- mainwindow.ui | 15 ++++-- 6 files changed, 115 insertions(+), 74 deletions(-) diff --git a/ffbdevice.cpp b/ffbdevice.cpp index 0588aaf..82c59cb 100644 --- a/ffbdevice.cpp +++ b/ffbdevice.cpp @@ -3,6 +3,8 @@ #include #include +#define CHECK_EFFECT_IDX(idx) if (idx < 0 || idx > c_maxEffectCount) return false + const quint8 FFBDevice::BITS_PER_LONG = sizeof(unsigned long) * 8; FFBDevice::FFBDevice(const int fd, const QString& path, const int maxEffectCount, QObject* parent) : @@ -223,87 +225,44 @@ bool FFBDevice::removeEffect(const int idx) return true; } -bool FFBDevice::startEffect(const int idx, FFBEffectTypes type, std::shared_ptr params) +bool FFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr parameters) { - bool dontStart = false; - std::shared_ptr effect = FFBEffectFactory::createEffect(type); - if (effect == nullptr) { - qDebug() << "Unable to create effect"; - return false; - } - if (!effect->setParameters(params)) { - qDebug() << "Unable to set effect parameters, some values are probably invalid."; - return false; - } + int ret; + std::shared_ptr effect; - if (idx < 0 || idx > c_maxEffectCount) { - qCritical() << "Effect index out of bounds"; - return false; - } + CHECK_EFFECT_IDX(idx); - /* There is no effect in the selected slot */ - if (m_effects[idx]->type() == FFBEffectTypes::NONE) { - qDebug() << "Creating new effect"; - } else { - if (*m_effects[idx] != *effect) { - removeEffect(idx); - qDebug() << "Recreating effect" << idx; - } else { - effect->setInternalIdx(m_effects[idx]->internalIdx()); - effect->setStatus(m_effects[idx]->status()); - if (effect->status() == FFBEffect::FFBEffectStatus::PLAYING) { - dontStart = true; - } - qDebug() << "Updating effect" << idx; - } - } - m_effects[idx] = effect; - - struct ff_effect* kernelEff = nullptr; - kernelEff = m_effects[idx]->createFFStruct(); - if (kernelEff == nullptr) { - QMessageBox::critical(nullptr, "FFB Device", "ff_effect struct could not have been created. Effect not uploaded."); - qDebug() << "struct ff_effect not created"; - return false; - } - - qDebug() << kernelEff->u.condition[0].center << kernelEff->u.condition[0].deadband << kernelEff->u.condition[1].center << kernelEff->u.condition[1].deadband; + effect = m_effects[idx]; - int ret = uploadEffect(kernelEff); - if (ret < 0) { - QMessageBox::critical(nullptr, "FFB Device", "Effect could not have been uploaded, error code: " + QString::number(ret)); - qDebug() << "Effect not uploaded" << ret; - delete kernelEff; - return false; + if (effect->status() == FFBEffect::FFBEffectStatus::NOT_LOADED) { + if (!uploadEffect(idx, type, parameters)) + return false; } - if (dontStart) + if (effect->status() == FFBEffect::FFBEffectStatus::PLAYING) return true; - m_effects[idx]->setInternalIdx(kernelEff->id); - m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::STOPPED); - /* Start playback */ struct input_event evt; evt.type = EV_FF; - evt.code = kernelEff->id; - evt.value = m_effects[idx]->parameters()->repeat; + evt.code = effect->internalIdx(); + evt.value = effect->parameters()->repeat; ret = write(c_fd, &evt, sizeof(struct input_event)); if (ret != sizeof(struct input_event)) { QMessageBox::critical(nullptr, "FFB Device", "Effect could not have been started, error code: " + QString::number(ret)); qDebug() << "Effect not started" << ret; - delete kernelEff; return false; } - m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::PLAYING); + effect->setStatus(FFBEffect::FFBEffectStatus::PLAYING); - delete kernelEff; return true; } bool FFBDevice::stopEffect(const int idx) { + CHECK_EFFECT_IDX(idx); + if (m_effects[idx] == nullptr) return true; @@ -321,17 +280,70 @@ bool FFBDevice::stopEffect(const int idx) if (ret != sizeof(struct input_event)) return false; - m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::STOPPED); + m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::UPLOADED); return true; } -int FFBDevice::uploadEffect(struct ff_effect* effect) +bool FFBDevice::uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr parameters) { - int ret = ioctl(c_fd, EVIOCSFF, effect); + struct ff_effect* kernelEff = nullptr; + std::shared_ptr effect = FFBEffectFactory::createEffect(type); + + CHECK_EFFECT_IDX(idx); + + if (effect == nullptr) { + qDebug() << "Unable to create effect"; + return false; + } + if (!effect->setParameters(parameters)) { + qDebug() << "Unable to set effect parameters, some values are probably invalid."; + return false; + } + + if (idx < 0 || idx > c_maxEffectCount) { + qCritical() << "Effect index out of bounds"; + return false; + } + + /* There is no effect in the selected slot */ + if (m_effects[idx]->type() == FFBEffectTypes::NONE) { + effect->setStatus(FFBEffect::FFBEffectStatus::UPLOADED); + qDebug() << "Creating new effect"; + } else { + if (*m_effects[idx] != *effect) { + if (!removeEffect(idx)) { + QMessageBox::critical(nullptr, "FFB Device", "Unable to remove effect"); + return false; + } + effect->setStatus(FFBEffect::FFBEffectStatus::UPLOADED); + qDebug() << "Recreating effect" << idx; + } else { + effect->setInternalIdx(m_effects[idx]->internalIdx()); + effect->setStatus(m_effects[idx]->status()); + qDebug() << "Updating effect" << idx; + } + } + + kernelEff = effect->createFFStruct(); + if (kernelEff == nullptr) { + QMessageBox::critical(nullptr, "FFB Device", "ff_effect struct could not have been created. Effect not uploaded."); + qDebug() << "struct ff_effect not created"; + return false; + } + + qDebug() << kernelEff->u.condition[0].center << kernelEff->u.condition[0].deadband << kernelEff->u.condition[1].center << kernelEff->u.condition[1].deadband; + + int ret = ioctl(c_fd, EVIOCSFF, kernelEff); if (ret < 0) { - qDebug() << "Error while uploading effect"; - return ret; + QMessageBox::critical(nullptr, "FFB Device", "Effect could not have been uploaded, error code: " + QString::number(ret)); + qDebug() << "Effect not uploaded" << ret; + delete kernelEff; + return false; } - return effect->id; + effect->setInternalIdx(kernelEff->id); + delete kernelEff; + + m_effects[idx] = effect; + return true; } diff --git a/ffbdevice.h b/ffbdevice.h index b1171b4..c467e5a 100644 --- a/ffbdevice.h +++ b/ffbdevice.h @@ -34,14 +34,14 @@ public: inline const QString& path() const { return c_path; } bool queryDeviceCapabilities(); bool removeAndEraseEffect(const int idx); - bool startEffect(const int idx, FFBEffectTypes type, std::shared_ptr params); + bool startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr parameters); bool stopEffect(const int idx); + bool uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr parameters); QString waveformName(const PeriodicWaveforms waveform) const; inline PeriodicWaveforms waveformByIdx(const int idx) const { return m_availablePeriodicWaveforms[idx]; } private: bool removeEffect(const int idx); - int uploadEffect(struct ff_effect* effect); std::vector m_availableConditionSubtypes; std::vector m_availableEffects; std::vector m_availablePeriodicWaveforms; diff --git a/ffbeffect.h b/ffbeffect.h index 2d678e8..36bb5d6 100644 --- a/ffbeffect.h +++ b/ffbeffect.h @@ -8,7 +8,7 @@ class FFBEffect { public: - enum class FFBEffectStatus { PLAYING, STOPPED, NOT_LOADED }; + enum class FFBEffectStatus { PLAYING, UPLOADED, NOT_LOADED }; explicit FFBEffect(FFBEffectTypes type); virtual struct ff_effect* createFFStruct() = 0; diff --git a/mainwindow.cpp b/mainwindow.cpp index dee56e5..2220057 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -7,7 +7,7 @@ const QString MainWindow::res_deviceErrorCap("Device error"); const QString MainWindow::res_effectNotLoaded("Not loaded"); const QString MainWindow::res_effectPlaying("Playing"); -const QString MainWindow::res_effectStopped("Stopped"); +const QString MainWindow::res_effectUploaded("Uploaded"); const QString MainWindow::res_inputFormatErrCap("Invalid input format."); MainWindow::MainWindow(std::shared_ptr prober, const QString& title, QWidget* parent) : @@ -40,6 +40,7 @@ MainWindow::MainWindow(std::shared_ptr prober, const QString& titl connect(ui->qpb_remove, SIGNAL(clicked()), this, SLOT(onRemoveEffectClicked())); connect(ui->qpb_start, SIGNAL(clicked()), this, SLOT(onStartEffectClicked())); connect(ui->qpb_stop, SIGNAL(clicked()), this, SLOT(onStopEffectClicked())); + connect(ui->qpb_upload, SIGNAL(clicked()), this, SLOT(onUploadEffectClicked())); } EffectSettings* MainWindow::effectSettingsByType(FFBEffectTypes type) @@ -182,6 +183,26 @@ void MainWindow::onStopEffectClicked() setEffectStatusText(m_activeDevice->effectStatusByIdx(effectSlot)); } +void MainWindow::onUploadEffectClicked() +{ + if (m_activeDevice == nullptr) + return; + + FFBEffectTypes type = m_activeDevice->effectTypeFromSelectionIdx(ui->cbox_effectTypes->currentIndex()); + std::shared_ptr params; + int effectSlot = ui->cbox_effectSlots->currentIndex(); + + if (!readEffectParameters(params, type)) { + qDebug() << "Cannot read effect params."; + return; + } + bool ret = m_activeDevice->uploadEffect(effectSlot, type, params); + if (ret) + setEffectStatusText(m_activeDevice->effectStatusByIdx(effectSlot)); + else + QMessageBox::warning(this, res_deviceErrorCap, "Unable to upload the effect."); +} + bool MainWindow::readEnvelopeParameters(std::shared_ptr params, const EnvelopeSettings* es) { if (!params->attackLengthFromString(es->attackLength())) { @@ -392,8 +413,8 @@ void MainWindow::setEffectStatusText(const FFBEffect::FFBEffectStatus status) case FFBEffect::FFBEffectStatus::PLAYING: ui->ql_effectStatus->setText(res_effectPlaying); break; - case FFBEffect::FFBEffectStatus::STOPPED: - ui->ql_effectStatus->setText(res_effectStopped); + case FFBEffect::FFBEffectStatus::UPLOADED: + ui->ql_effectStatus->setText(res_effectUploaded); break; } } diff --git a/mainwindow.h b/mainwindow.h index 73fe41a..bbe2216 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -49,7 +49,7 @@ private: static const QString res_deviceErrorCap; static const QString res_effectNotLoaded; static const QString res_effectPlaying; - static const QString res_effectStopped; + static const QString res_effectUploaded; static const QString res_inputFormatErrCap; private slots: @@ -60,6 +60,7 @@ private slots: void onRemoveEffectClicked(); void onStartEffectClicked(); void onStopEffectClicked(); + void onUploadEffectClicked(); }; #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index 475c256..59061df 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -201,28 +201,35 @@ - - + + Start - + Stop - + Remove + + + + Upload / Update + + + -- 2.43.5