Merge pull request #24470 from fuzzard/release_20.3
[xbmc.git] / xbmc / input / JoystickMapper.cpp
blob233238dbd3de3a142304f6688d5f8d921c788ec2
1 /*
2 * Copyright (C) 2017-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "JoystickMapper.h"
11 #include "input/WindowKeymap.h"
12 #include "input/actions/ActionIDs.h"
13 #include "input/actions/ActionTranslator.h"
14 #include "input/joysticks/JoystickTranslator.h"
15 #include "input/joysticks/JoystickUtils.h"
16 #include "utils/StringUtils.h"
17 #include "utils/XBMCTinyXML.h"
19 #include <algorithm>
20 #include <sstream>
21 #include <utility>
23 using namespace KODI;
25 #define JOYSTICK_XML_NODE_PROFILE "profile"
26 #define JOYSTICK_XML_ATTR_DIRECTION "direction"
27 #define JOYSTICK_XML_ATTR_HOLDTIME "holdtime"
28 #define JOYSTICK_XML_ATTR_HOTKEY "hotkey"
30 void CJoystickMapper::MapActions(int windowID, const TiXmlNode* pDevice)
32 std::string controllerId;
33 DeserializeJoystickNode(pDevice, controllerId);
34 if (controllerId.empty())
35 return;
37 // Update Controller IDs
38 if (std::find(m_controllerIds.begin(), m_controllerIds.end(), controllerId) ==
39 m_controllerIds.end())
40 m_controllerIds.emplace_back(controllerId);
42 // Create/overwrite keymap
43 auto& keymap = m_joystickKeymaps[controllerId];
44 if (!keymap)
45 keymap.reset(new CWindowKeymap(controllerId));
47 const TiXmlElement* pButton = pDevice->FirstChildElement();
48 while (pButton != nullptr)
50 std::string feature;
51 JOYSTICK::ANALOG_STICK_DIRECTION dir;
52 unsigned int holdtimeMs;
53 std::set<std::string> hotkeys;
54 std::string actionString;
55 if (DeserializeButton(pButton, feature, dir, holdtimeMs, hotkeys, actionString))
57 // Update keymap
58 unsigned int actionId = ACTION_NONE;
59 if (CActionTranslator::TranslateString(actionString, actionId))
61 JOYSTICK::KeymapAction action = {
62 actionId,
63 std::move(actionString),
64 holdtimeMs,
65 std::move(hotkeys),
67 keymap->MapAction(windowID, JOYSTICK::CJoystickUtils::MakeKeyName(feature, dir),
68 std::move(action));
71 pButton = pButton->NextSiblingElement();
75 void CJoystickMapper::Clear()
77 m_joystickKeymaps.clear();
78 m_controllerIds.clear();
81 std::vector<std::shared_ptr<const IWindowKeymap>> CJoystickMapper::GetJoystickKeymaps() const
83 std::vector<std::shared_ptr<const IWindowKeymap>> keymaps;
85 for (const auto& controllerId : m_controllerIds)
87 auto it = m_joystickKeymaps.find(controllerId);
88 if (it != m_joystickKeymaps.end())
89 keymaps.emplace_back(it->second);
92 return keymaps;
95 void CJoystickMapper::DeserializeJoystickNode(const TiXmlNode* pDevice, std::string& controllerId)
97 const TiXmlElement* deviceElem = pDevice->ToElement();
98 if (deviceElem != nullptr)
99 deviceElem->QueryValueAttribute(JOYSTICK_XML_NODE_PROFILE, &controllerId);
102 bool CJoystickMapper::DeserializeButton(const TiXmlElement* pButton,
103 std::string& feature,
104 JOYSTICK::ANALOG_STICK_DIRECTION& dir,
105 unsigned int& holdtimeMs,
106 std::set<std::string>& hotkeys,
107 std::string& actionStr)
109 const char* szButton = pButton->Value();
110 if (szButton != nullptr)
112 const char* szAction = nullptr;
114 const TiXmlNode* actionNode = pButton->FirstChild();
115 if (actionNode != nullptr)
116 szAction = actionNode->Value();
118 if (szAction != nullptr)
120 feature = szButton;
121 StringUtils::ToLower(feature);
122 actionStr = szAction;
126 if (!feature.empty() && !actionStr.empty())
128 // Handle direction
129 dir = JOYSTICK::ANALOG_STICK_DIRECTION::NONE;
130 const char* szDirection = pButton->Attribute(JOYSTICK_XML_ATTR_DIRECTION);
131 if (szDirection != nullptr)
132 dir = JOYSTICK::CJoystickTranslator::TranslateAnalogStickDirection(szDirection);
134 // Process holdtime parameter
135 holdtimeMs = 0;
136 std::string strHoldTime;
137 if (pButton->QueryValueAttribute(JOYSTICK_XML_ATTR_HOLDTIME, &strHoldTime) == TIXML_SUCCESS)
139 std::istringstream ss(strHoldTime);
140 ss >> holdtimeMs;
143 // Process hotkeys
144 hotkeys.clear();
145 std::string strHotkeys;
146 if (pButton->QueryValueAttribute(JOYSTICK_XML_ATTR_HOTKEY, &strHotkeys) == TIXML_SUCCESS)
148 std::vector<std::string> vecHotkeys = StringUtils::Split(strHotkeys, ",");
149 for (auto& hotkey : vecHotkeys)
150 hotkeys.insert(std::move(hotkey));
153 return true;
156 return false;