aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Brown <themagnificentmrb@gmail.com>2018-02-02 21:42:52 -0800
committerGitHub <noreply@github.com>2018-02-02 21:42:52 -0800
commitb1d31b530a232c1cde3b3c144f3139998128a4ed (patch)
tree064f572e04e2c25bf08cba73045a9fac3f1ad572
parentf5f683e8c61c8a2e8918b15f8eb73a74093c84ac (diff)
parent915bc44f64e620275ce63daca021465eda4b3694 (diff)
Merge pull request #13374 from garbear/keyboard-mapping
Games: Keyboard remapping support
-rw-r--r--addons/resource.language.en_gb/resources/strings.po17
-rwxr-xr-xsystem/settings/settings.xml107
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h11
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h37
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h11
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h29
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h6
-rw-r--r--xbmc/games/GameServices.cpp5
-rw-r--r--xbmc/games/GameServices.h1
-rw-r--r--xbmc/games/GameSettings.cpp40
-rw-r--r--xbmc/games/GameSettings.h1
-rw-r--r--xbmc/games/addons/GameClient.cpp2
-rw-r--r--xbmc/games/addons/GameClientTranslator.cpp18
-rw-r--r--xbmc/games/addons/GameClientTranslator.h4
-rw-r--r--xbmc/games/addons/input/GameClientInput.cpp67
-rw-r--r--xbmc/games/addons/input/GameClientKeyboard.cpp79
-rw-r--r--xbmc/games/addons/input/GameClientKeyboard.h15
-rw-r--r--xbmc/games/controllers/ControllerDefinitions.h4
-rw-r--r--xbmc/games/controllers/ControllerFeature.cpp31
-rw-r--r--xbmc/games/controllers/ControllerFeature.h4
-rw-r--r--xbmc/games/controllers/ControllerIDs.h1
-rw-r--r--xbmc/games/controllers/ControllerManager.cpp5
-rw-r--r--xbmc/games/controllers/ControllerManager.h7
-rw-r--r--xbmc/games/controllers/ControllerTranslator.cpp297
-rw-r--r--xbmc/games/controllers/ControllerTranslator.h19
-rw-r--r--xbmc/games/controllers/dialogs/GUIDialogButtonCapture.h2
-rw-r--r--xbmc/games/controllers/guicontrols/CMakeLists.txt2
-rw-r--r--xbmc/games/controllers/guicontrols/GUIControlTypes.h1
-rw-r--r--xbmc/games/controllers/guicontrols/GUIFeatureFactory.cpp4
-rw-r--r--xbmc/games/controllers/guicontrols/GUIFeatureTranslator.cpp1
-rw-r--r--xbmc/games/controllers/guicontrols/GUISelectKeyButton.cpp99
-rw-r--r--xbmc/games/controllers/guicontrols/GUISelectKeyButton.h62
-rw-r--r--xbmc/games/controllers/windows/GUIConfigurationWizard.cpp86
-rw-r--r--xbmc/games/controllers/windows/GUIConfigurationWizard.h23
-rw-r--r--xbmc/games/controllers/windows/GUIControllerDefines.h2
-rw-r--r--xbmc/games/controllers/windows/GUIControllerWindow.cpp8
-rw-r--r--xbmc/games/controllers/windows/GUIControllerWindow.h1
-rw-r--r--xbmc/games/controllers/windows/GUIFeatureList.cpp78
-rw-r--r--xbmc/games/controllers/windows/GUIFeatureList.h9
-rw-r--r--xbmc/games/controllers/windows/IConfigurationWindow.h32
-rw-r--r--xbmc/games/ports/PortManager.cpp10
-rw-r--r--xbmc/input/CMakeLists.txt4
-rw-r--r--xbmc/input/InputManager.cpp18
-rw-r--r--xbmc/input/InputManager.h13
-rw-r--r--xbmc/input/joysticks/DriverPrimitive.cpp19
-rw-r--r--xbmc/input/joysticks/DriverPrimitive.h16
-rw-r--r--xbmc/input/joysticks/JoystickTypes.h3
-rw-r--r--xbmc/input/joysticks/generic/ButtonMapping.cpp34
-rw-r--r--xbmc/input/joysticks/generic/ButtonMapping.h31
-rw-r--r--xbmc/input/joysticks/interfaces/IButtonMap.h28
-rw-r--r--xbmc/input/joysticks/interfaces/IButtonMapper.h16
-rw-r--r--xbmc/input/keyboard/CMakeLists.txt4
-rw-r--r--xbmc/input/keyboard/KeyboardEasterEgg.h6
-rw-r--r--xbmc/input/keyboard/KeyboardTypes.h40
-rw-r--r--xbmc/input/keyboard/generic/CMakeLists.txt4
-rw-r--r--xbmc/input/keyboard/generic/JoystickEmulation.cpp109
-rw-r--r--xbmc/input/keyboard/generic/JoystickEmulation.h68
-rw-r--r--xbmc/input/keyboard/generic/KeyboardInputHandling.cpp62
-rw-r--r--xbmc/input/keyboard/generic/KeyboardInputHandling.h57
-rw-r--r--xbmc/input/keyboard/interfaces/IKeyboardDriverHandler.h (renamed from xbmc/input/keyboard/interfaces/IKeyboardHandler.h)10
-rw-r--r--xbmc/input/keyboard/interfaces/IKeyboardInputHandler.h80
-rw-r--r--xbmc/input/keyboard/interfaces/IKeyboardInputProvider.h10
-rw-r--r--xbmc/peripherals/PeripheralTypes.h15
-rw-r--r--xbmc/peripherals/Peripherals.cpp34
-rw-r--r--xbmc/peripherals/addons/AddonButtonMap.cpp31
-rw-r--r--xbmc/peripherals/addons/AddonButtonMap.h10
-rw-r--r--xbmc/peripherals/addons/AddonButtonMapping.cpp14
-rw-r--r--xbmc/peripherals/addons/AddonButtonMapping.h6
-rw-r--r--xbmc/peripherals/addons/AddonInputHandling.cpp39
-rw-r--r--xbmc/peripherals/addons/AddonInputHandling.h18
-rw-r--r--xbmc/peripherals/addons/PeripheralAddon.cpp21
-rw-r--r--xbmc/peripherals/addons/PeripheralAddonTranslator.cpp19
-rw-r--r--xbmc/peripherals/bus/virtual/PeripheralBusApplication.cpp13
-rw-r--r--xbmc/peripherals/devices/CMakeLists.txt4
-rw-r--r--xbmc/peripherals/devices/Peripheral.cpp23
-rw-r--r--xbmc/peripherals/devices/Peripheral.h17
-rw-r--r--xbmc/peripherals/devices/PeripheralJoystickEmulation.cpp128
-rw-r--r--xbmc/peripherals/devices/PeripheralKeyboard.cpp121
-rw-r--r--xbmc/peripherals/devices/PeripheralKeyboard.h (renamed from xbmc/peripherals/devices/PeripheralJoystickEmulation.h)30
-rw-r--r--xbmc/settings/Settings.cpp9
-rw-r--r--xbmc/settings/Settings.h9
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 &params,
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;