]> Devoid-pointer.net GitWeb - FFBChecker.git/commitdiff
Allow uploading of effects without starting them right away.
authorMichal Malý <madcatxster@devoid-pointer.net>
Wed, 8 Jul 2015 10:58:53 +0000 (12:58 +0200)
committerMichal Malý <madcatxster@devoid-pointer.net>
Wed, 8 Jul 2015 10:58:53 +0000 (12:58 +0200)
ffbdevice.cpp
ffbdevice.h
ffbeffect.h
mainwindow.cpp
mainwindow.h
mainwindow.ui

index 0588aaf7976ab99747313ab822918787b0d3bc4c..82c59cbd0fa2c4cd0172d009ad2bc6e2ce556329 100644 (file)
@@ -3,6 +3,8 @@
 #include <QtWidgets/QMessageBox>
 #include <QDebug>
 
+#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<FFBEffectParameters> params)
+bool FFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters)
 {
-  bool dontStart = false;
-  std::shared_ptr<FFBEffect> 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<FFBEffect> 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<FFBEffectParameters> parameters)
 {
-  int ret = ioctl(c_fd, EVIOCSFF, effect);
+  struct ff_effect* kernelEff = nullptr;
+  std::shared_ptr<FFBEffect> 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;
 }
index b1171b4bccd03a1c4daf8d26cf56e0cfb8e0c640..c467e5a9f1874834f2b56da06a46f0499eceb6a0 100644 (file)
@@ -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<FFBEffectParameters> params);
+  bool startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters);
   bool stopEffect(const int idx);
+  bool uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> 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<ConditionSubtypes> m_availableConditionSubtypes;
   std::vector<FFBEffectTypes> m_availableEffects;
   std::vector<PeriodicWaveforms> m_availablePeriodicWaveforms;
index 2d678e8354ed3500878029efe866d3c507367553..36bb5d6e99ed179d365e1b9644bacf5d4fda33cb 100644 (file)
@@ -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;
index dee56e5f3303de847aef7a289b6709a69a90fd27..22200579233b0b6e3914943699a10de74311aa25 100644 (file)
@@ -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<DeviceProber> prober, const QString& title, QWidget* parent) :
@@ -40,6 +40,7 @@ MainWindow::MainWindow(std::shared_ptr<DeviceProber> 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<FFBEffectParameters> 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<FFBEnvelopeParameters> 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;
     }
 }
index 73fe41af0975cc7000b5952dfa636f076b8c84e4..bbe22169c09a0841be1258e8c49bad42afd7a6ad 100644 (file)
@@ -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
index 475c256e95013f71bfbaffbf9819d7c3faf8559d..59061df8a77ced7f0a15779414c47e817311dc98 100644 (file)
      <widget class="QStackedWidget" name="qstw_effectSpecifics"/>
     </item>
     <item>
-     <layout class="QHBoxLayout" name="horizontalLayout">
-      <item>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="1" column="0">
        <widget class="QPushButton" name="qpb_start">
         <property name="text">
          <string>Start</string>
         </property>
        </widget>
       </item>
-      <item>
+      <item row="2" column="0">
        <widget class="QPushButton" name="qpb_stop">
         <property name="text">
          <string>Stop</string>
         </property>
        </widget>
       </item>
-      <item>
+      <item row="2" column="1">
        <widget class="QPushButton" name="qpb_remove">
         <property name="text">
          <string>Remove</string>
         </property>
        </widget>
       </item>
+      <item row="1" column="1">
+       <widget class="QPushButton" name="qpb_upload">
+        <property name="text">
+         <string>Upload / Update</string>
+        </property>
+       </widget>
+      </item>
      </layout>
     </item>
     <item>