]> Devoid-pointer.net GitWeb - FFBChecker.git/commitdiff
Add an option to adjust overall gain
authorMichal Malý <madcatxster@devoid-pointer.net>
Sat, 1 Aug 2015 22:46:57 +0000 (00:46 +0200)
committerMichal Malý <madcatxster@devoid-pointer.net>
Sat, 1 Aug 2015 22:46:57 +0000 (00:46 +0200)
ffbdevice.h
linuxffbdevice.cpp
linuxffbdevice.h
mainwindow.cpp
mainwindow.h
mainwindow.ui
sdl2ffbdevice.cpp
sdl2ffbdevice.h

index 45352e0ec56a5b01b081fa6ebc4350efe1f35dc1..ed3ddc055241a16b06e19b106c03ba79a6c9af9c 100644 (file)
@@ -21,6 +21,7 @@ public:
   virtual void close() = 0;
   virtual bool queryDeviceCapabilities() = 0;
   virtual bool removeAndEraseEffect(const int idx) = 0;
+  virtual bool setGain(const int gain) = 0;
   virtual bool startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters) = 0;
   virtual bool stopEffect(const int idx) = 0;
   virtual bool uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters) = 0;
@@ -32,6 +33,8 @@ protected:
   std::vector<ConditionSubtypes> m_availableConditionSubtypes;
   std::vector<FFBEffectTypes> m_availableEffects;
   std::vector<PeriodicWaveforms> m_availablePeriodicWaveforms;
+  bool m_adjustableGain;
+
   std::vector<std::shared_ptr<FFBEffect>> m_effects;
 
   const int c_maxEffectCount;
index 6b9187d6e412d8c0a88deefcc033836775543fdd..9afcd3373af727b6866d98ca82b7df372482bdac 100644 (file)
@@ -10,6 +10,7 @@
 #define CHECK_EFFECT_IDX(idx) if (idx < 0 || idx > c_maxEffectCount) return false
 
 const quint8 LinuxFFBDevice::BITS_PER_LONG = sizeof(unsigned long) * 8;
+const QString LinuxFFBDevice::LNXDEV_ERR_CAPTION("Linux FFB device");
 
 LinuxFFBDevice::LinuxFFBDevice(const int fd, const int maxEffectCount, const QString path) :
   FFBDevice(maxEffectCount),
@@ -74,6 +75,10 @@ bool LinuxFFBDevice::queryDeviceCapabilities()
   if (testBit(FF_INERTIA, caps))
     m_availableConditionSubtypes.push_back(ConditionSubtypes::INERTIA);
 
+  /* Query device-wide capabilities */
+  if (testBit(FF_GAIN, caps))
+    m_adjustableGain = true;
+
   return true;
 }
 
@@ -115,6 +120,35 @@ bool LinuxFFBDevice::removeEffect(const int idx)
   return true;
 }
 
+bool LinuxFFBDevice::setGain(const int gain)
+{
+  struct input_event evt;
+  int ret;
+
+  if (!m_adjustableGain) {
+    QMessageBox::warning(nullptr, LNXDEV_ERR_CAPTION, "Device does not have adjustable gain");
+    return false;
+  }
+
+  if (gain < 0 || gain > 0xFFFF) {
+    QMessageBox::warning(nullptr, LNXDEV_ERR_CAPTION, "Gain must be within <0; 65535>");
+    return false;
+  }
+
+  evt.type = EV_FF;
+  evt.code = FF_GAIN;
+  evt.value = gain;
+
+  ret = write(c_fd, &evt, sizeof(struct input_event));
+  if (ret != sizeof(struct input_event)) {
+    QMessageBox::warning(nullptr, LNXDEV_ERR_CAPTION, QString("Unable to set gain"));
+    return false;
+  }
+
+  return true;
+}
+
+
 bool LinuxFFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters)
 {
   std::shared_ptr<LinuxFFBEffect> linEff;
@@ -139,7 +173,7 @@ bool LinuxFFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::
 
   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));
+    QMessageBox::critical(nullptr, LNXDEV_ERR_CAPTION, "Effect could not have been started, error code: " + QString::number(ret));
     qDebug() << "Effect not started" << ret;
     return false;
   }
