Permalink
Cannot retrieve contributors at this time
/* | |
* 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 "IRTranslator.h" | |
#include "ServiceBroker.h" | |
#include "filesystem/File.h" | |
#include "input/remote/IRRemote.h" | |
#include "profiles/ProfileManager.h" | |
#include "settings/SettingsComponent.h" | |
#include "utils/StringUtils.h" | |
#include "utils/URIUtils.h" | |
#include "utils/XBMCTinyXML.h" | |
#include "utils/log.h" | |
#include <stdlib.h> | |
#include <vector> | |
void CIRTranslator::Load(const std::string& irMapName) | |
{ | |
if (irMapName.empty()) | |
return; | |
Clear(); | |
bool success = false; | |
std::string irMapPath = URIUtils::AddFileToFolder("special://xbmc/system/", irMapName); | |
if (XFILE::CFile::Exists(irMapPath)) | |
success |= LoadIRMap(irMapPath); | |
else | |
CLog::Log(LOGDEBUG, "CIRTranslator::Load - no system %s found, skipping", irMapName.c_str()); | |
irMapPath = | |
CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetUserDataItem(irMapName); | |
if (XFILE::CFile::Exists(irMapPath)) | |
success |= LoadIRMap(irMapPath); | |
else | |
CLog::Log(LOGDEBUG, "CIRTranslator::Load - no userdata %s found, skipping", irMapName.c_str()); | |
if (!success) | |
CLog::Log(LOGERROR, "CIRTranslator::Load - unable to load remote map %s", irMapName.c_str()); | |
} | |
bool CIRTranslator::LoadIRMap(const std::string& irMapPath) | |
{ | |
std::string remoteMapTag = URIUtils::GetFileName(irMapPath); | |
size_t lastindex = remoteMapTag.find_last_of('.'); | |
if (lastindex != std::string::npos) | |
remoteMapTag = remoteMapTag.substr(0, lastindex); | |
StringUtils::ToLower(remoteMapTag); | |
// Load our xml file, and fill up our mapping tables | |
CXBMCTinyXML xmlDoc; | |
// Load the config file | |
CLog::Log(LOGINFO, "Loading %s", irMapPath.c_str()); | |
if (!xmlDoc.LoadFile(irMapPath)) | |
{ | |
CLog::Log(LOGERROR, "%s, Line %d\n%s", irMapPath.c_str(), xmlDoc.ErrorRow(), | |
xmlDoc.ErrorDesc()); | |
return false; | |
} | |
TiXmlElement* pRoot = xmlDoc.RootElement(); | |
std::string strValue = pRoot->Value(); | |
if (strValue != remoteMapTag) | |
{ | |
CLog::Log(LOGERROR, "%s Doesn't contain <%s>", irMapPath.c_str(), remoteMapTag.c_str()); | |
return false; | |
} | |
// Run through our window groups | |
TiXmlNode* pRemote = pRoot->FirstChild(); | |
while (pRemote != nullptr) | |
{ | |
if (pRemote->Type() == TiXmlNode::TINYXML_ELEMENT) | |
{ | |
const char* szRemote = pRemote->Value(); | |
if (szRemote != nullptr) | |
{ | |
TiXmlAttribute* pAttr = pRemote->ToElement()->FirstAttribute(); | |
if (pAttr != nullptr) | |
MapRemote(pRemote, pAttr->Value()); | |
} | |
} | |
pRemote = pRemote->NextSibling(); | |
} | |
return true; | |
} | |
void CIRTranslator::MapRemote(TiXmlNode* pRemote, const std::string& szDevice) | |
{ | |
CLog::Log(LOGINFO, "* Adding remote mapping for device '%s'", szDevice.c_str()); | |
std::vector<std::string> remoteNames; | |
auto it = m_irRemotesMap.find(szDevice); | |
if (it == m_irRemotesMap.end()) | |
m_irRemotesMap[szDevice].reset(new IRButtonMap); | |
std::shared_ptr<IRButtonMap>& buttons = m_irRemotesMap[szDevice]; | |
TiXmlElement* pButton = pRemote->FirstChildElement(); | |
while (pButton != nullptr) | |
{ | |
if (!pButton->NoChildren()) | |
{ | |
if (pButton->ValueStr() == "altname") | |
remoteNames.push_back(pButton->FirstChild()->ValueStr()); | |
else | |
(*buttons)[pButton->FirstChild()->ValueStr()] = pButton->ValueStr(); | |
} | |
pButton = pButton->NextSiblingElement(); | |
} | |
for (const auto& remoteName : remoteNames) | |
{ | |
CLog::Log(LOGINFO, "* Linking remote mapping for '%s' to '%s'", szDevice.c_str(), | |
remoteName.c_str()); | |
m_irRemotesMap[remoteName] = buttons; | |
} | |
} | |
void CIRTranslator::Clear() | |
{ | |
m_irRemotesMap.clear(); | |
} | |
unsigned int CIRTranslator::TranslateButton(const std::string& szDevice, | |
const std::string& szButton) | |
{ | |
// Find the device | |
auto it = m_irRemotesMap.find(szDevice); | |
if (it == m_irRemotesMap.end()) | |
return 0; | |
// Find the button | |
auto it2 = (*it).second->find(szButton); | |
if (it2 == (*it).second->end()) | |
return 0; | |
// Convert the button to code | |
if (StringUtils::CompareNoCase((*it2).second, "obc", 3) == 0) | |
return TranslateUniversalRemoteString((*it2).second); | |
return TranslateString((*it2).second); | |
} | |
uint32_t CIRTranslator::TranslateString(std::string strButton) | |
{ | |
if (strButton.empty()) | |
return 0; | |
uint32_t buttonCode = 0; | |
StringUtils::ToLower(strButton); | |
if (strButton == "left") | |
buttonCode = XINPUT_IR_REMOTE_LEFT; | |
else if (strButton == "right") | |
buttonCode = XINPUT_IR_REMOTE_RIGHT; | |
else if (strButton == "up") | |
buttonCode = XINPUT_IR_REMOTE_UP; | |
else if (strButton == "down") | |
buttonCode = XINPUT_IR_REMOTE_DOWN; | |
else if (strButton == "select") | |
buttonCode = XINPUT_IR_REMOTE_SELECT; | |
else if (strButton == "back") | |
buttonCode = XINPUT_IR_REMOTE_BACK; | |
else if (strButton == "menu") | |
buttonCode = XINPUT_IR_REMOTE_MENU; | |
else if (strButton == "info") | |
buttonCode = XINPUT_IR_REMOTE_INFO; | |
else if (strButton == "display") | |
buttonCode = XINPUT_IR_REMOTE_DISPLAY; | |
else if (strButton == "title") | |
buttonCode = XINPUT_IR_REMOTE_TITLE; | |
else if (strButton == "play") | |
buttonCode = XINPUT_IR_REMOTE_PLAY; | |
else if (strButton == "pause") | |
buttonCode = XINPUT_IR_REMOTE_PAUSE; | |
else if (strButton == "reverse") | |
buttonCode = XINPUT_IR_REMOTE_REVERSE; | |
else if (strButton == "forward") | |
buttonCode = XINPUT_IR_REMOTE_FORWARD; | |
else if (strButton == "skipplus") | |
buttonCode = XINPUT_IR_REMOTE_SKIP_PLUS; | |
else if (strButton == "skipminus") | |
buttonCode = XINPUT_IR_REMOTE_SKIP_MINUS; | |
else if (strButton == "stop") | |
buttonCode = XINPUT_IR_REMOTE_STOP; | |
else if (strButton == "zero") | |
buttonCode = XINPUT_IR_REMOTE_0; | |
else if (strButton == "one") | |
buttonCode = XINPUT_IR_REMOTE_1; | |
else if (strButton == "two") | |
buttonCode = XINPUT_IR_REMOTE_2; | |
else if (strButton == "three") | |
buttonCode = XINPUT_IR_REMOTE_3; | |
else if (strButton == "four") | |
buttonCode = XINPUT_IR_REMOTE_4; | |
else if (strButton == "five") | |
buttonCode = XINPUT_IR_REMOTE_5; | |
else if (strButton == "six") | |
buttonCode = XINPUT_IR_REMOTE_6; | |
else if (strButton == "seven") | |
buttonCode = XINPUT_IR_REMOTE_7; | |
else if (strButton == "eight") | |
buttonCode = XINPUT_IR_REMOTE_8; | |
else if (strButton == "nine") | |
buttonCode = XINPUT_IR_REMOTE_9; | |
// Additional keys from the media center extender for xbox remote | |
else if (strButton == "power") | |
buttonCode = XINPUT_IR_REMOTE_POWER; | |
else if (strButton == "mytv") | |
buttonCode = XINPUT_IR_REMOTE_MY_TV; | |
else if (strButton == "mymusic") | |
buttonCode = XINPUT_IR_REMOTE_MY_MUSIC; | |
else if (strButton == "mypictures") | |
buttonCode = XINPUT_IR_REMOTE_MY_PICTURES; | |
else if (strButton == "myvideo") | |
buttonCode = XINPUT_IR_REMOTE_MY_VIDEOS; | |
else if (strButton == "record") | |
buttonCode = XINPUT_IR_REMOTE_RECORD; | |
else if (strButton == "start") | |
buttonCode = XINPUT_IR_REMOTE_START; | |
else if (strButton == "volumeplus") | |
buttonCode = XINPUT_IR_REMOTE_VOLUME_PLUS; | |
else if (strButton == "volumeminus") | |
buttonCode = XINPUT_IR_REMOTE_VOLUME_MINUS; | |
else if (strButton == "channelplus") | |
buttonCode = XINPUT_IR_REMOTE_CHANNEL_PLUS; | |
else if (strButton == "channelminus") | |
buttonCode = XINPUT_IR_REMOTE_CHANNEL_MINUS; | |
else if (strButton == "pageplus") | |
buttonCode = XINPUT_IR_REMOTE_CHANNEL_PLUS; | |
else if (strButton == "pageminus") | |
buttonCode = XINPUT_IR_REMOTE_CHANNEL_MINUS; | |
else if (strButton == "mute") | |
buttonCode = XINPUT_IR_REMOTE_MUTE; | |
else if (strButton == "recordedtv") | |
buttonCode = XINPUT_IR_REMOTE_RECORDED_TV; | |
else if (strButton == "guide") | |
buttonCode = XINPUT_IR_REMOTE_GUIDE; | |
else if (strButton == "livetv") | |
buttonCode = XINPUT_IR_REMOTE_LIVE_TV; | |
else if (strButton == "liveradio") | |
buttonCode = XINPUT_IR_REMOTE_LIVE_RADIO; | |
else if (strButton == "epgsearch") | |
buttonCode = XINPUT_IR_REMOTE_EPG_SEARCH; | |
else if (strButton == "star") | |
buttonCode = XINPUT_IR_REMOTE_STAR; | |
else if (strButton == "hash") | |
buttonCode = XINPUT_IR_REMOTE_HASH; | |
else if (strButton == "clear") | |
buttonCode = XINPUT_IR_REMOTE_CLEAR; | |
else if (strButton == "enter") | |
buttonCode = XINPUT_IR_REMOTE_ENTER; | |
else if (strButton == "xbox") | |
buttonCode = XINPUT_IR_REMOTE_DISPLAY; // Same as display | |
else if (strButton == "playlist") | |
buttonCode = XINPUT_IR_REMOTE_PLAYLIST; | |
else if (strButton == "teletext") | |
buttonCode = XINPUT_IR_REMOTE_TELETEXT; | |
else if (strButton == "red") | |
buttonCode = XINPUT_IR_REMOTE_RED; | |
else if (strButton == "green") | |
buttonCode = XINPUT_IR_REMOTE_GREEN; | |
else if (strButton == "yellow") | |
buttonCode = XINPUT_IR_REMOTE_YELLOW; | |
else if (strButton == "blue") | |
buttonCode = XINPUT_IR_REMOTE_BLUE; | |
else if (strButton == "subtitle") | |
buttonCode = XINPUT_IR_REMOTE_SUBTITLE; | |
else if (strButton == "language") | |
buttonCode = XINPUT_IR_REMOTE_LANGUAGE; | |
else if (strButton == "eject") | |
buttonCode = XINPUT_IR_REMOTE_EJECT; | |
else if (strButton == "contentsmenu") | |
buttonCode = XINPUT_IR_REMOTE_CONTENTS_MENU; | |
else if (strButton == "rootmenu") | |
buttonCode = XINPUT_IR_REMOTE_ROOT_MENU; | |
else if (strButton == "topmenu") | |
buttonCode = XINPUT_IR_REMOTE_TOP_MENU; | |
else if (strButton == "dvdmenu") | |
buttonCode = XINPUT_IR_REMOTE_DVD_MENU; | |
else if (strButton == "print") | |
buttonCode = XINPUT_IR_REMOTE_PRINT; | |
else | |
CLog::Log(LOGERROR, "Remote Translator: Can't find button %s", strButton.c_str()); | |
return buttonCode; | |
} | |
uint32_t CIRTranslator::TranslateUniversalRemoteString(const std::string& szButton) | |
{ | |
if (szButton.empty() || szButton.length() < 4 || StringUtils::CompareNoCase(szButton, "obc", 3)) | |
return 0; | |
const char* szCode = szButton.c_str() + 3; | |
// Button Code is 255 - OBC (Original Button Code) of the button | |
uint32_t buttonCode = 255 - atol(szCode); | |
if (buttonCode > 255) | |
buttonCode = 0; | |
return buttonCode; | |
} |