From 5a4f526d9120d7c073eca3b5b4f489d9c54dec7a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Mal=C3=BD?= Date: Sat, 1 Aug 2015 16:34:18 +0200 Subject: [PATCH] Finish SDL2 support. --- sdl2ffbconditioneffect.cpp | 2 +- sdl2ffbconstanteffect.cpp | 11 +-- sdl2ffbconstanteffect.h | 2 +- sdl2ffbdevice.cpp | 167 +++++++++++++++++++++++++++++++++++-- sdl2ffbdevice.h | 2 + sdl2ffbeffect.cpp | 7 +- sdl2ffbeffect.h | 8 +- sdl2ffbperiodiceffect.cpp | 2 +- sdl2ffbrampeffect.cpp | 2 +- 9 files changed, 186 insertions(+), 17 deletions(-) diff --git a/sdl2ffbconditioneffect.cpp b/sdl2ffbconditioneffect.cpp index 2c13472..c683b0a 100644 --- a/sdl2ffbconditioneffect.cpp +++ b/sdl2ffbconditioneffect.cpp @@ -7,7 +7,7 @@ SDL2FFBConditionEffect::SDL2FFBConditionEffect() : SDL_HapticEffect* SDL2FFBConditionEffect::createFFstruct() { - SDL_HapticEffect* effect = SDL2FFBEffect::createFFstruct(); + SDL_HapticEffect* effect = initFFstruct(); if (effect == nullptr) return nullptr; diff --git a/sdl2ffbconstanteffect.cpp b/sdl2ffbconstanteffect.cpp index dc82be5..90c51f2 100644 --- a/sdl2ffbconstanteffect.cpp +++ b/sdl2ffbconstanteffect.cpp @@ -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_ptrdoSanityChecks) 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; } diff --git a/sdl2ffbconstanteffect.h b/sdl2ffbconstanteffect.h index 7787189..cf23391 100644 --- a/sdl2ffbconstanteffect.h +++ b/sdl2ffbconstanteffect.h @@ -8,7 +8,7 @@ class SDL2FFBConstantEffect : public SDL2FFBEffect { public: explicit SDL2FFBConstantEffect(); - SDL_HapticEffect* createFFStruct(); + SDL_HapticEffect* createFFstruct(); inline const std::shared_ptr parameters() const { return m_params; } bool setParameters(const std::shared_ptr params); diff --git a/sdl2ffbdevice.cpp b/sdl2ffbdevice.cpp index 5405fe5..17fbb19 100644 --- a/sdl2ffbdevice.cpp +++ b/sdl2ffbdevice.cpp @@ -1,5 +1,9 @@ #include "sdl2ffbdevice.h" #include "sdl2ffbeffectfactory.h" +#include +#include + +#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 sdlEff; + CHECK_EFFECT_IDX(idx); + + if (!stopEffect(idx)) + return false; + + if (m_effects[idx]->type() == FFBEffectTypes::NONE) + return true; + + sdlEff = std::static_pointer_cast(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 parameters) { - return false; + std::shared_ptr 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(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 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(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 parameters) { - return false; + SDL_HapticEffect* underlEff; + int intIdx; + std::shared_ptr effect = SDL2FFBEffectFactory::createEffect(type); + std::shared_ptr sdlEff; + + CHECK_EFFECT_IDX(idx); + + if (type != FFBEffectTypes::NONE) + sdlEff = std::static_pointer_cast(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(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; } diff --git a/sdl2ffbdevice.h b/sdl2ffbdevice.h index e1acae6..1c5d6aa 100644 --- a/sdl2ffbdevice.h +++ b/sdl2ffbdevice.h @@ -15,6 +15,8 @@ public: bool uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr parameters); private: + bool removeEffect(const int idx); + SDL_Haptic* c_haptic; }; diff --git a/sdl2ffbeffect.cpp b/sdl2ffbeffect.cpp index d3b04a2..e195d02 100644 --- a/sdl2ffbeffect.cpp +++ b/sdl2ffbeffect.cpp @@ -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_ptrrepeat < 0) { + reportError("Repeat count must be non-negative"); + return false; + } + return true; } diff --git a/sdl2ffbeffect.h b/sdl2ffbeffect.h index 27ffa00..92808c4 100644 --- a/sdl2ffbeffect.h +++ b/sdl2ffbeffect.h @@ -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 params); bool checkEnvelopeParameters(const int attackLength, const int attackLevel, const int fadeLength, const int fadeLevel); + +private: + int m_internalIdx; }; #endif // SDL2FFBEFFECT_H diff --git a/sdl2ffbperiodiceffect.cpp b/sdl2ffbperiodiceffect.cpp index 96ad998..5db9c92 100644 --- a/sdl2ffbperiodiceffect.cpp +++ b/sdl2ffbperiodiceffect.cpp @@ -7,7 +7,7 @@ SDL2FFBPeriodicEffect::SDL2FFBPeriodicEffect() : SDL_HapticEffect* SDL2FFBPeriodicEffect::createFFstruct() { - SDL_HapticEffect* effect = SDL2FFBEffect::createFFstruct(); + SDL_HapticEffect* effect = initFFstruct(); if (effect == nullptr) return nullptr; diff --git a/sdl2ffbrampeffect.cpp b/sdl2ffbrampeffect.cpp index d5b4517..1955056 100644 --- a/sdl2ffbrampeffect.cpp +++ b/sdl2ffbrampeffect.cpp @@ -7,7 +7,7 @@ SDL2FFBRampEffect::SDL2FFBRampEffect() : SDL_HapticEffect* SDL2FFBRampEffect::createFFstruct() { - SDL_HapticEffect* effect = SDL2FFBEffect::createFFstruct(); + SDL_HapticEffect* effect = initFFstruct(); if (effect == nullptr) return nullptr; -- 2.43.5