@@ -213,7 +247,7 @@ bool LinuxFFBDevice::uploadEffect(const int idx, const FFBEffectTypes type, std:
 
     if (*m_effects[idx] != *linEff) {
       if (!removeEffect(idx)) {
-        QMessageBox::critical(nullptr, "FFB Device", "Unable to remove effect");
+        QMessageBox::critical(nullptr, LNXDEV_ERR_CAPTION, "Unable to remove effect");
         return false;
       }
       linEff->setStatus(FFBEffect::FFBEffectStatus::UPLOADED);
@@ -227,14 +261,14 @@ bool LinuxFFBDevice::uploadEffect(const int idx, const FFBEffectTypes type, std:
 
   kernelEff = linEff->createFFStruct();
   if (kernelEff == nullptr) {
-    QMessageBox::critical(nullptr, "FFB Device", "ff_effect struct could not have been created. Effect not uploaded.");
+    QMessageBox::critical(nullptr, LNXDEV_ERR_CAPTION, "ff_effect struct could not have been created. Effect not uploaded.");
     qDebug() << "struct ff_effect not created";
     return false;
   }
 
   int ret = ioctl(c_fd, EVIOCSFF, kernelEff);
   if (ret < 0) {
-    QMessageBox::critical(nullptr, "FFB Device", "Effect could not have been uploaded, error code: " + QString::number(ret));
+    QMessageBox::critical(nullptr, LNXDEV_ERR_CAPTION, "Effect could not have been uploaded, error code: " + QString::number(ret));
     qDebug() << "Effect not uploaded" << ret;
     delete kernelEff;
     return false;
index afb511a9e38fb151689be83203d931dc80c13e23..52460bdb5571cd318c9033513d877b4b23d7f528 100644 (file)
@@ -14,6 +14,7 @@ public:
   void close();
   bool queryDeviceCapabilities();
   bool removeAndEraseEffect(const int idx);
+  bool setGain(const int gain);
   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);
@@ -30,6 +31,8 @@ private:
   static inline bool testBit(unsigned long bit, unsigned long* array) { return (array[longIdx(bit)] >> offset(bit)) & 1; }
 
   static const quint8 BITS_PER_LONG;
+  static const QString LNXDEV_ERR_CAPTION;
+
 signals:
 
 public slots:
index d035be97ecf3cfc8b30f5d39f11b074f3e750def..f260c06deb2cad7015cbb177128e6544d27625fc 100644 (file)
@@ -53,6 +53,7 @@ MainWindow::MainWindow(const QString& title, QWidget* parent) :
   connect(ui->cbox_interfaces, SIGNAL(activated(int)), this, SLOT(onInterfaceSelected(const int)));
   connect(ui->qpb_refreshDevices, SIGNAL(clicked()), this, SLOT(onRefreshDevicesClicked()));
   connect(ui->qpb_remove, SIGNAL(clicked()), this, SLOT(onRemoveEffectClicked()));
+  connect(ui->qpb_setGain, SIGNAL(clicked()), this, SLOT(onSetGainClicked()));
   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()));
@@ -272,6 +273,23 @@ void MainWindow::onRemoveEffectClicked()
     setEffectStatusText(m_activeDevice->effectStatusByIdx(effectIdx));
 }
 
+void MainWindow::onSetGainClicked()
+{
+  bool ok;
+  int gain;
+
+  if (m_activeDevice == nullptr)
+    return;
+
+  gain = ui->qle_gain->text().toInt(&ok);
+  if (!ok) {
+    QMessageBox::warning(this, res_inputFormatErrCap, "Invalid gain value");
+    return;
+  }
+
+  m_activeDevice->setGain(gain);
+}
+
 void MainWindow::onStartEffectClicked()
 {
   bool ok;
index 6770fa0cc33d2c75f8705933f3ca9eeca839de5c..36c0322ccd5901cb4fced2cf91aa84a606617e8a 100644 (file)
@@ -70,6 +70,7 @@ private slots:
   void onInterfaceSelected(const int cboxIdx);
   void onRefreshDevicesClicked();
   void onRemoveEffectClicked();
+  void onSetGainClicked();
   void onStartEffectClicked();
   void onStopEffectClicked();
   void onUploadEffectClicked();
index da999b91f734bf6a1a47208eb619e22bbc9b3679..96460689b9c21ad3586a27846164a6036e0e35d3 100644 (file)
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>444</width>
-    <height>546</height>
+    <height>623</height>
    </rect>
   </property>
   <property name="windowTitle">
       </item>
      </layout>
     </item>
+    <item>
+     <widget class="Line" name="line_4">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QLabel" name="ql_deviceSettings">
+      <property name="text">
+       <string>Device settings</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignCenter</set>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="qle_gain">
+        <property name="text">
+         <string>65535</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="0">
+       <widget class="QLabel" name="ql_gain">
+        <property name="text">
+         <string>Gain:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="2">
+       <widget class="QPushButton" name="qpb_setGain">
+        <property name="text">
+         <string>Set gain</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
     <item>
      <widget class="QLabel" name="ql_effectParameters">
       <property name="sizePolicy">
index f4b9cc0641788c64f059784928d2934d66c2c114..eeb73110c84f2c539b27601437b4eea9a196ca39 100644 (file)
@@ -5,6 +5,8 @@
 
 #define CHECK_EFFECT_IDX(idx) if (idx < 0 || idx > c_maxEffectCount) return false
 
+const QString SDL2FFBDevice::SDL2DEV_ERR_CAPTION("SDL2 device error");
+
 SDL2FFBDevice::SDL2FFBDevice(SDL_Haptic* haptic, const int maxEffectCount) :
     FFBDevice(maxEffectCount),
     c_haptic(haptic)
@@ -76,6 +78,9 @@ bool SDL2FFBDevice::queryDeviceCapabilities()
   if (hasCondition)
     m_availableEffects.push_back(FFBEffectTypes::CONDITION);
 
+  if (caps & SDL_HAPTIC_GAIN)
+    m_adjustableGain = true;
+
   return true;
 }
 
