summaryrefslogtreecommitdiffstats
path: root/xbmc/input/JoystickMapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/input/JoystickMapper.cpp')
-rw-r--r--xbmc/input/JoystickMapper.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/xbmc/input/JoystickMapper.cpp b/xbmc/input/JoystickMapper.cpp
new file mode 100644
index 0000000..233238d
--- /dev/null
+++ b/xbmc/input/JoystickMapper.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2017-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "JoystickMapper.h"
+
+#include "input/WindowKeymap.h"
+#include "input/actions/ActionIDs.h"
+#include "input/actions/ActionTranslator.h"
+#include "input/joysticks/JoystickTranslator.h"
+#include "input/joysticks/JoystickUtils.h"
+#include "utils/StringUtils.h"
+#include "utils/XBMCTinyXML.h"
+
+#include <algorithm>
+#include <sstream>
+#include <utility>
+
+using namespace KODI;
+
+#define JOYSTICK_XML_NODE_PROFILE "profile"
+#define JOYSTICK_XML_ATTR_DIRECTION "direction"
+#define JOYSTICK_XML_ATTR_HOLDTIME "holdtime"
+#define JOYSTICK_XML_ATTR_HOTKEY "hotkey"
+
+void CJoystickMapper::MapActions(int windowID, const TiXmlNode* pDevice)
+{
+ std::string controllerId;
+ DeserializeJoystickNode(pDevice, controllerId);
+ if (controllerId.empty())
+ return;
+
+ // Update Controller IDs
+ if (std::find(m_controllerIds.begin(), m_controllerIds.end(), controllerId) ==
+ m_controllerIds.end())
+ m_controllerIds.emplace_back(controllerId);
+
+ // Create/overwrite keymap
+ auto& keymap = m_joystickKeymaps[controllerId];
+ if (!keymap)
+ keymap.reset(new CWindowKeymap(controllerId));
+
+ const TiXmlElement* pButton = pDevice->FirstChildElement();
+ while (pButton != nullptr)
+ {
+ std::string feature;
+ JOYSTICK::ANALOG_STICK_DIRECTION dir;
+ unsigned int holdtimeMs;
+ std::set<std::string> hotkeys;
+ std::string actionString;
+ if (DeserializeButton(pButton, feature, dir, holdtimeMs, hotkeys, actionString))
+ {
+ // Update keymap
+ unsigned int actionId = ACTION_NONE;
+ if (CActionTranslator::TranslateString(actionString, actionId))
+ {
+ JOYSTICK::KeymapAction action = {
+ actionId,
+ std::move(actionString),
+ holdtimeMs,
+ std::move(hotkeys),
+ };
+ keymap->MapAction(windowID, JOYSTICK::CJoystickUtils::MakeKeyName(feature, dir),
+ std::move(action));
+ }
+ }
+ pButton = pButton->NextSiblingElement();
+ }
+}
+
+void CJoystickMapper::Clear()
+{
+ m_joystickKeymaps.clear();
+ m_controllerIds.clear();
+}
+
+std::vector<std::shared_ptr<const IWindowKeymap>> CJoystickMapper::GetJoystickKeymaps() const
+{
+ std::vector<std::shared_ptr<const IWindowKeymap>> keymaps;
+
+ for (const auto& controllerId : m_controllerIds)
+ {
+ auto it = m_joystickKeymaps.find(controllerId);
+ if (it != m_joystickKeymaps.end())
+ keymaps.emplace_back(it->second);
+ }
+
+ return keymaps;
+}
+
+void CJoystickMapper::DeserializeJoystickNode(const TiXmlNode* pDevice, std::string& controllerId)
+{
+ const TiXmlElement* deviceElem = pDevice->ToElement();
+ if (deviceElem != nullptr)
+ deviceElem->QueryValueAttribute(JOYSTICK_XML_NODE_PROFILE, &controllerId);
+}
+
+bool CJoystickMapper::DeserializeButton(const TiXmlElement* pButton,
+ std::string& feature,
+ JOYSTICK::ANALOG_STICK_DIRECTION& dir,
+ unsigned int& holdtimeMs,
+ std::set<std::string>& hotkeys,
+ std::string& actionStr)
+{
+ const char* szButton = pButton->Value();
+ if (szButton != nullptr)
+ {
+ const char* szAction = nullptr;
+
+ const TiXmlNode* actionNode = pButton->FirstChild();
+ if (actionNode != nullptr)
+ szAction = actionNode->Value();
+
+ if (szAction != nullptr)
+ {
+ feature = szButton;
+ StringUtils::ToLower(feature);
+ actionStr = szAction;
+ }
+ }
+
+ if (!feature.empty() && !actionStr.empty())
+ {
+ // Handle direction
+ dir = JOYSTICK::ANALOG_STICK_DIRECTION::NONE;
+ const char* szDirection = pButton->Attribute(JOYSTICK_XML_ATTR_DIRECTION);
+ if (szDirection != nullptr)
+ dir = JOYSTICK::CJoystickTranslator::TranslateAnalogStickDirection(szDirection);
+
+ // Process holdtime parameter
+ holdtimeMs = 0;
+ std::string strHoldTime;
+ if (pButton->QueryValueAttribute(JOYSTICK_XML_ATTR_HOLDTIME, &strHoldTime) == TIXML_SUCCESS)
+ {
+ std::istringstream ss(strHoldTime);
+ ss >> holdtimeMs;
+ }
+
+ // Process hotkeys
+ hotkeys.clear();
+ std::string strHotkeys;
+ if (pButton->QueryValueAttribute(JOYSTICK_XML_ATTR_HOTKEY, &strHotkeys) == TIXML_SUCCESS)
+ {
+ std::vector<std::string> vecHotkeys = StringUtils::Split(strHotkeys, ",");
+ for (auto& hotkey : vecHotkeys)
+ hotkeys.insert(std::move(hotkey));
+ }
+
+ return true;
+ }
+
+ return false;
+}