From 057a1b53f88d3da4ef3f680379365fa7a261d213 Mon Sep 17 00:00:00 2001 From: Frank Razenberg Date: Mon, 9 Feb 2015 22:20:43 +0100 Subject: [PATCH 1/4] [buttontranslator] Group joystick keymaps by family --- xbmc/input/ButtonTranslator.cpp | 165 ++++++++++++++++++++++---------- xbmc/input/ButtonTranslator.h | 19 ++-- 2 files changed, 129 insertions(+), 55 deletions(-) diff --git a/xbmc/input/ButtonTranslator.cpp b/xbmc/input/ButtonTranslator.cpp index 22f07576ab984..cbaee9f541a4a 100644 --- a/xbmc/input/ButtonTranslator.cpp +++ b/xbmc/input/ButtonTranslator.cpp @@ -652,7 +652,9 @@ bool CButtonTranslator::LoadKeymap(const std::string &keymapPath) const char *szWindow = pWindow->Value(); if (szWindow) { - if (strcmpi(szWindow, "global") == 0) + if (strcmpi(szWindow, "joystickFamily") == 0) + MapJoystickFamily(pWindow); + else if (strcmpi(szWindow, "global") == 0) windowID = -1; else windowID = TranslateWindow(szWindow); @@ -760,29 +762,84 @@ int CButtonTranslator::TranslateLircRemoteString(const char* szDevice, const cha } #if defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER) +void CButtonTranslator::MapJoystickFamily(TiXmlNode *pNode) +{ + TiXmlElement *pFamily = pNode->ToElement(); + if (pFamily && pFamily->Attribute("name")) + { + std::string joyFamilyName = pFamily->Attribute("name"); + JoystickFamily* joyFamily = &m_joystickFamilies[joyFamilyName]; + + TiXmlElement *pMember = pFamily->FirstChildElement(); + while (pMember) + { + TiXmlNode* pName = pMember->FirstChild(); + if (pName && pName->ValueStr() != "") { + boost::shared_ptr re(new CRegExp(true, CRegExp::asciiOnly)); + std::string joyRe = JoynameToRegex(pName->ValueStr()); + if (!re->RegComp(joyRe, CRegExp::StudyRegExp)) + { + CLog::Log(LOGNOTICE, "Invalid joystick regex specified: '%s'", pName->Value()); + continue; + } + AddFamilyRegex(joyFamily, re); + } + pMember = pMember->NextSiblingElement(); + } + } + else + { + CLog::Log(LOGNOTICE, "Ignoring nameless joystick family"); + } +} + void CButtonTranslator::MapJoystickActions(int windowID, TiXmlNode *pJoystick) { string joyname = JOYSTICK_DEFAULT_MAP; // default global map name - vector > joynames; + std::string joyFamilyName; map buttonMap; map axisMap; AxesConfig axesConfig; ActionMap hatMap; TiXmlElement *pJoy = pJoystick->ToElement(); - if (pJoy && pJoy->Attribute("name")) - joyname = pJoy->Attribute("name"); + if (pJoy && pJoy->Attribute("name")) { + // transform loose name to new family, including altnames + std::string joyName = pJoy->Attribute("name"); + joyFamilyName = joyName; + JoystickFamily* joyFamily = &m_joystickFamilies[joyFamilyName]; + + boost::shared_ptr re(new CRegExp(true, CRegExp::asciiOnly)); + std::string joyRe = JoynameToRegex(joyname); + if (!re->RegComp(joyRe, CRegExp::StudyRegExp)) + { + CLog::Log(LOGNOTICE, "Invalid joystick regex specified: '%s'", joyname.c_str()); + return; + } + AddFamilyRegex(joyFamily, re); + + // add altnames to family + TiXmlElement *pNode = pJoystick->FirstChildElement(); + while (pNode) { + const std::string &type = pNode->ValueStr(); + if (type == "altname") { + std::string altName = pNode->FirstChild()->ValueStr(); + boost::shared_ptr altRe(new CRegExp(true, CRegExp::asciiOnly)); + std::string altReStr = JoynameToRegex(altName); + if (!altRe->RegComp(altReStr, CRegExp::StudyRegExp)) + CLog::Log(LOGNOTICE, "Ignoring invalid joystick altname regex: '%s'", altReStr.c_str()); + else + AddFamilyRegex(joyFamily, altRe); + } + pNode = pNode->NextSiblingElement(); + } + + } + else if (pJoy && pJoy->Attribute("family")) + joyFamilyName = pJoy->Attribute("family"); else CLog::Log(LOGNOTICE, "No Joystick name specified, loading default map"); - boost::shared_ptr re(new CRegExp(true, CRegExp::asciiOnly)); - if (!re->RegComp(JoynameToRegex(joyname), CRegExp::StudyRegExp)) - { - CLog::Log(LOGNOTICE, "Invalid joystick regex specified: '%s'", joyname.c_str()); - return; - } - else - joynames.push_back(re); // parse map TiXmlElement *pButton = pJoystick->FirstChildElement(); @@ -856,30 +913,16 @@ void CButtonTranslator::MapJoystickActions(int windowID, TiXmlNode *pJoystick) else CLog::Log(LOGERROR, "Error reading joystick map element, unknown button type: %s", type.c_str()); } - else if (type == "altname") - { - boost::shared_ptr altRe(new CRegExp(true, CRegExp::asciiOnly)); - if (!altRe->RegComp(JoynameToRegex(action), CRegExp::StudyRegExp)) - CLog::Log(LOGNOTICE, "Ignoring invalid joystick altname regex: '%s'", action.c_str()); - else - joynames.push_back(altRe); - } else CLog::Log(LOGERROR, "Error reading joystick map element, Invalid id: %d", id); pButton = pButton->NextSiblingElement(); } - vector >::iterator it = joynames.begin(); - while (it!=joynames.end()) - { - MergeMap(*it, &m_joystickButtonMap, windowID, buttonMap); - MergeMap(*it, &m_joystickAxisMap, windowID, axisMap); - MergeMap(*it, &m_joystickHatMap, windowID, hatMap); - if (windowID == -1) - m_joystickAxesConfigs[*it] = axesConfig; -// CLog::Log(LOGDEBUG, "Found Joystick map for window %d using %s", windowID, it->c_str()); - ++it; - } + m_joystickButtonMap[joyFamilyName][windowID].insert(buttonMap.begin(), buttonMap.end()); + m_joystickAxisMap[joyFamilyName][windowID].insert(axisMap.begin(), axisMap.end()); + m_joystickHatMap[joyFamilyName][windowID].insert(hatMap.begin(), hatMap.end()); + if (windowID == -1) + m_joystickAxesConfigs[joyFamilyName] = axesConfig; } std::string CButtonTranslator::JoynameToRegex(const std::string& joyName) const @@ -895,34 +938,58 @@ std::string CButtonTranslator::JoynameToRegex(const std::string& joyName) const return "\\Q" + joyName + "\\E"; } -void CButtonTranslator::MergeMap(boost::shared_ptr joyName, JoystickMap *joystick, int windowID, const ActionMap &map) +bool CButtonTranslator::AddFamilyRegex(JoystickFamily* family, boost::shared_ptr regex) { - // find or create WindowMap entry, match on pattern equality - JoystickMap::iterator jit; - for (jit = joystick->begin(); jit != joystick->end(); ++jit) + // even though family is a set, this does not prevent the same regex + // from being added twice, so we manually match on pattern equality + JoystickFamily::iterator it; + for (it = family->begin(); it != family->end(); it++) { - if (jit->first->GetPattern() == joyName->GetPattern()) - break; + if ((*it)->GetPattern() == regex->GetPattern()) + return false; + } + family->insert(regex); + return true; +} + +const AxesConfig* CButtonTranslator::GetAxesConfigFor(const std::string& joyName) const +{ + JoystickFamilyMap::const_iterator familyIt = FindJoystickFamily(joyName); + if (familyIt == m_joystickFamilies.end()) + return NULL; + else { + std::map::const_iterator it = m_joystickAxesConfigs.find(familyIt->first); + if (it == m_joystickAxesConfigs.end()) + return NULL; + else + return &it->second; } - WindowMap *w = (jit == joystick->end()) ? &(*joystick)[joyName] : &jit->second; - - // find or create ActionMap, and merge/overwrite new entries - ActionMap *a = &(*w)[windowID]; - for (ActionMap::const_iterator it = map.begin(); it != map.end(); ++it) - (*a)[it->first] = it->second; } CButtonTranslator::JoystickMap::const_iterator CButtonTranslator::FindWindowMap(const std::string& joyName, const JoystickMap &maps) const { - JoystickMap::const_iterator it; - for (it = maps.begin(); it != maps.end(); ++it) + JoystickFamilyMap::const_iterator familyIt = FindJoystickFamily(joyName); + if (familyIt == m_joystickFamilies.end()) + return maps.end(); + else + return maps.find(familyIt->first); +} + +CButtonTranslator::JoystickFamilyMap::const_iterator CButtonTranslator::FindJoystickFamily(const std::string& joyName) const +{ + // find the family corresponding to a joystick name + JoystickFamilyMap::const_iterator it; + for (it = m_joystickFamilies.begin(); it != m_joystickFamilies.end(); it++) { - if (it->first->RegFind(joyName) >= 0) + JoystickFamily::const_iterator regexIt; + for (regexIt = it->second.begin(); regexIt != it->second.end(); regexIt++) { - // CLog::Log(LOGDEBUG, "Regex %s matches joystick %s", it->first->GetPattern().c_str(), joyName.c_str()); - break; + if ((*regexIt)->RegFind(joyName) >= 0) + { + // CLog::Log(LOGDEBUG, "Regex %s matches joystick %s", it->first->GetPattern().c_str(), joyName.c_str()); + return it; + } } - // CLog::Log(LOGDEBUG, "No match: %s for joystick %s", it->first->GetPattern().c_str(), joyName.c_str()); } return it; } diff --git a/xbmc/input/ButtonTranslator.h b/xbmc/input/ButtonTranslator.h index 1d10bca8c52ff..3bd47abc0eba8 100644 --- a/xbmc/input/ButtonTranslator.h +++ b/xbmc/input/ButtonTranslator.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "system.h" // for HAS_EVENT_SERVER, HAS_SDL_JOYSTICK #ifdef HAS_EVENT_SERVER @@ -99,7 +100,7 @@ class CButtonTranslator short inputType, int& action, std::string& strAction, bool &fullrange); - const std::map, AxesConfig>& GetAxesConfigs() { return m_joystickAxesConfigs; }; + const AxesConfig* GetAxesConfigFor(const std::string& joyName) const; #endif bool TranslateTouchAction(int window, int touchAction, int touchPointers, int &action); @@ -115,9 +116,11 @@ class CButtonTranslator int GetActionCode(int window, int action); int GetActionCode(int window, const CKey &key, std::string &strAction) const; #if defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER) + typedef std::set > JoystickFamily; + typedef std::map JoystickFamilyMap; typedef std::map ActionMap; // @@ -128,17 +189,7 @@ Left Right - - BigBen Interactive XBOX 360 Controller - Generic X-Box pad - Logitech Chillstream Controller - Mad Catz Wired Xbox 360 Controller - Mad Catz Wired Xbox 360 Controller (SFIV) - Pelican 'TSZ' Wired Xbox 360 Controller - Pelican PL-3601 'TSZ' Wired Xbox 360 Controller - Xbox 360 Wireless Receiver - Xbox 360 Wireless Receiver (XBOX) - Razer Sabertooth + @@ -171,110 +222,26 @@ - - Afterglow Gamepad for Xbox 360 (Controller) - Controller (Gamepad F310) - Controller (Gamepad for Xbox 360) - Controller (Rumble Gamepad F510) - Controller (Wireless Gamepad F710) - Controller (Xbox 360 Wireless Receiver for Windows) - Controller (Xbox wireless receiver for windows) - Controller (XBOX360 GAMEPAD) - Controller (Batarang wired controller (XBOX)) - Wireless Gamepad F710 (Controller) - XBOX 360 For Windows - XBOX 360 For Windows (Controller) - Xbox 360 Wireless Controller - Xbox Receiver for Windows (Wireless Controller) - Xbox wireless receiver for windows (Controller) - Gamepad F310 (Controller) - Razer Sabertooth Elite (Controller) - Controller (XBOX One For Windows) + - - BigBen Interactive XBOX 360 Controller - Generic X-Box pad - Logitech Chillstream Controller - Mad Catz Wired Xbox 360 Controller - Mad Catz Wired Xbox 360 Controller (SFIV) - Pelican 'TSZ' Wired Xbox 360 Controller - Pelican PL-3601 'TSZ' Wired Xbox 360 Controller - Xbox 360 Wireless Receiver - Xbox 360 Wireless Receiver (XBOX) - Razer Sabertooth + - - Afterglow Gamepad for Xbox 360 (Controller) - Controller (Gamepad F310) - Controller (Gamepad for Xbox 360) - Controller (Rumble Gamepad F510) - Controller (Wireless Gamepad F710) - Controller (Xbox 360 Wireless Receiver for Windows) - Controller (Xbox wireless receiver for windows) - Controller (XBOX360 GAMEPAD) - Controller (Batarang wired controller (XBOX)) - Wireless Gamepad F710 (Controller) - XBOX 360 For Windows - XBOX 360 For Windows (Controller) - Xbox 360 Wireless Controller - Xbox Receiver for Windows (Wireless Controller) - Xbox wireless receiver for windows (Controller) - Gamepad F310 (Controller) - Razer Sabertooth Elite (Controller) - Controller (XBOX One For Windows) + - - BigBen Interactive XBOX 360 Controller - Generic X-Box pad - Logitech Chillstream Controller - Mad Catz Wired Xbox 360 Controller - Mad Catz Wired Xbox 360 Controller (SFIV) - Pelican 'TSZ' Wired Xbox 360 Controller - Pelican PL-3601 'TSZ' Wired Xbox 360 Controller - Xbox 360 Wireless Receiver - Xbox 360 Wireless Receiver (XBOX) - Razer Sabertooth + - - Afterglow Gamepad for Xbox 360 (Controller) - Controller (Gamepad F310) - Controller (Gamepad for Xbox 360) - Controller (Rumble Gamepad F510) - Controller (Wireless Gamepad F710) - Controller (Xbox 360 Wireless Receiver for Windows) - Controller (Xbox wireless receiver for windows) - Controller (XBOX360 GAMEPAD) - Controller (Batarang wired controller (XBOX)) - Wireless Gamepad F710 (Controller) - XBOX 360 For Windows - XBOX 360 For Windows (Controller) - Xbox 360 Wireless Controller - Xbox Receiver for Windows (Wireless Controller) - Xbox wireless receiver for windows (Controller) - Gamepad F310 (Controller) - Razer Sabertooth Elite (Controller) - Controller (XBOX One For Windows) + - - BigBen Interactive XBOX 360 Controller - Generic X-Box pad - Logitech Chillstream Controller - Mad Catz Wired Xbox 360 Controller - Mad Catz Wired Xbox 360 Controller (SFIV) - Pelican 'TSZ' Wired Xbox 360 Controller - Pelican PL-3601 'TSZ' Wired Xbox 360 Controller - Xbox 360 Wireless Receiver - Xbox 360 Wireless Receiver (XBOX) - Razer Sabertooth + @@ -283,25 +250,7 @@ - - Afterglow Gamepad for Xbox 360 (Controller) - Controller (Gamepad F310) - Controller (Gamepad for Xbox 360) - Controller (Rumble Gamepad F510) - Controller (Wireless Gamepad F710) - Controller (Xbox 360 Wireless Receiver for Windows) - Controller (Xbox wireless receiver for windows) - Controller (XBOX360 GAMEPAD) - Controller (Batarang wired controller (XBOX)) - Wireless Gamepad F710 (Controller) - XBOX 360 For Windows - XBOX 360 For Windows (Controller) - Xbox 360 Wireless Controller - Xbox Receiver for Windows (Wireless Controller) - Xbox wireless receiver for windows (Controller) - Gamepad F310 (Controller) - Razer Sabertooth Elite (Controller) - Controller (XBOX One For Windows) +