From d826deeabf988a4c392de13693cd176bc6254b23 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Mal=C3=BD?= Date: Fri, 31 Jul 2015 02:26:27 +0200 Subject: [PATCH] - Query haptic devices directly insted of joysticks in SDL interface - Continue implementation of SDL2 interface --- CMakeLists.txt | 2 +- sdl2deviceprober.cpp | 55 ++++++++++++++--------- sdl2deviceprober.h | 4 ++ sdl2ffbdevice.cpp | 94 ++++++++++++++++++++++++++++++++++++++++ sdl2ffbdevice.h | 21 +++++++++ sdl2ffbeffectfactory.cpp | 11 +++++ sdl2ffbeffectfactory.h | 15 +++++++ 7 files changed, 181 insertions(+), 21 deletions(-) create mode 100644 sdl2ffbdevice.cpp create mode 100644 sdl2ffbdevice.h create mode 100644 sdl2ffbeffectfactory.cpp create mode 100644 sdl2ffbeffectfactory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b6231d8..3ce3737 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(FFBChecker_SRCS +set(FFBChecker_SRCS sdl2ffbeffectfactory.cpp sdl2ffbdevice.cpp conditioneffectsettings.cpp constanteffectsettings.cpp effectsettings.cpp diff --git a/sdl2deviceprober.cpp b/sdl2deviceprober.cpp index 0934463..3d40bd5 100644 --- a/sdl2deviceprober.cpp +++ b/sdl2deviceprober.cpp @@ -30,38 +30,23 @@ void SDL2DeviceProber::closeAllDevices() return; } - DeviceProber::DeviceList SDL2DeviceProber::listDevices() { DeviceProber::DeviceList devList; - int numJoy; + int numHapt; if (!s_SDLInited) return devList; - numJoy = SDL_NumJoysticks(); + numHapt = SDL_NumHaptics(); - for (int idx = 0; idx < numJoy; idx++) { + for (int idx = 0; idx < numHapt; idx++) { DeviceProber::DeviceInfo dinfo; - SDL_Joystick* joystick = SDL_JoystickOpen(idx); - - if (joystick == nullptr) { - qDebug() << "SDL2: Cannot open joystick at idx" << idx; - continue; - } - - if (SDL_JoystickIsHaptic(joystick) != 1) { - qDebug() << "SDL2: Joystick at idx" << idx << "does not support force feedback"; - SDL_JoystickClose(joystick); - continue; - } - - dinfo.name = QString(SDL_JoystickName(joystick)); + dinfo.name = QString(SDL_HapticName(idx)); dinfo.id = QVariant(idx); devList.push_back(dinfo); - SDL_JoystickClose(joystick); } return devList; @@ -69,9 +54,39 @@ DeviceProber::DeviceList SDL2DeviceProber::listDevices() std::shared_ptr SDL2DeviceProber::openDevice(const QString& id) { + SDL_Haptic* haptic; + std::shared_ptr device; + int idx; + int maxEffectCount; + bool ok; + if (!s_SDLInited) return nullptr; - return nullptr; + idx = id.toInt(&ok); + if (!ok) + return nullptr; + + haptic = SDL_HapticOpen(idx); + if (haptic == nullptr) + return nullptr; + + maxEffectCount = SDL_HapticNumEffects(haptic); + if (maxEffectCount < 1) { + QMessageBox::critical(nullptr, "SDL2 device error", "Maximum effect count for this device is zero."); + SDL_HapticClose(haptic); + return nullptr; + } + + device = std::make_shared(haptic, maxEffectCount); + if (!device->queryDeviceCapabilities()) { + QMessageBox::critical(nullptr, "SDL2 device error", "Unable to query device capabilities."); + device->close(); + return nullptr; + } + + m_openedDevices.push_back(device); + return device; } + diff --git a/sdl2deviceprober.h b/sdl2deviceprober.h index ae10f4d..a6cb90b 100644 --- a/sdl2deviceprober.h +++ b/sdl2deviceprober.h @@ -3,6 +3,8 @@ #include "deviceprober.h" #include "SDL.h" +#include "sdl2ffbdevice.h" +#include class SDL2DeviceProber : public DeviceProber { @@ -15,6 +17,8 @@ public: std::shared_ptr openDevice(const QString& id); private: + std::list> m_openedDevices; + static bool s_SDLInited; diff --git a/sdl2ffbdevice.cpp b/sdl2ffbdevice.cpp new file mode 100644 index 0000000..5405fe5 --- /dev/null +++ b/sdl2ffbdevice.cpp @@ -0,0 +1,94 @@ +#include "sdl2ffbdevice.h" +#include "sdl2ffbeffectfactory.h" + +SDL2FFBDevice::SDL2FFBDevice(SDL_Haptic* haptic, const int maxEffectCount) : + FFBDevice(maxEffectCount), + c_haptic(haptic) +{ + for (int i = 0; i < maxEffectCount; i++) + m_effects.push_back(SDL2FFBEffectFactory::createEffect(FFBEffectTypes::NONE)); +} + +void SDL2FFBDevice::close() +{ + SDL_HapticClose(c_haptic); +} + +bool SDL2FFBDevice::queryDeviceCapabilities() +{ + unsigned int caps; + bool hasPeriodic = false; + bool hasCondition = false; + + caps = SDL_HapticQuery(c_haptic); + if (caps == 0) + return false; + + if (caps & SDL_HAPTIC_CONSTANT) + m_availableEffects.push_back(FFBEffectTypes::CONSTANT); + + if (caps & SDL_HAPTIC_SINE) { + hasPeriodic = true; + m_availablePeriodicWaveforms.push_back(PeriodicWaveforms::SINE); + } + if (caps & SDL_HAPTIC_TRIANGLE) { + hasPeriodic = true; + m_availablePeriodicWaveforms.push_back(PeriodicWaveforms::TRIANGLE); + } + if (caps & SDL_HAPTIC_SAWTOOTHUP) { + hasPeriodic = true; + m_availablePeriodicWaveforms.push_back(PeriodicWaveforms::SAW_UP); + } + if (caps & SDL_HAPTIC_SAWTOOTHDOWN) { + hasPeriodic = true; + m_availablePeriodicWaveforms.push_back(PeriodicWaveforms::SAW_DOWN); + } + if (hasPeriodic) + m_availableEffects.push_back(FFBEffectTypes::PERIODIC); + + if (caps & SDL_HAPTIC_RAMP) + m_availableEffects.push_back(FFBEffectTypes::RAMP); + + if (caps & SDL_HAPTIC_SPRING) { + hasCondition = true; + m_availableConditionSubtypes.push_back(ConditionSubtypes::SPRING); + } + if (caps & SDL_HAPTIC_DAMPER) { + hasCondition = true; + m_availableConditionSubtypes.push_back(ConditionSubtypes::DAMPER); + } + if (caps & SDL_HAPTIC_INERTIA) { + hasCondition = true; + m_availableConditionSubtypes.push_back(ConditionSubtypes::INERTIA); + } + if (caps & SDL_HAPTIC_FRICTION) { + hasCondition = true; + m_availableConditionSubtypes.push_back(ConditionSubtypes::FRICTION); + } + + if (hasCondition) + m_availableEffects.push_back(FFBEffectTypes::CONDITION); + + return true; +} + +bool SDL2FFBDevice::removeAndEraseEffect(const int idx) +{ + return false; +} + +bool SDL2FFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr< FFBEffectParameters > parameters) +{ + return false; +} + +bool SDL2FFBDevice::stopEffect(const int idx) +{ + return false; +} + +bool SDL2FFBDevice::uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr< FFBEffectParameters > parameters) +{ + return false; +} + diff --git a/sdl2ffbdevice.h b/sdl2ffbdevice.h new file mode 100644 index 0000000..e1acae6 --- /dev/null +++ b/sdl2ffbdevice.h @@ -0,0 +1,21 @@ +#ifndef SDL2FFBDEVICE_H +#define SDL2FFBDEVICE_H + +#include "SDL.h" +#include "ffbdevice.h" + +class SDL2FFBDevice : public FFBDevice { +public: + SDL2FFBDevice(SDL_Haptic* haptic, const int maxEffectCount); + void close(); + bool queryDeviceCapabilities(); + bool removeAndEraseEffect(const int idx); + 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); + +private: + SDL_Haptic* c_haptic; +}; + +#endif // SDL2FFBDEVICE_H \ No newline at end of file diff --git a/sdl2ffbeffectfactory.cpp b/sdl2ffbeffectfactory.cpp new file mode 100644 index 0000000..5ace543 --- /dev/null +++ b/sdl2ffbeffectfactory.cpp @@ -0,0 +1,11 @@ +#include "sdl2ffbeffectfactory.h" + +std::shared_ptr SDL2FFBEffectFactory::createEffect(FFBEffectTypes type) +{ + switch (type) { + case FFBEffectTypes::NONE: + return std::shared_ptr(new FFBNullEffect()); + default: + return std::shared_ptr(new FFBNullEffect()); + } +} \ No newline at end of file diff --git a/sdl2ffbeffectfactory.h b/sdl2ffbeffectfactory.h new file mode 100644 index 0000000..599b021 --- /dev/null +++ b/sdl2ffbeffectfactory.h @@ -0,0 +1,15 @@ +#ifndef SDL2FFBEFFECTFACTORY_H +#define SDL2FFBEFFECTFACTORY_H + +#include "globals.h" +#include "ffbnulleffect.h" + +class SDL2FFBEffectFactory +{ +public: + static std::shared_ptr createEffect(FFBEffectTypes type); + + SDL2FFBEffectFactory() = delete; +}; + +#endif // LINUXFFBEFFECTFACTORY_H -- 2.43.5