diff options
author | Garrett Brown <themagnificentmrb@gmail.com> | 2018-02-02 21:42:52 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-02 21:42:52 -0800 |
commit | b1d31b530a232c1cde3b3c144f3139998128a4ed (patch) | |
tree | 064f572e04e2c25bf08cba73045a9fac3f1ad572 | |
parent | f5f683e8c61c8a2e8918b15f8eb73a74093c84ac (diff) | |
parent | 915bc44f64e620275ce63daca021465eda4b3694 (diff) |
Merge pull request #13374 from garbear/keyboard-mapping
Games: Keyboard remapping support
81 files changed, 1693 insertions, 738 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index a87e860621..184f64e309 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -17397,7 +17397,22 @@ msgctxt "#35167" msgid "Single keys" msgstr "" -#empty strings from id 35168 to 35199 +#. Name of the button that prompts you to select a key on the keyboard. Used in the controller mapping dialog. +msgctxt "#35168" +msgid "Select key" +msgstr "" + +#. Keyboard prompt without a timeout. Used in the controller mapping dialog. +msgctxt "#35169" +msgid "Press a key" +msgstr "" + +#. Keyboard prompt with timeout. {1:d} - seconds left in prompt. Used in the controller mapping dialog. +msgctxt "#35170" +msgid "Press a key ({1:d})" +msgstr "" + +#empty strings from id 35171 to 35199 #. This string is an early meme from the late 1990's that made fun of the poor translation in the 16-bit game Zero Wing from the late 1980's. DO NOT TRANSLATE! #: system/settings/settings.xml diff --git a/system/settings/settings.xml b/system/settings/settings.xml index 2537075b23..fc252bd86d 100755 --- a/system/settings/settings.xml +++ b/system/settings/settings.xml @@ -2086,113 +2086,6 @@ </setting> </group> </category> - <category id="gameskeyboard" label="35150"> - <group id="1" label="128"> - <setting id="gameskeyboard.enablekeyboard" type="boolean" label="35152" help="35153"> - <level>0</level> - <control type="toggle" /> - <default>true</default> - </setting> - </group> - <group id="2" label="35151"> - <setting id="gameskeyboard.keyboardplayers" type="integer" label="35154" help="35155"> - <level>0</level> - <default>1</default> - <constraints> - <minimum>1</minimum> - <step>1</step> - <maximum>8</maximum> - </constraints> - <dependencies> - <dependency type="enable" setting="gameskeyboard.enablekeyboard">true</dependency> - </dependencies> - <control type="slider" format="integer"> - <popup>true</popup> - <formatlabel>35156</formatlabel> <!-- TODO: Add a <formattype>integer</formattype> tag --> - </control> - </setting> - <setting id="gameskeyboard.keyboardplayerconfig1" type="action" label="35157" help="35155"> - <level>0</level> - <control type="button" format="action" /> - <dependencies> - <dependency type="visible"> - <condition on="property" name="gte" setting="gameskeyboard.keyboardplayers">1</condition> - </dependency> - <dependency type="enable" setting="gameskeyboard.enablekeyboard">true</dependency> - </dependencies> - </setting> - <setting id="gameskeyboard.keyboardplayerconfig2" type="action" label="35158" help="35155"> - <level>0</level> - <control type="button" format="action" /> - <dependencies> - <dependency type="visible"> - <condition on="property" name="gte" setting="gameskeyboard.keyboardplayers">2</condition> - </dependency> - <dependency type="enable" setting="gameskeyboard.enablekeyboard">true</dependency> - </dependencies> - </setting> - <setting id="gameskeyboard.keyboardplayerconfig3" type="action" label="35159" help="35155"> - <level>0</level> - <control type="button" format="action" /> - <dependencies> - <dependency type="visible"> - <condition on="property" name="gte" setting="gameskeyboard.keyboardplayers">3</condition> - </dependency> - <dependency type="enable" setting="gameskeyboard.enablekeyboard">true</dependency> - </dependencies> - </setting> - <setting id="gameskeyboard.keyboardplayerconfig4" type="action" label="35160" help="35155"> - <level>0</level> - <control type="button" format="action" /> - <dependencies> - <dependency type="visible"> - <condition on="property" name="gte" setting="gameskeyboard.keyboardplayers">4</condition> - </dependency> - <dependency type="enable" setting="gameskeyboard.enablekeyboard">true</dependency> - </dependencies> - </setting> - <setting id="gameskeyboard.keyboardplayerconfig5" type="action" label="35161" help="35155"> - <level>0</level> - <control type="button" format="action" /> - <dependencies> - <dependency type="visible"> - <condition on="property" name="gte" setting="gameskeyboard.keyboardplayers">5</condition> - </dependency> - <dependency type="enable" setting="gameskeyboard.enablekeyboard">true</dependency> - </dependencies> - </setting> - <setting id="gameskeyboard.keyboardplayerconfig6" type="action" label="35162" help="35155"> - <level>0</level> - <control type="button" format="action" /> - <dependencies> - <dependency type="visible"> - <condition on="property" name="gte" setting="gameskeyboard.keyboardplayers">6</condition> - </dependency> - <dependency type="enable" setting="gameskeyboard.enablekeyboard">true</dependency> - </dependencies> - </setting> - <setting id="gameskeyboard.keyboardplayerconfig7" type="action" label="35163" help="35155"> - <level>0</level> - <control type="button" format="action" /> - <dependencies> - <dependency type="visible"> - <condition on="property" name="gte" setting="gameskeyboard.keyboardplayers">7</condition> - </dependency> - <dependency type="enable" setting="gameskeyboard.enablekeyboard">true</dependency> - </dependencies> - </setting> - <setting id="gameskeyboard.keyboardplayerconfig8" type="action" label="35164" help="35155"> - <level>0</level> - <control type="button" format="action" /> - <dependencies> - <dependency type="visible"> - <condition on="property" name="gte" setting="gameskeyboard.keyboardplayers">8</condition> - </dependency> - <dependency type="enable" setting="gameskeyboard.enablekeyboard">true</dependency> - </dependencies> - </setting> - </group> - </category> </section> <section id="system" label="13000" help="36349"> <category id="display" label="14220" help="36603"> diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h index 0dae06cdbd..b50c300a12 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h @@ -149,6 +149,7 @@ extern "C" JOYSTICK_DRIVER_PRIMITIVE_TYPE_HAT_DIRECTION, JOYSTICK_DRIVER_PRIMITIVE_TYPE_SEMIAXIS, JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR, + JOYSTICK_DRIVER_PRIMITIVE_TYPE_KEY, } JOYSTICK_DRIVER_PRIMITIVE_TYPE; typedef struct JOYSTICK_DRIVER_BUTTON @@ -191,6 +192,11 @@ extern "C" int index; } ATTRIBUTE_PACKED JOYSTICK_DRIVER_MOTOR; + typedef struct JOYSTICK_DRIVER_KEY + { + char keycode[16]; + } ATTRIBUTE_PACKED JOYSTICK_DRIVER_KEY; + typedef struct JOYSTICK_DRIVER_PRIMITIVE { JOYSTICK_DRIVER_PRIMITIVE_TYPE type; @@ -200,6 +206,7 @@ extern "C" struct JOYSTICK_DRIVER_HAT hat; struct JOYSTICK_DRIVER_SEMIAXIS semiaxis; struct JOYSTICK_DRIVER_MOTOR motor; + struct JOYSTICK_DRIVER_KEY key; }; } ATTRIBUTE_PACKED JOYSTICK_DRIVER_PRIMITIVE; @@ -214,6 +221,7 @@ extern "C" JOYSTICK_FEATURE_TYPE_ABSPOINTER, JOYSTICK_FEATURE_TYPE_WHEEL, JOYSTICK_FEATURE_TYPE_THROTTLE, + JOYSTICK_FEATURE_TYPE_KEY, } JOYSTICK_FEATURE_TYPE; typedef enum JOYSTICK_FEATURE_PRIMITIVE @@ -243,6 +251,9 @@ extern "C" JOYSTICK_THROTTLE_UP = 0, JOYSTICK_THROTTLE_DOWN = 1, + // Key + JOYSTICK_KEY_PRIMITIVE = 0, + // Maximum number of primitives JOYSTICK_PRIMITIVE_MAX = 4, } JOYSTICK_FEATURE_PRIMITIVE; diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h index 3c4cab3154..98f3e0074b 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h @@ -23,8 +23,8 @@ #include <array> // Requires c++11 #include <cstring> -#include <map> #include <string> +#include <utility> #include <vector> #define PERIPHERAL_SAFE_DELETE(x) do { delete (x); (x) = NULL; } while (0) @@ -445,6 +445,20 @@ namespace addon return DriverPrimitive(JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR, motorIndex); } + /*! + * \brief Construct a driver primitive representing a key on a keyboard + */ + DriverPrimitive(std::string keycode) : + m_type(JOYSTICK_DRIVER_PRIMITIVE_TYPE_KEY), + m_driverIndex(0), + m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN), + m_center(0), + m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN), + m_range(1), + m_keycode(std::move(keycode)) + { + } + explicit DriverPrimitive(const JOYSTICK_DRIVER_PRIMITIVE& primitive) : m_type(primitive.type), m_driverIndex(0), @@ -479,6 +493,11 @@ namespace addon m_driverIndex = primitive.motor.index; break; } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_KEY: + { + m_keycode = primitive.key.keycode; + break; + } default: break; } @@ -490,6 +509,7 @@ namespace addon int Center(void) const { return m_center; } JOYSTICK_DRIVER_SEMIAXIS_DIRECTION SemiAxisDirection(void) const { return m_semiAxisDirection; } unsigned int Range(void) const { return m_range; } + const std::string& Keycode(void) const { return m_keycode; } bool operator==(const DriverPrimitive& other) const { @@ -514,6 +534,10 @@ namespace addon m_semiAxisDirection == other.m_semiAxisDirection && m_range == other.m_range; } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_KEY: + { + return m_keycode == other.m_keycode; + } default: break; } @@ -550,6 +574,13 @@ namespace addon driver_primitive.motor.index = m_driverIndex; break; } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_KEY: + { + const size_t size = sizeof(driver_primitive.key.keycode); + std::strncpy(driver_primitive.key.keycode, m_keycode.c_str(), size - 1); + driver_primitive.key.keycode[size - 1] = '\0'; + break; + } default: break; } @@ -567,6 +598,7 @@ namespace addon int m_center; JOYSTICK_DRIVER_SEMIAXIS_DIRECTION m_semiAxisDirection; unsigned int m_range; + std::string m_keycode; }; typedef PeripheralVector<DriverPrimitive, JOYSTICK_DRIVER_PRIMITIVE> DriverPrimitives; @@ -584,6 +616,7 @@ namespace addon * 6) absolute pointer * 7) wheel * 8) throttle + * 9) keyboard key * * [1] All three driver primitives (buttons, hats and axes) have a state that * can be represented using a single scalar value. For this reason, @@ -598,7 +631,7 @@ namespace addon JoystickFeature(const std::string& name = "", JOYSTICK_FEATURE_TYPE type = JOYSTICK_FEATURE_TYPE_UNKNOWN) : m_name(name), m_type(type), - m_primitives() + m_primitives{} { } diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h index 4ce5bbc4c3..6501b43458 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h @@ -156,6 +156,16 @@ void UpdatePort(int port, bool connected, const game_controller* controller); bool HasFeature(const char* controller_id, const char* feature_name); /*! + * \brief Enable/disable keyboard input using the specified controller + * + * \param enable True to enable input, false otherwise + * \param controller The controller info if enabling, or unused if disabling + * + * \return True if keyboard input was enabled, false otherwise + */ +bool EnableKeyboard(bool enable, const game_controller* controller); + +/*! * \brief Notify the add-on of an input event * * \param event The input event @@ -249,6 +259,7 @@ void __declspec(dllexport) get_addon(void* ptr) pClient->toAddon.HwContextDestroy = HwContextDestroy; pClient->toAddon.UpdatePort = UpdatePort; pClient->toAddon.HasFeature = HasFeature; + pClient->toAddon.EnableKeyboard = EnableKeyboard; pClient->toAddon.InputEvent = InputEvent; pClient->toAddon.SerializeSize = SerializeSize; pClient->toAddon.Serialize = Serialize; diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h index 72403d3081..d54ee22b0c 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h @@ -162,7 +162,6 @@ typedef enum GAME_HW_CONTEXT_TYPE typedef enum GAME_INPUT_PORT { GAME_INPUT_PORT_JOYSTICK_START = 0, // Non-negative values are for joystick ports - GAME_INPUT_PORT_KEYBOARD = -1, GAME_INPUT_PORT_MOUSE = -2, } GAME_INPUT_PORT; @@ -181,17 +180,17 @@ typedef enum GAME_INPUT_EVENT_SOURCE typedef enum GAME_KEY_MOD { - GAME_KEY_MOD_NONE = 0x00, + GAME_KEY_MOD_NONE = 0x0000, - GAME_KEY_MOD_SHIFT = 0x01, - GAME_KEY_MOD_CTRL = 0x02, - GAME_KEY_MOD_ALT = 0x04, - GAME_KEY_MOD_RALT = 0x08, - GAME_KEY_MOD_META = 0x10, + GAME_KEY_MOD_SHIFT = 0x0001, + GAME_KEY_MOD_CTRL = 0x0002, + GAME_KEY_MOD_ALT = 0x0004, + GAME_KEY_MOD_META = 0x0008, + GAME_KEY_MOD_SUPER = 0x0010, - GAME_KEY_MOD_NUMLOCK = 0x20, - GAME_KEY_MOD_CAPSLOCK = 0x40, - GAME_KEY_MOD_SCROLLOCK = 0x80, + GAME_KEY_MOD_NUMLOCK = 0x0100, + GAME_KEY_MOD_CAPSLOCK = 0x0200, + GAME_KEY_MOD_SCROLLOCK = 0x0400, } GAME_KEY_MOD; /*! Returned from game_get_region() */ @@ -321,7 +320,14 @@ typedef struct game_accelerometer_event typedef struct game_key_event { bool pressed; - XBMCVKey character; + + /*! + * If the keypress generates a printing character, the unicode value + * contains the character generated. If the key is a non-printing character, + * e.g. a function or arrow key, the unicode value is zero. + */ + uint32_t unicode; + GAME_KEY_MOD modifiers; } ATTRIBUTE_PACKED game_key_event; @@ -495,6 +501,7 @@ typedef struct KodiToAddonFuncTable_Game GAME_ERROR (__cdecl* HwContextDestroy)(void); void (__cdecl* UpdatePort)(int, bool, const game_controller*); bool (__cdecl* HasFeature)(const char* controller_id, const char* feature_name); + bool (__cdecl* EnableKeyboard)(bool, const game_controller*); bool (__cdecl* InputEvent)(const game_input_event*); size_t (__cdecl* SerializeSize)(void); GAME_ERROR (__cdecl* Serialize)(uint8_t*, size_t); diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h index db8508ef24..f547ff72c9 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h @@ -91,8 +91,8 @@ #define ADDON_INSTANCE_VERSION_AUDIOENCODER_XML_ID "kodi.binary.instance.audioencoder" #define ADDON_INSTANCE_VERSION_AUDIOENCODER_DEPENDS "addon-instance/AudioEncoder.h" -#define ADDON_INSTANCE_VERSION_GAME "1.0.33" -#define ADDON_INSTANCE_VERSION_GAME_MIN "1.0.33" +#define ADDON_INSTANCE_VERSION_GAME "1.0.34" +#define ADDON_INSTANCE_VERSION_GAME_MIN "1.0.34" #define ADDON_INSTANCE_VERSION_GAME_XML_ID "kodi.binary.instance.game" #define ADDON_INSTANCE_VERSION_GAME_DEPENDS "kodi_game_dll.h" \ "kodi_game_types.h" \ @@ -108,7 +108,7 @@ #define ADDON_INSTANCE_VERSION_INPUTSTREAM_XML_ID "kodi.binary.instance.inputstream" #define ADDON_INSTANCE_VERSION_INPUTSTREAM_DEPENDS "addon-instance/Inputstream.h" -#define ADDON_INSTANCE_VERSION_PERIPHERAL "1.3.5" +#define ADDON_INSTANCE_VERSION_PERIPHERAL "1.3.6" #define ADDON_INSTANCE_VERSION_PERIPHERAL_MIN "1.3.4" #define ADDON_INSTANCE_VERSION_PERIPHERAL_XML_ID "kodi.binary.instance.peripheral" #define ADDON_INSTANCE_VERSION_PERIPHERAL_DEPENDS "addon-instance/Peripheral.h" \ diff --git a/xbmc/games/GameServices.cpp b/xbmc/games/GameServices.cpp index 84da1c2952..e6a4d5c90c 100644 --- a/xbmc/games/GameServices.cpp +++ b/xbmc/games/GameServices.cpp @@ -53,6 +53,11 @@ ControllerPtr CGameServices::GetDefaultController() return m_controllerManager.GetDefaultController(); } +ControllerPtr CGameServices::GetDefaultKeyboard() +{ + return m_controllerManager.GetDefaultKeyboard(); +} + ControllerVector CGameServices::GetControllers() { return m_controllerManager.GetControllers(); diff --git a/xbmc/games/GameServices.h b/xbmc/games/GameServices.h index 5a2ea18e83..300cbec644 100644 --- a/xbmc/games/GameServices.h +++ b/xbmc/games/GameServices.h @@ -57,6 +57,7 @@ namespace GAME ControllerPtr GetController(const std::string& controllerId); ControllerPtr GetDefaultController(); + ControllerPtr GetDefaultKeyboard(); ControllerVector GetControllers(); std::string GetSavestatesFolder() const; diff --git a/xbmc/games/GameSettings.cpp b/xbmc/games/GameSettings.cpp index 52f9be0276..8f3a05f6b0 100644 --- a/xbmc/games/GameSettings.cpp +++ b/xbmc/games/GameSettings.cpp @@ -19,34 +19,16 @@ */ #include "GameSettings.h" -#include "guilib/GUIWindowManager.h" -#include "guilib/WindowIDs.h" -#include "peripherals/Peripherals.h" #include "settings/lib/Setting.h" #include "settings/Settings.h" -#include "utils/StringUtils.h" -#include "ServiceBroker.h" - -#include <cstring> using namespace KODI; using namespace GAME; -#define SETTING_GAMES_KEYBOARD_PLAYERCONFIG_PREFIX "gameskeyboard.keyboardplayerconfig" //! @todo - CGameSettings::CGameSettings(CSettings &settings) : m_settings(settings) { m_settings.RegisterCallback(this, { - CSettings::SETTING_GAMES_KEYBOARD_PLAYERS, - CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_1, - CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_2, - CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_3, - CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_4, - CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_5, - CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_6, - CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_7, - CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_8, CSettings::SETTING_GAMES_ENABLEREWIND, CSettings::SETTING_GAMES_REWINDTIME, }); @@ -63,27 +45,11 @@ void CGameSettings::OnSettingChanged(std::shared_ptr<const CSetting> setting) return; const std::string& settingId = setting->GetId(); - if (settingId == CSettings::SETTING_GAMES_KEYBOARD_PLAYERS) - { - CServiceBroker::GetPeripherals().TriggerDeviceScan(PERIPHERALS::PERIPHERAL_BUS_APPLICATION); - } - else if (settingId == CSettings::SETTING_GAMES_ENABLEREWIND || - settingId == CSettings::SETTING_GAMES_REWINDTIME) + + if (settingId == CSettings::SETTING_GAMES_ENABLEREWIND || + settingId == CSettings::SETTING_GAMES_REWINDTIME) { SetChanged(); NotifyObservers(ObservableMessageSettingsChanged); } } - -void CGameSettings::OnSettingAction(std::shared_ptr<const CSetting> setting) -{ - if (setting == nullptr) - return; - - const std::string& settingId = setting->GetId(); - if (StringUtils::StartsWith(settingId, SETTING_GAMES_KEYBOARD_PLAYERCONFIG_PREFIX)) - { - std::string strControllerIndex = settingId.substr(std::strlen(SETTING_GAMES_KEYBOARD_PLAYERCONFIG_PREFIX)); - g_windowManager.ActivateWindow(WINDOW_DIALOG_GAME_CONTROLLERS, strControllerIndex); - } -} diff --git a/xbmc/games/GameSettings.h b/xbmc/games/GameSettings.h index 0706d58b51..b1386d2a9a 100644 --- a/xbmc/games/GameSettings.h +++ b/xbmc/games/GameSettings.h @@ -39,7 +39,6 @@ public: // Inherited from ISettingCallback virtual void OnSettingChanged(std::shared_ptr<const CSetting> setting) override; - virtual void OnSettingAction(std::shared_ptr<const CSetting> setting) override; private: // Construction parameters diff --git a/xbmc/games/addons/GameClient.cpp b/xbmc/games/addons/GameClient.cpp index 759d2717a1..d411c58814 100644 --- a/xbmc/games/addons/GameClient.cpp +++ b/xbmc/games/addons/GameClient.cpp @@ -37,6 +37,8 @@ #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" #include "guilib/WindowIDs.h" +#include "input/Action.h" +#include "input/ActionIDs.h" #include "messaging/ApplicationMessenger.h" #include "messaging/helpers/DialogOKHelper.h" #include "settings/Settings.h" diff --git a/xbmc/games/addons/GameClientTranslator.cpp b/xbmc/games/addons/GameClientTranslator.cpp index 34c486df80..4ed1f976f0 100644 --- a/xbmc/games/addons/GameClientTranslator.cpp +++ b/xbmc/games/addons/GameClientTranslator.cpp @@ -136,15 +136,21 @@ AVCodecID CGameClientTranslator::TranslateAudioCodec(GAME_AUDIO_CODEC codec) return AV_CODEC_ID_NONE; } -GAME_KEY_MOD CGameClientTranslator::GetModifiers(CKey::Modifier modifier) +GAME_KEY_MOD CGameClientTranslator::GetModifiers(KEYBOARD::Modifier modifier) { + using namespace KEYBOARD; + unsigned int mods = GAME_KEY_MOD_NONE; - if (modifier & CKey::MODIFIER_CTRL) mods |= GAME_KEY_MOD_CTRL; - if (modifier & CKey::MODIFIER_SHIFT) mods |= GAME_KEY_MOD_SHIFT; - if (modifier & CKey::MODIFIER_ALT) mods |= GAME_KEY_MOD_ALT; - if (modifier & CKey::MODIFIER_RALT) mods |= GAME_KEY_MOD_RALT; - if (modifier & CKey::MODIFIER_META) mods |= GAME_KEY_MOD_META; + if (modifier & Modifier::MODIFIER_CTRL) mods |= GAME_KEY_MOD_CTRL; + if (modifier & Modifier::MODIFIER_SHIFT) mods |= GAME_KEY_MOD_SHIFT; + if (modifier & Modifier::MODIFIER_ALT) mods |= GAME_KEY_MOD_ALT; + if (modifier & Modifier::MODIFIER_RALT) mods |= GAME_KEY_MOD_ALT; + if (modifier & Modifier::MODIFIER_META) mods |= GAME_KEY_MOD_META; + if (modifier & Modifier::MODIFIER_SUPER) mods |= GAME_KEY_MOD_SUPER; + if (modifier & Modifier::MODIFIER_NUMLOCK) mods |= GAME_KEY_MOD_NUMLOCK; + if (modifier & Modifier::MODIFIER_CAPSLOCK) mods |= GAME_KEY_MOD_CAPSLOCK; + if (modifier & Modifier::MODIFIER_SCROLLLOCK) mods |= GAME_KEY_MOD_SCROLLOCK; return static_cast<GAME_KEY_MOD>(mods); } diff --git a/xbmc/games/addons/GameClientTranslator.h b/xbmc/games/addons/GameClientTranslator.h index 0e84ea2da0..f8c95cf201 100644 --- a/xbmc/games/addons/GameClientTranslator.h +++ b/xbmc/games/addons/GameClientTranslator.h @@ -21,7 +21,7 @@ #include "addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h" #include "cores/AudioEngine/Utils/AEChannelData.h" -#include "input/Key.h" +#include "input/keyboard/KeyboardTypes.h" #include "libavcodec/avcodec.h" #include "libavutil/pixfmt.h" @@ -95,7 +95,7 @@ namespace GAME * \param modifiers The key modifiers to translate (e.g. Shift, Ctrl). * \return Translated key modifiers. */ - static GAME_KEY_MOD GetModifiers(CKey::Modifier modifier); + static GAME_KEY_MOD GetModifiers(KEYBOARD::Modifier modifier); /*! * \brief Translate region to string representation (e.g. for logging). diff --git a/xbmc/games/addons/input/GameClientInput.cpp b/xbmc/games/addons/input/GameClientInput.cpp index 9dcf62669f..75a04c7d4f 100644 --- a/xbmc/games/addons/input/GameClientInput.cpp +++ b/xbmc/games/addons/input/GameClientInput.cpp @@ -33,6 +33,7 @@ #include "input/joysticks/JoystickTypes.h" #include "input/InputManager.h" #include "peripherals/Peripherals.h" +#include "peripherals/PeripheralTypes.h" //! @todo //#include "threads/SingleLock.h" #include "utils/log.h" #include "ServiceBroker.h" @@ -160,7 +161,7 @@ void CGameClientInput::UpdatePort(unsigned int port, const ControllerPtr& contro controllerStruct.analog_button_count = controller->FeatureCount(FEATURE_TYPE::SCALAR, INPUT_TYPE::ANALOG); controllerStruct.analog_stick_count = controller->FeatureCount(FEATURE_TYPE::ANALOG_STICK); controllerStruct.accelerometer_count = controller->FeatureCount(FEATURE_TYPE::ACCELEROMETER); - controllerStruct.key_count = 0; //! @todo + controllerStruct.key_count = controller->FeatureCount(FEATURE_TYPE::KEY); controllerStruct.rel_pointer_count = controller->FeatureCount(FEATURE_TYPE::RELPOINTER); controllerStruct.abs_pointer_count = controller->FeatureCount(FEATURE_TYPE::ABSPOINTER); controllerStruct.motor_count = controller->FeatureCount(FEATURE_TYPE::MOTOR); @@ -178,12 +179,74 @@ void CGameClientInput::UpdatePort(unsigned int port, const ControllerPtr& contro void CGameClientInput::OpenKeyboard() { - m_keyboard.reset(new CGameClientKeyboard(m_gameClient, m_struct.toAddon, &CServiceBroker::GetInputManager())); + using namespace JOYSTICK; + + //! @todo Move to player manager + PERIPHERALS::PeripheralVector keyboards; + CServiceBroker::GetPeripherals().GetPeripheralsWithFeature(keyboards, PERIPHERALS::FEATURE_KEYBOARD); + + if (keyboards.empty()) + return; + + CGameServices& gameServices = CServiceBroker::GetGameServices(); + + ControllerPtr controller = gameServices.GetDefaultKeyboard(); //! @todo + + std::string controllerId = controller->ID(); + + game_controller controllerStruct{}; + + controllerStruct.controller_id = controllerId.c_str(); + controllerStruct.digital_button_count = controller->FeatureCount(FEATURE_TYPE::SCALAR, INPUT_TYPE::DIGITAL); + controllerStruct.analog_button_count = controller->FeatureCount(FEATURE_TYPE::SCALAR, INPUT_TYPE::ANALOG); + controllerStruct.analog_stick_count = controller->FeatureCount(FEATURE_TYPE::ANALOG_STICK); + controllerStruct.accelerometer_count = controller->FeatureCount(FEATURE_TYPE::ACCELEROMETER); + controllerStruct.key_count = controller->FeatureCount(FEATURE_TYPE::KEY); + controllerStruct.rel_pointer_count = controller->FeatureCount(FEATURE_TYPE::RELPOINTER); + controllerStruct.abs_pointer_count = controller->FeatureCount(FEATURE_TYPE::ABSPOINTER); + controllerStruct.motor_count = controller->FeatureCount(FEATURE_TYPE::MOTOR); + + bool bSuccess = false; + + { + CSingleLock lock(m_clientAccess); + + if (m_gameClient.Initialized()) + { + try + { + bSuccess = m_struct.toAddon.EnableKeyboard(true, &controllerStruct); + } + catch (...) + { + m_gameClient.LogException("EnableKeyboard()"); + } + } + } + + if (bSuccess) + m_keyboard.reset(new CGameClientKeyboard(m_gameClient, controllerId, m_struct.toAddon, keyboards.at(0).get())); } void CGameClientInput::CloseKeyboard() { m_keyboard.reset(); + + { + CSingleLock lock(m_clientAccess); + + if (m_gameClient.Initialized()) + { + try + { + m_struct.toAddon.EnableKeyboard(false, nullptr); + } + catch (...) + { + m_gameClient.LogException("EnableKeyboard()"); + } + } + } } void CGameClientInput::OpenMouse() diff --git a/xbmc/games/addons/input/GameClientKeyboard.cpp b/xbmc/games/addons/input/GameClientKeyboard.cpp index 964c63bdee..51c011e084 100644 --- a/xbmc/games/addons/input/GameClientKeyboard.cpp +++ b/xbmc/games/addons/input/GameClientKeyboard.cpp @@ -27,19 +27,23 @@ #include "input/Key.h" #include "utils/log.h" +#include <utility> + using namespace KODI; using namespace GAME; #define BUTTON_INDEX_MASK 0x01ff CGameClientKeyboard::CGameClientKeyboard(const CGameClient &gameClient, + std::string controllerId, const KodiToAddonFuncTable_Game &dllStruct, KEYBOARD::IKeyboardInputProvider *inputProvider) : m_gameClient(gameClient), + m_controllerId(std::move(controllerId)), m_dllStruct(dllStruct), m_inputProvider(inputProvider) { - m_inputProvider->RegisterKeyboardHandler(this); + m_inputProvider->RegisterKeyboardHandler(this, false); } CGameClientKeyboard::~CGameClientKeyboard() @@ -47,7 +51,26 @@ CGameClientKeyboard::~CGameClientKeyboard() m_inputProvider->UnregisterKeyboardHandler(this); } -bool CGameClientKeyboard::OnKeyPress(const CKey& key) +std::string CGameClientKeyboard::ControllerID() const +{ + return m_controllerId; +} + +bool CGameClientKeyboard::HasKey(const KEYBOARD::KeyName &key) const +{ + try + { + return m_dllStruct.HasFeature(ControllerID().c_str(), key.c_str()); + } + catch (...) + { + CLog::Log(LOGERROR, "GAME: %s: exception caught in HasFeature()", m_gameClient.ID().c_str()); + } + + return false; +} + +bool CGameClientKeyboard::OnKeyPress(const KEYBOARD::KeyName &key, KEYBOARD::Modifier mod, uint32_t unicode) { // Only allow activated input in fullscreen game if (!m_gameClient.Input().AcceptsInput()) @@ -58,56 +81,46 @@ bool CGameClientKeyboard::OnKeyPress(const CKey& key) bool bHandled = false; - CKey::Modifier mod = static_cast<CKey::Modifier>(key.GetModifiers() | key.GetLockingModifiers()); - game_input_event event; event.type = GAME_INPUT_EVENT_KEY; - event.port = GAME_INPUT_PORT_KEYBOARD; - event.controller_id = ""; //! @todo - event.feature_name = ""; //! @todo + event.port = 0; //! @todo Remove in port refactor + event.controller_id = m_controllerId.c_str(); + event.feature_name = key.c_str(); event.key.pressed = true; - event.key.character = static_cast<XBMCVKey>(key.GetButtonCode() & BUTTON_INDEX_MASK); + event.key.unicode = unicode; event.key.modifiers = CGameClientTranslator::GetModifiers(mod); - if (event.key.character != 0) + try { - try - { - bHandled = m_dllStruct.InputEvent(&event); - } - catch (...) - { - CLog::Log(LOGERROR, "GAME: %s: exception caught in InputEvent()", m_gameClient.ID().c_str()); - } + bHandled = m_dllStruct.InputEvent(&event); + } + catch (...) + { + CLog::Log(LOGERROR, "GAME: %s: exception caught in InputEvent()", m_gameClient.ID().c_str()); } return bHandled; } -void CGameClientKeyboard::OnKeyRelease(const CKey& key) +void CGameClientKeyboard::OnKeyRelease(const KEYBOARD::KeyName &key, KEYBOARD::Modifier mod, uint32_t unicode) { - CKey::Modifier mod = static_cast<CKey::Modifier>(key.GetModifiers() | key.GetLockingModifiers()); - game_input_event event; event.type = GAME_INPUT_EVENT_KEY; - event.port = GAME_INPUT_PORT_KEYBOARD; - event.controller_id = ""; //! @todo - event.feature_name = ""; //! @todo + event.port = 0; //! @todo Remove in port refactor + event.controller_id = m_controllerId.c_str(); + event.feature_name = key.c_str(); event.key.pressed = false; - event.key.character = static_cast<XBMCVKey>(key.GetButtonCode() & BUTTON_INDEX_MASK); + event.key.unicode = unicode; event.key.modifiers = CGameClientTranslator::GetModifiers(mod); - if (event.key.character != 0) + try + { + m_dllStruct.InputEvent(&event); + } + catch (...) { - try - { - m_dllStruct.InputEvent(&event); - } - catch (...) - { - CLog::Log(LOGERROR, "GAME: %s: exception caught in InputEvent()", m_gameClient.ID().c_str()); - } + CLog::Log(LOGERROR, "GAME: %s: exception caught in InputEvent()", m_gameClient.ID().c_str()); } } diff --git a/xbmc/games/addons/input/GameClientKeyboard.h b/xbmc/games/addons/input/GameClientKeyboard.h index 271d3ff471..75741cfe41 100644 --- a/xbmc/games/addons/input/GameClientKeyboard.h +++ b/xbmc/games/addons/input/GameClientKeyboard.h @@ -19,7 +19,7 @@ */ #pragma once -#include "input/keyboard/interfaces/IKeyboardHandler.h" +#include "input/keyboard/interfaces/IKeyboardInputHandler.h" struct KodiToAddonFuncTable_Game; @@ -40,16 +40,18 @@ namespace GAME * * Listens to keyboard events and forwards them to the games (as game_input_event). */ - class CGameClientKeyboard : public KEYBOARD::IKeyboardHandler + class CGameClientKeyboard : public KEYBOARD::IKeyboardInputHandler { public: /*! * \brief Constructor registers for keyboard events at CInputManager. * \param gameClient The game client implementation. + * \param controllerId The controller profile used for input * \param dllStruct The emulator or game to which the events are sent. * \param inputProvider The interface providing us with keyboard input. */ CGameClientKeyboard(const CGameClient &gameClient, + std::string controllerId, const KodiToAddonFuncTable_Game &dllStruct, KEYBOARD::IKeyboardInputProvider *inputProvider); @@ -58,13 +60,16 @@ namespace GAME */ virtual ~CGameClientKeyboard(); - // implementation of IKeyboardHandler - virtual bool OnKeyPress(const CKey& key) override; - virtual void OnKeyRelease(const CKey& key) override; + // implementation of IKeyboardInputHandler + std::string ControllerID() const override; + bool HasKey(const KEYBOARD::KeyName &key) const override; + bool OnKeyPress(const KEYBOARD::KeyName &key, KEYBOARD::Modifier mod, uint32_t unicode) override; + void OnKeyRelease(const KEYBOARD::KeyName &key, KEYBOARD::Modifier mod, uint32_t unicode) override; private: // Construction parameters const CGameClient &m_gameClient; + const std::string m_controllerId; const KodiToAddonFuncTable_Game &m_dllStruct; KEYBOARD::IKeyboardInputProvider *const m_inputProvider; }; diff --git a/xbmc/games/controllers/ControllerDefinitions.h b/xbmc/games/controllers/ControllerDefinitions.h index 244fdc09cf..bb4dd52ae1 100644 --- a/xbmc/games/controllers/ControllerDefinitions.h +++ b/xbmc/games/controllers/ControllerDefinitions.h @@ -19,6 +19,7 @@ */ #pragma once +// XML definitions #define LAYOUT_XML_ROOT "layout" #define LAYOUT_XML_ELM_CATEGORY "category" #define LAYOUT_XML_ELM_BUTTON "button" @@ -29,6 +30,7 @@ #define LAYOUT_XML_ELM_ABSPOINTER "abspointer" #define LAYOUT_XML_ELM_WHEEL "wheel" #define LAYOUT_XML_ELM_THROTTLE "throttle" +#define LAYOUT_XML_ELM_KEY "key" #define LAYOUT_XML_ATTR_LAYOUT_LABEL "label" #define LAYOUT_XML_ATTR_LAYOUT_ICON "icon" #define LAYOUT_XML_ATTR_LAYOUT_IMAGE "image" @@ -37,7 +39,9 @@ #define LAYOUT_XML_ATTR_FEATURE_NAME "name" #define LAYOUT_XML_ATTR_FEATURE_LABEL "label" #define LAYOUT_XML_ATTR_INPUT_TYPE "type" +#define LAYOUT_XML_ATTR_KEY_SYMBOL "symbol" +// Controller definitions #define FEATURE_CATEGORY_FACE "face" #define FEATURE_CATEGORY_SHOULDER "shoulder" #define FEATURE_CATEGORY_TRIGGER "triggers" diff --git a/xbmc/games/controllers/ControllerFeature.cpp b/xbmc/games/controllers/ControllerFeature.cpp index cebbf35ca4..1356547c0e 100644 --- a/xbmc/games/controllers/ControllerFeature.cpp +++ b/xbmc/games/controllers/ControllerFeature.cpp @@ -32,6 +32,12 @@ using namespace KODI; using namespace GAME; using namespace JOYSTICK; +CControllerFeature::CControllerFeature(int labelId) +{ + Reset(); + m_labelId = labelId; +} + void CControllerFeature::Reset(void) { *this = CControllerFeature(); @@ -48,6 +54,7 @@ CControllerFeature& CControllerFeature::operator=(const CControllerFeature& rhs) m_strName = rhs.m_strName; m_labelId = rhs.m_labelId; m_inputType = rhs.m_inputType; + m_keycode = rhs.m_keycode; } return *this; } @@ -72,6 +79,9 @@ std::string CControllerFeature::Label() const if (m_labelId >= 0 && m_controller != nullptr) label = g_localizeStrings.GetAddonString(m_controller->ID(), m_labelId); + if (label.empty()) + label = g_localizeStrings.Get(m_labelId); + return label; } @@ -135,6 +145,27 @@ bool CControllerFeature::Deserialize(const TiXmlElement* pElement, } } + // Keycode + if (m_type == FEATURE_TYPE::KEY) + { + std::string strSymbol = XMLUtils::GetAttribute(pElement, LAYOUT_XML_ATTR_KEY_SYMBOL); + if (strSymbol.empty()) + { + CLog::Log(LOGERROR, "<%s> tag has no \"%s\" attribute", strType.c_str(), LAYOUT_XML_ATTR_KEY_SYMBOL); + return false; + } + else + { + m_keycode = CControllerTranslator::TranslateKeysym(strSymbol); + if (m_keycode == XBMCK_UNKNOWN) + { + CLog::Log(LOGERROR, "<%s> tag - attribute \"%s\" is invalid: \"%s\"", + strType.c_str(), LAYOUT_XML_ATTR_KEY_SYMBOL, strSymbol.c_str()); + return false; + } + } + } + // Save controller for string translation m_controller = controller; diff --git a/xbmc/games/controllers/ControllerFeature.h b/xbmc/games/controllers/ControllerFeature.h index 29a12cb3db..72a9ac3a70 100644 --- a/xbmc/games/controllers/ControllerFeature.h +++ b/xbmc/games/controllers/ControllerFeature.h @@ -21,6 +21,7 @@ #include "ControllerTypes.h" #include "input/joysticks/JoystickTypes.h" +#include "input/XBMC_keysym.h" #include <string> @@ -35,6 +36,7 @@ class CControllerFeature { public: CControllerFeature() = default; + CControllerFeature(int labelId); CControllerFeature(const CControllerFeature& other) { *this = other; } void Reset(void); @@ -52,6 +54,7 @@ public: // Input properties JOYSTICK::INPUT_TYPE InputType(void) const { return m_inputType; } + XBMCKey Keycode() const { return m_keycode; } bool Deserialize(const TiXmlElement* pElement, const CController* controller, @@ -66,6 +69,7 @@ private: std::string m_strName; int m_labelId = -1; JOYSTICK::INPUT_TYPE m_inputType = JOYSTICK::INPUT_TYPE::UNKNOWN; + XBMCKey m_keycode = XBMCK_UNKNOWN; }; } diff --git a/xbmc/games/controllers/ControllerIDs.h b/xbmc/games/controllers/ControllerIDs.h index d31fe383ca..427c14f12a 100644 --- a/xbmc/games/controllers/ControllerIDs.h +++ b/xbmc/games/controllers/ControllerIDs.h @@ -21,4 +21,5 @@ // Default controller IDs #define DEFAULT_CONTROLLER_ID "game.controller.default" +#define DEFAULT_KEYBOARD_ID "game.controller.keyboard" #define DEFAULT_REMOTE_ID "game.controller.remote" diff --git a/xbmc/games/controllers/ControllerManager.cpp b/xbmc/games/controllers/ControllerManager.cpp index af18eca8e8..feffa5c7d6 100644 --- a/xbmc/games/controllers/ControllerManager.cpp +++ b/xbmc/games/controllers/ControllerManager.cpp @@ -48,6 +48,11 @@ ControllerPtr CControllerManager::GetDefaultController() return GetController(DEFAULT_CONTROLLER_ID); } +ControllerPtr CControllerManager::GetDefaultKeyboard() +{ + return GetController(DEFAULT_KEYBOARD_ID); +} + ControllerVector CControllerManager::GetControllers() { using namespace ADDON; diff --git a/xbmc/games/controllers/ControllerManager.h b/xbmc/games/controllers/ControllerManager.h index 27eca3fa83..540ef59fef 100644 --- a/xbmc/games/controllers/ControllerManager.h +++ b/xbmc/games/controllers/ControllerManager.h @@ -57,6 +57,13 @@ namespace GAME ControllerPtr GetDefaultController(); /*! + * \brief Get the default keyboard + * + * \return The keyboard controller, or empty if the controller failed to load + */ + ControllerPtr GetDefaultKeyboard(); + + /*! * \brief Get installed controllers * * \return The installed controllers that loaded successfully diff --git a/xbmc/games/controllers/ControllerTranslator.cpp b/xbmc/games/controllers/ControllerTranslator.cpp index 75d119720e..fe3601cccf 100644 --- a/xbmc/games/controllers/ControllerTranslator.cpp +++ b/xbmc/games/controllers/ControllerTranslator.cpp @@ -37,6 +37,7 @@ const char* CControllerTranslator::TranslateFeatureType(FEATURE_TYPE type) case FEATURE_TYPE::ABSPOINTER: return LAYOUT_XML_ELM_ABSPOINTER; case FEATURE_TYPE::WHEEL: return LAYOUT_XML_ELM_WHEEL; case FEATURE_TYPE::THROTTLE: return LAYOUT_XML_ELM_THROTTLE; + case FEATURE_TYPE::KEY: return LAYOUT_XML_ELM_KEY; default: break; } @@ -53,6 +54,7 @@ FEATURE_TYPE CControllerTranslator::TranslateFeatureType(const std::string& strT if (strType == LAYOUT_XML_ELM_ABSPOINTER) return FEATURE_TYPE::ABSPOINTER; if (strType == LAYOUT_XML_ELM_WHEEL) return FEATURE_TYPE::WHEEL; if (strType == LAYOUT_XML_ELM_THROTTLE) return FEATURE_TYPE::THROTTLE; + if (strType == LAYOUT_XML_ELM_KEY) return FEATURE_TYPE::KEY; return FEATURE_TYPE::UNKNOWN; } @@ -124,3 +126,298 @@ INPUT_TYPE CControllerTranslator::TranslateInputType(const std::string& strType) return INPUT_TYPE::UNKNOWN; } + +XBMCKey CControllerTranslator::TranslateKeysym(const std::string &symbol) +{ + if (symbol == "backspace") return XBMCK_BACKSPACE; + if (symbol == "tab") return XBMCK_TAB; + if (symbol == "clear") return XBMCK_CLEAR; + if (symbol == "enter") return XBMCK_RETURN; + if (symbol == "pause") return XBMCK_PAUSE; + if (symbol == "escape") return XBMCK_ESCAPE; + if (symbol == "space") return XBMCK_SPACE; + if (symbol == "exclaim") return XBMCK_EXCLAIM; + if (symbol == "doublequote") return XBMCK_QUOTEDBL; + if (symbol == "hash") return XBMCK_HASH; + if (symbol == "dollar") return XBMCK_DOLLAR; + if (symbol == "ampersand") return XBMCK_AMPERSAND; + if (symbol == "quote") return XBMCK_QUOTE; + if (symbol == "leftparen") return XBMCK_LEFTPAREN; + if (symbol == "rightparen") return XBMCK_RIGHTPAREN; + if (symbol == "asterisk") return XBMCK_ASTERISK; + if (symbol == "plus") return XBMCK_PLUS; + if (symbol == "comma") return XBMCK_COMMA; + if (symbol == "minus") return XBMCK_MINUS; + if (symbol == "period") return XBMCK_PERIOD; + if (symbol == "slash") return XBMCK_SLASH; + if (symbol == "0") return XBMCK_0; + if (symbol == "1") return XBMCK_1; + if (symbol == "2") return XBMCK_2; + if (symbol == "3") return XBMCK_3; + if (symbol == "4") return XBMCK_4; + if (symbol == "5") return XBMCK_5; + if (symbol == "6") return XBMCK_6; + if (symbol == "7") return XBMCK_7; + if (symbol == "8") return XBMCK_8; + if (symbol == "9") return XBMCK_9; + if (symbol == "colon") return XBMCK_COLON; + if (symbol == "semicolon") return XBMCK_SEMICOLON; + if (symbol == "less") return XBMCK_LESS; + if (symbol == "equals") return XBMCK_EQUALS; + if (symbol == "greater") return XBMCK_GREATER; + if (symbol == "question") return XBMCK_QUESTION; + if (symbol == "at") return XBMCK_AT; + if (symbol == "leftbracket") return XBMCK_LEFTBRACKET; + if (symbol == "backslash") return XBMCK_BACKSLASH; + if (symbol == "rightbracket") return XBMCK_RIGHTBRACKET; + if (symbol == "caret") return XBMCK_CARET; + if (symbol == "underscore") return XBMCK_UNDERSCORE; + if (symbol == "grave") return XBMCK_BACKQUOTE; + if (symbol == "a") return XBMCK_a; + if (symbol == "b") return XBMCK_b; + if (symbol == "c") return XBMCK_c; + if (symbol == "d") return XBMCK_d; + if (symbol == "e") return XBMCK_e; + if (symbol == "f") return XBMCK_f; + if (symbol == "g") return XBMCK_g; + if (symbol == "h") return XBMCK_h; + if (symbol == "i") return XBMCK_i; + if (symbol == "j") return XBMCK_j; + if (symbol == "k") return XBMCK_k; + if (symbol == "l") return XBMCK_l; + if (symbol == "m") return XBMCK_m; + if (symbol == "n") return XBMCK_n; + if (symbol == "o") return XBMCK_o; + if (symbol == "p") return XBMCK_p; + if (symbol == "q") return XBMCK_q; + if (symbol == "r") return XBMCK_r; + if (symbol == "s") return XBMCK_s; + if (symbol == "t") return XBMCK_t; + if (symbol == "u") return XBMCK_u; + if (symbol == "v") return XBMCK_v; + if (symbol == "w") return XBMCK_w; + if (symbol == "x") return XBMCK_x; + if (symbol == "y") return XBMCK_y; + if (symbol == "z") return XBMCK_z; + if (symbol == "leftbrace") return XBMCK_LEFTBRACE; + if (symbol == "bar") return XBMCK_PIPE; + if (symbol == "rightbrace") return XBMCK_RIGHTBRACE; + if (symbol == "tilde") return XBMCK_TILDE; + if (symbol == "delete") return XBMCK_DELETE; + if (symbol == "kp0") return XBMCK_KP0; + if (symbol == "kp1") return XBMCK_KP1; + if (symbol == "kp2") return XBMCK_KP2; + if (symbol == "kp3") return XBMCK_KP3; + if (symbol == "kp4") return XBMCK_KP4; + if (symbol == "kp5") return XBMCK_KP5; + if (symbol == "kp6") return XBMCK_KP6; + if (symbol == "kp7") return XBMCK_KP7; + if (symbol == "kp8") return XBMCK_KP8; + if (symbol == "kp9") return XBMCK_KP9; + if (symbol == "kpperiod") return XBMCK_KP_PERIOD; + if (symbol == "kpdivide") return XBMCK_KP_DIVIDE; + if (symbol == "kpmultiply") return XBMCK_KP_MULTIPLY; + if (symbol == "kpminus") return XBMCK_KP_MINUS; + if (symbol == "kpplus") return XBMCK_KP_PLUS; + if (symbol == "kpenter") return XBMCK_KP_ENTER; + if (symbol == "kpequals") return XBMCK_KP_EQUALS; + if (symbol == "up") return XBMCK_UP; + if (symbol == "down") return XBMCK_DOWN; + if (symbol == "right") return XBMCK_RIGHT; + if (symbol == "left") return XBMCK_LEFT; + if (symbol == "insert") return XBMCK_INSERT; + if (symbol == "home") return XBMCK_HOME; + if (symbol == "end") return XBMCK_END; + if (symbol == "pageup") return XBMCK_PAGEUP; + if (symbol == "pagedown") return XBMCK_PAGEDOWN; + if (symbol == "f1") return XBMCK_F1; + if (symbol == "f2") return XBMCK_F2; + if (symbol == "f3") return XBMCK_F3; + if (symbol == "f4") return XBMCK_F4; + if (symbol == "f5") return XBMCK_F5; + if (symbol == "f6") return XBMCK_F6; + if (symbol == "f7") return XBMCK_F7; + if (symbol == "f8") return XBMCK_F8; + if (symbol == "f9") return XBMCK_F9; + if (symbol == "f10") return XBMCK_F10; + if (symbol == "f11") return XBMCK_F11; + if (symbol == "f12") return XBMCK_F12; + if (symbol == "f13") return XBMCK_F13; + if (symbol == "f14") return XBMCK_F14; + if (symbol == "f15") return XBMCK_F15; + if (symbol == "numlock") return XBMCK_NUMLOCK; + if (symbol == "capslock") return XBMCK_CAPSLOCK; + if (symbol == "scrolllock") return XBMCK_SCROLLOCK; + if (symbol == "leftshift") return XBMCK_LSHIFT; + if (symbol == "rightshift") return XBMCK_RSHIFT; + if (symbol == "leftctrl") return XBMCK_LCTRL; + if (symbol == "rightctrl") return XBMCK_RCTRL; + if (symbol == "leftalt") return XBMCK_LALT; + if (symbol == "rightalt") return XBMCK_RALT; + if (symbol == "leftmeta") return XBMCK_LMETA; + if (symbol == "rightmeta") return XBMCK_RMETA; + if (symbol == "leftsuper") return XBMCK_LSUPER; + if (symbol == "rightsuper") return XBMCK_RSUPER; + if (symbol == "mode") return XBMCK_MODE; + if (symbol == "compose") return XBMCK_COMPOSE; + if (symbol == "help") return XBMCK_HELP; + if (symbol == "printscreen") return XBMCK_PRINT; + if (symbol == "sysreq") return XBMCK_SYSREQ; + if (symbol == "break") return XBMCK_BREAK; + if (symbol == "menu") return XBMCK_MENU; + if (symbol == "power") return XBMCK_POWER; + if (symbol == "euro") return XBMCK_EURO; + if (symbol == "undo") return XBMCK_UNDO; + + return XBMCK_UNKNOWN; +} + +const char *CControllerTranslator::TranslateKeycode(XBMCKey keycode) +{ + switch (keycode) + { + case XBMCK_BACKSPACE: return "backspace"; + case XBMCK_TAB: return "tab"; + case XBMCK_CLEAR: return "clear"; + case XBMCK_RETURN: return "enter"; + case XBMCK_PAUSE: return "pause"; + case XBMCK_ESCAPE: return "escape"; + case XBMCK_SPACE: return "space"; + case XBMCK_EXCLAIM: return "exclaim"; + case XBMCK_QUOTEDBL: return "doublequote"; + case XBMCK_HASH: return "hash"; + case XBMCK_DOLLAR: return "dollar"; + case XBMCK_AMPERSAND: return "ampersand"; + case XBMCK_QUOTE: return "quote"; + case XBMCK_LEFTPAREN: return "leftparen"; + case XBMCK_RIGHTPAREN: return "rightparen"; + case XBMCK_ASTERISK: return "asterisk"; + case XBMCK_PLUS: return "plus"; + case XBMCK_COMMA: return "comma"; + case XBMCK_MINUS: return "minus"; + case XBMCK_PERIOD: return "period"; + case XBMCK_SLASH: return "slash"; + case XBMCK_0: return "0"; + case XBMCK_1: return "1"; + case XBMCK_2: return "2"; + case XBMCK_3: return "3"; + case XBMCK_4: return "4"; + case XBMCK_5: return "5"; + case XBMCK_6: return "6"; + case XBMCK_7: return "7"; + case XBMCK_8: return "8"; + case XBMCK_9: return "9"; + case XBMCK_COLON: return "colon"; + case XBMCK_SEMICOLON: return "semicolon"; + case XBMCK_LESS: return "less"; + case XBMCK_EQUALS: return "equals"; + case XBMCK_GREATER: return "greater"; + case XBMCK_QUESTION: return "question"; + case XBMCK_AT: return "at"; + case XBMCK_LEFTBRACKET: return "leftbracket"; + case XBMCK_BACKSLASH: return "backslash"; + case XBMCK_RIGHTBRACKET: return "rightbracket"; + case XBMCK_CARET: return "caret"; + case XBMCK_UNDERSCORE: return "underscore"; + case XBMCK_BACKQUOTE: return "grave"; + case XBMCK_a: return "a"; + case XBMCK_b: return "b"; + case XBMCK_c: return "c"; + case XBMCK_d: return "d"; + case XBMCK_e: return "e"; + case XBMCK_f: return "f"; + case XBMCK_g: return "g"; + case XBMCK_h: return "h"; + case XBMCK_i: return "i"; + case XBMCK_j: return "j"; + case XBMCK_k: return "k"; + case XBMCK_l: return "l"; + case XBMCK_m: return "m"; + case XBMCK_n: return "n"; + case XBMCK_o: return "o"; + case XBMCK_p: return "p"; + case XBMCK_q: return "q"; + case XBMCK_r: return "r"; + case XBMCK_s: return "s"; + case XBMCK_t: return "t"; + case XBMCK_u: return "u"; + case XBMCK_v: return "v"; + case XBMCK_w: return "w"; + case XBMCK_x: return "x"; + case XBMCK_y: return "y"; + case XBMCK_z: return "z"; + case XBMCK_LEFTBRACE: return "leftbrace"; + case XBMCK_PIPE: return "bar"; + case XBMCK_RIGHTBRACE: return "rightbrace"; + case XBMCK_TILDE: return "tilde"; + case XBMCK_DELETE: return "delete"; + case XBMCK_KP0: return "kp0"; + case XBMCK_KP1: return "kp1"; + case XBMCK_KP2: return "kp2"; + case XBMCK_KP3: return "kp3"; + case XBMCK_KP4: return "kp4"; + case XBMCK_KP5: return "kp5"; + case XBMCK_KP6: return "kp6"; + case XBMCK_KP7: return "kp7"; + case XBMCK_KP8: return "kp8"; + case XBMCK_KP9: return "kp9"; + case XBMCK_KP_PERIOD: return "kpperiod"; + case XBMCK_KP_DIVIDE: return "kpdivide"; + case XBMCK_KP_MULTIPLY: return "kpmultiply"; + case XBMCK_KP_MINUS: return "kpminus"; + case XBMCK_KP_PLUS: return "kpplus"; + case XBMCK_KP_ENTER: return "kpenter"; + case XBMCK_KP_EQUALS: return "kpequals"; + case XBMCK_UP: return "up"; + case XBMCK_DOWN: return "down"; + case XBMCK_RIGHT: return "right"; + case XBMCK_LEFT: return "left"; + case XBMCK_INSERT: return "insert"; + case XBMCK_HOME: return "home"; + case XBMCK_END: return "end"; + case XBMCK_PAGEUP: return "pageup"; + case XBMCK_PAGEDOWN: return "pagedown"; + case XBMCK_F1: return "f1"; + case XBMCK_F2: return "f2"; + case XBMCK_F3: return "f3"; + case XBMCK_F4: return "f4"; + case XBMCK_F5: return "f5"; + case XBMCK_F6: return "f6"; + case XBMCK_F7: return "f7"; + case XBMCK_F8: return "f8"; + case XBMCK_F9: return "f9"; + case XBMCK_F10: return "f10"; + case XBMCK_F11: return "f11"; + case XBMCK_F12: return "f12"; + case XBMCK_F13: return "f13"; + case XBMCK_F14: return "f14"; + case XBMCK_F15: return "f15"; + case XBMCK_NUMLOCK: return "numlock"; + case XBMCK_CAPSLOCK: return "capslock"; + case XBMCK_SCROLLOCK: return "scrolllock"; + case XBMCK_LSHIFT: return "leftshift"; + case XBMCK_RSHIFT: return "rightshift"; + case XBMCK_LCTRL: return "leftctrl"; + case XBMCK_RCTRL: return "rightctrl"; + case XBMCK_LALT: return "leftalt"; + case XBMCK_RALT: return "rightalt"; + case XBMCK_LMETA: return "leftmeta"; + case XBMCK_RMETA: return "rightmeta"; + case XBMCK_LSUPER: return "leftsuper"; + case XBMCK_RSUPER: return "rightsuper"; + case XBMCK_MODE: return "mode"; + case XBMCK_COMPOSE: return "compose"; + case XBMCK_HELP: return "help"; + case XBMCK_PRINT: return "printscreen"; + case XBMCK_SYSREQ: return "sysreq"; + case XBMCK_BREAK: return "break"; + case XBMCK_MENU: return "menu"; + case XBMCK_POWER: return "power"; + case XBMCK_EURO: return "euro"; + case XBMCK_UNDO: return "undo"; + default: + break; + } + + return ""; +} diff --git a/xbmc/games/controllers/ControllerTranslator.h b/xbmc/games/controllers/ControllerTranslator.h index 4278510be8..9ebae5f423 100644 --- a/xbmc/games/controllers/ControllerTranslator.h +++ b/xbmc/games/controllers/ControllerTranslator.h @@ -20,6 +20,7 @@ #pragma once #include "input/joysticks/JoystickTypes.h" +#include "input/XBMC_keysym.h" #include <string> @@ -39,6 +40,24 @@ public: static const char* TranslateInputType(JOYSTICK::INPUT_TYPE type); static JOYSTICK::INPUT_TYPE TranslateInputType(const std::string& strType); + + /*! + * \brief Translate a keyboard symbol to a Kodi key code + * + * \param symbol The key's symbol, defined in the kodi-game-controllers project + * + * \return The layout-independent keycode associated with the key + */ + static XBMCKey TranslateKeysym(const std::string &symbol); + + /*! + * \brief Translate a Kodi key code to a keyboard symbol + * + * \param keycode The Kodi key code + * + * \return The key's symbol, or an empty string if no symbol is defined for the keycode + */ + static const char *TranslateKeycode(XBMCKey keycode); }; } diff --git a/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.h b/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.h index a1a7675080..fdd4a92e69 100644 --- a/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.h +++ b/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.h @@ -43,8 +43,6 @@ namespace GAME // implementation of IButtonMapper virtual std::string ControllerID(void) const override; virtual bool NeedsCooldown(void) const override { return false; } - virtual bool Emulation(void) const override { return false; } - virtual unsigned int ControllerNumber(void) const override { return 0; } virtual bool MapPrimitive(JOYSTICK::IButtonMap* buttonMap, IKeymap* keymap, const JOYSTICK::CDriverPrimitive& primitive) override; diff --git a/xbmc/games/controllers/guicontrols/CMakeLists.txt b/xbmc/games/controllers/guicontrols/CMakeLists.txt index 6844a8aa44..bbec218bbf 100644 --- a/xbmc/games/controllers/guicontrols/CMakeLists.txt +++ b/xbmc/games/controllers/guicontrols/CMakeLists.txt @@ -6,6 +6,7 @@ set(SOURCES GUIAnalogStickButton.cpp GUIFeatureTranslator.cpp GUIGameController.cpp GUIScalarFeatureButton.cpp + GUISelectKeyButton.cpp GUIThrottleButton.cpp GUIWheelButton.cpp ) @@ -19,6 +20,7 @@ set(HEADERS GUIAnalogStickButton.h GUIFeatureTranslator.h GUIGameController.h GUIScalarFeatureButton.h + GUISelectKeyButton.h GUIThrottleButton.h GUIWheelButton.h ) diff --git a/xbmc/games/controllers/guicontrols/GUIControlTypes.h b/xbmc/games/controllers/guicontrols/GUIControlTypes.h index e83916bfb7..ef32908a5a 100644 --- a/xbmc/games/controllers/guicontrols/GUIControlTypes.h +++ b/xbmc/games/controllers/guicontrols/GUIControlTypes.h @@ -33,6 +33,7 @@ namespace GAME ANALOG_STICK, WHEEL, THROTTLE, + SELECT_KEY, }; } } diff --git a/xbmc/games/controllers/guicontrols/GUIFeatureFactory.cpp b/xbmc/games/controllers/guicontrols/GUIFeatureFactory.cpp index 270a3f4871..ce445465c7 100644 --- a/xbmc/games/controllers/guicontrols/GUIFeatureFactory.cpp +++ b/xbmc/games/controllers/guicontrols/GUIFeatureFactory.cpp @@ -21,6 +21,7 @@ #include "GUIFeatureFactory.h" #include "GUIAnalogStickButton.h" #include "GUIScalarFeatureButton.h" +#include "GUISelectKeyButton.h" #include "GUIThrottleButton.h" #include "GUIWheelButton.h" @@ -47,6 +48,9 @@ CGUIButtonControl* CGUIFeatureFactory::CreateButton(BUTTON_TYPE type, case BUTTON_TYPE::THROTTLE: return new CGUIThrottleButton(buttonTemplate, wizard, feature, index); + case BUTTON_TYPE::SELECT_KEY: + return new CGUISelectKeyButton(buttonTemplate, wizard, index); + default: break; } diff --git a/xbmc/games/controllers/guicontrols/GUIFeatureTranslator.cpp b/xbmc/games/controllers/guicontrols/GUIFeatureTranslator.cpp index ecc6f358f0..9a7a67b1c9 100644 --- a/xbmc/games/controllers/guicontrols/GUIFeatureTranslator.cpp +++ b/xbmc/games/controllers/guicontrols/GUIFeatureTranslator.cpp @@ -28,6 +28,7 @@ BUTTON_TYPE CGUIFeatureTranslator::GetButtonType(JOYSTICK::FEATURE_TYPE featureT switch (featureType) { case JOYSTICK::FEATURE_TYPE::SCALAR: + case JOYSTICK::FEATURE_TYPE::KEY: return BUTTON_TYPE::BUTTON; case JOYSTICK::FEATURE_TYPE::ANALOG_STICK: diff --git a/xbmc/games/controllers/guicontrols/GUISelectKeyButton.cpp b/xbmc/games/controllers/guicontrols/GUISelectKeyButton.cpp new file mode 100644 index 0000000000..086cad41f9 --- /dev/null +++ b/xbmc/games/controllers/guicontrols/GUISelectKeyButton.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2017 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 "GUISelectKeyButton.h" +#include "guilib/LocalizeStrings.h" +#include "utils/StringUtils.h" + +#include <string> + +using namespace KODI; +using namespace GAME; + +CGUISelectKeyButton::CGUISelectKeyButton(const CGUIButtonControl& buttonTemplate, + IConfigurationWizard* wizard, + unsigned int index) : + CGUIFeatureButton(buttonTemplate, wizard, GetFeature(), index) +{ +} + +const CControllerFeature& CGUISelectKeyButton::Feature(void) const +{ + if (m_state == STATE::NEED_INPUT) + return m_selectedKey; + + return CGUIFeatureButton::Feature(); +} + +bool CGUISelectKeyButton::PromptForInput(CEvent& waitEvent) +{ + bool bInterrupted = false; + + switch (m_state) + { + case STATE::NEED_KEY: + { + std::string strPrompt = g_localizeStrings.Get(35169); // "Press a key" + std::string strWarn = g_localizeStrings.Get(35170); // "Press a key ({1:d})" + + bInterrupted = DoPrompt(strPrompt, strWarn, "", waitEvent); + + m_state = GetNextState(m_state); + + break; + } + case STATE::NEED_INPUT: + { + std::string strPrompt = g_localizeStrings.Get(35090); // "Press {0:s}" + std::string strWarn = g_localizeStrings.Get(35091); // "Press {0:s} ({1:d})" + + bInterrupted = DoPrompt(strPrompt, strWarn, m_selectedKey.Label(), waitEvent); + + m_state = GetNextState(m_state); + + break; + } + default: + break; + } + + return bInterrupted; +} + +bool CGUISelectKeyButton::IsFinished(void) const +{ + return m_state >= STATE::FINISHED; +} + +void CGUISelectKeyButton::SetKey(const CControllerFeature &key) +{ + m_selectedKey = key; +} + +void CGUISelectKeyButton::Reset(void) +{ + m_state = STATE::NEED_KEY; + m_selectedKey.Reset(); +} + +CControllerFeature CGUISelectKeyButton::GetFeature() +{ + return CControllerFeature(35168); // "Select key" +} diff --git a/xbmc/games/controllers/guicontrols/GUISelectKeyButton.h b/xbmc/games/controllers/guicontrols/GUISelectKeyButton.h new file mode 100644 index 0000000000..3429693f85 --- /dev/null +++ b/xbmc/games/controllers/guicontrols/GUISelectKeyButton.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2017 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 "GUIFeatureButton.h" +#include "games/controllers/ControllerFeature.h" + +namespace KODI +{ +namespace GAME +{ + class CGUISelectKeyButton : public CGUIFeatureButton + { + public: + CGUISelectKeyButton(const CGUIButtonControl& buttonTemplate, + IConfigurationWizard* wizard, + unsigned int index); + + virtual ~CGUISelectKeyButton() = default; + + // implementation of IFeatureButton + const CControllerFeature& Feature(void) const override; + bool AllowWizard() const override { return false; } + virtual bool PromptForInput(CEvent& waitEvent) override; + virtual bool IsFinished(void) const override; + bool NeedsKey() const override { return m_state == STATE::NEED_KEY; } + void SetKey(const CControllerFeature &key) override; + virtual void Reset(void) override; + + private: + static CControllerFeature GetFeature(); + + enum class STATE + { + NEED_KEY, + NEED_INPUT, + FINISHED, + }; + + STATE m_state = STATE::NEED_KEY; + + CControllerFeature m_selectedKey; + }; +} +} diff --git a/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp b/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp index 42851f957d..f89aa44880 100644 --- a/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp +++ b/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp @@ -23,6 +23,7 @@ #include "games/controllers/guicontrols/GUIFeatureButton.h" #include "games/controllers/Controller.h" #include "games/controllers/ControllerFeature.h" +#include "games/controllers/ControllerTranslator.h" #include "input/joysticks/interfaces/IButtonMap.h" #include "input/joysticks/interfaces/IButtonMapCallback.h" #include "input/joysticks/JoystickUtils.h" @@ -43,10 +44,8 @@ using namespace GAME; // Duration to wait for axes to neutralize after mapping is finished #define POST_MAPPING_WAIT_TIME_MS (5 * 1000) -CGUIConfigurationWizard::CGUIConfigurationWizard(bool bEmulation, unsigned int controllerNumber /* = 0 */) : +CGUIConfigurationWizard::CGUIConfigurationWizard() : CThread("GUIConfigurationWizard"), - m_bEmulation(bEmulation), - m_controllerNumber(controllerNumber), m_actionMap(new KEYBOARD::CKeymapActionMap) { InitializeState(); @@ -111,6 +110,17 @@ bool CGUIConfigurationWizard::Abort(bool bWait /* = true */) return bWasRunning; } +void CGUIConfigurationWizard::RegisterKey(const CControllerFeature &key) +{ + if (key.Keycode() != XBMCK_UNKNOWN) + m_keyMap[key.Keycode()] = key; +} + +void CGUIConfigurationWizard::UnregisterKeys() +{ + m_keyMap.clear(); +} + void CGUIConfigurationWizard::Process(void) { CLog::Log(LOGDEBUG, "Starting configuration wizard"); @@ -135,9 +145,14 @@ void CGUIConfigurationWizard::Process(void) // Wait for input { + using namespace JOYSTICK; + CSingleExit exit(m_stateMutex); - CLog::Log(LOGDEBUG, "%s: Waiting for input for feature \"%s\"", m_strControllerId.c_str(), button->Feature().Name().c_str()); + if (button->Feature().Type() == FEATURE_TYPE::UNKNOWN) + CLog::Log(LOGDEBUG, "%s: Waiting for input", m_strControllerId.c_str()); + else + CLog::Log(LOGDEBUG, "%s: Waiting for input for feature \"%s\"", m_strControllerId.c_str(), button->Feature().Name().c_str()); if (!button->PromptForInput(m_inputEvent)) Abort(false); @@ -238,12 +253,6 @@ bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap, // Discard input bHandled = true; } - else if (primitive.Type() == PRIMITIVE_TYPE::BUTTON && - primitive.Index() == ESC_KEY_CODE) - { - // Handle esc key - bHandled = Abort(false); - } else if (m_history.find(primitive) != m_history.end()) { // Primitive has already been mapped this round, ignore it @@ -270,15 +279,29 @@ bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap, if (currentButton) { - const CControllerFeature& feature = currentButton->Feature(); - - if (feature.Type() == JOYSTICK::FEATURE_TYPE::UNKNOWN) + // Check if we were expecting a keyboard key + if (currentButton->NeedsKey()) { - // Unknown feature, absorb input + if (primitive.Type() == PRIMITIVE_TYPE::KEY) + { + auto it = m_keyMap.find(primitive.Keycode()); + if (it != m_keyMap.end()) + { + const CControllerFeature &key = it->second; + currentButton->SetKey(key); + m_inputEvent.Set(); + } + } + else + { + //! @todo Check if primitive is a cancel or motion action + } bHandled = true; } else { + const CControllerFeature& feature = currentButton->Feature(); + CLog::Log(LOGDEBUG, "%s: mapping feature \"%s\" for device %s", m_strControllerId.c_str(), feature.Name().c_str(), buttonMap->DeviceName().c_str()); @@ -314,6 +337,12 @@ bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap, bHandled = true; break; } + case FEATURE_TYPE::KEY: + { + buttonMap->AddKey(feature.Name(), primitive); + bHandled = true; + break; + } default: break; } @@ -326,7 +355,10 @@ bool CGUIConfigurationWizard::MapPrimitive(JOYSTICK::IButtonMap* buttonMap, m_inputEvent.Set(); if (m_deviceName.empty()) + { m_deviceName = buttonMap->DeviceName(); + m_bIsKeyboard = (primitive.Type() == PRIMITIVE_TYPE::KEY); + } } } } @@ -371,7 +403,20 @@ bool CGUIConfigurationWizard::OnKeyPress(const CKey& key) bool bHandled = false; if (!m_bStop) - bHandled = OnKeyAction(m_actionMap->GetActionID(key)); + { + // Only allow key to abort the prompt if we know for sure that we're mapping + // a controller + const bool bIsMappingController = (IsMapping() && !m_bIsKeyboard); + + if (bIsMappingController) + { + bHandled = OnKeyAction(m_actionMap->GetActionID(key)); + } + else + { + // Allow key press to fall through to the button mapper + } + } return bHandled; } @@ -429,21 +474,14 @@ void CGUIConfigurationWizard::InstallHooks(void) { CServiceBroker::GetPeripherals().RegisterJoystickButtonMapper(this); CServiceBroker::GetPeripherals().RegisterObserver(this); - - // If we're not using emulation, allow keyboard input to abort prompt - if (!m_bEmulation) - CServiceBroker::GetInputManager().RegisterKeyboardHandler(this); - + CServiceBroker::GetInputManager().RegisterKeyboardDriverHandler(this); CServiceBroker::GetInputManager().RegisterMouseHandler(this); } void CGUIConfigurationWizard::RemoveHooks(void) { CServiceBroker::GetInputManager().UnregisterMouseHandler(this); - - if (!m_bEmulation) - CServiceBroker::GetInputManager().UnregisterKeyboardHandler(this); - + CServiceBroker::GetInputManager().UnregisterKeyboardDriverHandler(this); CServiceBroker::GetPeripherals().UnregisterObserver(this); CServiceBroker::GetPeripherals().UnregisterJoystickButtonMapper(this); } diff --git a/xbmc/games/controllers/windows/GUIConfigurationWizard.h b/xbmc/games/controllers/windows/GUIConfigurationWizard.h index 69fa21af4e..b980bc5ae7 100644 --- a/xbmc/games/controllers/windows/GUIConfigurationWizard.h +++ b/xbmc/games/controllers/windows/GUIConfigurationWizard.h @@ -20,15 +20,18 @@ #pragma once #include "IConfigurationWindow.h" +#include "games/controllers/ControllerFeature.h" #include "input/joysticks/DriverPrimitive.h" #include "input/joysticks/interfaces/IButtonMapper.h" -#include "input/keyboard/interfaces/IKeyboardHandler.h" +#include "input/keyboard/interfaces/IKeyboardDriverHandler.h" #include "input/mouse/interfaces/IMouseInputHandler.h" +#include "input/XBMC_keysym.h" #include "threads/CriticalSection.h" #include "threads/Event.h" #include "threads/Thread.h" #include "utils/Observer.h" +#include <map> #include <memory> #include <set> #include <string> @@ -45,13 +48,13 @@ namespace GAME { class CGUIConfigurationWizard : public IConfigurationWizard, public JOYSTICK::IButtonMapper, - public KEYBOARD::IKeyboardHandler, + public KEYBOARD::IKeyboardDriverHandler, public MOUSE::IMouseInputHandler, public Observer, protected CThread { public: - CGUIConfigurationWizard(bool bEmulation, unsigned int controllerNumber = 0); + CGUIConfigurationWizard(); virtual ~CGUIConfigurationWizard(void); @@ -59,19 +62,19 @@ namespace GAME virtual void Run(const std::string& strControllerId, const std::vector<IFeatureButton*>& buttons) override; virtual void OnUnfocus(IFeatureButton* button) override; virtual bool Abort(bool bWait = true) override; + void RegisterKey(const CControllerFeature &key) override; + void UnregisterKeys() override; // implementation of IButtonMapper virtual std::string ControllerID(void) const override { return m_strControllerId; } virtual bool NeedsCooldown(void) const override { return true; } - virtual bool Emulation(void) const override { return m_bEmulation; } - virtual unsigned int ControllerNumber(void) const override { return m_controllerNumber; } virtual bool MapPrimitive(JOYSTICK::IButtonMap* buttonMap, IKeymap* keymap, const JOYSTICK::CDriverPrimitive& primitive) override; virtual void OnEventFrame(const JOYSTICK::IButtonMap* buttonMap, bool bMotion) override; virtual void OnLateAxis(const JOYSTICK::IButtonMap* buttonMap, unsigned int axisIndex) override; - // implementation of IKeyboardHandler + // implementation of IKeyboardDriverHandler virtual bool OnKeyPress(const CKey& key) override; virtual void OnKeyRelease(const CKey& key) override { } @@ -101,10 +104,6 @@ namespace GAME bool OnKeyAction(unsigned int actionId); - // Construction parameters - const bool m_bEmulation; - const unsigned int m_controllerNumber; - // Run() parameters std::string m_strControllerId; std::vector<IFeatureButton*> m_buttons; @@ -116,7 +115,8 @@ namespace GAME JOYSTICK::THROTTLE_DIRECTION m_throttleDirection; std::set<JOYSTICK::CDriverPrimitive> m_history; // History to avoid repeated features bool m_lateAxisDetected; // Set to true if an axis is detected during button mapping - std::string m_deviceName; + std::string m_deviceName; // Name of device that we're mapping + bool m_bIsKeyboard = false; // True if we're mapping keyboard keys CCriticalSection m_stateMutex; // Synchronization events @@ -127,6 +127,7 @@ namespace GAME // Keyboard handling std::unique_ptr<KEYBOARD::IActionMap> m_actionMap; + std::map<XBMCKey, CControllerFeature> m_keyMap; // Keycode -> feature }; } } diff --git a/xbmc/games/controllers/windows/GUIControllerDefines.h b/xbmc/games/controllers/windows/GUIControllerDefines.h index 8b421d0cc4..96101b6f6e 100644 --- a/xbmc/games/controllers/windows/GUIControllerDefines.h +++ b/xbmc/games/controllers/windows/GUIControllerDefines.h @@ -40,7 +40,7 @@ #define CONTROL_GAME_CONTROLLER 31 #define MAX_CONTROLLER_COUNT 100 // large enough -#define MAX_FEATURE_COUNT 100 // large enough +#define MAX_FEATURE_COUNT 200 // large enough #define CONTROL_CONTROLLER_BUTTONS_START 100 #define CONTROL_CONTROLLER_BUTTONS_END (CONTROL_CONTROLLER_BUTTONS_START + MAX_CONTROLLER_COUNT) diff --git a/xbmc/games/controllers/windows/GUIControllerWindow.cpp b/xbmc/games/controllers/windows/GUIControllerWindow.cpp index cc87f73c56..691e99f0be 100644 --- a/xbmc/games/controllers/windows/GUIControllerWindow.cpp +++ b/xbmc/games/controllers/windows/GUIControllerWindow.cpp @@ -101,12 +101,6 @@ bool CGUIControllerWindow::OnMessage(CGUIMessage& message) switch (message.GetMessage()) { - case GUI_MSG_WINDOW_INIT: - { - //! @todo Process params here, don't just record them for later - m_param = message.GetStringParam(); - break; - } case GUI_MSG_CLICKED: { int controlId = message.GetSenderId(); @@ -210,7 +204,7 @@ void CGUIControllerWindow::OnInitWindow(void) if (!m_featureList) { - m_featureList = new CGUIFeatureList(this, m_param); + m_featureList = new CGUIFeatureList(this); if (!m_featureList->Initialize()) { delete m_featureList; diff --git a/xbmc/games/controllers/windows/GUIControllerWindow.h b/xbmc/games/controllers/windows/GUIControllerWindow.h index b58cfa9064..41c2235748 100644 --- a/xbmc/games/controllers/windows/GUIControllerWindow.h +++ b/xbmc/games/controllers/windows/GUIControllerWindow.h @@ -60,7 +60,6 @@ namespace GAME IControllerList* m_controllerList; IFeatureList* m_featureList; - std::string m_param; // First auxiliary parameter in call to ActivateWindow() }; } } diff --git a/xbmc/games/controllers/windows/GUIFeatureList.cpp b/xbmc/games/controllers/windows/GUIFeatureList.cpp index bc8142193c..0afb79cb26 100644 --- a/xbmc/games/controllers/windows/GUIFeatureList.cpp +++ b/xbmc/games/controllers/windows/GUIFeatureList.cpp @@ -33,32 +33,20 @@ #include "guilib/GUILabelControl.h" #include "guilib/GUIMessage.h" #include "guilib/GUIWindow.h" +#include "guilib/LocalizeStrings.h" #include "messaging/ApplicationMessenger.h" using namespace KODI; using namespace GAME; -CGUIFeatureList::CGUIFeatureList(CGUIWindow* window, const std::string& windowParam) : +CGUIFeatureList::CGUIFeatureList(CGUIWindow* window) : m_window(window), m_guiList(nullptr), m_guiButtonTemplate(nullptr), m_guiGroupTitle(nullptr), m_guiFeatureSeparator(nullptr), - m_wizard(nullptr) + m_wizard(new CGUIConfigurationWizard) { - if (windowParam.empty()) - { - // Run wizard for all physical controllers - m_wizard = new CGUIConfigurationWizard(false); - } - else - { - // Run wizard for specified emulated controller - unsigned int number; - std::istringstream str(windowParam); - str >> number; - m_wizard = new CGUIConfigurationWizard(true, number); - } } CGUIFeatureList::~CGUIFeatureList(void) @@ -117,9 +105,22 @@ void CGUIFeatureList::Load(const ControllerPtr& controller) for (auto itGroup = featureGroups.begin(); itGroup != featureGroups.end(); ++itGroup) { const std::string& groupName = itGroup->groupName; + const bool bIsVirtualKey = itGroup->bIsVirtualKey; + + std::vector<CGUIButtonControl*> buttons; // Create buttons - std::vector<CGUIButtonControl*> buttons = GetButtons(itGroup->features, m_buttonCount); + if (bIsVirtualKey) + { + CGUIButtonControl* button = GetSelectKeyButton(itGroup->features, m_buttonCount); + if (button != nullptr) + buttons.push_back(button); + } + else + { + buttons = GetButtons(itGroup->features, m_buttonCount); + } + if (!buttons.empty()) { // Just in case @@ -156,8 +157,18 @@ void CGUIFeatureList::OnSelect(unsigned int buttonIndex) for ( ; buttonIndex < m_buttonCount; buttonIndex++) { IFeatureButton* control = GetButtonControl(buttonIndex); - if (control) + if (control == nullptr) + continue; + + if (control->AllowWizard()) buttons.push_back(control); + else + { + // Only map this button if it's the only one + if (buttons.empty()) + buttons.push_back(control); + break; + } } m_wizard->Run(m_controller->ID(), buttons); @@ -175,6 +186,7 @@ void CGUIFeatureList::CleanupButtons(void) m_buttonCount = 0; m_wizard->Abort(true); + m_wizard->UnregisterKeys(); if (m_guiList) m_guiList->ClearAll(); @@ -198,15 +210,33 @@ std::vector<CGUIFeatureList::FeatureGroup> CGUIFeatureList::GetFeatureGroups(con // Add feature to previous group previousGroup.features.emplace_back(feature); bAdded = true; + + // If feature is a key, add it to the preceding virtual group as well + if (feature.Category() == JOYSTICK::FEATURE_CATEGORY::KEY && groups.size() >= 2) + { + FeatureGroup &virtualGroup = *(groups.rbegin() + 1); + if (virtualGroup.bIsVirtualKey) + virtualGroup.features.emplace_back(feature); + } } } if (!bAdded) { + // If feature is a key, create a virtual group that allows the user to + // select which key to map + if (feature.Category() == JOYSTICK::FEATURE_CATEGORY::KEY) + { + FeatureGroup virtualGroup; + virtualGroup.groupName = g_localizeStrings.Get(35166); // "All keys" + virtualGroup.bIsVirtualKey = true; + virtualGroup.features.emplace_back(feature); + groups.emplace_back(std::move(virtualGroup)); + } + // Create new group and add feature FeatureGroup group; group.groupName = feature.CategoryLabel(); - group.category = feature.Category(); group.features.emplace_back(feature); groups.emplace_back(std::move(group)); } @@ -242,3 +272,15 @@ std::vector<CGUIButtonControl*> CGUIFeatureList::GetButtons(const std::vector<CC return buttons; } + +CGUIButtonControl* CGUIFeatureList::GetSelectKeyButton(const std::vector<CControllerFeature>& features, unsigned int buttonIndex) +{ + // Expose keycodes to the wizard + for (const CControllerFeature& feature : features) + { + if (feature.Type() == JOYSTICK::FEATURE_TYPE::KEY) + m_wizard->RegisterKey(feature); + } + + return CGUIFeatureFactory::CreateButton(BUTTON_TYPE::SELECT_KEY, *m_guiButtonTemplate, m_wizard, CControllerFeature(), buttonIndex); +} diff --git a/xbmc/games/controllers/windows/GUIFeatureList.h b/xbmc/games/controllers/windows/GUIFeatureList.h index 4389bcdb5f..e09d4b0e91 100644 --- a/xbmc/games/controllers/windows/GUIFeatureList.h +++ b/xbmc/games/controllers/windows/GUIFeatureList.h @@ -37,7 +37,7 @@ namespace GAME class CGUIFeatureList : public IFeatureList { public: - CGUIFeatureList(CGUIWindow* window, const std::string& windowParam); + CGUIFeatureList(CGUIWindow* window); virtual ~CGUIFeatureList(void); // implementation of IFeatureList @@ -57,11 +57,16 @@ namespace GAME struct FeatureGroup { std::string groupName; - JOYSTICK::FEATURE_CATEGORY category = JOYSTICK::FEATURE_CATEGORY::UNKNOWN; std::vector<CControllerFeature> features; + /*! + * True if this group is a button that allows the user to map a key of + * their choosing. + */ + bool bIsVirtualKey = false; }; static std::vector<FeatureGroup> GetFeatureGroups(const std::vector<CControllerFeature>& features); std::vector<CGUIButtonControl*> GetButtons(const std::vector<CControllerFeature>& features, unsigned int startIndex); + CGUIButtonControl* GetSelectKeyButton(const std::vector<CControllerFeature>& features, unsigned int buttonIndex); // GUI stuff CGUIWindow* const m_window; diff --git a/xbmc/games/controllers/windows/IConfigurationWindow.h b/xbmc/games/controllers/windows/IConfigurationWindow.h index 9d3e3d2882..870a773165 100644 --- a/xbmc/games/controllers/windows/IConfigurationWindow.h +++ b/xbmc/games/controllers/windows/IConfigurationWindow.h @@ -165,6 +165,12 @@ namespace GAME virtual const CControllerFeature& Feature(void) const = 0; /*! + * \brief Allow the wizard to include this feature in a list of buttons + * to map + */ + virtual bool AllowWizard() const { return true; } + + /*! * \brief Prompt the user for a single input element * \param waitEvent The event to block on while prompting for input * \return true if input was received (event fired), false if the prompt timed out @@ -202,6 +208,18 @@ namespace GAME virtual JOYSTICK::THROTTLE_DIRECTION GetThrottleDirection(void) const = 0; /*! + * \brief True if the button is waiting for a key press + */ + virtual bool NeedsKey() const { return false; } + + /*! + * \brief Set the pressed key that the user will be prompted to map + * + * \param key The key that was pressed + */ + virtual void SetKey(const CControllerFeature &key) { } + + /*! * \brief Reset button after prompting for input has finished */ virtual void Reset(void) = 0; @@ -234,6 +252,20 @@ namespace GAME * \return true if aborted, or false if the wizard wasn't running */ virtual bool Abort(bool bWait = true) = 0; + + /*! + * \brief Register a key by its keycode + * \param key A key with a valid keycode + * + * This should be called before Run(). It allows the user to choose a key + * to map instead of scrolling through a long list. + */ + virtual void RegisterKey(const CControllerFeature &key) = 0; + + /*! + * \brief Unregister all registered keys + */ + virtual void UnregisterKeys() = 0; }; } } diff --git a/xbmc/games/ports/PortManager.cpp b/xbmc/games/ports/PortManager.cpp index 4446e58503..2dbc9f5637 100644 --- a/xbmc/games/ports/PortManager.cpp +++ b/xbmc/games/ports/PortManager.cpp @@ -24,7 +24,6 @@ #include "input/joysticks/interfaces/IInputHandler.h" #include "peripherals/devices/Peripheral.h" #include "peripherals/devices/PeripheralJoystick.h" -#include "peripherals/devices/PeripheralJoystickEmulation.h" #include "peripherals/Peripherals.h" #include "utils/log.h" @@ -128,15 +127,6 @@ void CPortManager::MapDevices(const PeripheralVector& devices, return i->RequestedPort() < j->RequestedPort(); } - if (lhs->Type() == PERIPHERAL_JOYSTICK_EMULATION && rhs->Type() == PERIPHERAL_JOYSTICK_EMULATION) - { - std::shared_ptr<CPeripheralJoystickEmulation> i = std::static_pointer_cast<CPeripheralJoystickEmulation>(lhs); - std::shared_ptr<CPeripheralJoystickEmulation> j = std::static_pointer_cast<CPeripheralJoystickEmulation>(rhs); - - // Sort emulated joysticks by player number - return i->ControllerNumber() < j->ControllerNumber(); - } - return false; }); diff --git a/xbmc/input/CMakeLists.txt b/xbmc/input/CMakeLists.txt index 6c3243aaec..c2cb7a0825 100644 --- a/xbmc/input/CMakeLists.txt +++ b/xbmc/input/CMakeLists.txt @@ -27,6 +27,10 @@ set(SOURCES Action.cpp XBMC_keytable.cpp) set(HEADERS hardware/IHardwareInput.h + mouse/interfaces/IMouseButtonMap.h + mouse/interfaces/IMouseDriverHandler.h + mouse/interfaces/IMouseInputHandler.h + mouse/interfaces/IMouseInputProvider.h Action.h ActionIDs.h ActionTranslator.h diff --git a/xbmc/input/InputManager.cpp b/xbmc/input/InputManager.cpp index 278c75acbb..cd4cee9348 100644 --- a/xbmc/input/InputManager.cpp +++ b/xbmc/input/InputManager.cpp @@ -28,7 +28,7 @@ #include "JoystickMapper.h" #include "KeymapEnvironment.h" #include "TouchTranslator.h" -#include "input/keyboard/interfaces/IKeyboardHandler.h" +#include "input/keyboard/interfaces/IKeyboardDriverHandler.h" #include "input/mouse/generic/MouseInputHandling.h" #include "input/mouse/interfaces/IMouseDriverHandler.h" #include "input/mouse/MouseWindowingButtonMap.h" @@ -85,7 +85,7 @@ CInputManager::CInputManager(const CAppParamParser ¶ms, m_buttonTranslator->RegisterMapper("customcontroller", m_customControllerTranslator.get()); m_buttonTranslator->RegisterMapper("joystick", m_joystickTranslator.get()); - RegisterKeyboardHandler(m_keyboardEasterEgg.get()); + RegisterKeyboardDriverHandler(m_keyboardEasterEgg.get()); if (!params.RemoteControlName().empty()) SetRemoteControlName(params.RemoteControlName()); @@ -106,7 +106,7 @@ CInputManager::~CInputManager() // Unregister settings CServiceBroker::GetSettings().UnregisterCallback(this); - UnregisterKeyboardHandler(m_keyboardEasterEgg.get()); + UnregisterKeyboardDriverHandler(m_keyboardEasterEgg.get()); m_buttonTranslator->UnregisterMapper(m_touchTranslator.get()); m_buttonTranslator->UnregisterMapper(m_customControllerTranslator.get()); @@ -483,9 +483,9 @@ bool CInputManager::OnKey(const CKey& key) { bool bHandled = false; - for (std::vector<KEYBOARD::IKeyboardHandler*>::iterator it = m_keyboardHandlers.begin(); it != m_keyboardHandlers.end(); ++it) + for (auto handler : m_keyboardHandlers) { - if ((*it)->OnKeyPress(key)) + if (handler->OnKeyPress(key)) { bHandled = true; break; @@ -673,8 +673,8 @@ bool CInputManager::HandleKey(const CKey& key) void CInputManager::OnKeyUp(const CKey& key) { - for (std::vector<KEYBOARD::IKeyboardHandler*>::iterator it = m_keyboardHandlers.begin(); it != m_keyboardHandlers.end(); ++it) - (*it)->OnKeyRelease(key); + for (auto handler : m_keyboardHandlers) + handler->OnKeyRelease(key); if (m_LastKey.GetButtonCode() != KEY_INVALID && !(m_LastKey.GetButtonCode() & CKey::MODIFIER_LONG)) { @@ -995,13 +995,13 @@ int CInputManager::TranslateLircRemoteString(const std::string &szDevice, const return m_irTranslator->TranslateButton(szDevice, szButton); } -void CInputManager::RegisterKeyboardHandler(KEYBOARD::IKeyboardHandler* handler) +void CInputManager::RegisterKeyboardDriverHandler(KEYBOARD::IKeyboardDriverHandler* handler) { if (std::find(m_keyboardHandlers.begin(), m_keyboardHandlers.end(), handler) == m_keyboardHandlers.end()) m_keyboardHandlers.insert(m_keyboardHandlers.begin(), handler); } -void CInputManager::UnregisterKeyboardHandler(KEYBOARD::IKeyboardHandler* handler) +void CInputManager::UnregisterKeyboardDriverHandler(KEYBOARD::IKeyboardDriverHandler* handler) { m_keyboardHandlers.erase(std::remove(m_keyboardHandlers.begin(), m_keyboardHandlers.end(), handler), m_keyboardHandlers.end()); } diff --git a/xbmc/input/InputManager.h b/xbmc/input/InputManager.h index f40bd644fe..97266c45ae 100644 --- a/xbmc/input/InputManager.h +++ b/xbmc/input/InputManager.h @@ -33,7 +33,6 @@ #include "Action.h" #include "windowing/XBMC_events.h" -#include "input/keyboard/interfaces/IKeyboardInputProvider.h" #include "input/mouse/interfaces/IMouseInputProvider.h" #include "input/KeyboardStat.h" #include "input/MouseStat.h" @@ -57,7 +56,7 @@ namespace KODI { namespace KEYBOARD { - class IKeyboardHandler; + class IKeyboardDriverHandler; } namespace MOUSE @@ -83,7 +82,6 @@ namespace MOUSE */ class CInputManager : public ISettingCallback, public IActionListener, - public KODI::KEYBOARD::IKeyboardInputProvider, public KODI::MOUSE::IMouseInputProvider, public Observable { @@ -287,9 +285,8 @@ public: // implementation of IActionListener virtual bool OnAction(const CAction& action) override; - // implementation of IKeyboardInputProvider - virtual void RegisterKeyboardHandler(KODI::KEYBOARD::IKeyboardHandler* handler) override; - virtual void UnregisterKeyboardHandler(KODI::KEYBOARD::IKeyboardHandler* handler) override; + void RegisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler); + void UnregisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler); // implementation of IMouseInputProvider virtual std::string RegisterMouseHandler(KODI::MOUSE::IMouseInputHandler* handler) override; @@ -366,7 +363,7 @@ private: std::unique_ptr<CTouchTranslator> m_touchTranslator; std::unique_ptr<CJoystickMapper> m_joystickTranslator; - std::vector<KODI::KEYBOARD::IKeyboardHandler*> m_keyboardHandlers; + std::vector<KODI::KEYBOARD::IKeyboardDriverHandler*> m_keyboardHandlers; struct MouseHandlerHandle { @@ -377,7 +374,7 @@ private: std::vector<MouseHandlerHandle> m_mouseHandlers; std::unique_ptr<KODI::MOUSE::IMouseButtonMap> m_mouseButtonMap; - std::unique_ptr<KODI::KEYBOARD::IKeyboardHandler> m_keyboardEasterEgg; + std::unique_ptr<KODI::KEYBOARD::IKeyboardDriverHandler> m_keyboardEasterEgg; }; /// \} diff --git a/xbmc/input/joysticks/DriverPrimitive.cpp b/xbmc/input/joysticks/DriverPrimitive.cpp index 2b7d8b44c0..66cc47c9ea 100644 --- a/xbmc/input/joysticks/DriverPrimitive.cpp +++ b/xbmc/input/joysticks/DriverPrimitive.cpp @@ -20,6 +20,8 @@ #include "DriverPrimitive.h" +#include <utility> + using namespace KODI; using namespace JOYSTICK; @@ -47,6 +49,12 @@ CDriverPrimitive::CDriverPrimitive(unsigned int axisIndex, int center, SEMIAXIS_ { } +CDriverPrimitive::CDriverPrimitive(XBMCKey keycode) : + m_type(PRIMITIVE_TYPE::KEY), + m_keycode(keycode) +{ +} + bool CDriverPrimitive::operator==(const CDriverPrimitive& rhs) const { if (m_type == rhs.m_type) @@ -63,6 +71,8 @@ bool CDriverPrimitive::operator==(const CDriverPrimitive& rhs) const m_center == rhs.m_center && m_semiAxisDirection == rhs.m_semiAxisDirection && m_range == rhs.m_range; + case PRIMITIVE_TYPE::KEY: + return m_keycode == rhs.m_keycode; default: return true; } @@ -102,6 +112,12 @@ bool CDriverPrimitive::operator<(const CDriverPrimitive& rhs) const if (m_range > rhs.m_range) return false; } + if (m_type == PRIMITIVE_TYPE::KEY) + { + if (m_keycode < rhs.m_keycode) return true; + if (m_keycode > rhs.m_keycode) return false; + } + return false; } @@ -153,5 +169,8 @@ bool CDriverPrimitive::IsValid(void) const return 1 <= m_range && m_range <= maxRange; } + if (m_type == PRIMITIVE_TYPE::KEY) + return m_keycode != XBMCK_UNKNOWN; + return false; } diff --git a/xbmc/input/joysticks/DriverPrimitive.h b/xbmc/input/joysticks/DriverPrimitive.h index df80271b41..32be317992 100644 --- a/xbmc/input/joysticks/DriverPrimitive.h +++ b/xbmc/input/joysticks/DriverPrimitive.h @@ -20,6 +20,7 @@ #pragma once #include "JoystickTypes.h" +#include "input/XBMC_keysym.h" #include <stdint.h> @@ -63,6 +64,9 @@ namespace JOYSTICK * Motor: * - driver index * + * Key: + * - keycode + * * For more info, see "Chapter 2. Joystick drivers" in the documentation * thread: http://forum.kodi.tv/showthread.php?tid=257764 */ @@ -91,6 +95,11 @@ namespace JOYSTICK */ CDriverPrimitive(unsigned int axisIndex, int center, SEMIAXIS_DIRECTION direction, unsigned int range); + /*! + * \brief Construct a driver primitive representing a key on a keyboard + */ + CDriverPrimitive(XBMCKey keycode); + bool operator==(const CDriverPrimitive& rhs) const; bool operator<(const CDriverPrimitive& rhs) const; @@ -136,12 +145,18 @@ namespace JOYSTICK unsigned int Range() const { return m_range; } /*! + * \brief The keybord symbol (valid for keys) + */ + XBMCKey Keycode() const { return m_keycode; } + + /*! * \brief Test if an driver primitive is valid * * A driver primitive is valid if it has a known type and: * * 1) for hats, it is a cardinal direction * 2) for semi-axes, it is a positive or negative direction + * 3) for keys, the keycode is non-empty */ bool IsValid(void) const; @@ -152,6 +167,7 @@ namespace JOYSTICK int m_center = 0; SEMIAXIS_DIRECTION m_semiAxisDirection = SEMIAXIS_DIRECTION::ZERO; unsigned int m_range = 1; + XBMCKey m_keycode = XBMCK_UNKNOWN; }; } } diff --git a/xbmc/input/joysticks/JoystickTypes.h b/xbmc/input/joysticks/JoystickTypes.h index 6690a6b278..44f0214bc3 100644 --- a/xbmc/input/joysticks/JoystickTypes.h +++ b/xbmc/input/joysticks/JoystickTypes.h @@ -49,6 +49,7 @@ namespace JOYSTICK * 6) absolute pointer * 7) wheel * 8) throttle + * 9) keyboard key * * [*] All three driver primitives (buttons, hats and axes) have a state that * can be represented using a single scalar value. For this reason, @@ -65,6 +66,7 @@ namespace JOYSTICK ABSPOINTER, WHEEL, THROTTLE, + KEY, }; /*! @@ -174,6 +176,7 @@ namespace JOYSTICK HAT, // one of the four direction arrows on a D-pad SEMIAXIS, // the positive or negative half of an axis MOTOR, // a rumble motor + KEY // a keyboard key }; /*! diff --git a/xbmc/input/joysticks/generic/ButtonMapping.cpp b/xbmc/input/joysticks/generic/ButtonMapping.cpp index 90cb2a8caa..4c7c7c2194 100644 --- a/xbmc/input/joysticks/generic/ButtonMapping.cpp +++ b/xbmc/input/joysticks/generic/ButtonMapping.cpp @@ -245,6 +245,22 @@ void CAxisDetector::DetectType(float position) } } +// --- CKeyDetector --------------------------------------------------------- + +CKeyDetector::CKeyDetector(CButtonMapping* buttonMapping, XBMCKey keycode) : + CPrimitiveDetector(buttonMapping), + m_keycode(keycode) +{ +} + +bool CKeyDetector::OnMotion(bool bPressed) +{ + if (bPressed) + return MapPrimitive(CDriverPrimitive(m_keycode)); + + return false; +} + // --- CButtonMapping ---------------------------------------------------------- CButtonMapping::CButtonMapping(IButtonMapper* buttonMapper, IButtonMap* buttonMap, IKeymap* keymap) : @@ -321,6 +337,11 @@ void CButtonMapping::ProcessAxisMotions(void) m_frameCount++; } +bool CButtonMapping::OnKeyPress(const CKey& key) +{ + return GetKey(static_cast<XBMCKey>(key.GetKeycode())).OnMotion(true); +} + void CButtonMapping::SaveButtonMap() { m_buttonMap->SaveButtonMap(); @@ -434,6 +455,19 @@ CAxisDetector& CButtonMapping::GetAxis(unsigned int axisIndex, return itAxis->second; } +CKeyDetector& CButtonMapping::GetKey(XBMCKey keycode) +{ + auto itKey = m_keys.find(keycode); + + if (itKey == m_keys.end()) + { + m_keys.insert(std::make_pair(keycode, CKeyDetector(this, keycode))); + itKey = m_keys.find(keycode); + } + + return itKey->second; +} + void CButtonMapping::OnLateDiscovery(unsigned int axisIndex) { m_buttonMapper->OnLateAxis(m_buttonMap, axisIndex); diff --git a/xbmc/input/joysticks/generic/ButtonMapping.h b/xbmc/input/joysticks/generic/ButtonMapping.h index e5e31c8414..22f124271c 100644 --- a/xbmc/input/joysticks/generic/ButtonMapping.h +++ b/xbmc/input/joysticks/generic/ButtonMapping.h @@ -22,6 +22,7 @@ #include "input/joysticks/interfaces/IButtonMapCallback.h" #include "input/joysticks/interfaces/IDriverHandler.h" #include "input/joysticks/DriverPrimitive.h" +#include "input/keyboard/interfaces/IKeyboardDriverHandler.h" #include <map> #include <stdint.h> @@ -224,6 +225,29 @@ namespace JOYSTICK }; /*! + * \brief Detects when a keyboard key should be mapped + */ + class CKeyDetector : public CPrimitiveDetector + { + public: + CKeyDetector(CButtonMapping* buttonMapping, XBMCKey keycode); + + /*! + * \brief Key state has been updated + * + * \param bPressed The new state + * + * \return True if this press was handled, false if it should fall through + * to the next driver handler + */ + bool OnMotion(bool bPressed); + + private: + // Construction parameters + const XBMCKey m_keycode; + }; + + /*! * \ingroup joystick * \brief Generic implementation of a class that provides button mapping by * translating driver events to button mapping commands @@ -235,6 +259,7 @@ namespace JOYSTICK * activation. */ class CButtonMapping : public IDriverHandler, + public KEYBOARD::IKeyboardDriverHandler, public IButtonMapCallback { public: @@ -254,6 +279,10 @@ namespace JOYSTICK virtual bool OnAxisMotion(unsigned int axisIndex, float position, int center, unsigned int range) override; virtual void ProcessAxisMotions(void) override; + // implementation of IKeyboardDriverHandler + bool OnKeyPress(const CKey& key) override; + void OnKeyRelease(const CKey& key) override { } + // implementation of IButtonMapCallback virtual void SaveButtonMap() override; virtual void ResetIgnoredPrimitives() override; @@ -280,6 +309,7 @@ namespace JOYSTICK CButtonDetector& GetButton(unsigned int buttonIndex); CHatDetector& GetHat(unsigned int hatIndex); CAxisDetector& GetAxis(unsigned int axisIndex, float position, const AxisConfiguration& initialConfig = AxisConfiguration()); + CKeyDetector& GetKey(XBMCKey keycode); // Construction parameters IButtonMapper* const m_buttonMapper; @@ -289,6 +319,7 @@ namespace JOYSTICK std::map<unsigned int, CButtonDetector> m_buttons; std::map<unsigned int, CHatDetector> m_hats; std::map<unsigned int, CAxisDetector> m_axes; + std::map<XBMCKey, CKeyDetector> m_keys; unsigned int m_lastAction; uint64_t m_frameCount; }; diff --git a/xbmc/input/joysticks/interfaces/IButtonMap.h b/xbmc/input/joysticks/interfaces/IButtonMap.h index 941a3c2cfe..ed76f2835b 100644 --- a/xbmc/input/joysticks/interfaces/IButtonMap.h +++ b/xbmc/input/joysticks/interfaces/IButtonMap.h @@ -298,6 +298,34 @@ namespace JOYSTICK ) = 0; /*! + * \brief Get the driver primitive for a keyboard key + * + * \param feature Must be a key + * \param primitive The resolved driver primitive + * + * \return True if the feature resolved to a driver primitive, false if the + * feature didn't resolve or isn't a scalar feature + */ + virtual bool GetKey( + const FeatureName& feature, + CDriverPrimitive& primitive + ) = 0; + + /*! + * \brief Add or update a key + * + * \param feature Must be a key + * \param primitive The feature's driver primitive + * + * \return True if the feature was updated, false if the feature is + * unchanged or failure occurs + */ + virtual void AddKey( + const FeatureName& feature, + const CDriverPrimitive& primitive + ) = 0; + + /*! * \brief Set a list of driver primitives to be ignored * * This is necessary to prevent features from interfering with the button diff --git a/xbmc/input/joysticks/interfaces/IButtonMapper.h b/xbmc/input/joysticks/interfaces/IButtonMapper.h index c2f4549536..9eb3355fde 100644 --- a/xbmc/input/joysticks/interfaces/IButtonMapper.h +++ b/xbmc/input/joysticks/interfaces/IButtonMapper.h @@ -63,22 +63,6 @@ namespace JOYSTICK virtual bool NeedsCooldown(void) const = 0; /*! - * \brief Test if the mapping process is being performed for an emulated controller - * - * \return true if an emulated controller is being mapped, false otherwise - */ - virtual bool Emulation(void) const = 0; - - /*! - * \brief Get the number of the emulated controller being mapped - * - * \return The number, or 0 if an emulated controller is not being mapped - * - * \remark Emulated controllers are 1-indexed - */ - virtual unsigned int ControllerNumber(void) const = 0; - - /*! * \brief Handle button/hat press or axis threshold * * \param buttonMap The button map being manipulated diff --git a/xbmc/input/keyboard/CMakeLists.txt b/xbmc/input/keyboard/CMakeLists.txt index 8cfa745ca7..14d48a802e 100644 --- a/xbmc/input/keyboard/CMakeLists.txt +++ b/xbmc/input/keyboard/CMakeLists.txt @@ -3,9 +3,11 @@ set(SOURCES KeyboardEasterEgg.cpp ) set(HEADERS interfaces/IActionMap.h - interfaces/IKeyboardHandler.h + interfaces/IKeyboardDriverHandler.h + interfaces/IKeyboardInputHandler.h interfaces/IKeyboardInputProvider.h KeyboardEasterEgg.h + KeyboardTypes.h KeymapActionMap.h ) diff --git a/xbmc/input/keyboard/KeyboardEasterEgg.h b/xbmc/input/keyboard/KeyboardEasterEgg.h index a624f1342a..f7852d8c6f 100644 --- a/xbmc/input/keyboard/KeyboardEasterEgg.h +++ b/xbmc/input/keyboard/KeyboardEasterEgg.h @@ -19,7 +19,7 @@ */ #pragma once -#include "input/keyboard/interfaces/IKeyboardHandler.h" +#include "input/keyboard/interfaces/IKeyboardDriverHandler.h" #include "input/XBMC_vkeys.h" #include <vector> @@ -31,13 +31,13 @@ namespace KEYBOARD /*! * \brief Hush!!! */ - class CKeyboardEasterEgg : public IKeyboardHandler + class CKeyboardEasterEgg : public IKeyboardDriverHandler { public: CKeyboardEasterEgg(void); ~CKeyboardEasterEgg() override = default; - // implementation of IKeyboardHandler + // implementation of IKeyboardDriverHandler bool OnKeyPress(const CKey& key) override; void OnKeyRelease(const CKey& key) override { } diff --git a/xbmc/input/keyboard/KeyboardTypes.h b/xbmc/input/keyboard/KeyboardTypes.h new file mode 100644 index 0000000000..b70cc06634 --- /dev/null +++ b/xbmc/input/keyboard/KeyboardTypes.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2017 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/Key.h" + +#include <string> + +namespace KODI +{ +namespace KEYBOARD +{ + /*! + * \brief Name of a hardware-indendent symbol representing a key + * + * Names are defined in the keyboard's controller profile. + */ + using KeyName = std::string; + + //! @todo Move CKey enum to this file + using Modifier = CKey::Modifier; +} +} diff --git a/xbmc/input/keyboard/generic/CMakeLists.txt b/xbmc/input/keyboard/generic/CMakeLists.txt index a5c9295aae..993a1f438c 100644 --- a/xbmc/input/keyboard/generic/CMakeLists.txt +++ b/xbmc/input/keyboard/generic/CMakeLists.txt @@ -1,5 +1,5 @@ -set(SOURCES JoystickEmulation.cpp) +set(SOURCES KeyboardInputHandling.cpp) -set(HEADERS JoystickEmulation.h) +set(HEADERS KeyboardInputHandling.h) core_add_library(input_keyboard_generic) diff --git a/xbmc/input/keyboard/generic/JoystickEmulation.cpp b/xbmc/input/keyboard/generic/JoystickEmulation.cpp deleted file mode 100644 index b4eb0c9502..0000000000 --- a/xbmc/input/keyboard/generic/JoystickEmulation.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2015-2017 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 "JoystickEmulation.h" -#include "input/joysticks/interfaces/IDriverHandler.h" -#include "input/Key.h" - -#include <algorithm> -#include <assert.h> - -#define BUTTON_INDEX_MASK 0x01ff - -using namespace KODI; -using namespace KEYBOARD; - -CJoystickEmulation::CJoystickEmulation(JOYSTICK::IDriverHandler* handler) : - m_handler(handler) -{ - assert(m_handler != nullptr); -} - -bool CJoystickEmulation::OnKeyPress(const CKey& key) -{ - bool bHandled = false; - - unsigned int buttonIndex = GetButtonIndex(key); - if (buttonIndex != 0) - bHandled = OnPress(buttonIndex); - - return bHandled; -} - -void CJoystickEmulation::OnKeyRelease(const CKey& key) -{ - unsigned int buttonIndex = GetButtonIndex(key); - if (buttonIndex != 0) - OnRelease(buttonIndex); -} - -bool CJoystickEmulation::OnPress(unsigned int buttonIndex) -{ - bool bHandled = false; - - KeyEvent event; - if (GetEvent(buttonIndex, event)) - { - bHandled = event.bHandled; - } - else - { - bHandled = m_handler->OnButtonMotion(buttonIndex, true); - m_pressedKeys.push_back({buttonIndex, bHandled}); - } - - return bHandled; -} - -void CJoystickEmulation::OnRelease(unsigned int buttonIndex) -{ - KeyEvent event; - if (GetEvent(buttonIndex, event)) - { - m_handler->OnButtonMotion(buttonIndex, false); - m_pressedKeys.erase(std::remove_if(m_pressedKeys.begin(), m_pressedKeys.end(), - [buttonIndex](const KeyEvent& event) - { - return buttonIndex == event.buttonIndex; - }), m_pressedKeys.end()); - } -} - -bool CJoystickEmulation::GetEvent(unsigned int buttonIndex, KeyEvent& event) const -{ - std::vector<KeyEvent>::const_iterator it = std::find_if(m_pressedKeys.begin(), m_pressedKeys.end(), - [buttonIndex](const KeyEvent& event) - { - return buttonIndex == event.buttonIndex; - }); - - if (it != m_pressedKeys.end()) - { - event = *it; - return true; - } - - return false; -} - -unsigned int CJoystickEmulation::GetButtonIndex(const CKey& key) -{ - return key.GetButtonCode() & BUTTON_INDEX_MASK; -} diff --git a/xbmc/input/keyboard/generic/JoystickEmulation.h b/xbmc/input/keyboard/generic/JoystickEmulation.h deleted file mode 100644 index 2d6b5290a7..0000000000 --- a/xbmc/input/keyboard/generic/JoystickEmulation.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2015-2017 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/keyboard/interfaces/IKeyboardHandler.h" - -#include <vector> - -namespace KODI -{ -namespace JOYSTICK -{ - class IDriverHandler; -} - -namespace KEYBOARD -{ - /*! - * \ingroup keyboard - * \brief Generic implementation of a handler for joysticks that use keyboard - * drivers. It basically emulates a joystick with many buttons. - */ - class CJoystickEmulation : public IKeyboardHandler - { - public: - explicit CJoystickEmulation(JOYSTICK::IDriverHandler* handler); - - ~CJoystickEmulation(void) override = default; - - // implementation of IKeyboardHandler - bool OnKeyPress(const CKey& key) override; - void OnKeyRelease(const CKey& key) override; - - private: - struct KeyEvent - { - unsigned int buttonIndex; - bool bHandled; - }; - - bool OnPress(unsigned int buttonIndex); - void OnRelease(unsigned int buttonIndex); - bool GetEvent(unsigned int buttonIndex, KeyEvent& event) const; - - static unsigned int GetButtonIndex(const CKey& key); - - JOYSTICK::IDriverHandler* const m_handler; - std::vector<KeyEvent> m_pressedKeys; - }; -} -} diff --git a/xbmc/input/keyboard/generic/KeyboardInputHandling.cpp b/xbmc/input/keyboard/generic/KeyboardInputHandling.cpp new file mode 100644 index 0000000000..859c473435 --- /dev/null +++ b/xbmc/input/keyboard/generic/KeyboardInputHandling.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2017 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 "KeyboardInputHandling.h" +#include "input/joysticks/interfaces/IButtonMap.h" +#include "input/joysticks/DriverPrimitive.h" +#include "input/keyboard/interfaces/IKeyboardInputHandler.h" +#include "input/XBMC_keysym.h" + +using namespace KODI; +using namespace KEYBOARD; + +CKeyboardInputHandling::CKeyboardInputHandling(IKeyboardInputHandler* handler, JOYSTICK::IButtonMap* buttonMap) : + m_handler(handler), + m_buttonMap(buttonMap) +{ +} + +bool CKeyboardInputHandling::OnKeyPress(const CKey& key) +{ + bool bHandled = false; + + JOYSTICK::CDriverPrimitive source(static_cast<XBMCKey>(key.GetKeycode())); + + KeyName keyName; + if (m_buttonMap->GetFeature(source, keyName)) + { + const Modifier mod = static_cast<Modifier>(key.GetModifiers() | key.GetLockingModifiers()); + bHandled = m_handler->OnKeyPress(keyName, mod, key.GetUnicode()); + } + + return bHandled; +} + +void CKeyboardInputHandling::OnKeyRelease(const CKey& key) +{ + JOYSTICK::CDriverPrimitive source(static_cast<XBMCKey>(key.GetKeycode())); + + KeyName keyName; + if (m_buttonMap->GetFeature(source, keyName)) + { + const Modifier mod = static_cast<Modifier>(key.GetModifiers() | key.GetLockingModifiers()); + m_handler->OnKeyRelease(keyName, mod, key.GetUnicode()); + } +} diff --git a/xbmc/input/keyboard/generic/KeyboardInputHandling.h b/xbmc/input/keyboard/generic/KeyboardInputHandling.h new file mode 100644 index 0000000000..73fd8d46d3 --- /dev/null +++ b/xbmc/input/keyboard/generic/KeyboardInputHandling.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 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/keyboard/interfaces/IKeyboardDriverHandler.h" + +namespace KODI +{ + namespace JOYSTICK + { + class IButtonMap; + } + + namespace KEYBOARD + { + class IKeyboardInputHandler; + + /*! + * \ingroup keyboard + * \brief Class to translate input from Kodi keycodes to key names defined + * by the keyboard's controller profile + */ + class CKeyboardInputHandling : public IKeyboardDriverHandler + { + public: + CKeyboardInputHandling(IKeyboardInputHandler* handler, JOYSTICK::IButtonMap* buttonMap); + + ~CKeyboardInputHandling(void) override = default; + + // implementation of IKeyboardDriverHandler + bool OnKeyPress(const CKey& key) override; + void OnKeyRelease(const CKey& key) override; + + private: + // Construction parameters + IKeyboardInputHandler* const m_handler; + JOYSTICK::IButtonMap* const m_buttonMap; + }; + } +} diff --git a/xbmc/input/keyboard/interfaces/IKeyboardHandler.h b/xbmc/input/keyboard/interfaces/IKeyboardDriverHandler.h index 64855a1f30..3359f42436 100644 --- a/xbmc/input/keyboard/interfaces/IKeyboardHandler.h +++ b/xbmc/input/keyboard/interfaces/IKeyboardDriverHandler.h @@ -29,24 +29,24 @@ namespace KEYBOARD * \ingroup keyboard * \brief Interface for handling keyboard events */ - class IKeyboardHandler + class IKeyboardDriverHandler { public: - virtual ~IKeyboardHandler() = default; + virtual ~IKeyboardDriverHandler() = default; /*! * \brief A key has been pressed * - * \param key The pressed key + * \param key The pressed key * - * \return True if the event was handled otherwise false + * \return True if the event was handled, false otherwise */ virtual bool OnKeyPress(const CKey& key) = 0; /*! * \brief A key has been released * - * \param key The released key + * \param key The released key */ virtual void OnKeyRelease(const CKey& key) = 0; }; diff --git a/xbmc/input/keyboard/interfaces/IKeyboardInputHandler.h b/xbmc/input/keyboard/interfaces/IKeyboardInputHandler.h new file mode 100644 index 0000000000..a26022a6a1 --- /dev/null +++ b/xbmc/input/keyboard/interfaces/IKeyboardInputHandler.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2017 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/keyboard/KeyboardTypes.h" + +#include <stdint.h> +#include <string> + +namespace KODI +{ +namespace KEYBOARD +{ + /*! + * \ingroup keyboard + * \brief Interface for handling input events for keyboards + * + * Input events are an abstraction over driver events. Keys are identified by + * the name defined in the keyboard's controller profile. + */ + class IKeyboardInputHandler + { + public: + virtual ~IKeyboardInputHandler() = default; + + /*! + * \brief The add-on ID of the keyboard's controller profile + * + * \return The ID of the controller profile add-on + */ + virtual std::string ControllerID() const = 0; + + /*! + * \brief Return true if the input handler accepts the given key + * + * \param key A key belonging to the controller specified by ControllerID() + * + * \return True if the key is used for input, false otherwise + */ + virtual bool HasKey(const KeyName &key) const = 0; + + /*! + * \brief A key has been pressed + * + * \param key A key belonging to the controller specified by ControllerID() + * \param mod A combination of modifiers + * \param unicode The unicode value associated with the key, or 0 if unknown + * + * \return True if the event was handled, false otherwise + */ + virtual bool OnKeyPress(const KeyName &key, Modifier mod, uint32_t unicode) = 0; + + /*! + * \brief A key has been released + * + * \param key A key belonging to the controller specified by ControllerID() + * \param mod A combination of modifiers + * \param unicode The unicode value associated with the key, or 0 if unknown + */ + virtual void OnKeyRelease(const KeyName &key, Modifier mod, uint32_t unicode) = 0; + }; +} +} diff --git a/xbmc/input/keyboard/interfaces/IKeyboardInputProvider.h b/xbmc/input/keyboard/interfaces/IKeyboardInputProvider.h index eeb7d8719f..c4f4ca95cc 100644 --- a/xbmc/input/keyboard/interfaces/IKeyboardInputProvider.h +++ b/xbmc/input/keyboard/interfaces/IKeyboardInputProvider.h @@ -23,11 +23,11 @@ namespace KODI { namespace KEYBOARD { - class IKeyboardHandler; + class IKeyboardInputHandler; /*! * \ingroup mouse - * \brief Interface for classes that can provide mouse input + * \brief Interface for classes that can provide keyboard input */ class IKeyboardInputProvider { @@ -38,15 +38,17 @@ namespace KEYBOARD * \brief Registers a handler to be called on keyboard input * * \param handler The handler to receive keyboard input provided by this class + * \param bPromiscuous True to observe all events without affecting the + * input's destination */ - virtual void RegisterKeyboardHandler(IKeyboardHandler* handler) = 0; + virtual void RegisterKeyboardHandler(IKeyboardInputHandler* handler, bool bPromiscuous) = 0; /*! * \brief Unregisters handler from keyboard input * * \param handler The handler that was receiving keyboard input */ - virtual void UnregisterKeyboardHandler(IKeyboardHandler* handler) = 0; + virtual void UnregisterKeyboardHandler(IKeyboardInputHandler* handler) = 0; }; } } diff --git a/xbmc/peripherals/PeripheralTypes.h b/xbmc/peripherals/PeripheralTypes.h index 3ad64c9b38..acde742d3e 100644 --- a/xbmc/peripherals/PeripheralTypes.h +++ b/xbmc/peripherals/PeripheralTypes.h @@ -62,6 +62,7 @@ namespace PERIPHERALS FEATURE_JOYSTICK, FEATURE_RUMBLE, FEATURE_POWER_OFF, + FEATURE_KEYBOARD, }; enum PeripheralType @@ -76,7 +77,7 @@ namespace PERIPHERALS PERIPHERAL_TUNER, PERIPHERAL_IMON, PERIPHERAL_JOYSTICK, - PERIPHERAL_JOYSTICK_EMULATION, + PERIPHERAL_KEYBOARD, }; class CPeripheral; @@ -137,8 +138,8 @@ namespace PERIPHERALS return "imon"; case PERIPHERAL_JOYSTICK: return "joystick"; - case PERIPHERAL_JOYSTICK_EMULATION: - return "joystickemulation"; + case PERIPHERAL_KEYBOARD: + return "keyboard"; default: return "unknown"; } @@ -167,8 +168,8 @@ namespace PERIPHERALS return PERIPHERAL_IMON; else if (strTypeLowerCase == "joystick") return PERIPHERAL_JOYSTICK; - else if (strTypeLowerCase == "joystickemulation") - return PERIPHERAL_JOYSTICK_EMULATION; + else if (strTypeLowerCase == "keyboard") + return PERIPHERAL_KEYBOARD; return PERIPHERAL_UNKNOWN; }; @@ -249,6 +250,8 @@ namespace PERIPHERALS return "rumble"; case FEATURE_POWER_OFF: return "poweroff"; + case FEATURE_KEYBOARD: + return "keyboard"; case FEATURE_UNKNOWN: default: return "unknown"; @@ -280,6 +283,8 @@ namespace PERIPHERALS return FEATURE_RUMBLE; else if (strTypeLowerCase == "poweroff") return FEATURE_POWER_OFF; + else if (strTypeLowerCase == "keyboard") + return FEATURE_KEYBOARD; return FEATURE_UNKNOWN; }; diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp index 8e6b3c194d..68b0f74cc1 100644 --- a/xbmc/peripherals/Peripherals.cpp +++ b/xbmc/peripherals/Peripherals.cpp @@ -39,7 +39,7 @@ #include "devices/PeripheralHID.h" #include "devices/PeripheralImon.h" #include "devices/PeripheralJoystick.h" -#include "devices/PeripheralJoystickEmulation.h" +#include "devices/PeripheralKeyboard.h" #include "devices/PeripheralNIC.h" #include "devices/PeripheralNyxboard.h" #include "devices/PeripheralTuner.h" @@ -354,8 +354,8 @@ void CPeripherals::CreatePeripheral(CPeripheralBus &bus, const PeripheralScanRes peripheral = PeripheralPtr(new CPeripheralJoystick(*this, mappedResult, &bus)); break; - case PERIPHERAL_JOYSTICK_EMULATION: - peripheral = PeripheralPtr(new CPeripheralJoystickEmulation(*this, mappedResult, &bus)); + case PERIPHERAL_KEYBOARD: + peripheral = PeripheralPtr(new CPeripheralKeyboard(*this, mappedResult, &bus)); break; default: @@ -387,10 +387,6 @@ void CPeripherals::OnDeviceAdded(const CPeripheralBus &bus, const CPeripheral &p if (!bus.IsInitialised()) bNotify = false; - // don't show a notification for emulated peripherals - if (peripheral.Type() == PERIPHERAL_JOYSTICK_EMULATION) //! @todo Change to peripheral.IsEmulated() - bNotify = false; - if (bNotify) CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(35005), peripheral.DeviceName()); #endif @@ -404,10 +400,6 @@ void CPeripherals::OnDeviceDeleted(const CPeripheralBus &bus, const CPeripheral #if 0 bool bNotify = true; - // don't show a notification for emulated peripherals - if (peripheral.Type() == PERIPHERAL_JOYSTICK_EMULATION) //! @todo Change to peripheral.IsEmulated() - bNotify = false; - if (bNotify) CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(35006), peripheral.DeviceName()); #endif @@ -877,27 +869,10 @@ void CPeripherals::RegisterJoystickButtonMapper(IButtonMapper* mapper) { PeripheralVector peripherals; GetPeripheralsWithFeature(peripherals, FEATURE_JOYSTICK); + GetPeripheralsWithFeature(peripherals, FEATURE_KEYBOARD); for (auto& peripheral : peripherals) - { - if (mapper->Emulation()) - { - if (peripheral->Type() != PERIPHERAL_JOYSTICK_EMULATION) - continue; - - unsigned int controllerNumber = std::static_pointer_cast<CPeripheralJoystickEmulation>(peripheral)->ControllerNumber(); - - if (mapper->ControllerNumber() != controllerNumber) - continue; - } - else - { - if (peripheral->Type() != PERIPHERAL_JOYSTICK) - continue; - } - peripheral->RegisterJoystickButtonMapper(mapper); - } } void CPeripherals::UnregisterJoystickButtonMapper(IButtonMapper* mapper) @@ -906,6 +881,7 @@ void CPeripherals::UnregisterJoystickButtonMapper(IButtonMapper* mapper) PeripheralVector peripherals; GetPeripheralsWithFeature(peripherals, FEATURE_JOYSTICK); + GetPeripheralsWithFeature(peripherals, FEATURE_KEYBOARD); for (auto& peripheral : peripherals) peripheral->UnregisterJoystickButtonMapper(mapper); diff --git a/xbmc/peripherals/addons/AddonButtonMap.cpp b/xbmc/peripherals/addons/AddonButtonMap.cpp index d5375d6243..f6cd1a8d36 100644 --- a/xbmc/peripherals/addons/AddonButtonMap.cpp +++ b/xbmc/peripherals/addons/AddonButtonMap.cpp @@ -420,6 +420,36 @@ void CAddonButtonMap::AddThrottle(const KODI::JOYSTICK::FeatureName& feature, Load(); } +bool CAddonButtonMap::GetKey(const FeatureName& feature, CDriverPrimitive& primitive) +{ + bool retVal(false); + + CSingleLock lock(m_mutex); + + FeatureMap::const_iterator it = m_features.find(feature); + if (it != m_features.end()) + { + const kodi::addon::JoystickFeature& addonFeature = it->second; + + if (addonFeature.Type() == JOYSTICK_FEATURE_TYPE_KEY) + { + primitive = CPeripheralAddonTranslator::TranslatePrimitive(addonFeature.Primitive(JOYSTICK_SCALAR_PRIMITIVE)); + retVal = true; + } + } + + return retVal; +} + +void CAddonButtonMap::AddKey(const FeatureName& feature, const CDriverPrimitive& primitive) +{ + kodi::addon::JoystickFeature scalar(feature, JOYSTICK_FEATURE_TYPE_KEY); + scalar.SetPrimitive(JOYSTICK_SCALAR_PRIMITIVE, CPeripheralAddonTranslator::TranslatePrimitive(primitive)); + + if (auto addon = m_addon.lock()) + addon->MapFeature(m_device, m_strControllerId, scalar); +} + void CAddonButtonMap::SetIgnoredPrimitives(const std::vector<JOYSTICK::CDriverPrimitive>& primitives) { if (auto addon = m_addon.lock()) @@ -478,6 +508,7 @@ CAddonButtonMap::DriverMap CAddonButtonMap::CreateLookupTable(const FeatureMap& switch (feature.Type()) { case JOYSTICK_FEATURE_TYPE_SCALAR: + case JOYSTICK_FEATURE_TYPE_KEY: { driverMap[CPeripheralAddonTranslator::TranslatePrimitive(feature.Primitive(JOYSTICK_SCALAR_PRIMITIVE))] = it->first; break; diff --git a/xbmc/peripherals/addons/AddonButtonMap.h b/xbmc/peripherals/addons/AddonButtonMap.h index 5eeb7c9177..628cb0d194 100644 --- a/xbmc/peripherals/addons/AddonButtonMap.h +++ b/xbmc/peripherals/addons/AddonButtonMap.h @@ -130,6 +130,16 @@ namespace PERIPHERALS const KODI::JOYSTICK::CDriverPrimitive& primitive ) override; + bool GetKey( + const KODI::JOYSTICK::FeatureName& feature, + KODI::JOYSTICK::CDriverPrimitive& primitive + ) override; + + void AddKey( + const KODI::JOYSTICK::FeatureName& feature, + const KODI::JOYSTICK::CDriverPrimitive& primitive + ) override; + void SetIgnoredPrimitives(const std::vector<KODI::JOYSTICK::CDriverPrimitive>& primitives) override; bool IsIgnored(const KODI::JOYSTICK::CDriverPrimitive& primitive) override; diff --git a/xbmc/peripherals/addons/AddonButtonMapping.cpp b/xbmc/peripherals/addons/AddonButtonMapping.cpp index d49408e88a..03e47efe7e 100644 --- a/xbmc/peripherals/addons/AddonButtonMapping.cpp +++ b/xbmc/peripherals/addons/AddonButtonMapping.cpp @@ -90,6 +90,20 @@ void CAddonButtonMapping::ProcessAxisMotions(void) m_buttonMapping->ProcessAxisMotions(); } +bool CAddonButtonMapping::OnKeyPress(const CKey& key) +{ + if (m_buttonMapping) + return m_buttonMapping->OnKeyPress(key); + + return false; +} + +void CAddonButtonMapping::OnKeyRelease(const CKey& key) +{ + if (m_buttonMapping) + m_buttonMapping->OnKeyRelease(key); +} + void CAddonButtonMapping::SaveButtonMap() { if (m_buttonMapping) diff --git a/xbmc/peripherals/addons/AddonButtonMapping.h b/xbmc/peripherals/addons/AddonButtonMapping.h index b8a84111a9..e19a174b19 100644 --- a/xbmc/peripherals/addons/AddonButtonMapping.h +++ b/xbmc/peripherals/addons/AddonButtonMapping.h @@ -21,6 +21,7 @@ #include "input/joysticks/interfaces/IButtonMapCallback.h" #include "input/joysticks/interfaces/IDriverHandler.h" +#include "input/keyboard/interfaces/IKeyboardDriverHandler.h" #include <memory> @@ -40,6 +41,7 @@ namespace PERIPHERALS class CPeripherals; class CAddonButtonMapping : public KODI::JOYSTICK::IDriverHandler, + public KODI::KEYBOARD::IKeyboardDriverHandler, public KODI::JOYSTICK::IButtonMapCallback { public: @@ -53,6 +55,10 @@ namespace PERIPHERALS bool OnAxisMotion(unsigned int axisIndex, float position, int center, unsigned int range) override; void ProcessAxisMotions(void) override; + // implementation of IKeyboardDriverHandler + bool OnKeyPress(const CKey& key) override; + void OnKeyRelease(const CKey& key) override; + // implementation of IButtonMapCallback void SaveButtonMap() override; void ResetIgnoredPrimitives() override; diff --git a/xbmc/peripherals/addons/AddonInputHandling.cpp b/xbmc/peripherals/addons/AddonInputHandling.cpp index ce0b4b3819..add2ebdaa7 100644 --- a/xbmc/peripherals/addons/AddonInputHandling.cpp +++ b/xbmc/peripherals/addons/AddonInputHandling.cpp @@ -23,6 +23,8 @@ #include "input/joysticks/generic/InputHandling.h" #include "input/joysticks/interfaces/IInputHandler.h" #include "input/joysticks/interfaces/IDriverReceiver.h" +#include "input/keyboard/generic/KeyboardInputHandling.h" +#include "input/keyboard/interfaces/IKeyboardInputHandler.h" #include "peripherals/addons/AddonButtonMap.h" #include "peripherals/devices/PeripheralJoystick.h" #include "peripherals/Peripherals.h" @@ -62,10 +64,33 @@ CAddonInputHandling::CAddonInputHandling(CPeripherals& manager, CPeripheral* per } } +CAddonInputHandling::CAddonInputHandling(CPeripherals& manager, CPeripheral* peripheral, KEYBOARD::IKeyboardInputHandler* handler) +{ + PeripheralAddonPtr addon = manager.GetAddonWithButtonMap(peripheral); + + if (!addon) + { + CLog::Log(LOGDEBUG, "Failed to locate add-on for \"%s\"", peripheral->DeviceName().c_str()); + } + else + { + m_buttonMap.reset(new CAddonButtonMap(peripheral, addon, handler->ControllerID())); + if (m_buttonMap->Load()) + { + m_keyboardHandler.reset(new KEYBOARD::CKeyboardInputHandling(handler, m_buttonMap.get())); + } + else + { + m_buttonMap.reset(); + } + } +} + CAddonInputHandling::~CAddonInputHandling(void) { m_driverHandler.reset(); m_inputReceiver.reset(); + m_keyboardHandler.reset(); m_buttonMap.reset(); } @@ -99,6 +124,20 @@ void CAddonInputHandling::ProcessAxisMotions(void) m_driverHandler->ProcessAxisMotions(); } +bool CAddonInputHandling::OnKeyPress(const CKey& key) +{ + if (m_keyboardHandler) + return m_keyboardHandler->OnKeyPress(key); + + return false; +} + +void CAddonInputHandling::OnKeyRelease(const CKey& key) +{ + if (m_keyboardHandler) + m_keyboardHandler->OnKeyRelease(key); +} + bool CAddonInputHandling::SetRumbleState(const JOYSTICK::FeatureName& feature, float magnitude) { if (m_inputReceiver) diff --git a/xbmc/peripherals/addons/AddonInputHandling.h b/xbmc/peripherals/addons/AddonInputHandling.h index ce23114aa4..3a3a87390c 100644 --- a/xbmc/peripherals/addons/AddonInputHandling.h +++ b/xbmc/peripherals/addons/AddonInputHandling.h @@ -21,6 +21,7 @@ #include "input/joysticks/interfaces/IDriverHandler.h" #include "input/joysticks/interfaces/IInputReceiver.h" +#include "input/keyboard/interfaces/IKeyboardDriverHandler.h" #include <memory> @@ -32,6 +33,11 @@ namespace JOYSTICK class IDriverReceiver; class IInputHandler; } + +namespace KEYBOARD +{ + class IKeyboardInputHandler; +} } namespace PERIPHERALS @@ -40,7 +46,8 @@ namespace PERIPHERALS class CPeripherals; class CAddonInputHandling : public KODI::JOYSTICK::IDriverHandler, - public KODI::JOYSTICK::IInputReceiver + public KODI::JOYSTICK::IInputReceiver, + public KODI::KEYBOARD::IKeyboardDriverHandler { public: CAddonInputHandling(CPeripherals& manager, @@ -48,6 +55,10 @@ namespace PERIPHERALS KODI::JOYSTICK::IInputHandler* handler, KODI::JOYSTICK::IDriverReceiver* receiver); + CAddonInputHandling(CPeripherals& manager, + CPeripheral* peripheral, + KODI::KEYBOARD::IKeyboardInputHandler* handler); + ~CAddonInputHandling(void) override; // implementation of IDriverHandler @@ -56,12 +67,17 @@ namespace PERIPHERALS bool OnAxisMotion(unsigned int axisIndex, float position, int center, unsigned int range) override; void ProcessAxisMotions(void) override; + // implementation of IKeyboardDriverHandler + bool OnKeyPress(const CKey& key) override; + void OnKeyRelease(const CKey& key) override; + // implementation of IInputReceiver bool SetRumbleState(const KODI::JOYSTICK::FeatureName& feature, float magnitude) override; private: std::unique_ptr<KODI::JOYSTICK::IDriverHandler> m_driverHandler; std::unique_ptr<KODI::JOYSTICK::IInputReceiver> m_inputReceiver; + std::unique_ptr<KODI::KEYBOARD::IKeyboardDriverHandler> m_keyboardHandler; std::unique_ptr<KODI::JOYSTICK::IButtonMap> m_buttonMap; }; } diff --git a/xbmc/peripherals/addons/PeripheralAddon.cpp b/xbmc/peripherals/addons/PeripheralAddon.cpp index 5808581a64..df90468cb1 100644 --- a/xbmc/peripherals/addons/PeripheralAddon.cpp +++ b/xbmc/peripherals/addons/PeripheralAddon.cpp @@ -35,7 +35,6 @@ #include "peripherals/Peripherals.h" #include "peripherals/bus/virtual/PeripheralBusAddon.h" #include "peripherals/devices/PeripheralJoystick.h" -#include "peripherals/devices/PeripheralJoystickEmulation.h" #include "settings/Settings.h" #include "threads/SingleLock.h" #include "utils/log.h" @@ -50,8 +49,8 @@ using namespace JOYSTICK; using namespace PERIPHERALS; using namespace XFILE; -#define JOYSTICK_EMULATION_BUTTON_MAP_NAME "Keyboard" -#define JOYSTICK_EMULATION_PROVIDER "application" +#define KEYBOARD_BUTTON_MAP_NAME "Keyboard" +#define KEYBOARD_PROVIDER "application" #ifndef SAFE_DELETE #define SAFE_DELETE(p) do { delete (p); (p) = NULL; } while (0) @@ -829,12 +828,10 @@ void CPeripheralAddon::GetJoystickInfo(const CPeripheral* device, kodi::addon::J joystickInfo.SetMotorCount(joystick->MotorCount()); joystickInfo.SetSupportsPowerOff(joystick->SupportsPowerOff()); } - else if (device->Type() == PERIPHERAL_JOYSTICK_EMULATION) + else if (device->Type() == PERIPHERAL_KEYBOARD) { - const CPeripheralJoystickEmulation* joystick = static_cast<const CPeripheralJoystickEmulation*>(device); - joystickInfo.SetName(GetDeviceName(PERIPHERAL_JOYSTICK_EMULATION)); // Override name with non-localized version - joystickInfo.SetProvider(GetProvider(PERIPHERAL_JOYSTICK_EMULATION)); - joystickInfo.SetIndex(joystick->ControllerNumber()); + joystickInfo.SetName(GetDeviceName(PERIPHERAL_KEYBOARD)); // Override name with non-localized version + joystickInfo.SetProvider(GetProvider(PERIPHERAL_KEYBOARD)); } } @@ -864,8 +861,8 @@ std::string CPeripheralAddon::GetDeviceName(PeripheralType type) { switch (type) { - case PERIPHERAL_JOYSTICK_EMULATION: - return JOYSTICK_EMULATION_BUTTON_MAP_NAME; + case PERIPHERAL_KEYBOARD: + return KEYBOARD_BUTTON_MAP_NAME; default: break; } @@ -877,8 +874,8 @@ std::string CPeripheralAddon::GetProvider(PeripheralType type) { switch (type) { - case PERIPHERAL_JOYSTICK_EMULATION: - return JOYSTICK_EMULATION_PROVIDER; + case PERIPHERAL_KEYBOARD: + return KEYBOARD_PROVIDER; default: break; } diff --git a/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp b/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp index 4af54d433b..5c0b659322 100644 --- a/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp +++ b/xbmc/peripherals/addons/PeripheralAddonTranslator.cpp @@ -19,6 +19,7 @@ */ #include "PeripheralAddonTranslator.h" +#include "games/controllers/ControllerTranslator.h" #include "input/joysticks/JoystickUtils.h" #include <algorithm> @@ -65,8 +66,6 @@ PeripheralType CPeripheralAddonTranslator::TranslateType(PERIPHERAL_TYPE type) { case PERIPHERAL_TYPE_JOYSTICK: return PERIPHERAL_JOYSTICK; - case PERIPHERAL_TYPE_KEYBOARD: - return PERIPHERAL_JOYSTICK_EMULATION; default: break; } @@ -79,8 +78,6 @@ PERIPHERAL_TYPE CPeripheralAddonTranslator::TranslateType(PeripheralType type) { case PERIPHERAL_JOYSTICK: return PERIPHERAL_TYPE_JOYSTICK; - case PERIPHERAL_JOYSTICK_EMULATION: - return PERIPHERAL_TYPE_KEYBOARD; default: break; } @@ -113,6 +110,12 @@ CDriverPrimitive CPeripheralAddonTranslator::TranslatePrimitive(const kodi::addo retVal = CDriverPrimitive(PRIMITIVE_TYPE::MOTOR, primitive.DriverIndex()); break; } + case JOYSTICK_DRIVER_PRIMITIVE_TYPE_KEY: + { + XBMCKey keycode = GAME::CControllerTranslator::TranslateKeysym(primitive.Keycode()); + retVal = CDriverPrimitive(keycode); + break; + } default: break; } @@ -146,6 +149,12 @@ kodi::addon::DriverPrimitive CPeripheralAddonTranslator::TranslatePrimitive(cons retVal = kodi::addon::DriverPrimitive::CreateMotor(primitive.Index()); break; } + case PRIMITIVE_TYPE::KEY: + { + std::string keysym = GAME::CControllerTranslator::TranslateKeycode(primitive.Keycode()); + retVal = kodi::addon::DriverPrimitive(keysym); + break; + } default: break; } @@ -251,6 +260,7 @@ JOYSTICK::FEATURE_TYPE CPeripheralAddonTranslator::TranslateFeatureType(JOYSTICK case JOYSTICK_FEATURE_TYPE_ABSPOINTER: return JOYSTICK::FEATURE_TYPE::ABSPOINTER; case JOYSTICK_FEATURE_TYPE_WHEEL: return JOYSTICK::FEATURE_TYPE::WHEEL; case JOYSTICK_FEATURE_TYPE_THROTTLE: return JOYSTICK::FEATURE_TYPE::THROTTLE; + case JOYSTICK_FEATURE_TYPE_KEY: return JOYSTICK::FEATURE_TYPE::KEY; default: break; } @@ -269,6 +279,7 @@ JOYSTICK_FEATURE_TYPE CPeripheralAddonTranslator::TranslateFeatureType(JOYSTICK: case JOYSTICK::FEATURE_TYPE::ABSPOINTER: return JOYSTICK_FEATURE_TYPE_ABSPOINTER; case JOYSTICK::FEATURE_TYPE::WHEEL: return JOYSTICK_FEATURE_TYPE_WHEEL; case JOYSTICK::FEATURE_TYPE::THROTTLE: return JOYSTICK_FEATURE_TYPE_THROTTLE; + case JOYSTICK::FEATURE_TYPE::KEY: return JOYSTICK_FEATURE_TYPE_KEY; default: break; } diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusApplication.cpp b/xbmc/peripherals/bus/virtual/PeripheralBusApplication.cpp index 942983f835..51e1df8835 100644 --- a/xbmc/peripherals/bus/virtual/PeripheralBusApplication.cpp +++ b/xbmc/peripherals/bus/virtual/PeripheralBusApplication.cpp @@ -41,17 +41,14 @@ void CPeripheralBusApplication::Initialise(void) bool CPeripheralBusApplication::PerformDeviceScan(PeripheralScanResults& results) { - const unsigned int controllerCount = CServiceBroker::GetSettings().GetInt(CSettings::SETTING_GAMES_KEYBOARD_PLAYERS); - - for (unsigned int i = 1; i <= controllerCount; i++) { PeripheralScanResult result(Type()); - result.m_type = PERIPHERAL_JOYSTICK_EMULATION; - result.m_strDeviceName = g_localizeStrings.Get(35165); // "Keyboard player" - result.m_strLocation = MakeLocation(i); + result.m_type = PERIPHERAL_KEYBOARD; + result.m_strDeviceName = g_localizeStrings.Get(35150); // "Keyboard" + result.m_strLocation = PeripheralTypeTranslator::TypeToString(PERIPHERAL_KEYBOARD); result.m_iVendorId = 0; result.m_iProductId = 0; - result.m_mappedType = PERIPHERAL_JOYSTICK_EMULATION; + result.m_mappedType = PERIPHERAL_KEYBOARD; result.m_mappedBusType = Type(); result.m_iSequence = 0; @@ -64,7 +61,7 @@ bool CPeripheralBusApplication::PerformDeviceScan(PeripheralScanResults& results void CPeripheralBusApplication::GetDirectory(const std::string &strPath, CFileItemList &items) const { - // Don't list emulated joysticks in the GUI + // Don't list virtual devices in the GUI } std::string CPeripheralBusApplication::MakeLocation(unsigned int controllerIndex) const diff --git a/xbmc/peripherals/devices/CMakeLists.txt b/xbmc/peripherals/devices/CMakeLists.txt index 5134f00351..bd967340b9 100644 --- a/xbmc/peripherals/devices/CMakeLists.txt +++ b/xbmc/peripherals/devices/CMakeLists.txt @@ -4,7 +4,7 @@ set(SOURCES Peripheral.cpp PeripheralHID.cpp PeripheralImon.cpp PeripheralJoystick.cpp - PeripheralJoystickEmulation.cpp + PeripheralKeyboard.cpp PeripheralNIC.cpp PeripheralNyxboard.cpp PeripheralTuner.cpp) @@ -15,7 +15,7 @@ set(HEADERS Peripheral.h PeripheralHID.h PeripheralImon.h PeripheralJoystick.h - PeripheralJoystickEmulation.h + PeripheralKeyboard.h PeripheralNIC.h PeripheralNyxboard.h PeripheralTuner.h) diff --git a/xbmc/peripherals/devices/Peripheral.cpp b/xbmc/peripherals/devices/Peripheral.cpp index f035131da1..9e0ca5c9e7 100644 --- a/xbmc/peripherals/devices/Peripheral.cpp +++ b/xbmc/peripherals/devices/Peripheral.cpp @@ -584,6 +584,27 @@ void CPeripheral::UnregisterInputHandler(IInputHandler* handler) } } +void CPeripheral::RegisterKeyboardHandler(KEYBOARD::IKeyboardInputHandler* handler, bool bPromiscuous) +{ + auto it = m_keyboardHandlers.find(handler); + if (it == m_keyboardHandlers.end()) + { + std::unique_ptr<CAddonInputHandling> addonInput(new CAddonInputHandling(m_manager, this, handler)); + RegisterKeyboardDriverHandler(addonInput.get(), bPromiscuous); + m_keyboardHandlers[handler] = std::move(addonInput); + } +} + +void CPeripheral::UnregisterKeyboardHandler(KEYBOARD::IKeyboardInputHandler* handler) +{ + auto it = m_keyboardHandlers.find(handler); + if (it != m_keyboardHandlers.end()) + { + UnregisterKeyboardDriverHandler(it->second.get()); + m_keyboardHandlers.erase(it); + } +} + void CPeripheral::RegisterJoystickButtonMapper(IButtonMapper* mapper) { auto it = m_buttonMappers.find(mapper); @@ -592,6 +613,7 @@ void CPeripheral::RegisterJoystickButtonMapper(IButtonMapper* mapper) std::unique_ptr<CAddonButtonMapping> addonMapping(new CAddonButtonMapping(m_manager, this, mapper)); RegisterJoystickDriverHandler(addonMapping.get(), false); + RegisterKeyboardDriverHandler(addonMapping.get(), false); m_buttonMappers[mapper] = std::move(addonMapping); } @@ -602,6 +624,7 @@ void CPeripheral::UnregisterJoystickButtonMapper(IButtonMapper* mapper) auto it = m_buttonMappers.find(mapper); if (it != m_buttonMappers.end()) { + UnregisterKeyboardDriverHandler(it->second.get()); UnregisterJoystickDriverHandler(it->second.get()); m_buttonMappers.erase(it); diff --git a/xbmc/peripherals/devices/Peripheral.h b/xbmc/peripherals/devices/Peripheral.h index bdad0d2dea..9dd5aaf562 100644 --- a/xbmc/peripherals/devices/Peripheral.h +++ b/xbmc/peripherals/devices/Peripheral.h @@ -25,6 +25,7 @@ #include <vector> #include "input/joysticks/interfaces/IInputProvider.h" +#include "input/keyboard/interfaces/IKeyboardInputProvider.h" #include "peripherals/PeripheralTypes.h" class TiXmlDocument; @@ -40,6 +41,11 @@ namespace JOYSTICK class IDriverReceiver; class IInputHandler; } + +namespace KEYBOARD +{ + class IKeyboardDriverHandler; +} } namespace PERIPHERALS @@ -56,7 +62,8 @@ namespace PERIPHERALS STATE_STANDBY } CecStateChange; - class CPeripheral : public KODI::JOYSTICK::IInputProvider + class CPeripheral : public KODI::JOYSTICK::IInputProvider, + public KODI::KEYBOARD::IKeyboardInputProvider { friend class CGUIDialogPeripheralSettings; @@ -202,10 +209,17 @@ namespace PERIPHERALS virtual void RegisterJoystickDriverHandler(KODI::JOYSTICK::IDriverHandler* handler, bool bPromiscuous) { } virtual void UnregisterJoystickDriverHandler(KODI::JOYSTICK::IDriverHandler* handler) { } + virtual void RegisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler, bool bPromiscuous) { } + virtual void UnregisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler) { } + // implementation of IInputProvider void RegisterInputHandler(KODI::JOYSTICK::IInputHandler* handler, bool bPromiscuous) override; void UnregisterInputHandler(KODI::JOYSTICK::IInputHandler* handler) override; + // implementation of IKeyboardInputProvider + void RegisterKeyboardHandler(KODI::KEYBOARD::IKeyboardInputHandler* handler, bool bPromiscuous) override; + void UnregisterKeyboardHandler(KODI::KEYBOARD::IKeyboardInputHandler* handler) override; + virtual void RegisterJoystickButtonMapper(KODI::JOYSTICK::IButtonMapper* mapper); virtual void UnregisterJoystickButtonMapper(KODI::JOYSTICK::IButtonMapper* mapper); @@ -238,6 +252,7 @@ namespace PERIPHERALS std::set<std::string> m_changedSettings; CPeripheralBus* m_bus; std::map<KODI::JOYSTICK::IInputHandler*, std::unique_ptr<KODI::JOYSTICK::IDriverHandler>> m_inputHandlers; + std::map<KODI::KEYBOARD::IKeyboardInputHandler*, std::unique_ptr<KODI::KEYBOARD::IKeyboardDriverHandler>> m_keyboardHandlers; std::map<KODI::JOYSTICK::IButtonMapper*, std::unique_ptr<CAddonButtonMapping>> m_buttonMappers; }; } diff --git a/xbmc/peripherals/devices/PeripheralJoystickEmulation.cpp b/xbmc/peripherals/devices/PeripheralJoystickEmulation.cpp deleted file mode 100644 index fa9080809d..0000000000 --- a/xbmc/peripherals/devices/PeripheralJoystickEmulation.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2015-2017 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 "PeripheralJoystickEmulation.h" -#include "input/keyboard/generic/JoystickEmulation.h" -#include "input/InputManager.h" -#include "peripherals/Peripherals.h" -#include "threads/SingleLock.h" - -#include <algorithm> -#include <sstream> - -using namespace KODI; -using namespace PERIPHERALS; - -CPeripheralJoystickEmulation::CPeripheralJoystickEmulation(CPeripherals& manager, const PeripheralScanResult& scanResult, CPeripheralBus* bus) : - CPeripheral(manager, scanResult, bus) -{ - m_features.push_back(FEATURE_JOYSTICK); -} - -CPeripheralJoystickEmulation::~CPeripheralJoystickEmulation(void) -{ - m_manager.GetInputManager().UnregisterKeyboardHandler(this); -} - -bool CPeripheralJoystickEmulation::InitialiseFeature(const PeripheralFeature feature) -{ - bool bSuccess = false; - - if (CPeripheral::InitialiseFeature(feature)) - { - if (feature == FEATURE_JOYSTICK) - { - m_manager.GetInputManager().RegisterKeyboardHandler(this); - } - bSuccess = true; - } - - return bSuccess; -} - -void CPeripheralJoystickEmulation::RegisterJoystickDriverHandler(JOYSTICK::IDriverHandler* handler, bool bPromiscuous) -{ - using namespace KEYBOARD; - - CSingleLock lock(m_mutex); - - KeyboardHandle handle{ handler, new CJoystickEmulation(handler), bPromiscuous }; - m_keyboardHandlers.insert(m_keyboardHandlers.begin(), std::move(handle)); -} - -void CPeripheralJoystickEmulation::UnregisterJoystickDriverHandler(JOYSTICK::IDriverHandler* handler) -{ - CSingleLock lock(m_mutex); - - KeyboardHandlers::iterator it = std::find_if(m_keyboardHandlers.begin(), m_keyboardHandlers.end(), - [handler](const KeyboardHandle &handle) - { - return handle.joystickHandler == handler; - }); - - if (it != m_keyboardHandlers.end()) - { - delete it->handler; - m_keyboardHandlers.erase(it); - } -} - -bool CPeripheralJoystickEmulation::OnKeyPress(const CKey& key) -{ - CSingleLock lock(m_mutex); - - bool bHandled = false; - - // Process promiscuous handlers - for (KeyboardHandlers::iterator it = m_keyboardHandlers.begin(); it != m_keyboardHandlers.end(); ++it) - { - if (it->bPromiscuous) - it->handler->OnKeyPress(key); - } - - // Process handlers until one is handled - for (KeyboardHandlers::iterator it = m_keyboardHandlers.begin(); it != m_keyboardHandlers.end(); ++it) - { - if (!it->bPromiscuous) - { - bHandled = it->handler->OnKeyPress(key); - if (bHandled) - break; - } - } - - return bHandled; -} - -void CPeripheralJoystickEmulation::OnKeyRelease(const CKey& key) -{ - CSingleLock lock(m_mutex); - - for (KeyboardHandlers::iterator it = m_keyboardHandlers.begin(); it != m_keyboardHandlers.end(); ++it) - it->handler->OnKeyRelease(key); -} - -unsigned int CPeripheralJoystickEmulation::ControllerNumber(void) const -{ - unsigned int number; - std::istringstream str(m_strLocation); - str >> number; - return number; -} diff --git a/xbmc/peripherals/devices/PeripheralKeyboard.cpp b/xbmc/peripherals/devices/PeripheralKeyboard.cpp new file mode 100644 index 0000000000..a50b53bc80 --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralKeyboard.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2017 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 "PeripheralKeyboard.h" +#include "input/InputManager.h" +#include "peripherals/Peripherals.h" +#include "threads/SingleLock.h" + +#include <sstream> + +using namespace KODI; +using namespace PERIPHERALS; + +CPeripheralKeyboard::CPeripheralKeyboard(CPeripherals& manager, const PeripheralScanResult& scanResult, CPeripheralBus* bus) : + CPeripheral(manager, scanResult, bus) +{ + // Initialize CPeripheral + m_features.push_back(FEATURE_KEYBOARD); +} + +CPeripheralKeyboard::~CPeripheralKeyboard(void) +{ + m_manager.GetInputManager().UnregisterKeyboardDriverHandler(this); +} + +bool CPeripheralKeyboard::InitialiseFeature(const PeripheralFeature feature) +{ + bool bSuccess = false; + + if (CPeripheral::InitialiseFeature(feature)) + { + switch (feature) + { + case FEATURE_KEYBOARD: + { + m_manager.GetInputManager().RegisterKeyboardDriverHandler(this); + break; + } + default: + break; + } + + bSuccess = true; + } + + return bSuccess; +} + +void CPeripheralKeyboard::RegisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler, bool bPromiscuous) +{ + CSingleLock lock(m_mutex); + + KeyboardHandle handle{ handler, bPromiscuous }; + m_keyboardHandlers.insert(m_keyboardHandlers.begin(), handle); +} + +void CPeripheralKeyboard::UnregisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler) +{ + CSingleLock lock(m_mutex); + + auto it = std::find_if(m_keyboardHandlers.begin(), m_keyboardHandlers.end(), + [handler](const KeyboardHandle &handle) + { + return handle.handler == handler; + }); + + if (it != m_keyboardHandlers.end()) + m_keyboardHandlers.erase(it); +} + +bool CPeripheralKeyboard::OnKeyPress(const CKey& key) +{ + CSingleLock lock(m_mutex); + + bool bHandled = false; + + // Process promiscuous handlers + for (const KeyboardHandle &handle : m_keyboardHandlers) + { + if (handle.bPromiscuous) + handle.handler->OnKeyPress(key); + } + + // Process handlers until one is handled + for (const KeyboardHandle &handle : m_keyboardHandlers) + { + if (!handle.bPromiscuous) + { + bHandled = handle.handler->OnKeyPress(key); + if (bHandled) + break; + } + } + + return bHandled; +} + +void CPeripheralKeyboard::OnKeyRelease(const CKey& key) +{ + CSingleLock lock(m_mutex); + + for (const KeyboardHandle &handle : m_keyboardHandlers) + handle.handler->OnKeyRelease(key); +} diff --git a/xbmc/peripherals/devices/PeripheralJoystickEmulation.h b/xbmc/peripherals/devices/PeripheralKeyboard.h index 0c2cb0a87d..64daf92a08 100644 --- a/xbmc/peripherals/devices/PeripheralJoystickEmulation.h +++ b/xbmc/peripherals/devices/PeripheralKeyboard.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2017 Team Kodi + * Copyright (C) 2017 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify @@ -20,46 +20,38 @@ #pragma once #include "Peripheral.h" -#include "input/keyboard/interfaces/IKeyboardHandler.h" +#include "input/keyboard/interfaces/IKeyboardDriverHandler.h" #include "threads/CriticalSection.h" #include <vector> namespace PERIPHERALS { - class CPeripheralJoystickEmulation : public CPeripheral, - public KODI::KEYBOARD::IKeyboardHandler + class CPeripheralKeyboard : public CPeripheral, + public KODI::KEYBOARD::IKeyboardDriverHandler { public: - CPeripheralJoystickEmulation(CPeripherals& manager, const PeripheralScanResult& scanResult, CPeripheralBus* bus); + CPeripheralKeyboard(CPeripherals& manager, const PeripheralScanResult& scanResult, CPeripheralBus* bus); - ~CPeripheralJoystickEmulation(void) override; + ~CPeripheralKeyboard(void) override; // implementation of CPeripheral bool InitialiseFeature(const PeripheralFeature feature) override; - void RegisterJoystickDriverHandler(KODI::JOYSTICK::IDriverHandler* handler, bool bPromiscuous) override; - void UnregisterJoystickDriverHandler(KODI::JOYSTICK::IDriverHandler* handler) override; + void RegisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler, bool bPromiscuous) override; + void UnregisterKeyboardDriverHandler(KODI::KEYBOARD::IKeyboardDriverHandler* handler) override; - // implementation of IKeyboardHandler + // implementation of IKeyboardDriverHandler bool OnKeyPress(const CKey& key) override; void OnKeyRelease(const CKey& key) override; - /*! - * \brief Number of the emulated controller (1-indexed) - */ - unsigned int ControllerNumber(void) const; - private: struct KeyboardHandle { - KODI::JOYSTICK::IDriverHandler* joystickHandler; - KODI::KEYBOARD::IKeyboardHandler* handler; + KODI::KEYBOARD::IKeyboardDriverHandler* handler; bool bPromiscuous; }; - using KeyboardHandlers = std::vector<KeyboardHandle>; - - KeyboardHandlers m_keyboardHandlers; + std::vector<KeyboardHandle> m_keyboardHandlers; CCriticalSection m_mutex; }; } diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index d9eb033c80..1a5669d79a 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -432,15 +432,6 @@ const std::string CSettings::SETTING_GENERAL_ADDONBROKENFILTER = "general.addonb const std::string CSettings::SETTING_SOURCE_VIDEOS = "source.videos"; const std::string CSettings::SETTING_SOURCE_MUSIC = "source.music"; const std::string CSettings::SETTING_SOURCE_PICTURES = "source.pictures"; -const std::string CSettings::SETTING_GAMES_KEYBOARD_PLAYERS = "gameskeyboard.keyboardplayers"; -const std::string CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_1 = "gameskeyboard.keyboardplayerconfig1"; -const std::string CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_2 = "gameskeyboard.keyboardplayerconfig2"; -const std::string CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_3 = "gameskeyboard.keyboardplayerconfig3"; -const std::string CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_4 = "gameskeyboard.keyboardplayerconfig4"; -const std::string CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_5 = "gameskeyboard.keyboardplayerconfig5"; -const std::string CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_6 = "gameskeyboard.keyboardplayerconfig6"; -const std::string CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_7 = "gameskeyboard.keyboardplayerconfig7"; -const std::string CSettings::SETTING_GAMES_KEYBOARD_PLAYERCONFIG_8 = "gameskeyboard.keyboardplayerconfig8"; const std::string CSettings::SETTING_GAMES_ENABLE = "gamesgeneral.enable"; const std::string CSettings::SETTING_GAMES_ENABLEREWIND = "gamesgeneral.enablerewind"; const std::string CSettings::SETTING_GAMES_REWINDTIME = "gamesgeneral.rewindtime"; diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h index 55f0a8030b..6e3674d49d 100644 --- a/xbmc/settings/Settings.h +++ b/xbmc/settings/Settings.h @@ -384,15 +384,6 @@ public: static const std::string SETTING_SOURCE_VIDEOS; static const std::string SETTING_SOURCE_MUSIC; static const std::string SETTING_SOURCE_PICTURES; - static const std::string SETTING_GAMES_KEYBOARD_PLAYERS; - static const std::string SETTING_GAMES_KEYBOARD_PLAYERCONFIG_1; - static const std::string SETTING_GAMES_KEYBOARD_PLAYERCONFIG_2; - static const std::string SETTING_GAMES_KEYBOARD_PLAYERCONFIG_3; - static const std::string SETTING_GAMES_KEYBOARD_PLAYERCONFIG_4; - static const std::string SETTING_GAMES_KEYBOARD_PLAYERCONFIG_5; - static const std::string SETTING_GAMES_KEYBOARD_PLAYERCONFIG_6; - static const std::string SETTING_GAMES_KEYBOARD_PLAYERCONFIG_7; - static const std::string SETTING_GAMES_KEYBOARD_PLAYERCONFIG_8; static const std::string SETTING_GAMES_ENABLE; static const std::string SETTING_GAMES_ENABLEREWIND; static const std::string SETTING_GAMES_REWINDTIME; |