Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #540 from jhsrennie/mulhiddev

Support multiple simultaneous HID device mappings
  • Loading branch information...
commit 3b2d89a3376aeb6d0a2d3872bcd4c30f3da44059 2 parents 01da319 + 2c47ca6
John Rennie authored
View
2  xbmc/Application.cpp
@@ -748,7 +748,7 @@ bool CApplication::Create()
// The key mappings may already have been loaded by a peripheral
CLog::Log(LOGINFO, "load keymapping");
- if (!CButtonTranslator::GetInstance().Loaded() && !CButtonTranslator::GetInstance().Load())
+ if (!CButtonTranslator::GetInstance().Load())
FatalErrorHandler(false, false, true);
int iResolution = g_graphicsContext.GetVideoResolution();
View
146 xbmc/input/ButtonTranslator.cpp
@@ -362,19 +362,55 @@ CButtonTranslator& CButtonTranslator::GetInstance()
}
CButtonTranslator::CButtonTranslator()
-{}
+{
+ m_baseMap.clear();
+ m_deviceList.clear();
+ m_Loaded = false;
+}
CButtonTranslator::~CButtonTranslator()
{}
-bool CButtonTranslator::Load(const char* szDevice)
+// Add the supplied device name to the list of connected devices
+void CButtonTranslator::AddDevice(CStdString& strDevice)
{
- translatorMap.clear();
+ // Only add the device if it isn't already in the list
+ std::list<CStdString>::iterator it;
+ for (it = m_deviceList.begin(); it != m_deviceList.end(); it++)
+ if (*it == strDevice)
+ return;
+
+ // Add the device
+ m_deviceList.push_back(strDevice);
+ m_deviceList.sort();
+
+ // New device added so reload the key mappings
+ Load();
+}
+
+void CButtonTranslator::RemoveDevice(CStdString& strDevice)
+{
+ // Find the device
+ std::list<CStdString>::iterator it;
+ for (it = m_deviceList.begin(); it != m_deviceList.end(); it++)
+ if (*it == strDevice)
+ break;
+ if (it == m_deviceList.end())
+ return;
+
+ // Remove the device
+ m_deviceList.remove(strDevice);
- //directories to search for keymaps
- //they're applied in this order,
- //so keymaps in profile/keymaps/
- //override e.g. system/keymaps
+ // Device removed so reload the key mappings
+ Load();
+}
+
+bool CButtonTranslator::Load(void)
+{
+ m_translatorMap.clear();
+
+ // Directories to search for keymaps. They're applied in this order,
+ // so keymaps in profile/keymaps/ override e.g. system/keymaps
static const char* DIRS_TO_CHECK[] = {
"special://xbmc/system/keymaps/",
"special://masterprofile/keymaps/",
@@ -382,25 +418,34 @@ bool CButtonTranslator::Load(const char* szDevice)
};
bool success = false;
- for(unsigned int dirIndex = 0; dirIndex < sizeof(DIRS_TO_CHECK)/sizeof(DIRS_TO_CHECK[0]); ++dirIndex) {
- if( XFILE::CDirectory::Exists(DIRS_TO_CHECK[dirIndex]) )
- {
- CFileItemList files;
- XFILE::CDirectory::GetDirectory(DIRS_TO_CHECK[dirIndex], files, "*.xml");
- // Sort the list for filesystem based priorities, e.g. 01-keymap.xml, 02-keymap-overrides.xml
- files.Sort(SORT_METHOD_FILE, SORT_ORDER_ASC);
- // In (at least) Windows the GetDirectory returns all files not just *.xml files
- for(int fileIndex = 0; fileIndex<files.Size(); ++fileIndex)
- if (files[fileIndex]->GetPath().Right(4) == ".xml")
- success |= LoadKeymap(files[fileIndex]->GetPath());
- }
+ // If we've already loaded the m_baseMap we don't need to load it again
+ if (m_Loaded)
+ {
+ m_translatorMap = m_baseMap;
}
- if (!success)
+ // Else load the standard mappings
+ else
{
- CLog::Log(LOGERROR, "Error loading keymaps from: %s or %s or %s", DIRS_TO_CHECK[0], DIRS_TO_CHECK[1], DIRS_TO_CHECK[2]);
- return false;
- }
+ for(unsigned int dirIndex = 0; dirIndex < sizeof(DIRS_TO_CHECK)/sizeof(DIRS_TO_CHECK[0]); ++dirIndex) {
+ if( XFILE::CDirectory::Exists(DIRS_TO_CHECK[dirIndex]) )
+ {
+ CFileItemList files;
+ XFILE::CDirectory::GetDirectory(DIRS_TO_CHECK[dirIndex], files, "*.xml");
+ // Sort the list for filesystem based priorities, e.g. 01-keymap.xml, 02-keymap-overrides.xml
+ files.Sort(SORT_METHOD_FILE, SORT_ORDER_ASC);
+ // In (at least) Windows the GetDirectory returns all files not just *.xml files
+ for(int fileIndex = 0; fileIndex<files.Size(); ++fileIndex)
+ if (files[fileIndex]->GetPath().Right(4) == ".xml")
+ success |= LoadKeymap(files[fileIndex]->GetPath());
+ }
+ }
+
+ if (!success)
+ {
+ CLog::Log(LOGERROR, "Error loading keymaps from: %s or %s or %s", DIRS_TO_CHECK[0], DIRS_TO_CHECK[1], DIRS_TO_CHECK[2]);
+ return false;
+ }
#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
#ifdef _LINUX
@@ -408,33 +453,38 @@ bool CButtonTranslator::Load(const char* szDevice)
#else
#define REMOTEMAP "IRSSmap.xml"
#endif
- CStdString lircmapPath;
- URIUtils::AddFileToFolder("special://xbmc/system/", REMOTEMAP, lircmapPath);
- lircRemotesMap.clear();
- if(CFile::Exists(lircmapPath))
- success |= LoadLircMap(lircmapPath);
- else
- CLog::Log(LOGDEBUG, "CButtonTranslator::Load - no system %s found, skipping", REMOTEMAP);
+ CStdString lircmapPath;
+ URIUtils::AddFileToFolder("special://xbmc/system/", REMOTEMAP, lircmapPath);
+ lircRemotesMap.clear();
+ if(CFile::Exists(lircmapPath))
+ success |= LoadLircMap(lircmapPath);
+ else
+ CLog::Log(LOGDEBUG, "CButtonTranslator::Load - no system %s found, skipping", REMOTEMAP);
- lircmapPath = g_settings.GetUserDataItem(REMOTEMAP);
- if(CFile::Exists(lircmapPath))
- success |= LoadLircMap(lircmapPath);
- else
- CLog::Log(LOGDEBUG, "CButtonTranslator::Load - no userdata %s found, skipping", REMOTEMAP);
+ lircmapPath = g_settings.GetUserDataItem(REMOTEMAP);
+ if(CFile::Exists(lircmapPath))
+ success |= LoadLircMap(lircmapPath);
+ else
+ CLog::Log(LOGDEBUG, "CButtonTranslator::Load - no userdata %s found, skipping", REMOTEMAP);
- if (!success)
- CLog::Log(LOGERROR, "CButtonTranslator::Load - unable to load remote map %s", REMOTEMAP);
+ if (!success)
+ CLog::Log(LOGERROR, "CButtonTranslator::Load - unable to load remote map %s", REMOTEMAP);
// don't return false - it is to only indicate a fatal error (which this is not)
-
#endif
- // If we were called with a device name try loading mappings for that device now
- if (szDevice && strlen(szDevice) != 0)
+ // Standard mappings have been loaded into m_translatorMap, copy them to
+ // m_baseMap for future reuse.
+ m_baseMap = m_translatorMap;
+ }
+
+ // Load mappings for any HID devices we have connected
+ std::list<CStdString>::iterator it;
+ for (it = m_deviceList.begin(); it != m_deviceList.end(); it++)
{
for(unsigned int dirIndex = 0; dirIndex < sizeof(DIRS_TO_CHECK)/sizeof(DIRS_TO_CHECK[0]); ++dirIndex)
{
CStdString devicedir = DIRS_TO_CHECK[dirIndex];
- devicedir.append(szDevice);
+ devicedir.append(*it);
devicedir.append("/");
if( XFILE::CDirectory::Exists(devicedir) )
{
@@ -820,8 +870,8 @@ int CButtonTranslator::GetActionCode(int window, const CKey &key, CStdString &st
{
uint32_t code = key.GetButtonCode();
- map<int, buttonMap>::const_iterator it = translatorMap.find(window);
- if (it == translatorMap.end())
+ map<int, buttonMap>::const_iterator it = m_translatorMap.find(window);
+ if (it == m_translatorMap.end())
return 0;
buttonMap::const_iterator it2 = (*it).second.find(code);
int action = 0;
@@ -889,11 +939,11 @@ void CButtonTranslator::MapWindowActions(TiXmlNode *pWindow, int windowID)
if (HasDeviceType(pWindow, type))
{
buttonMap map;
- std::map<int, buttonMap>::iterator it = translatorMap.find(windowID);
- if (it != translatorMap.end())
+ std::map<int, buttonMap>::iterator it = m_translatorMap.find(windowID);
+ if (it != m_translatorMap.end())
{
map = it->second;
- translatorMap.erase(it);
+ m_translatorMap.erase(it);
}
pDevice = pWindow->FirstChild(type);
@@ -923,7 +973,7 @@ void CButtonTranslator::MapWindowActions(TiXmlNode *pWindow, int windowID)
// add our map to our table
if (map.size() > 0)
- translatorMap.insert(pair<int, buttonMap>( windowID, map));
+ m_translatorMap.insert(pair<int, buttonMap>( windowID, map));
}
}
@@ -1232,7 +1282,7 @@ uint32_t CButtonTranslator::TranslateMouseCommand(const char *szButton)
void CButtonTranslator::Clear()
{
- translatorMap.clear();
+ m_translatorMap.clear();
#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
lircRemotesMap.clear();
#endif
View
17 xbmc/input/ButtonTranslator.h
@@ -64,12 +64,14 @@ class CButtonTranslator
///access to singleton
static CButtonTranslator& GetInstance();
+ // Add/remove a HID device with custom mappings
+ void AddDevice(CStdString& strDevice);
+ void RemoveDevice(CStdString& strDevice);
+
/// loads Lircmap.xml/IRSSmap.xml (if enabled) and Keymap.xml
- bool Load(const char* szDevice = NULL);
+ bool Load(void);
/// clears the maps
void Clear();
- /// map has been loaded
- inline bool Loaded(void) { return m_Loaded; }
CAction GetAction(int window, const CKey &key, bool fallback = true);
@@ -98,7 +100,14 @@ class CButtonTranslator
private:
typedef std::multimap<uint32_t, CButtonAction> buttonMap; // our button map to fill in
- std::map<int, buttonMap> translatorMap; // mapping of windows to button maps
+
+ // m_baseMap contains all the standard mappings
+ std::map<int, buttonMap> m_baseMap;
+ // m_translatorMap contains all mappings i.e. m_BaseMap + HID device mappings
+ std::map<int, buttonMap> m_translatorMap;
+ // m_deviceList contains the list of connected HID devices
+ std::list<CStdString> m_deviceList;
+
int GetActionCode(int window, const CKey &key, CStdString &strAction) const;
static uint32_t TranslateGamepadString(const char *szButton);
View
17 xbmc/peripherals/devices/PeripheralHID.cpp
@@ -37,11 +37,10 @@ CPeripheralHID::CPeripheralHID(const PeripheralType type, const PeripheralBusTyp
CPeripheralHID::~CPeripheralHID(void)
{
- if (!m_strKeymap.IsEmpty() && GetSettingBool("keymap_enabled") && g_settings.m_activeKeyboardMapping.Equals(m_strKeymap))
+ if (!m_strKeymap.IsEmpty() && GetSettingBool("keymap_enabled"))
{
CLog::Log(LOGDEBUG, "%s - switching active keymapping to: default", __FUNCTION__);
- CButtonTranslator::GetInstance().Load();
- g_settings.m_activeKeyboardMapping = "default";
+ CButtonTranslator::GetInstance().RemoveDevice(m_strKeymap);
}
}
@@ -65,15 +64,13 @@ bool CPeripheralHID::InitialiseFeature(const PeripheralFeature feature)
bool bKeymapEnabled(GetSettingBool("keymap_enabled"));
if (bKeymapEnabled)
{
- CLog::Log(LOGDEBUG, "%s - switching active keymapping to: %s", __FUNCTION__, m_strKeymap.c_str());
- CButtonTranslator::GetInstance().Load(m_strKeymap.c_str());
- g_settings.m_activeKeyboardMapping = m_strKeymap;
+ CLog::Log(LOGDEBUG, "%s - adding keymapping for: %s", __FUNCTION__, m_strKeymap.c_str());
+ CButtonTranslator::GetInstance().AddDevice(m_strKeymap);
}
- else if (!bKeymapEnabled && g_settings.m_activeKeyboardMapping.Equals(m_strKeymap))
+ else if (!bKeymapEnabled)
{
- CLog::Log(LOGDEBUG, "%s - switching active keymapping to: default", __FUNCTION__);
- CButtonTranslator::GetInstance().Load();
- g_settings.m_activeKeyboardMapping = "default";
+ CLog::Log(LOGDEBUG, "%s - removing keymapping for: %s", __FUNCTION__, m_strKeymap.c_str());
+ CButtonTranslator::GetInstance().RemoveDevice(m_strKeymap);
}
}
View
2  xbmc/settings/Settings.cpp
@@ -138,8 +138,6 @@ void CSettings::Initialize()
m_lastUsedProfile = 0;
m_currentProfile = 0;
m_nextIdProfile = 0;
-
- m_activeKeyboardMapping = "default";
}
CSettings::~CSettings(void)
View
2  xbmc/settings/Settings.h
@@ -161,8 +161,6 @@ class CSettings
CStdString m_logFolder;
- CStdString m_activeKeyboardMapping;
-
bool m_bMyMusicSongInfoInVis;
bool m_bMyMusicSongThumbInVis;
Please sign in to comment.
Something went wrong with that request. Please try again.