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.
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"
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())
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
];
45 keymap
.reset(new CWindowKeymap(controllerId
));
47 const TiXmlElement
* pButton
= pDevice
->FirstChildElement();
48 while (pButton
!= nullptr)
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
))
58 unsigned int actionId
= ACTION_NONE
;
59 if (CActionTranslator::TranslateString(actionString
, actionId
))
61 JOYSTICK::KeymapAction action
= {
63 std::move(actionString
),
67 keymap
->MapAction(windowID
, JOYSTICK::CJoystickUtils::MakeKeyName(feature
, dir
),
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
);
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)
121 StringUtils::ToLower(feature
);
122 actionStr
= szAction
;
126 if (!feature
.empty() && !actionStr
.empty())
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
136 std::string strHoldTime
;
137 if (pButton
->QueryValueAttribute(JOYSTICK_XML_ATTR_HOLDTIME
, &strHoldTime
) == TIXML_SUCCESS
)
139 std::istringstream
ss(strHoldTime
);
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
));