diff options
author | Garrett Brown <themagnificentmrb@gmail.com> | 2016-04-13 18:35:05 -0700 |
---|---|---|
committer | Garrett Brown <themagnificentmrb@gmail.com> | 2016-08-06 12:55:52 -0700 |
commit | c1819651563ee9350be07dde810fcd682b5ea7d3 (patch) | |
tree | dcf83147cf32cbb3513ec48112604d2f19b62a00 | |
parent | 3c295e15494aea6ad47597659e06c377a77024c1 (diff) |
[peripheral API] v1.0.18 - Add rumble capability
32 files changed, 496 insertions, 57 deletions
diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj index a9f87d2f6d..436be8c44e 100644 --- a/Kodi.xcodeproj/project.pbxproj +++ b/Kodi.xcodeproj/project.pbxproj @@ -253,6 +253,8 @@ 5EB3113C1A978B9B00551907 /* CueInfoLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EB3113A1A978B9B00551907 /* CueInfoLoader.cpp */; }; 5EE4F9181A9FF36F002E20F8 /* CueInfoLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EB3113A1A978B9B00551907 /* CueInfoLoader.cpp */; }; 5EF801001A97892A0035AA4D /* ReplayGain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EF800FE1A97892A0035AA4D /* ReplayGain.cpp */; }; + 6861B9EA1CC248EE00F62655 /* DriverReceiving.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6861B9E81CC248EE00F62655 /* DriverReceiving.cpp */; }; + 6861B9EB1CC248EE00F62655 /* DriverReceiving.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6861B9E81CC248EE00F62655 /* DriverReceiving.cpp */; }; 68AE5BA51C92412900C4D527 /* AddonCallbacksPeripheral.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 68AE5BA31C92412900C4D527 /* AddonCallbacksPeripheral.cpp */; }; 68AE5BA61C92412900C4D527 /* AddonCallbacksPeripheral.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 68AE5BA31C92412900C4D527 /* AddonCallbacksPeripheral.cpp */; }; 68AE5BBD1C9241DF00C4D527 /* DefaultJoystick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 68AE5BAC1C9241DF00C4D527 /* DefaultJoystick.cpp */; }; @@ -2743,6 +2745,10 @@ 5EB3113B1A978B9B00551907 /* CueInfoLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CueInfoLoader.h; sourceTree = "<group>"; }; 5EF800FE1A97892A0035AA4D /* ReplayGain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReplayGain.cpp; sourceTree = "<group>"; }; 5EF800FF1A97892A0035AA4D /* ReplayGain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReplayGain.h; sourceTree = "<group>"; }; + 6861B9E81CC248EE00F62655 /* DriverReceiving.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DriverReceiving.cpp; path = joysticks/generic/DriverReceiving.cpp; sourceTree = "<group>"; }; + 6861B9E91CC248EE00F62655 /* DriverReceiving.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DriverReceiving.h; path = joysticks/generic/DriverReceiving.h; sourceTree = "<group>"; }; + 6861B9EC1CC248F600F62655 /* IDriverReceiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IDriverReceiver.h; path = joysticks/IDriverReceiver.h; sourceTree = "<group>"; }; + 6861B9ED1CC248F600F62655 /* IInputReceiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IInputReceiver.h; path = joysticks/IInputReceiver.h; sourceTree = "<group>"; }; 68AE5BA01C923E5300C4D527 /* kodi_vfs_utils.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = kodi_vfs_utils.hpp; path = "kodi-addon-dev-kit/include/kodi/kodi_vfs_utils.hpp"; sourceTree = "<group>"; }; 68AE5BA31C92412900C4D527 /* AddonCallbacksPeripheral.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AddonCallbacksPeripheral.cpp; path = addons/binary/interfaces/api1/Peripheral/AddonCallbacksPeripheral.cpp; sourceTree = "<group>"; }; 68AE5BA41C92412900C4D527 /* AddonCallbacksPeripheral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AddonCallbacksPeripheral.h; path = addons/binary/interfaces/api1/Peripheral/AddonCallbacksPeripheral.h; sourceTree = "<group>"; }; @@ -6123,7 +6129,9 @@ 68AE5BB01C9241DF00C4D527 /* IButtonMap.h */, 68AE5BB11C9241DF00C4D527 /* IButtonMapper.h */, 68AE5BB21C9241DF00C4D527 /* IDriverHandler.h */, + 6861B9EC1CC248F600F62655 /* IDriverReceiver.h */, 68AE5BB31C9241DF00C4D527 /* IInputHandler.h */, + 6861B9ED1CC248F600F62655 /* IInputReceiver.h */, 68AE5BB41C9241DF00C4D527 /* IKeymapHandler.h */, 68AE5BB51C9241DF00C4D527 /* JoystickMonitor.cpp */, 68AE5BB61C9241DF00C4D527 /* JoystickMonitor.h */, @@ -6142,6 +6150,8 @@ children = ( 68AE5BC81C9241F800C4D527 /* ButtonMapping.cpp */, 68AE5BC91C9241F800C4D527 /* ButtonMapping.h */, + 6861B9E81CC248EE00F62655 /* DriverReceiving.cpp */, + 6861B9E91CC248EE00F62655 /* DriverReceiving.h */, 68AE5BCA1C9241F800C4D527 /* FeatureHandling.cpp */, 68AE5BCB1C9241F800C4D527 /* FeatureHandling.h */, 68AE5BCC1C9241F800C4D527 /* InputHandling.cpp */, @@ -10014,6 +10024,7 @@ 8883CEA10DD817D1004E8B72 /* DVDOverlayCodecSSA.cpp in Sources */, 8883CEA70DD81807004E8B72 /* DVDSubtitleParserSSA.cpp in Sources */, 8883CEA80DD81807004E8B72 /* DVDSubtitlesLibass.cpp in Sources */, + 6861B9EA1CC248EE00F62655 /* DriverReceiving.cpp in Sources */, 5EF801001A97892A0035AA4D /* ReplayGain.cpp in Sources */, 8863281D0E07B37200BB3DAB /* GUIDialogFullScreenInfo.cpp in Sources */, 8863281E0E07B37200BB3DAB /* GUIViewStatePictures.cpp in Sources */, @@ -10847,6 +10858,7 @@ E49911AE174E5CFE00741B6D /* AEStreamInfo.cpp in Sources */, E49911AF174E5CFE00741B6D /* AEUtil.cpp in Sources */, E49911B1174E5CFE00741B6D /* AEFactory.cpp in Sources */, + 6861B9EB1CC248EE00F62655 /* DriverReceiving.cpp in Sources */, E49911B2174E5D0A00741B6D /* EmuFileWrapper.cpp in Sources */, E49911B3174E5D0A00741B6D /* emu_dummy.cpp in Sources */, E49911B4174E5D0A00741B6D /* emu_kernel32.cpp in Sources */, diff --git a/addons/kodi.peripheral/addon.xml b/addons/kodi.peripheral/addon.xml index f2732cf5b4..9c2572de03 100644 --- a/addons/kodi.peripheral/addon.xml +++ b/addons/kodi.peripheral/addon.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<addon id="kodi.peripheral" version="1.0.17" provider-name="Team-Kodi"> - <backwards-compatibility abi="1.0.16"/> +<addon id="kodi.peripheral" version="1.0.18" provider-name="Team-Kodi"> + <backwards-compatibility abi="1.0.18"/> <requires> <import addon="xbmc.core" version="0.1.0"/> </requires> diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_dll.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_dll.h index 31433a401a..08db4a292e 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_dll.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_dll.h @@ -100,6 +100,14 @@ extern "C" * @param events The array of allocated events */ void FreeEvents(unsigned int event_count, PERIPHERAL_EVENT* events); + + /*! + * @brief Send an input event to the specified peripheral + * @param peripheralIndex The index of the device receiving the input event + * @param event The input event + * @return true if the event was handled, false otherwise + */ + bool SendEvent(const PERIPHERAL_EVENT* event); ///} /// @name Joystick operations @@ -180,6 +188,7 @@ extern "C" pClient->FreeScanResults = FreeScanResults; pClient->GetEvents = GetEvents; pClient->FreeEvents = FreeEvents; + pClient->SendEvent = SendEvent; #ifdef PERIPHERAL_ADDON_JOYSTICKS pClient->GetJoystickInfo = GetJoystickInfo; diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_types.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_types.h index f81ee74df9..be815ad3a5 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_types.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_types.h @@ -50,10 +50,10 @@ #endif /* current Peripheral API version */ -#define PERIPHERAL_API_VERSION "1.0.17" +#define PERIPHERAL_API_VERSION "1.0.18" /* min. Peripheral API version */ -#define PERIPHERAL_MIN_API_VERSION "1.0.16" +#define PERIPHERAL_MIN_API_VERSION "1.0.18" /* indicates a joystick has no preference for port number */ #define NO_PORT_REQUESTED (-1) @@ -122,6 +122,7 @@ extern "C" PERIPHERAL_EVENT_TYPE_DRIVER_BUTTON, /*!< @brief state changed for joystick driver button */ PERIPHERAL_EVENT_TYPE_DRIVER_HAT, /*!< @brief state changed for joystick driver hat */ PERIPHERAL_EVENT_TYPE_DRIVER_AXIS, /*!< @brief state changed for joystick driver axis */ + PERIPHERAL_EVENT_TYPE_SET_MOTOR, /*!< @brief set the state for joystick rumble motor */ } PERIPHERAL_EVENT_TYPE; typedef enum JOYSTICK_STATE_BUTTON @@ -152,6 +153,8 @@ extern "C" */ typedef float JOYSTICK_STATE_AXIS; + typedef float JOYSTICK_STATE_MOTOR; + typedef struct PERIPHERAL_EVENT { unsigned int peripheral_index; @@ -160,6 +163,7 @@ extern "C" JOYSTICK_STATE_BUTTON driver_button_state; JOYSTICK_STATE_HAT driver_hat_state; JOYSTICK_STATE_AXIS driver_axis_state; + JOYSTICK_STATE_MOTOR motor_state; } ATTRIBUTE_PACKED PERIPHERAL_EVENT; ///} @@ -173,6 +177,7 @@ extern "C" unsigned int button_count; /*!< @brief number of buttons reported by the driver */ unsigned int hat_count; /*!< @brief number of hats reported by the driver */ unsigned int axis_count; /*!< @brief number of axes reported by the driver */ + unsigned int motor_count; /*!< @brief number of motors reported by the driver */ } ATTRIBUTE_PACKED JOYSTICK_INFO; typedef enum JOYSTICK_DRIVER_PRIMITIVE_TYPE @@ -181,6 +186,7 @@ extern "C" JOYSTICK_DRIVER_PRIMITIVE_TYPE_BUTTON, JOYSTICK_DRIVER_PRIMITIVE_TYPE_HAT_DIRECTION, JOYSTICK_DRIVER_PRIMITIVE_TYPE_SEMIAXIS, + JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR, } JOYSTICK_DRIVER_PRIMITIVE_TYPE; typedef struct JOYSTICK_DRIVER_BUTTON @@ -216,6 +222,11 @@ extern "C" JOYSTICK_DRIVER_SEMIAXIS_DIRECTION direction; } ATTRIBUTE_PACKED JOYSTICK_DRIVER_SEMIAXIS; + typedef struct JOYSTICK_DRIVER_MOTOR + { + int index; + } ATTRIBUTE_PACKED JOYSTICK_DRIVER_MOTOR; + typedef struct JOYSTICK_DRIVER_PRIMITIVE { JOYSTICK_DRIVER_PRIMITIVE_TYPE type; @@ -224,6 +235,7 @@ extern "C" struct JOYSTICK_DRIVER_BUTTON button; struct JOYSTICK_DRIVER_HAT hat; struct JOYSTICK_DRIVER_SEMIAXIS semiaxis; + struct JOYSTICK_DRIVER_MOTOR motor; }; } ATTRIBUTE_PACKED JOYSTICK_DRIVER_PRIMITIVE; @@ -233,6 +245,7 @@ extern "C" JOYSTICK_FEATURE_TYPE_SCALAR, JOYSTICK_FEATURE_TYPE_ANALOG_STICK, JOYSTICK_FEATURE_TYPE_ACCELEROMETER, + JOYSTICK_FEATURE_TYPE_MOTOR, } JOYSTICK_FEATURE_TYPE; typedef struct JOYSTICK_FEATURE_SCALAR @@ -255,6 +268,11 @@ extern "C" struct JOYSTICK_DRIVER_PRIMITIVE positive_z; } ATTRIBUTE_PACKED JOYSTICK_FEATURE_ACCELEROMETER; + typedef struct JOYSTICK_FEATURE_MOTOR + { + struct JOYSTICK_DRIVER_PRIMITIVE primitive; + } ATTRIBUTE_PACKED JOYSTICK_FEATURE_MOTOR; + typedef struct JOYSTICK_FEATURE { char* name; @@ -264,6 +282,7 @@ extern "C" struct JOYSTICK_FEATURE_SCALAR scalar; struct JOYSTICK_FEATURE_ANALOG_STICK analog_stick; struct JOYSTICK_FEATURE_ACCELEROMETER accelerometer; + struct JOYSTICK_FEATURE_MOTOR motor; }; } ATTRIBUTE_PACKED JOYSTICK_FEATURE; ///} @@ -282,6 +301,7 @@ extern "C" void (__cdecl* FreeScanResults)(unsigned int, PERIPHERAL_INFO*); PERIPHERAL_ERROR (__cdecl* GetEvents)(unsigned int*, PERIPHERAL_EVENT**); void (__cdecl* FreeEvents)(unsigned int, PERIPHERAL_EVENT*); + bool (__cdecl* SendEvent)(const PERIPHERAL_EVENT*); /// @name Joystick operations ///{ diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_utils.hpp b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_utils.hpp index 4423cb4d39..d4d725b2af 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_utils.hpp +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_utils.hpp @@ -204,6 +204,7 @@ namespace ADDON JOYSTICK_STATE_BUTTON ButtonState(void) const { return m_event.driver_button_state; } JOYSTICK_STATE_HAT HatState(void) const { return m_event.driver_hat_state; } JOYSTICK_STATE_AXIS AxisState(void) const { return m_event.driver_axis_state; } + JOYSTICK_STATE_MOTOR MotorState(void) const { return m_event.motor_state; } void SetType(PERIPHERAL_EVENT_TYPE type) { m_event.type = type; } void SetPeripheralIndex(unsigned int index) { m_event.peripheral_index = index; } @@ -211,6 +212,7 @@ namespace ADDON void SetButtonState(JOYSTICK_STATE_BUTTON state) { m_event.driver_button_state = state; } void SetHatState(JOYSTICK_STATE_HAT state) { m_event.driver_hat_state = state; } void SetAxisState(JOYSTICK_STATE_AXIS state) { m_event.driver_axis_state = state; } + void SetMotorState(JOYSTICK_STATE_MOTOR state) { m_event.motor_state = state; } void ToStruct(PERIPHERAL_EVENT& event) const { @@ -243,7 +245,8 @@ namespace ADDON m_requestedPort(NO_PORT_REQUESTED), m_buttonCount(0), m_hatCount(0), - m_axisCount(0) + m_axisCount(0), + m_motorCount(0) { } @@ -258,7 +261,8 @@ namespace ADDON m_requestedPort(info.requested_port), m_buttonCount(info.button_count), m_hatCount(info.hat_count), - m_axisCount(info.axis_count) + m_axisCount(info.axis_count), + m_motorCount(info.motor_count) { } @@ -275,6 +279,7 @@ namespace ADDON m_buttonCount = rhs.m_buttonCount; m_hatCount = rhs.m_hatCount; m_axisCount = rhs.m_axisCount; + m_motorCount = rhs.m_motorCount; } return *this; } @@ -284,6 +289,7 @@ namespace ADDON unsigned int ButtonCount(void) const { return m_buttonCount; } unsigned int HatCount(void) const { return m_hatCount; } unsigned int AxisCount(void) const { return m_axisCount; } + unsigned int MotorCount(void) const { return m_motorCount; } // Derived property: Counts are unknown if all are zero bool AreElementCountsKnown(void) const { return m_buttonCount != 0 || m_hatCount != 0 || m_axisCount != 0; } @@ -293,6 +299,7 @@ namespace ADDON void SetButtonCount(unsigned int buttonCount) { m_buttonCount = buttonCount; } void SetHatCount(unsigned int hatCount) { m_hatCount = hatCount; } void SetAxisCount(unsigned int axisCount) { m_axisCount = axisCount; } + void SetMotorCount(unsigned int motorCount) { m_motorCount = motorCount; } void ToStruct(JOYSTICK_INFO& info) const { @@ -303,6 +310,7 @@ namespace ADDON info.button_count = m_buttonCount; info.hat_count = m_hatCount; info.axis_count = m_axisCount; + info.motor_count = m_motorCount; std::strcpy(info.provider, m_provider.c_str()); } @@ -320,6 +328,7 @@ namespace ADDON unsigned int m_buttonCount; unsigned int m_hatCount; unsigned int m_axisCount; + unsigned int m_motorCount; }; typedef PeripheralVector<Joystick, JOYSTICK_INFO> Joysticks; @@ -332,6 +341,7 @@ namespace ADDON * 1) a button * 2) a hat direction * 3) a semiaxis (either the positive or negative half of an axis) + * 4) a motor * * The type determines the fields in use: * @@ -345,9 +355,24 @@ namespace ADDON * Semiaxis: * - driver index * - semiaxis direction + * + * Motor: + * - driver index */ class DriverPrimitive { + protected: + /*! + * \brief Construct a driver primitive of the specified type + */ + DriverPrimitive(JOYSTICK_DRIVER_PRIMITIVE_TYPE type, unsigned int driverIndex) : + m_type(type), + m_driverIndex(driverIndex), + m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN), + m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN) + { + } + public: /*! * \brief Construct an invalid driver primitive @@ -363,12 +388,9 @@ namespace ADDON /*! * \brief Construct a driver primitive representing a button */ - DriverPrimitive(unsigned int buttonIndex) : - m_type(JOYSTICK_DRIVER_PRIMITIVE_TYPE_BUTTON), - m_driverIndex(buttonIndex), - m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN), - m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN) + static DriverPrimitive CreateButton(unsigned int buttonIndex) { + return DriverPrimitive(JOYSTICK_DRIVER_PRIMITIVE_TYPE_BUTTON, buttonIndex); } /*! @@ -395,6 +417,14 @@ namespace ADDON { } + /*! + * \brief Construct a driver primitive representing a motor + */ + static DriverPrimitive CreateMotor(unsigned int motorIndex) + { + return DriverPrimitive(JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR, motorIndex); + } + DriverPrimitive(const JOYSTICK_DRIVER_PRIMITIVE& primitive) : m_type(primitive.type), m_driverIndex(0), @@ -420,6 +450,11 @@ namespace ADDON m_semiAxisDirection = primitive.semiaxis.direction; break; } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR: + { + m_driverIndex = primitive.motor.index; + break; + } default: break; } @@ -437,6 +472,7 @@ namespace ADDON switch (m_type) { case JOYSTICK_DRIVER_PRIMITIVE_TYPE_BUTTON: + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR: { return m_driverIndex == other.m_driverIndex; } @@ -479,6 +515,11 @@ namespace ADDON driver_primitive.semiaxis.direction = m_semiAxisDirection; break; } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR: + { + driver_primitive.motor.index = m_driverIndex; + break; + } default: break; } @@ -499,6 +540,7 @@ namespace ADDON * 1) scalar[1] * 2) analog stick * 3) accelerometer + * 4) motor * * [1] All three driver primitives (buttons, hats and axes) have a state that * can be represented using a single scalar value. For this reason, @@ -520,6 +562,9 @@ namespace ADDON * - positive X * - positive Y * - positive Z + * + * Motor: + * - primitive */ class JoystickFeature { @@ -565,6 +610,9 @@ namespace ADDON SetPositiveY(feature.accelerometer.positive_y); SetPositiveZ(feature.accelerometer.positive_z); break; + case JOYSTICK_FEATURE_TYPE_MOTOR: + SetPrimitive(feature.motor.primitive); + break; default: break; } @@ -636,6 +684,9 @@ namespace ADDON PositiveY().ToStruct(feature.accelerometer.positive_y); PositiveZ().ToStruct(feature.accelerometer.positive_z); break; + case JOYSTICK_FEATURE_TYPE_MOTOR: + Primitive().ToStruct(feature.motor.primitive); + break; default: break; } diff --git a/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp b/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp index b48986ba65..729d8e1926 100644 --- a/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp +++ b/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp @@ -137,7 +137,7 @@ bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap, cons bool bHandled = false; // Handle esc key separately - if (primitive.Type() == CDriverPrimitive::BUTTON && + if (primitive.Type() == PRIMITIVE_TYPE::BUTTON && primitive.Index() == ESC_KEY_CODE) { bHandled = Abort(false); diff --git a/xbmc/input/joysticks/CMakeLists.txt b/xbmc/input/joysticks/CMakeLists.txt index db2db696fe..57306bd402 100644 --- a/xbmc/input/joysticks/CMakeLists.txt +++ b/xbmc/input/joysticks/CMakeLists.txt @@ -9,7 +9,9 @@ set(HEADERS DefaultJoystick.h IButtonMap.h IButtonMapper.h IDriverHandler.h + IDriverReceiver.h IInputHandler.h + IInputReceiver.h IKeymapHandler.h JoystickMonitor.h JoystickTranslator.h diff --git a/xbmc/input/joysticks/DriverPrimitive.cpp b/xbmc/input/joysticks/DriverPrimitive.cpp index 70bd2e0d9b..8630a40253 100644 --- a/xbmc/input/joysticks/DriverPrimitive.cpp +++ b/xbmc/input/joysticks/DriverPrimitive.cpp @@ -30,9 +30,9 @@ CDriverPrimitive::CDriverPrimitive(void) { } -CDriverPrimitive::CDriverPrimitive(unsigned int buttonIndex) - : m_type(BUTTON), - m_driverIndex(buttonIndex), +CDriverPrimitive::CDriverPrimitive(PRIMITIVE_TYPE type, unsigned int index) + : m_type(type), + m_driverIndex(index), m_hatDirection(), m_semiAxisDirection() { @@ -61,6 +61,7 @@ bool CDriverPrimitive::operator==(const CDriverPrimitive& rhs) const switch (m_type) { case BUTTON: + case MOTOR: return m_driverIndex == rhs.m_driverIndex; case HAT: return m_driverIndex == rhs.m_driverIndex && m_hatDirection == rhs.m_hatDirection; @@ -102,7 +103,7 @@ bool CDriverPrimitive::operator<(const CDriverPrimitive& rhs) const bool CDriverPrimitive::IsValid(void) const { - if (m_type == BUTTON) + if (m_type == BUTTON || m_type == MOTOR) return true; if (m_type == HAT) diff --git a/xbmc/input/joysticks/DriverPrimitive.h b/xbmc/input/joysticks/DriverPrimitive.h index 626a368bf5..fad150b706 100644 --- a/xbmc/input/joysticks/DriverPrimitive.h +++ b/xbmc/input/joysticks/DriverPrimitive.h @@ -55,6 +55,9 @@ namespace JOYSTICK * - driver index * - semiaxis direction (positive/negative) * + * Motor: + * - driver index + * * For more info, see "Chapter 2. Joystick drivers" in the documentation * thread: http://forum.kodi.tv/showthread.php?tid=257764 */ @@ -62,25 +65,14 @@ namespace JOYSTICK { public: /*! - * \brief Type of driver primitive - */ - enum PrimitiveType - { - UNKNOWN = 0, // primitive has no type (invalid) - BUTTON, // a digital button - HAT, // one of the four direction arrows on a D-pad - SEMIAXIS, // the positive or negative half of an axis - }; - - /*! * \brief Construct an invalid driver primitive */ CDriverPrimitive(void); /*! - * \brief Construct a driver primitive representing a button + * \brief Construct a driver primitive representing a button or motor */ - CDriverPrimitive(unsigned int buttonIndex); + CDriverPrimitive(PRIMITIVE_TYPE type, unsigned int index); /*! * \brief Construct a driver primitive representing one of the four @@ -105,7 +97,7 @@ namespace JOYSTICK /*! * \brief The type of driver primitive */ - PrimitiveType Type(void) const { return m_type; } + PRIMITIVE_TYPE Type(void) const { return m_type; } /*! * \brief The index used by the driver (valid for all types) @@ -133,7 +125,7 @@ namespace JOYSTICK bool IsValid(void) const; private: - PrimitiveType m_type; + PRIMITIVE_TYPE m_type; unsigned int m_driverIndex; HAT_DIRECTION m_hatDirection; SEMIAXIS_DIRECTION m_semiAxisDirection; diff --git a/xbmc/input/joysticks/IDriverReceiver.h b/xbmc/input/joysticks/IDriverReceiver.h new file mode 100644 index 0000000000..c1a2a2083f --- /dev/null +++ b/xbmc/input/joysticks/IDriverReceiver.h @@ -0,0 +1,42 @@ +/* +* Copyright (C) 2016 Team Kodi +* http://kodi.tv +* +* This Program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This Program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this Program; see the file COPYING. If not, see +* <http://www.gnu.org/licenses/>. +* +*/ +#pragma once + +namespace JOYSTICK +{ + /*! + * \brief Interface for sending input events to joystick drivers + */ + class IDriverReceiver + { + public: + virtual ~IDriverReceiver(void) { } + + /*! + * \brief Set the value of a rumble motor + * + * \param motorIndex The driver index of the motor to rumble + * \param magnitude The motor's new magnitude of vibration in the closed interval [0, 1] + * + * \return True if the event was handled otherwise false + */ + virtual bool SetMotorState(unsigned int motorIndex, float magnitude) = 0; + }; +} diff --git a/xbmc/input/joysticks/IInputHandler.h b/xbmc/input/joysticks/IInputHandler.h index 20ce7efcae..7c13c84609 100644 --- a/xbmc/input/joysticks/IInputHandler.h +++ b/xbmc/input/joysticks/IInputHandler.h @@ -25,12 +25,16 @@ namespace JOYSTICK { + class IInputReceiver; + /*! * \brief Interface for handling input events for game controllers */ class IInputHandler { public: + IInputHandler(void) : m_receiver(nullptr) { } + virtual ~IInputHandler(void) { } /*! @@ -93,5 +97,13 @@ namespace JOYSTICK * \return True if the event was handled otherwise false */ virtual bool OnAccelerometerMotion(const FeatureName& feature, float x, float y, float z) { return false; } + + // Input receiver interface + void SetInputReceiver(IInputReceiver* receiver) { m_receiver = receiver; } + void ResetInputReceiver(void) { m_receiver = nullptr; } + IInputReceiver* InputReceiver(void) { return m_receiver; } + + private: + IInputReceiver* m_receiver; }; } diff --git a/xbmc/input/joysticks/IInputReceiver.h b/xbmc/input/joysticks/IInputReceiver.h new file mode 100644 index 0000000000..5bc89d72fa --- /dev/null +++ b/xbmc/input/joysticks/IInputReceiver.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2014-2016 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ +#pragma once + +#include "JoystickTypes.h" + +namespace JOYSTICK +{ + /*! + * \brief Interface for sending input events to game controllers + */ + class IInputReceiver + { + public: + virtual ~IInputReceiver(void) { } + + /*! + * \brief Set the value of a rumble motor + * + * \param feature The name of the motor to rumble + * \param magnitude The motor's new magnitude of vibration in the closed interval [0, 1] + * + * \return True if the event was handled otherwise false + */ + virtual bool SetRumbleState(const FeatureName& feature, float magnitude) = 0; + }; +} diff --git a/xbmc/input/joysticks/JoystickTypes.h b/xbmc/input/joysticks/JoystickTypes.h index dce8a46215..25e15162cc 100644 --- a/xbmc/input/joysticks/JoystickTypes.h +++ b/xbmc/input/joysticks/JoystickTypes.h @@ -123,4 +123,16 @@ namespace JOYSTICK DIGITAL, ANALOG, }; + + /*! + * \brief Type of driver primitive + */ + enum PRIMITIVE_TYPE + { + UNKNOWN = 0, // primitive has no type (invalid) + BUTTON, // a digital button + HAT, // one of the four direction arrows on a D-pad + SEMIAXIS, // the positive or negative half of an axis + MOTOR, // a rumble motor + }; } diff --git a/xbmc/input/joysticks/generic/ButtonMapping.cpp b/xbmc/input/joysticks/generic/ButtonMapping.cpp index e49d32d24c..6bbe3382a2 100644 --- a/xbmc/input/joysticks/generic/ButtonMapping.cpp +++ b/xbmc/input/joysticks/generic/ButtonMapping.cpp @@ -49,7 +49,7 @@ bool CButtonMapping::OnButtonMotion(unsigned int buttonIndex, bool bPressed) { if (bPressed) { - CDriverPrimitive buttonPrimitive(buttonIndex); + CDriverPrimitive buttonPrimitive(PRIMITIVE_TYPE::BUTTON, buttonIndex); if (buttonPrimitive.IsValid()) { MapPrimitive(buttonPrimitive); diff --git a/xbmc/input/joysticks/generic/CMakeLists.txt b/xbmc/input/joysticks/generic/CMakeLists.txt index 2d7a219010..f44258a548 100644 --- a/xbmc/input/joysticks/generic/CMakeLists.txt +++ b/xbmc/input/joysticks/generic/CMakeLists.txt @@ -1,8 +1,10 @@ set(SOURCES ButtonMapping.cpp + DriverReceiving.cpp FeatureHandling.cpp InputHandling.cpp) set(HEADERS ButtonMapping.h + DriverReceiving.h FeatureHandling.h InputHandling.h) diff --git a/xbmc/input/joysticks/generic/DriverReceiving.cpp b/xbmc/input/joysticks/generic/DriverReceiving.cpp new file mode 100644 index 0000000000..d44eabd1c0 --- /dev/null +++ b/xbmc/input/joysticks/generic/DriverReceiving.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "DriverReceiving.h" +#include "input/joysticks/DriverPrimitive.h" +#include "input/joysticks/IButtonMap.h" +#include "input/joysticks/IDriverReceiver.h" + +using namespace JOYSTICK; + +CDriverReceiving::CDriverReceiving(IDriverReceiver* receiver, IButtonMap* buttonMap) + : m_receiver(receiver), + m_buttonMap(buttonMap) +{ +} + +bool CDriverReceiving::SetRumbleState(const FeatureName& feature, float magnitude) +{ + bool bHandled = false; + + if (m_receiver != nullptr && m_buttonMap != nullptr) + { + CDriverPrimitive primitive; + if (m_buttonMap->GetScalar(feature, primitive)) + { + if (primitive.Type() == PRIMITIVE_TYPE::MOTOR) + bHandled = m_receiver->SetMotorState(primitive.Index(), magnitude); + } + } + + return bHandled; +} diff --git a/xbmc/input/joysticks/generic/DriverReceiving.h b/xbmc/input/joysticks/generic/DriverReceiving.h new file mode 100644 index 0000000000..531ffc92df --- /dev/null +++ b/xbmc/input/joysticks/generic/DriverReceiving.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ +#pragma once + +#include "input/joysticks/IInputReceiver.h" +#include "input/joysticks/JoystickTypes.h" + +#include <map> + +namespace JOYSTICK +{ + class IDriverReceiver; + class IButtonMap; + + /*! + * \brief Class to translate input events from higher-level features to driver primitives + * + * A button map is used to translate controller features to driver primitives. + * The button map has been abstracted away behind the IButtonMap interface + * so that it can be provided by an add-on. + */ + class CDriverReceiving : public IInputReceiver + { + public: + CDriverReceiving(IDriverReceiver* receiver, IButtonMap* buttonMap); + + virtual ~CDriverReceiving(void) { } + + // implementation of IInputReceiver + virtual bool SetRumbleState(const FeatureName& feature, float magnitude) override; + + private: + IDriverReceiver* const m_receiver; + IButtonMap* const m_buttonMap; + }; +} diff --git a/xbmc/input/joysticks/generic/InputHandling.cpp b/xbmc/input/joysticks/generic/InputHandling.cpp index 1a35e52862..8982491037 100644 --- a/xbmc/input/joysticks/generic/InputHandling.cpp +++ b/xbmc/input/joysticks/generic/InputHandling.cpp @@ -21,7 +21,6 @@ #include "InputHandling.h" #include "input/joysticks/DriverPrimitive.h" #include "input/joysticks/IButtonMap.h" -#include "input/joysticks/IInputHandler.h" #include "input/joysticks/JoystickUtils.h" using namespace JOYSTICK; @@ -38,7 +37,7 @@ CInputHandling::~CInputHandling(void) bool CInputHandling::OnButtonMotion(unsigned int buttonIndex, bool bPressed) { - return OnDigitalMotion(CDriverPrimitive(buttonIndex), bPressed); + return OnDigitalMotion(CDriverPrimitive(PRIMITIVE_TYPE::BUTTON, buttonIndex), bPressed); } bool CInputHandling::OnHatMotion(unsigned int hatIndex, HAT_STATE state) diff --git a/xbmc/input/joysticks/generic/Makefile b/xbmc/input/joysticks/generic/Makefile index 19134f1b34..189df859f5 100644 --- a/xbmc/input/joysticks/generic/Makefile +++ b/xbmc/input/joysticks/generic/Makefile @@ -1,4 +1,5 @@ SRCS=ButtonMapping.cpp \ + DriverReceiving.cpp \ FeatureHandling.cpp \ InputHandling.cpp \ diff --git a/xbmc/peripherals/PeripheralTypes.h b/xbmc/peripherals/PeripheralTypes.h index f93adc2811..565de4bf66 100644 --- a/xbmc/peripherals/PeripheralTypes.h +++ b/xbmc/peripherals/PeripheralTypes.h @@ -59,6 +59,7 @@ namespace PERIPHERALS FEATURE_TUNER, FEATURE_IMON, FEATURE_JOYSTICK, + FEATURE_RUMBLE, }; enum PeripheralType diff --git a/xbmc/peripherals/addons/AddonButtonMap.cpp b/xbmc/peripherals/addons/AddonButtonMap.cpp index ae65bd8c88..ff61dd9763 100644 --- a/xbmc/peripherals/addons/AddonButtonMap.cpp +++ b/xbmc/peripherals/addons/AddonButtonMap.cpp @@ -107,7 +107,8 @@ bool CAddonButtonMap::GetScalar(const FeatureName& feature, CDriverPrimitive& pr { const ADDON::JoystickFeature& addonFeature = it->second; - if (addonFeature.Type() == JOYSTICK_FEATURE_TYPE_SCALAR) + if (addonFeature.Type() == JOYSTICK_FEATURE_TYPE_SCALAR || + addonFeature.Type() == JOYSTICK_FEATURE_TYPE_MOTOR) { primitive = CPeripheralAddonTranslator::TranslatePrimitive(addonFeature.Primitive()); retVal = true; @@ -129,7 +130,9 @@ bool CAddonButtonMap::AddScalar(const FeatureName& feature, const CDriverPrimiti { UnmapPrimitive(primitive); - ADDON::JoystickFeature scalar(feature, JOYSTICK_FEATURE_TYPE_SCALAR); + const bool bMotor = (primitive.Type() == PRIMITIVE_TYPE::MOTOR); + + ADDON::JoystickFeature scalar(feature, bMotor ? JOYSTICK_FEATURE_TYPE_MOTOR : JOYSTICK_FEATURE_TYPE_SCALAR); scalar.SetPrimitive(CPeripheralAddonTranslator::TranslatePrimitive(primitive)); m_features[feature] = scalar; diff --git a/xbmc/peripherals/addons/AddonInputHandling.cpp b/xbmc/peripherals/addons/AddonInputHandling.cpp index 24ec85784e..7a29c9ea77 100644 --- a/xbmc/peripherals/addons/AddonInputHandling.cpp +++ b/xbmc/peripherals/addons/AddonInputHandling.cpp @@ -19,15 +19,18 @@ */ #include "AddonInputHandling.h" +#include "input/joysticks/generic/DriverReceiving.h" #include "input/joysticks/generic/InputHandling.h" #include "input/joysticks/IInputHandler.h" +#include "input/joysticks/IDriverReceiver.h" #include "peripherals/addons/AddonButtonMap.h" +#include "peripherals/devices/PeripheralJoystick.h" #include "peripherals/Peripherals.h" using namespace JOYSTICK; using namespace PERIPHERALS; -CAddonInputHandling::CAddonInputHandling(CPeripheral* peripheral, IInputHandler* handler) +CAddonInputHandling::CAddonInputHandling(CPeripheral* peripheral, IInputHandler* handler, IDriverReceiver* receiver) { PeripheralAddonPtr addon = g_peripherals.GetAddon(peripheral); @@ -39,15 +42,28 @@ CAddonInputHandling::CAddonInputHandling(CPeripheral* peripheral, IInputHandler* { m_buttonMap.reset(new CAddonButtonMap(peripheral, addon, handler->ControllerID())); if (m_buttonMap->Load()) + { m_driverHandler.reset(new CInputHandling(handler, m_buttonMap.get())); + + if (receiver) + { + m_inputReceiver.reset(new CDriverReceiving(receiver, m_buttonMap.get())); + + // Interfaces are connected here because they share button map as a common resource + handler->SetInputReceiver(m_inputReceiver.get()); + } + } else + { m_buttonMap.reset(); + } } } CAddonInputHandling::~CAddonInputHandling(void) { m_driverHandler.reset(); + m_inputReceiver.reset(); m_buttonMap.reset(); } @@ -80,3 +96,11 @@ void CAddonInputHandling::ProcessAxisMotions(void) if (m_driverHandler) m_driverHandler->ProcessAxisMotions(); } + +bool CAddonInputHandling::SetRumbleState(const JOYSTICK::FeatureName& feature, float magnitude) +{ + if (m_inputReceiver) + return m_inputReceiver->SetRumbleState(feature, magnitude); + + return false; +} diff --git a/xbmc/peripherals/addons/AddonInputHandling.h b/xbmc/peripherals/addons/AddonInputHandling.h index c7bef2ea5d..54f1020e4a 100644 --- a/xbmc/peripherals/addons/AddonInputHandling.h +++ b/xbmc/peripherals/addons/AddonInputHandling.h @@ -20,12 +20,14 @@ #pragma once #include "input/joysticks/IDriverHandler.h" +#include "input/joysticks/IInputReceiver.h" #include <memory> namespace JOYSTICK { class IButtonMap; + class IDriverReceiver; class IInputHandler; } @@ -33,10 +35,11 @@ namespace PERIPHERALS { class CPeripheral; - class CAddonInputHandling : public JOYSTICK::IDriverHandler + class CAddonInputHandling : public JOYSTICK::IDriverHandler, + public JOYSTICK::IInputReceiver { public: - CAddonInputHandling(CPeripheral* peripheral, JOYSTICK::IInputHandler* handler); + CAddonInputHandling(CPeripheral* peripheral, JOYSTICK::IInputHandler* handler, JOYSTICK::IDriverReceiver* receiver); virtual ~CAddonInputHandling(void); @@ -46,8 +49,12 @@ namespace PERIPHERALS virtual bool OnAxisMotion(unsigned int axisIndex, float position) override; virtual void ProcessAxisMotions(void) override; + // implementation of IInputReceiver + virtual bool SetRumbleState(const JOYSTICK::FeatureName& feature, float magnitude) override; + private: std::unique_ptr<JOYSTICK::IDriverHandler> m_driverHandler; + std::unique_ptr<JOYSTICK::IInputReceiver> m_inputReceiver; std::unique_ptr<JOYSTICK::IButtonMap> m_buttonMap; }; } diff --git a/xbmc/peripherals/addons/PeripheralAddon.cpp b/xbmc/peripherals/addons/PeripheralAddon.cpp index 2911123bd6..0587e37306 100644 --- a/xbmc/peripherals/addons/PeripheralAddon.cpp +++ b/xbmc/peripherals/addons/PeripheralAddon.cpp @@ -455,6 +455,23 @@ bool CPeripheralAddon::ProcessEvents(void) return false; } +bool CPeripheralAddon::SendRumbleEvent(unsigned int peripheralIndex, unsigned int driverIndex, float magnitude) +{ + bool bHandled = false; + + PERIPHERAL_EVENT eventStruct = { }; + + eventStruct.peripheral_index = peripheralIndex; + eventStruct.type = PERIPHERAL_EVENT_TYPE_SET_MOTOR; + eventStruct.driver_index = driverIndex; + eventStruct.motor_state = magnitude; + + try { bHandled = m_pStruct->SendEvent(&eventStruct); } + catch (std::exception &e) { LogException(e, "SendEvent()"); } + + return bHandled; +} + bool CPeripheralAddon::GetJoystickProperties(unsigned int index, CPeripheralJoystick& joystick) { if (!m_bProvidesJoysticks) @@ -622,6 +639,7 @@ void CPeripheralAddon::GetJoystickInfo(const CPeripheral* device, ADDON::Joystic joystickInfo.SetButtonCount(joystick->ButtonCount()); joystickInfo.SetHatCount(joystick->HatCount()); joystickInfo.SetAxisCount(joystick->AxisCount()); + joystickInfo.SetMotorCount(joystick->MotorCount()); } } @@ -632,6 +650,7 @@ void CPeripheralAddon::SetJoystickInfo(CPeripheralJoystick& joystick, const ADDO joystick.SetButtonCount(joystickInfo.ButtonCount()); joystick.SetHatCount(joystickInfo.HatCount()); joystick.SetAxisCount(joystickInfo.AxisCount()); + joystick.SetMotorCount(joystickInfo.MotorCount()); } bool CPeripheralAddon::LogError(const PERIPHERAL_ERROR error, const char *strMethod) const diff --git a/xbmc/peripherals/addons/PeripheralAddon.h b/xbmc/peripherals/addons/PeripheralAddon.h index 347c1ee17d..e439c82095 100644 --- a/xbmc/peripherals/addons/PeripheralAddon.h +++ b/xbmc/peripherals/addons/PeripheralAddon.h @@ -75,6 +75,7 @@ namespace PERIPHERALS //@{ bool PerformDeviceScan(PeripheralScanResults &results); bool ProcessEvents(void); + bool SendRumbleEvent(unsigned int index, unsigned int driverIndex, float magnitude); //@} /** @name Joystick methods */ diff --git a/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp b/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp index 2399eb0564..2c00677f62 100644 --- a/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp +++ b/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp @@ -63,7 +63,7 @@ CDriverPrimitive CPeripheralAddonTranslator::TranslatePrimitive(const ADDON::Dri { case JOYSTICK_DRIVER_PRIMITIVE_TYPE_BUTTON: { - retVal = CDriverPrimitive(primitive.DriverIndex()); + retVal = CDriverPrimitive(PRIMITIVE_TYPE::BUTTON, primitive.DriverIndex()); break; } case JOYSTICK_DRIVER_PRIMITIVE_TYPE_HAT_DIRECTION: @@ -76,6 +76,11 @@ CDriverPrimitive CPeripheralAddonTranslator::TranslatePrimitive(const ADDON::Dri retVal = CDriverPrimitive(primitive.DriverIndex(), TranslateSemiAxisDirection(primitive.SemiAxisDirection())); break; } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR: + { + retVal = CDriverPrimitive(PRIMITIVE_TYPE::MOTOR, primitive.DriverIndex()); + break; + } default: break; } @@ -89,21 +94,26 @@ ADDON::DriverPrimitive CPeripheralAddonTranslator::TranslatePrimitive(const CDri switch (primitive.Type()) { - case CDriverPrimitive::BUTTON: + case BUTTON: { - retVal = ADDON::DriverPrimitive(primitive.Index()); + retVal = ADDON::DriverPrimitive::CreateButton(primitive.Index()); break; } - case CDriverPrimitive::HAT: + case HAT: { retVal = ADDON::DriverPrimitive(primitive.Index(), TranslateHatDirection(primitive.HatDirection())); break; } - case CDriverPrimitive::SEMIAXIS: + case SEMIAXIS: { retVal = ADDON::DriverPrimitive(primitive.Index(), TranslateSemiAxisDirection(primitive.SemiAxisDirection())); break; } + case MOTOR: + { + retVal = ADDON::DriverPrimitive::CreateMotor(primitive.Index()); + break; + } default: break; } @@ -182,6 +192,7 @@ JOYSTICK::FEATURE_TYPE CPeripheralAddonTranslator::TranslateFeatureType(JOYSTICK case JOYSTICK_FEATURE_TYPE_SCALAR: return JOYSTICK::FEATURE_TYPE::SCALAR; case JOYSTICK_FEATURE_TYPE_ANALOG_STICK: return JOYSTICK::FEATURE_TYPE::ANALOG_STICK; case JOYSTICK_FEATURE_TYPE_ACCELEROMETER: return JOYSTICK::FEATURE_TYPE::ACCELEROMETER; + case JOYSTICK_FEATURE_TYPE_MOTOR: return JOYSTICK::FEATURE_TYPE::MOTOR; default: break; } @@ -195,6 +206,7 @@ JOYSTICK_FEATURE_TYPE CPeripheralAddonTranslator::TranslateFeatureType(JOYSTICK: case JOYSTICK::FEATURE_TYPE::SCALAR: return JOYSTICK_FEATURE_TYPE_SCALAR; case JOYSTICK::FEATURE_TYPE::ANALOG_STICK: return JOYSTICK_FEATURE_TYPE_ANALOG_STICK; case JOYSTICK::FEATURE_TYPE::ACCELEROMETER: return JOYSTICK_FEATURE_TYPE_ACCELEROMETER; + case JOYSTICK::FEATURE_TYPE::MOTOR: return JOYSTICK_FEATURE_TYPE_MOTOR; default: break; } diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp index e563222c21..b533686db6 100644 --- a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp +++ b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp @@ -135,6 +135,18 @@ bool CPeripheralBusAddon::InitializeProperties(CPeripheral* peripheral) return bSuccess; } +bool CPeripheralBusAddon::SendRumbleEvent(const std::string& strLocation, unsigned int motorIndex, float magnitude) +{ + bool bHandled = false; + + PeripheralAddonPtr addon; + unsigned int peripheralIndex; + if (SplitLocation(strLocation, addon, peripheralIndex)) + bHandled = addon->SendRumbleEvent(peripheralIndex, motorIndex, magnitude); + + return bHandled; +} + void CPeripheralBusAddon::ProcessEvents(void) { PeripheralAddonVector addons; diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h index 626938db4c..42d3495c6e 100644 --- a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h +++ b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h @@ -60,6 +60,19 @@ namespace PERIPHERALS */ bool InitializeProperties(CPeripheral* peripheral); + /*! + * \brief Set the rumble state of a rumble motor + * + * \param strLocation The location of the peripheral with the motor + * \param motorIndex The index of the motor being rumbled + * \param magnitude The amount of vibration in the closed interval [0.0, 1.0] + * + * \return true if the rumble motor's state is set, false otherwise + * + * TODO: Move declaration to parent class + */ + bool SendRumbleEvent(const std::string& strLocation, unsigned int motorIndex, float magnitude); + // Inherited from CPeripheralBus virtual void Register(CPeripheral *peripheral) override; virtual void GetFeatures(std::vector<PeripheralFeature> &features) const override; @@ -70,6 +83,7 @@ namespace PERIPHERALS virtual size_t GetNumberOfPeripherals(void) const override; virtual size_t GetNumberOfPeripheralsWithId(const int iVendorId, const int iProductId) const override; virtual void GetDirectory(const std::string &strPath, CFileItemList &items) const override; + virtual void ProcessEvents(void) override; // implementation of IAddonMgrCallback bool RequestRestart(ADDON::AddonPtr addon, bool datachanged) override; @@ -81,7 +95,6 @@ namespace PERIPHERALS // Inherited from CPeripheralBus virtual bool PerformDeviceScan(PeripheralScanResults &results) override; virtual void UnregisterRemovedDevices(const PeripheralScanResults &results) override; - virtual void ProcessEvents(void) override; private: void UpdateAddons(void); diff --git a/xbmc/peripherals/devices/Peripheral.cpp b/xbmc/peripherals/devices/Peripheral.cpp index 95aa63a03d..587cdc7cb7 100644 --- a/xbmc/peripherals/devices/Peripheral.cpp +++ b/xbmc/peripherals/devices/Peripheral.cpp @@ -23,6 +23,7 @@ #include <utility> #include "guilib/LocalizeStrings.h" +#include "input/joysticks/IInputHandler.h" #include "peripherals/Peripherals.h" #include "settings/lib/Setting.h" #include "peripherals/addons/AddonButtonMapping.h" @@ -543,22 +544,21 @@ void CPeripheral::ClearSettings(void) void CPeripheral::RegisterJoystickInputHandler(IInputHandler* handler) { - std::map<IInputHandler*, IDriverHandler*>::iterator it = m_inputHandlers.find(handler); + auto it = m_inputHandlers.find(handler); if (it == m_inputHandlers.end()) { - CAddonInputHandling* inputHandling = new CAddonInputHandling(this, handler); - RegisterJoystickDriverHandler(inputHandling, false); - m_inputHandlers[handler] = inputHandling; + CAddonInputHandling* addonInput = new CAddonInputHandling(this, handler, GetDriverReceiver()); + RegisterJoystickDriverHandler(addonInput, false); + m_inputHandlers[handler].reset(addonInput); } } void CPeripheral::UnregisterJoystickInputHandler(IInputHandler* handler) { - std::map<IInputHandler*, IDriverHandler*>::iterator it = m_inputHandlers.find(handler); + auto it = m_inputHandlers.find(handler); if (it != m_inputHandlers.end()) { - UnregisterJoystickDriverHandler(it->second); - delete it->second; + UnregisterJoystickDriverHandler(it->second.get()); m_inputHandlers.erase(it); } } @@ -568,7 +568,7 @@ void CPeripheral::RegisterJoystickButtonMapper(IButtonMapper* mapper) std::map<IButtonMapper*, IDriverHandler*>::iterator it = m_buttonMappers.find(mapper); if (it == m_buttonMappers.end()) { - CAddonButtonMapping* addonMapping = new CAddonButtonMapping(this, mapper); + IDriverHandler* addonMapping = new CAddonButtonMapping(this, mapper); RegisterJoystickDriverHandler(addonMapping, false); m_buttonMappers[mapper] = addonMapping; } diff --git a/xbmc/peripherals/devices/Peripheral.h b/xbmc/peripherals/devices/Peripheral.h index 646f588c29..cd481bf731 100644 --- a/xbmc/peripherals/devices/Peripheral.h +++ b/xbmc/peripherals/devices/Peripheral.h @@ -32,6 +32,7 @@ namespace JOYSTICK { class IButtonMapper; class IDriverHandler; + class IDriverReceiver; class IInputHandler; } @@ -181,6 +182,8 @@ namespace PERIPHERALS virtual void RegisterJoystickButtonMapper(JOYSTICK::IButtonMapper* mapper); virtual void UnregisterJoystickButtonMapper(JOYSTICK::IButtonMapper* mapper); + virtual JOYSTICK::IDriverReceiver* GetDriverReceiver() { return nullptr; } + protected: virtual void ClearSettings(void); @@ -204,7 +207,7 @@ namespace PERIPHERALS std::map<std::string, PeripheralDeviceSetting> m_settings; std::set<std::string> m_changedSettings; CPeripheralBus* m_bus; - std::map<JOYSTICK::IInputHandler*, JOYSTICK::IDriverHandler*> m_inputHandlers; + std::map<JOYSTICK::IInputHandler*, std::unique_ptr<JOYSTICK::IDriverHandler>> m_inputHandlers; std::map<JOYSTICK::IButtonMapper*, JOYSTICK::IDriverHandler*> m_buttonMappers; }; } diff --git a/xbmc/peripherals/devices/PeripheralJoystick.cpp b/xbmc/peripherals/devices/PeripheralJoystick.cpp index 5e9f82cd3d..283fa34cb6 100644 --- a/xbmc/peripherals/devices/PeripheralJoystick.cpp +++ b/xbmc/peripherals/devices/PeripheralJoystick.cpp @@ -35,9 +35,11 @@ CPeripheralJoystick::CPeripheralJoystick(const PeripheralScanResult& scanResult, m_requestedPort(JOYSTICK_PORT_UNKNOWN), m_buttonCount(0), m_hatCount(0), - m_axisCount(0) + m_axisCount(0), + m_motorCount(0) { m_features.push_back(FEATURE_JOYSTICK); + // FEATURE_RUMBLE conditionally added via SetMotorCount() } CPeripheralJoystick::~CPeripheralJoystick(void) @@ -79,6 +81,10 @@ bool CPeripheralJoystick::InitialiseFeature(const PeripheralFeature feature) } #endif } + else if (feature == FEATURE_RUMBLE) + { + bSuccess = true; // Nothing to do + } } if (bSuccess) @@ -219,3 +225,28 @@ void CPeripheralJoystick::ProcessAxisMotions(void) for (std::vector<DriverHandler>::iterator it = m_driverHandlers.begin(); it != m_driverHandlers.end(); ++it) it->handler->ProcessAxisMotions(); } + +bool CPeripheralJoystick::SetMotorState(unsigned int motorIndex, float magnitude) +{ + bool bHandled = false; + + if (m_mappedBusType == PERIPHERAL_BUS_ADDON) + { + CPeripheralBusAddon* addonBus = static_cast<CPeripheralBusAddon*>(m_bus); + if (addonBus) + { + bHandled = addonBus->SendRumbleEvent(m_strLocation, motorIndex, magnitude); + } + } + return bHandled; +} + +void CPeripheralJoystick::SetMotorCount(unsigned int motorCount) +{ + m_motorCount = motorCount; + + if (m_motorCount == 0) + m_features.erase(std::remove(m_features.begin(), m_features.end(), FEATURE_RUMBLE), m_features.end()); + else if (std::find(m_features.begin(), m_features.end(), FEATURE_RUMBLE) == m_features.end()) + m_features.push_back(FEATURE_RUMBLE); +} diff --git a/xbmc/peripherals/devices/PeripheralJoystick.h b/xbmc/peripherals/devices/PeripheralJoystick.h index 965285e897..b8ef977872 100644 --- a/xbmc/peripherals/devices/PeripheralJoystick.h +++ b/xbmc/peripherals/devices/PeripheralJoystick.h @@ -22,6 +22,7 @@ #include "Peripheral.h" #include "input/joysticks/DefaultJoystick.h" #include "input/joysticks/IDriverHandler.h" +#include "input/joysticks/IDriverReceiver.h" #include "input/joysticks/JoystickMonitor.h" #include "input/joysticks/JoystickTypes.h" #include "threads/CriticalSection.h" @@ -34,7 +35,8 @@ namespace PERIPHERALS { class CPeripheralJoystick : public CPeripheral, //! @todo extend CPeripheralHID - public JOYSTICK::IDriverHandler + public JOYSTICK::IDriverHandler, + public JOYSTICK::IDriverReceiver { public: CPeripheralJoystick(const PeripheralScanResult& scanResult, CPeripheralBus* bus); @@ -45,6 +47,7 @@ namespace PERIPHERALS virtual bool InitialiseFeature(const PeripheralFeature feature) override; virtual void RegisterJoystickDriverHandler(IDriverHandler* handler, bool bPromiscuous) override; virtual void UnregisterJoystickDriverHandler(IDriverHandler* handler) override; + virtual JOYSTICK::IDriverReceiver* GetDriverReceiver() override { return this; } // implementation of IDriverHandler virtual bool OnButtonMotion(unsigned int buttonIndex, bool bPressed) override; @@ -52,6 +55,9 @@ namespace PERIPHERALS virtual bool OnAxisMotion(unsigned int axisIndex, float position) override; virtual void ProcessAxisMotions(void) override; + // implementation of IDriverReceiver + virtual bool SetMotorState(unsigned int motorIndex, float magnitude) override; + /*! * \brief Get the name of the driver or API providing this joystick */ @@ -74,18 +80,23 @@ namespace PERIPHERALS unsigned int ButtonCount(void) const { return m_buttonCount; } unsigned int HatCount(void) const { return m_hatCount; } unsigned int AxisCount(void) const { return m_axisCount; } + unsigned int MotorCount(void) const { return m_motorCount; } + /*! + * \brief Set joystick properties + */ void SetProvider(const std::string& provider) { m_strProvider = provider; } void SetRequestedPort(int port) { m_requestedPort = port; } void SetButtonCount(unsigned int buttonCount) { m_buttonCount = buttonCount; } void SetHatCount(unsigned int hatCount) { m_hatCount = hatCount; } void SetAxisCount(unsigned int axisCount) { m_axisCount = axisCount; } + void SetMotorCount(unsigned int motorCount); // specialized to update m_features protected: struct DriverHandler { JOYSTICK::IDriverHandler* handler; - bool bPromiscuous; + bool bPromiscuous; }; std::string m_strProvider; @@ -93,6 +104,7 @@ namespace PERIPHERALS unsigned int m_buttonCount; unsigned int m_hatCount; unsigned int m_axisCount; + unsigned int m_motorCount; JOYSTICK::CDefaultJoystick m_defaultInputHandler; JOYSTICK::CJoystickMonitor m_joystickMonitor; std::vector<DriverHandler> m_driverHandlers; |