]> Devoid-pointer.net GitWeb - FFBChecker.git/commitdiff
Finish SDL2 support.
authorMichal Malý <madcatxster@devoid-pointer.net>
Sat, 1 Aug 2015 14:34:18 +0000 (16:34 +0200)
committerMichal Malý <madcatxster@devoid-pointer.net>
Sat, 1 Aug 2015 14:34:18 +0000 (16:34 +0200)
sdl2ffbconditioneffect.cpp
sdl2ffbconstanteffect.cpp
sdl2ffbconstanteffect.h
sdl2ffbdevice.cpp
sdl2ffbdevice.h
sdl2ffbeffect.cpp
sdl2ffbeffect.h
sdl2ffbperiodiceffect.cpp
sdl2ffbrampeffect.cpp

index 2c1347219e7e2a17897ace01a10c5c5b053380ab..c683b0a10ec9a2ea25cd43f62a7e6397e3be21c9 100644 (file)
@@ -7,7 +7,7 @@ SDL2FFBConditionEffect::SDL2FFBConditionEffect() :
 
 SDL_HapticEffect* SDL2FFBConditionEffect::createFFstruct()
 {
-  SDL_HapticEffect* effect = SDL2FFBEffect::createFFstruct();
+  SDL_HapticEffect* effect = initFFstruct();
   if (effect == nullptr)
     return nullptr;
 
index dc82be5da12f11ec5f709571d84746b5f4b0c7ff..90c51f2cf7624f16944f1ffd2389db9dbcaae17c 100644 (file)
@@ -5,13 +5,14 @@ SDL2FFBConstantEffect::SDL2FFBConstantEffect() :
   SDL2FFBEffect(FFBEffectTypes::CONSTANT)
 {}
 
-SDL_HapticEffect* SDL2FFBConstantEffect::createFFStruct()
+SDL_HapticEffect* SDL2FFBConstantEffect::createFFstruct()
 {
-  SDL_HapticEffect* effect = SDL2FFBEffect::createFFstruct();
+  SDL_HapticEffect* effect = initFFstruct();
   if (effect == nullptr)
     return nullptr;
 
   effect->type = SDL_HAPTIC_CONSTANT;
+  effect->constant.type = SDL_HAPTIC_CONSTANT;
   effect->constant.direction.type = SDL_HAPTIC_POLAR;
   effect->constant.direction.dir[0] = m_params->direction;
 
@@ -47,13 +48,13 @@ bool SDL2FFBConstantEffect::setParameters(const std::shared_ptr<FFBConstantEffec
   if (!GlobalSettings::GS()->doSanityChecks)
     return true;
 
-  if (!checkGenericParameters(m_params))
+  if (!checkGenericParameters(params))
     return false;
 
-  if (!checkEnvelopeParameters(m_params->attackLength, m_params->attackLevel, m_params->fadeLength, m_params->fadeLevel))
+  if (!checkEnvelopeParameters(params->attackLength, params->attackLevel, params->fadeLength, params->fadeLevel))
     return false;
 
-  if (!checkBoundsInclusive(m_params->level, -0x7FFF, 0x7FFF)) {
+  if (!checkBoundsInclusive(params->level, -0x7FFF, 0x7FFF)) {
     reportError("Level parameters must be within <-32767; 32767>");
     return false;
   }
index 7787189077a8c321f57a9c45b1b10d4a500f9e89..cf233918a91e0cff38e2235758b970ac738905b9 100644 (file)
@@ -8,7 +8,7 @@ class SDL2FFBConstantEffect :  public SDL2FFBEffect
 {
 public:
   explicit SDL2FFBConstantEffect();
-  SDL_HapticEffect* createFFStruct();
+  SDL_HapticEffect* createFFstruct();
   inline const std::shared_ptr<FFBEffectParameters> parameters() const { return m_params; }
   bool setParameters(const std::shared_ptr<FFBEffectParameters> params);
 
index 5405fe55ede472da5f3c46a026f8588d58900f4d..17fbb192d2f6b183449cc599f5b3d4fa2bd075c5 100644 (file)
@@ -1,5 +1,9 @@
 #include "sdl2ffbdevice.h"
 #include "sdl2ffbeffectfactory.h"
+#include <QtWidgets/QMessageBox>
+#include <QtCore/QDebug>
+
+#define CHECK_EFFECT_IDX(idx) if (idx < 0 || idx > c_maxEffectCount) return false
 
 SDL2FFBDevice::SDL2FFBDevice(SDL_Haptic* haptic, const int maxEffectCount) :
     FFBDevice(maxEffectCount),
@@ -11,6 +15,9 @@ SDL2FFBDevice::SDL2FFBDevice(SDL_Haptic* haptic, const int maxEffectCount) :
 
 void SDL2FFBDevice::close()
 {
+  for (int idx = 0; idx < c_maxEffectCount; idx++)
+    removeAndEraseEffect(idx);
+
   SDL_HapticClose(c_haptic);
 }
 
@@ -72,23 +79,171 @@ bool SDL2FFBDevice::queryDeviceCapabilities()
   return true;
 }
 
+bool SDL2FFBDevice::removeEffect(const int idx)
+{
+  std::shared_ptr<SDL2FFBEffect> sdlEff;
+  CHECK_EFFECT_IDX(idx);
+
+  if (!stopEffect(idx))
+    return false;
+
+  if (m_effects[idx]->type() == FFBEffectTypes::NONE)
+    return true;
+
+  sdlEff = std::static_pointer_cast<SDL2FFBEffect>(m_effects[idx]);
+
+  SDL_HapticDestroyEffect(c_haptic, sdlEff->internalIdx());
+
+  return true;
+}
+
+
 bool SDL2FFBDevice::removeAndEraseEffect(const int idx)
 {
-  return false;
+  CHECK_EFFECT_IDX(idx);
+
+  if (m_effects[idx]->status() == FFBEffect::FFBEffectStatus::NOT_LOADED)
+    return true;
+
+  if (removeEffect(idx)) {
+    m_effects[idx] = SDL2FFBEffectFactory::createEffect(FFBEffectTypes::NONE);
+    if (m_effects[idx]->type() != FFBEffectTypes::NONE) {
+      qCritical("Unable to empty the effect slot.");
+      return false;
+    }
+  } else {
+    qCritical("Unable to stop the effect.");
+    return false;
+  }
+
+  m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::NOT_LOADED);
+  return true;
 }
 
-bool SDL2FFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr< FFBEffectParameters > parameters)
+bool SDL2FFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters)
 {
-  return false;
+  std::shared_ptr<SDL2FFBEffect> sdlEff;
+  Uint32 repeat;
+
+  CHECK_EFFECT_IDX(idx);
+
+  if (m_effects[idx]->status() == FFBEffect::FFBEffectStatus::NOT_LOADED) {
+    if (!uploadEffect(idx, type, parameters))
+      return false;
+  }
+  if (m_effects[idx]->status() == FFBEffect::FFBEffectStatus::PLAYING)
+    return true;
+
+  sdlEff = std::static_pointer_cast<SDL2FFBEffect>(m_effects[idx]);
+  if (sdlEff->parameters()->repeat == 0) {
+    if (sdlEff->parameters()->replayLength > 0)
+      repeat = SDL_HAPTIC_INFINITY;
+  } else
+    repeat = 1;
+
+  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()));
+    return false;
+  }
+
+  sdlEff->setStatus(FFBEffect::FFBEffectStatus::PLAYING);
+  return true;
 }
 
 bool SDL2FFBDevice::stopEffect(const int idx)
 {
-  return false;
+  std::shared_ptr<SDL2FFBEffect> sdlEff;
+  CHECK_EFFECT_IDX(idx);
+
+  if (m_effects[idx] == nullptr)
+    return true;
+
+  if (m_effects[idx]->status() != FFBEffect::FFBEffectStatus::PLAYING)
+    return true;
+
+  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()));
+    return false;
+  }
+
+  sdlEff->setStatus(FFBEffect::FFBEffectStatus::UPLOADED);
+  return true;
 }
 