@@ -120,6 +125,26 @@ bool SDL2FFBDevice::removeAndEraseEffect(const int idx)
   return true;
 }
 
+bool SDL2FFBDevice::setGain(const int gain)
+{
+  if (!m_adjustableGain) {
+    QMessageBox::warning(nullptr, SDL2DEV_ERR_CAPTION, "Device does not have adjustable gain");
+    return false;
+  }
+
+  if (gain < 0 || gain > 100) {
+    QMessageBox::warning(nullptr, SDL2DEV_ERR_CAPTION, "Gain must be within <0; 100>");
+    return false;
+  }
+
+  if (SDL_HapticSetGain(c_haptic, gain) < 0) {
+    QMessageBox::warning(nullptr, SDL2DEV_ERR_CAPTION, QString("Unable to set gain:\n%1").arg(SDL_GetError()));
+    return false;
+  }
+
+  return true;
+}
+
 bool SDL2FFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters)
 {
   std::shared_ptr<SDL2FFBEffect> sdlEff;
@@ -144,7 +169,7 @@ bool SDL2FFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::s
     repeat = sdlEff->parameters()->repeat;
 
   if (SDL_HapticRunEffect(c_haptic, sdlEff->internalIdx(), repeat) < 0) {
-    QMessageBox::warning(nullptr, "SDL2 error", QString("Unable to start the effect:\n%1").arg(SDL_GetError()));
+    QMessageBox::warning(nullptr, SDL2DEV_ERR_CAPTION, QString("Unable to start the effect:\n%1").arg(SDL_GetError()));
     return false;
   }
 
@@ -165,7 +190,7 @@ bool SDL2FFBDevice::stopEffect(const int idx)
 
   sdlEff = std::static_pointer_cast<SDL2FFBEffect>(m_effects[idx]);
   if (SDL_HapticStopEffect(c_haptic, sdlEff->internalIdx()) < 0) {
-    QMessageBox::critical(nullptr, "SDL2 error", QString("Unable to stop the effect:\n%1").arg(SDL_GetError()));
+    QMessageBox::critical(nullptr, SDL2DEV_ERR_CAPTION, QString("Unable to stop the effect:\n%1").arg(SDL_GetError()));
     return false;
   }
 
@@ -217,7 +242,7 @@ bool SDL2FFBDevice::uploadEffect(const int idx, const FFBEffectTypes type, std::
 
       intIdx = SDL_HapticUpdateEffect(c_haptic, std::static_pointer_cast<SDL2FFBEffect>(m_effects[idx])->internalIdx(), underlEff);
       if (intIdx < 0) {
-       QMessageBox::critical(nullptr, "SDL2 error", QString("Unable to update the effect:\n%1").arg(SDL_GetError()));
+       QMessageBox::critical(nullptr, SDL2DEV_ERR_CAPTION, QString("Unable to update the effect:\n%1").arg(SDL_GetError()));
        m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::UPLOADED);
        return true;
       }
@@ -236,7 +261,7 @@ bool SDL2FFBDevice::uploadEffect(const int idx, const FFBEffectTypes type, std::
 
   intIdx = SDL_HapticNewEffect(c_haptic, underlEff);
   if (intIdx < 0) {
-    QMessageBox::critical(nullptr, "SDL2 error", QString("Unable to create effect:\n%1").arg(SDL_GetError()));
+    QMessageBox::critical(nullptr, SDL2DEV_ERR_CAPTION, QString("Unable to create effect:\n%1").arg(SDL_GetError()));
     return false;
   }
   sdlEff->setStatus(FFBEffect::FFBEffectStatus::UPLOADED);
index 1c5d6aaf78f101d8f48e27512a8a58a4d0e4fbf2..e25cd757c6dabd075ad7c7f220aaa65e4832a1d5 100644 (file)
@@ -10,6 +10,7 @@ public:
   void close();
   bool queryDeviceCapabilities();
   bool removeAndEraseEffect(const int idx);
+  bool setGain(const int idx);
   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);
@@ -18,6 +19,8 @@ private:
   bool removeEffect(const int idx);
 
   SDL_Haptic* c_haptic;
+
+  static const QString SDL2DEV_ERR_CAPTION;
 };
 
 #endif // SDL2FFBDEVICE_H
\ No newline at end of file