-bool SDL2FFBDevice::uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr< FFBEffectParameters > parameters)
+bool SDL2FFBDevice::uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters)
 {
-  return false;
+  SDL_HapticEffect* underlEff;
+  int intIdx;
+  std::shared_ptr<FFBEffect> effect = SDL2FFBEffectFactory::createEffect(type);
+  std::shared_ptr<SDL2FFBEffect> sdlEff;
+
+  CHECK_EFFECT_IDX(idx);
+
+  if (type != FFBEffectTypes::NONE)
+    sdlEff = std::static_pointer_cast<SDL2FFBEffect>(effect);
+  else
+    return false;
+
+  if (sdlEff == nullptr) {
+    qDebug() << "Unable to create effect";
+    return false;
+  }
+
+  if (!sdlEff->setParameters(parameters)) {
+    qDebug() << "Unable to set effect parameters, some values are probably invalid.";
+    return false;
+  }
+
+  /* There is no effect in the selected slot */
+  if (m_effects[idx]->type() != FFBEffectTypes::NONE) {
+    /* Effects are not of the same type, delete the previous effect and create a new one */
+    if (*m_effects[idx] != *sdlEff) {
+      if (!removeEffect(idx)) {
+       qDebug() << "Recreating effect";
+       return false;
+      }
+    } else {
+      /* Effects are of the same type, update it */
+      qDebug() << "Updating effect";
+
+      underlEff = sdlEff->createFFstruct();
+      if (underlEff == nullptr) {
+       qDebug() << "SDL2: Unable to create effect data";
+       return false;
+      }
+
+      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()));
+       m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::UPLOADED);
+       return true;
+      }
+      sdlEff->setStatus(m_effects[idx]->status());
+
+      goto out;
+    }
+  }
+
+  qDebug() << "Creating new effect";
+  underlEff = sdlEff->createFFstruct();
+  if (underlEff == nullptr) {
+    qDebug() << "SDL2: Unable to create effect data";
+    return false;
+  }
+
+  intIdx = SDL_HapticNewEffect(c_haptic, underlEff);
+  if (intIdx < 0) {
+    QMessageBox::critical(nullptr, "SDL2 error", QString("Unable to create effect:\n%1").arg(SDL_GetError()));
+    return false;
+  }
+  sdlEff->setStatus(FFBEffect::FFBEffectStatus::UPLOADED);
+
+out:
+  sdlEff->setInternalIdx(intIdx);
+  delete underlEff;
+  m_effects[idx] = sdlEff;
+
+  return true;
 }
 
index e1acae6bc236e48b0c85944bf9ba8e801570f06f..1c5d6aaf78f101d8f48e27512a8a58a4d0e4fbf2 100644 (file)
@@ -15,6 +15,8 @@ public:
   bool uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters);
 
 private:
+  bool removeEffect(const int idx);
+
   SDL_Haptic* c_haptic;
 };
 
index d3b04a214f9b837d48587ec4d1a8f2e6aae55a6f..e195d0212505d9af3aec327ab82ed15d0b424655 100644 (file)
@@ -1,7 +1,7 @@
 #include "sdl2ffbeffect.h"
 #include "globalsettings.h"
 
-SDL_HapticEffect* SDL2FFBEffect::createFFstruct()
+SDL_HapticEffect* SDL2FFBEffect::initFFstruct()
 {
   SDL_HapticEffect* effect = new SDL_HapticEffect;
   if (effect == nullptr)
@@ -60,6 +60,11 @@ bool SDL2FFBEffect::checkGenericParameters(const std::shared_ptr<FFBEffectParame
     return false;
   }
 
+  if (params->repeat < 0) {
+    reportError("Repeat count must be non-negative");
+    return false;
+  }
+
   return true;
 }
 
index 27ffa00e35098541ed267a039e457027ff8bf488..92808c457d930c22f436d38297e8e18f9a7d52a4 100644 (file)
@@ -8,11 +8,17 @@ class SDL2FFBEffect : public FFBEffect
 {
 public:
   explicit SDL2FFBEffect(FFBEffectTypes type) : FFBEffect(type) {}
-  virtual SDL_HapticEffect* createFFstruct();
+  virtual SDL_HapticEffect* createFFstruct() = 0;
+  inline int internalIdx() const { return m_internalIdx; }
+  inline void setInternalIdx(const int idx) { m_internalIdx = idx; }
 
 protected:
+  SDL_HapticEffect* initFFstruct();
   virtual bool checkGenericParameters(const std::shared_ptr<FFBEffectParameters> params);
   bool checkEnvelopeParameters(const int attackLength, const int attackLevel, const int fadeLength, const int fadeLevel);
+
+private:
+  int m_internalIdx;
 };
 
 #endif // SDL2FFBEFFECT_H
index 96ad998622876520e9274e5a8dc745a861947499..5db9c926ae61f651f1f02c08ebb1821100503bde 100644 (file)
@@ -7,7 +7,7 @@ SDL2FFBPeriodicEffect::SDL2FFBPeriodicEffect() :
 
 SDL_HapticEffect* SDL2FFBPeriodicEffect::createFFstruct()
 {
-  SDL_HapticEffect* effect = SDL2FFBEffect::createFFstruct();
+  SDL_HapticEffect* effect = initFFstruct();
 
   if (effect == nullptr)
     return nullptr;
index d5b4517c6d2d2de96478d3ade7a76cf6289d7bf0..195505667b8f00323ef0ac674c641bfedfca6fae 100644 (file)
@@ -7,7 +7,7 @@ SDL2FFBRampEffect::SDL2FFBRampEffect() :
 
 SDL_HapticEffect* SDL2FFBRampEffect::createFFstruct()
 {
-  SDL_HapticEffect* effect = SDL2FFBEffect::createFFstruct();
+  SDL_HapticEffect* effect = initFFstruct();
 
   if (effect == nullptr)
     return nullptr;