mirror of
https://github.com/Team-Resurgent/XBMC4Xbox.git
synced 2026-08-15 11:18:13 -07:00
If ever adding the XBMC4Xbox source to GitHub use "git add -f -A" or it wont add all the files.
994 lines
40 KiB
C++
994 lines
40 KiB
C++
/*
|
|
* Copyright (C) 2005-2013 Team XBMC
|
|
* http://xbmc.org
|
|
*
|
|
* This Program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This Program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with XBMC; see the file COPYING. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "system.h"
|
|
#include "utils/log.h"
|
|
#include "interfaces/Builtins.h"
|
|
#include "input/ButtonTranslator.h"
|
|
#include "Util.h"
|
|
#include "settings/Settings.h"
|
|
#include "Key.h"
|
|
#include "FileSystem/File.h"
|
|
#include "FileSystem/Directory.h"
|
|
#include "FileItem.h"
|
|
|
|
using namespace std;
|
|
using namespace XFILE;
|
|
|
|
extern CStdString g_LoadErrorStr;
|
|
|
|
typedef struct
|
|
{
|
|
const char* name;
|
|
int action;
|
|
} ActionMapping;
|
|
|
|
// remember the fixed length names (hence max 31 char)!
|
|
static const ActionMapping actions[] =
|
|
{{"left" , ACTION_MOVE_LEFT},
|
|
{"right" , ACTION_MOVE_RIGHT},
|
|
{"up" , ACTION_MOVE_UP},
|
|
{"down" , ACTION_MOVE_DOWN},
|
|
{"pageup" , ACTION_PAGE_UP},
|
|
{"pagedown" , ACTION_PAGE_DOWN},
|
|
{"select" , ACTION_SELECT_ITEM},
|
|
{"highlight" , ACTION_HIGHLIGHT_ITEM},
|
|
{"parentdir" , ACTION_NAV_BACK}, // backward compatibility
|
|
{"parentfolder" , ACTION_PARENT_DIR},
|
|
{"back" , ACTION_NAV_BACK},
|
|
{"previousmenu" , ACTION_PREVIOUS_MENU},
|
|
{"info" , ACTION_SHOW_INFO},
|
|
{"pause" , ACTION_PAUSE},
|
|
{"stop" , ACTION_STOP},
|
|
{"skipnext" , ACTION_NEXT_ITEM},
|
|
{"skipprevious" , ACTION_PREV_ITEM},
|
|
{"fullscreen" , ACTION_SHOW_GUI},
|
|
{"aspectratio" , ACTION_ASPECT_RATIO},
|
|
{"stepforward" , ACTION_STEP_FORWARD},
|
|
{"stepback" , ACTION_STEP_BACK},
|
|
{"bigstepforward" , ACTION_BIG_STEP_FORWARD},
|
|
{"bigstepback" , ACTION_BIG_STEP_BACK},
|
|
{"osd" , ACTION_SHOW_OSD},
|
|
{"showsubtitles" , ACTION_SHOW_SUBTITLES},
|
|
{"nextsubtitle" , ACTION_NEXT_SUBTITLE},
|
|
{"codecinfo" , ACTION_SHOW_CODEC},
|
|
{"nextpicture" , ACTION_NEXT_PICTURE},
|
|
{"previouspicture" , ACTION_PREV_PICTURE},
|
|
{"zoomout" , ACTION_ZOOM_OUT},
|
|
{"zoomin" , ACTION_ZOOM_IN},
|
|
{"playlist" , ACTION_SHOW_PLAYLIST},
|
|
{"queue" , ACTION_QUEUE_ITEM},
|
|
{"zoomnormal" , ACTION_ZOOM_LEVEL_NORMAL},
|
|
{"zoomlevel1" , ACTION_ZOOM_LEVEL_1},
|
|
{"zoomlevel2" , ACTION_ZOOM_LEVEL_2},
|
|
{"zoomlevel3" , ACTION_ZOOM_LEVEL_3},
|
|
{"zoomlevel4" , ACTION_ZOOM_LEVEL_4},
|
|
{"zoomlevel5" , ACTION_ZOOM_LEVEL_5},
|
|
{"zoomlevel6" , ACTION_ZOOM_LEVEL_6},
|
|
{"zoomlevel7" , ACTION_ZOOM_LEVEL_7},
|
|
{"zoomlevel8" , ACTION_ZOOM_LEVEL_8},
|
|
{"zoomlevel9" , ACTION_ZOOM_LEVEL_9},
|
|
{"nextcalibration" , ACTION_CALIBRATE_SWAP_ARROWS},
|
|
{"resetcalibration" , ACTION_CALIBRATE_RESET},
|
|
{"analogmove" , ACTION_ANALOG_MOVE},
|
|
{"rotate" , ACTION_ROTATE_PICTURE},
|
|
{"close" , ACTION_NAV_BACK}, // backwards compatibility
|
|
{"subtitledelayminus", ACTION_SUBTITLE_DELAY_MIN},
|
|
{"subtitledelay" , ACTION_SUBTITLE_DELAY},
|
|
{"subtitledelayplus" , ACTION_SUBTITLE_DELAY_PLUS},
|
|
{"audiodelayminus" , ACTION_AUDIO_DELAY_MIN},
|
|
{"audiodelay" , ACTION_AUDIO_DELAY},
|
|
{"audiodelayplus" , ACTION_AUDIO_DELAY_PLUS},
|
|
{"audionextlanguage" , ACTION_AUDIO_NEXT_LANGUAGE},
|
|
{"nextresolution" , ACTION_CHANGE_RESOLUTION},
|
|
{"audiotoggledigital", ACTION_TOGGLE_DIGITAL_ANALOG},
|
|
{"number0" , REMOTE_0},
|
|
{"number1" , REMOTE_1},
|
|
{"number2" , REMOTE_2},
|
|
{"number3" , REMOTE_3},
|
|
{"number4" , REMOTE_4},
|
|
{"number5" , REMOTE_5},
|
|
{"number6" , REMOTE_6},
|
|
{"number7" , REMOTE_7},
|
|
{"number8" , REMOTE_8},
|
|
{"number9" , REMOTE_9},
|
|
{"osdleft" , ACTION_OSD_SHOW_LEFT},
|
|
{"osdright" , ACTION_OSD_SHOW_RIGHT},
|
|
{"osdup" , ACTION_OSD_SHOW_UP},
|
|
{"osddown" , ACTION_OSD_SHOW_DOWN},
|
|
{"osdselect" , ACTION_OSD_SHOW_SELECT},
|
|
{"osdvalueplus" , ACTION_OSD_SHOW_VALUE_PLUS},
|
|
{"osdvalueminus" , ACTION_OSD_SHOW_VALUE_MIN},
|
|
{"smallstepback" , ACTION_SMALL_STEP_BACK},
|
|
{"fastforward" , ACTION_PLAYER_FORWARD},
|
|
{"rewind" , ACTION_PLAYER_REWIND},
|
|
{"play" , ACTION_PLAYER_PLAY},
|
|
{"delete" , ACTION_DELETE_ITEM},
|
|
{"copy" , ACTION_COPY_ITEM},
|
|
{"move" , ACTION_MOVE_ITEM},
|
|
{"mplayerosd" , ACTION_SHOW_MPLAYER_OSD},
|
|
{"hidesubmenu" , ACTION_OSD_HIDESUBMENU},
|
|
{"screenshot" , ACTION_TAKE_SCREENSHOT},
|
|
{"poweroff" , ACTION_POWERDOWN},
|
|
{"rename" , ACTION_RENAME_ITEM},
|
|
{"togglewatched" , ACTION_TOGGLE_WATCHED},
|
|
{"scanitem" , ACTION_SCAN_ITEM},
|
|
{"reloadkeymaps" , ACTION_RELOAD_KEYMAPS},
|
|
{"volumeup" , ACTION_VOLUME_UP},
|
|
{"volumedown" , ACTION_VOLUME_DOWN},
|
|
{"mute" , ACTION_MUTE},
|
|
{"backspace" , ACTION_BACKSPACE},
|
|
{"scrollup" , ACTION_SCROLL_UP},
|
|
{"scrolldown" , ACTION_SCROLL_DOWN},
|
|
{"analogfastforward" , ACTION_ANALOG_FORWARD},
|
|
{"analogrewind" , ACTION_ANALOG_REWIND},
|
|
{"moveitemup" , ACTION_MOVE_ITEM_UP},
|
|
{"moveitemdown" , ACTION_MOVE_ITEM_DOWN},
|
|
{"contextmenu" , ACTION_CONTEXT_MENU},
|
|
{"shift" , ACTION_SHIFT},
|
|
{"symbols" , ACTION_SYMBOLS},
|
|
{"cursorleft" , ACTION_CURSOR_LEFT},
|
|
{"cursorright" , ACTION_CURSOR_RIGHT},
|
|
{"showtime" , ACTION_SHOW_OSD_TIME},
|
|
{"analogseekforward" , ACTION_ANALOG_SEEK_FORWARD},
|
|
{"analogseekback" , ACTION_ANALOG_SEEK_BACK},
|
|
{"showpreset" , ACTION_VIS_PRESET_SHOW},
|
|
{"presetlist" , ACTION_VIS_PRESET_LIST},
|
|
{"nextpreset" , ACTION_VIS_PRESET_NEXT},
|
|
{"previouspreset" , ACTION_VIS_PRESET_PREV},
|
|
{"lockpreset" , ACTION_VIS_PRESET_LOCK},
|
|
{"randompreset" , ACTION_VIS_PRESET_RANDOM},
|
|
{"increasevisrating" , ACTION_VIS_RATE_PRESET_PLUS},
|
|
{"decreasevisrating" , ACTION_VIS_RATE_PRESET_MINUS},
|
|
{"showvideomenu" , ACTION_SHOW_VIDEOMENU},
|
|
{"enter" , ACTION_ENTER},
|
|
{"increaserating" , ACTION_INCREASE_RATING},
|
|
{"decreaserating" , ACTION_DECREASE_RATING},
|
|
{"togglefullscreen" , ACTION_TOGGLE_FULLSCREEN},
|
|
{"nextscene" , ACTION_NEXT_SCENE},
|
|
{"previousscene" , ACTION_PREV_SCENE},
|
|
{"nextletter" , ACTION_NEXT_LETTER},
|
|
{"prevletter" , ACTION_PREV_LETTER},
|
|
{"jumpsms2" , ACTION_JUMP_SMS2},
|
|
{"jumpsms3" , ACTION_JUMP_SMS3},
|
|
{"jumpsms4" , ACTION_JUMP_SMS4},
|
|
{"jumpsms5" , ACTION_JUMP_SMS5},
|
|
{"jumpsms6" , ACTION_JUMP_SMS6},
|
|
{"jumpsms7" , ACTION_JUMP_SMS7},
|
|
{"jumpsms8" , ACTION_JUMP_SMS8},
|
|
{"jumpsms9" , ACTION_JUMP_SMS9},
|
|
{"filterclear" , ACTION_FILTER_CLEAR},
|
|
{"filtersms2" , ACTION_FILTER_SMS2},
|
|
{"filtersms3" , ACTION_FILTER_SMS3},
|
|
{"filtersms4" , ACTION_FILTER_SMS4},
|
|
{"filtersms5" , ACTION_FILTER_SMS5},
|
|
{"filtersms6" , ACTION_FILTER_SMS6},
|
|
{"filtersms7" , ACTION_FILTER_SMS7},
|
|
{"filtersms8" , ACTION_FILTER_SMS8},
|
|
{"filtersms9" , ACTION_FILTER_SMS9},
|
|
{"firstpage" , ACTION_FIRST_PAGE},
|
|
{"lastpage" , ACTION_LAST_PAGE},
|
|
{"increasepar" , ACTION_INCREASE_PAR},
|
|
{"decreasepar" , ACTION_DECREASE_PAR}};
|
|
|
|
static const ActionMapping windows[] =
|
|
{{"home" , WINDOW_HOME},
|
|
{"programs" , WINDOW_PROGRAMS},
|
|
{"pictures" , WINDOW_PICTURES},
|
|
{"filemanager" , WINDOW_FILES},
|
|
{"files" , WINDOW_FILES},
|
|
{"settings" , WINDOW_SETTINGS_MENU},
|
|
{"music" , WINDOW_MUSIC},
|
|
{"video" , WINDOW_VIDEOS},
|
|
{"videos" , WINDOW_VIDEOS},
|
|
{"systeminfo" , WINDOW_SYSTEM_INFORMATION},
|
|
{"screencalibration" , WINDOW_SCREEN_CALIBRATION},
|
|
{"guicalibration" , WINDOW_SCREEN_CALIBRATION},
|
|
{"picturessettings" , WINDOW_SETTINGS_MYPICTURES},
|
|
{"programssettings" , WINDOW_SETTINGS_MYPROGRAMS},
|
|
{"weathersettings" , WINDOW_SETTINGS_MYWEATHER},
|
|
{"musicsettings" , WINDOW_SETTINGS_MYMUSIC},
|
|
{"systemsettings" , WINDOW_SETTINGS_SYSTEM},
|
|
{"videossettings" , WINDOW_SETTINGS_MYVIDEOS},
|
|
{"networksettings" , WINDOW_SETTINGS_NETWORK},
|
|
{"appearancesettings" , WINDOW_SETTINGS_APPEARANCE},
|
|
{"scripts" , WINDOW_SCRIPTS},
|
|
{"videofiles" , WINDOW_VIDEO_FILES},
|
|
{"videolibrary" , WINDOW_VIDEO_NAV},
|
|
{"videoplaylist" , WINDOW_VIDEO_PLAYLIST},
|
|
{"loginscreen" , WINDOW_LOGIN_SCREEN},
|
|
{"profiles" , WINDOW_SETTINGS_PROFILES},
|
|
{"yesnodialog" , WINDOW_DIALOG_YES_NO},
|
|
{"progressdialog" , WINDOW_DIALOG_PROGRESS},
|
|
{"virtualkeyboard" , WINDOW_DIALOG_KEYBOARD},
|
|
{"volumebar" , WINDOW_DIALOG_VOLUME_BAR},
|
|
{"submenu" , WINDOW_DIALOG_SUB_MENU},
|
|
{"contextmenu" , WINDOW_DIALOG_CONTEXT_MENU},
|
|
{"infodialog" , WINDOW_DIALOG_KAI_TOAST},
|
|
{"numericinput" , WINDOW_DIALOG_NUMERIC},
|
|
{"gamepadinput" , WINDOW_DIALOG_GAMEPAD},
|
|
{"shutdownmenu" , WINDOW_DIALOG_BUTTON_MENU},
|
|
{"musicscan" , WINDOW_DIALOG_MUSIC_SCAN},
|
|
{"mutebug" , WINDOW_DIALOG_MUTE_BUG},
|
|
{"playercontrols" , WINDOW_DIALOG_PLAYER_CONTROLS},
|
|
{"seekbar" , WINDOW_DIALOG_SEEK_BAR},
|
|
{"musicosd" , WINDOW_DIALOG_MUSIC_OSD},
|
|
{"pluginsettings" , WINDOW_DIALOG_PLUGIN_SETTINGS},
|
|
{"visualisationsettings" , WINDOW_DIALOG_VIS_SETTINGS},
|
|
{"visualisationpresetlist" , WINDOW_DIALOG_VIS_PRESET_LIST},
|
|
{"osdvideosettings" , WINDOW_DIALOG_VIDEO_OSD_SETTINGS},
|
|
{"osdaudiosettings" , WINDOW_DIALOG_AUDIO_OSD_SETTINGS},
|
|
{"videobookmarks" , WINDOW_DIALOG_VIDEO_BOOKMARKS},
|
|
{"filebrowser" , WINDOW_DIALOG_FILE_BROWSER},
|
|
{"networksetup" , WINDOW_DIALOG_NETWORK_SETUP},
|
|
{"mediasource" , WINDOW_DIALOG_MEDIA_SOURCE},
|
|
{"profilesettings" , WINDOW_DIALOG_PROFILE_SETTINGS},
|
|
{"locksettings" , WINDOW_DIALOG_LOCK_SETTINGS},
|
|
{"contentsettings" , WINDOW_DIALOG_CONTENT_SETTINGS},
|
|
{"favourites" , WINDOW_DIALOG_FAVOURITES},
|
|
{"songinformation" , WINDOW_DIALOG_SONG_INFO},
|
|
{"smartplaylisteditor" , WINDOW_DIALOG_SMART_PLAYLIST_EDITOR},
|
|
{"smartplaylistrule" , WINDOW_DIALOG_SMART_PLAYLIST_RULE},
|
|
{"busydialog" , WINDOW_DIALOG_BUSY},
|
|
{"pictureinfo" , WINDOW_DIALOG_PICTURE_INFO},
|
|
{"fullscreeninfo" , WINDOW_DIALOG_FULLSCREEN_INFO},
|
|
{"sliderdialog" , WINDOW_DIALOG_SLIDER},
|
|
{"musicplaylist" , WINDOW_MUSIC_PLAYLIST},
|
|
{"musicfiles" , WINDOW_MUSIC_FILES},
|
|
{"musiclibrary" , WINDOW_MUSIC_NAV},
|
|
{"musicplaylisteditor" , WINDOW_MUSIC_PLAYLIST_EDITOR},
|
|
{"selectdialog" , WINDOW_DIALOG_SELECT},
|
|
{"musicinformation" , WINDOW_MUSIC_INFO},
|
|
{"okdialog" , WINDOW_DIALOG_OK},
|
|
{"movieinformation" , WINDOW_VIDEO_INFO},
|
|
{"textviewer" , WINDOW_DIALOG_TEXT_VIEWER},
|
|
{"fullscreenvideo" , WINDOW_FULLSCREEN_VIDEO},
|
|
{"visualisation" , WINDOW_VISUALISATION},
|
|
{"slideshow" , WINDOW_SLIDESHOW},
|
|
{"filestackingdialog" , WINDOW_DIALOG_FILESTACKING},
|
|
{"weather" , WINDOW_WEATHER},
|
|
{"screensaver" , WINDOW_SCREENSAVER},
|
|
{"videoosd" , WINDOW_OSD},
|
|
{"videomenu" , WINDOW_VIDEO_MENU},
|
|
{"videotimeseek" , WINDOW_VIDEO_TIME_SEEK},
|
|
{"musicoverlay" , WINDOW_MUSIC_OVERLAY},
|
|
{"videooverlay" , WINDOW_VIDEO_OVERLAY},
|
|
{"trainersettings" , WINDOW_DIALOG_TRAINER_SETTINGS},
|
|
{"gamesaves" , WINDOW_GAMESAVES},
|
|
{"startwindow" , WINDOW_START},
|
|
{"startup" , WINDOW_STARTUP_ANIM}};
|
|
|
|
CButtonTranslator& CButtonTranslator::GetInstance()
|
|
{
|
|
static CButtonTranslator sl_instance;
|
|
return sl_instance;
|
|
}
|
|
|
|
CButtonTranslator::CButtonTranslator()
|
|
{}
|
|
|
|
CButtonTranslator::~CButtonTranslator()
|
|
{}
|
|
|
|
bool CButtonTranslator::Load()
|
|
{
|
|
translatorMap.clear();
|
|
|
|
bool success = false;
|
|
// Load the config file(s)
|
|
//first from system/keymaps/ directory
|
|
const CStdString systemKeymapDirPath = "special://xbmc/system/keymaps/";
|
|
if( XFILE::CDirectory::Exists(systemKeymapDirPath) )
|
|
{
|
|
CFileItemList files;
|
|
XFILE::CDirectory::GetDirectory(systemKeymapDirPath, files, "*.xml");
|
|
//sort the list for filesystem based prioties, e.g. 01-keymap.xml, 02-keymap-overrides.xml
|
|
files.Sort(SORT_METHOD_FILE, SORT_ORDER_ASC);
|
|
for(int i = 0; i<files.Size(); ++i)
|
|
success |= LoadKeymap(files[i]->GetPath());
|
|
}
|
|
//load from user's keymaps/ directory
|
|
const CStdString userKeymapDirPath = g_settings.GetUserDataItem("keymaps/");
|
|
if( XFILE::CDirectory::Exists(userKeymapDirPath) )
|
|
{
|
|
CFileItemList files;
|
|
XFILE::CDirectory::GetDirectory(userKeymapDirPath, files, "*.xml");
|
|
//sort the list for filesystem based prioties, e.g. 01-keymap.xml, 02-keymap-overrides.xml
|
|
files.Sort(SORT_METHOD_FILE, SORT_ORDER_ASC);
|
|
for(int i = 0; i<files.Size(); ++i)
|
|
success |= LoadKeymap(files[i]->GetPath());
|
|
}
|
|
|
|
//try to load userdata/Keymap.xml for backward compatibility
|
|
const CStdString oldKeymapPath = g_settings.GetUserDataItem("Keymap.xml");
|
|
if( CFile::Exists(oldKeymapPath) )
|
|
{
|
|
CLog::Log(LOGINFO, "CButtonTranslator::Load - old Keymap.xml in userdata found (%s). Please consider moving it to the \"keymaps/\" folder", oldKeymapPath.c_str());
|
|
success |= LoadKeymap(oldKeymapPath);
|
|
}
|
|
|
|
if (!success)
|
|
{
|
|
g_LoadErrorStr.Format("Error loading keymaps from: %s or %s", systemKeymapDirPath.c_str(), userKeymapDirPath.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Done!
|
|
return true;
|
|
}
|
|
|
|
bool CButtonTranslator::LoadKeymap(const CStdString &keymapPath)
|
|
{
|
|
TiXmlDocument xmlDoc;
|
|
|
|
CLog::Log(LOGINFO, "Loading %s", keymapPath.c_str());
|
|
if (!xmlDoc.LoadFile(keymapPath))
|
|
{
|
|
CLog::Log(LOGERROR, "Error loading keymap: %s, Line %d\n%s", keymapPath.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
|
|
return false;
|
|
}
|
|
TiXmlElement* pRoot = xmlDoc.RootElement();
|
|
CStdString strValue = pRoot->Value();
|
|
if ( strValue != "keymap")
|
|
{
|
|
CLog::Log(LOGERROR, "%s Doesn't contain <keymap>", keymapPath.c_str());
|
|
return false;
|
|
}
|
|
// run through our window groups
|
|
TiXmlNode* pWindow = pRoot->FirstChild();
|
|
while (pWindow)
|
|
{
|
|
if (pWindow->Type() == TiXmlNode::ELEMENT)
|
|
{
|
|
int windowID = WINDOW_INVALID;
|
|
const char *szWindow = pWindow->Value();
|
|
if (szWindow)
|
|
{
|
|
if (strcmpi(szWindow, "global") == 0)
|
|
windowID = -1;
|
|
else
|
|
windowID = TranslateWindow(szWindow);
|
|
}
|
|
MapWindowActions(pWindow, windowID);
|
|
}
|
|
pWindow = pWindow->NextSibling();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#if defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
|
|
void CButtonTranslator::MapJoystickActions(int windowID, TiXmlNode *pJoystick)
|
|
{
|
|
string joyname = "_xbmc_"; // default global map name
|
|
vector<string> joynames;
|
|
map<int, string> buttonMap;
|
|
map<int, string> axisMap;
|
|
|
|
TiXmlElement *pJoy = pJoystick->ToElement();
|
|
if (pJoy && pJoy->Attribute("name"))
|
|
{
|
|
joyname = pJoy->Attribute("name");
|
|
}
|
|
else
|
|
{
|
|
CLog::Log(LOGNOTICE, "No Joystick name specified, loading default map");
|
|
}
|
|
|
|
joynames.push_back(joyname);
|
|
|
|
// parse map
|
|
TiXmlElement *pButton = pJoystick->FirstChildElement();
|
|
int id = 0;
|
|
//char* szId;
|
|
const char* szType;
|
|
const char *szAction;
|
|
while (pButton)
|
|
{
|
|
szType = pButton->Value();
|
|
szAction = pButton->GetText();
|
|
if (szAction == NULL)
|
|
szAction = "";
|
|
if (szType)
|
|
{
|
|
if ((pButton->QueryIntAttribute("id", &id) == TIXML_SUCCESS) && id>=0 && id<=256)
|
|
{
|
|
if (strcmpi(szType, "button")==0)
|
|
{
|
|
buttonMap[id] = string(szAction);
|
|
}
|
|
else if (strcmpi(szType, "axis")==0)
|
|
{
|
|
int limit = 0;
|
|
if (pButton->QueryIntAttribute("limit", &limit) == TIXML_SUCCESS)
|
|
{
|
|
if (limit==-1)
|
|
{
|
|
axisMap[-id] = string(szAction);
|
|
}
|
|
else if (limit==1)
|
|
{
|
|
axisMap[id] = string(szAction);
|
|
}
|
|
else if (limit==0)
|
|
{
|
|
axisMap[id|0xFFFF0000] = string(szAction);
|
|
}
|
|
else
|
|
{
|
|
axisMap[id] = string(szAction);
|
|
axisMap[-id] = string(szAction);
|
|
CLog::Log(LOGERROR, "Error in joystick map, invalid limit specified %d for axis %d", limit, id);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
axisMap[id] = string(szAction);
|
|
axisMap[-id] = string(szAction);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CLog::Log(LOGERROR, "Error reading joystick map element, unknown button type: %s", szType);
|
|
}
|
|
}
|
|
else if (strcmpi(szType, "altname")==0)
|
|
{
|
|
joynames.push_back(string(szAction));
|
|
}
|
|
else
|
|
{
|
|
CLog::Log(LOGERROR, "Error reading joystick map element, Invalid id: %d", id);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CLog::Log(LOGERROR, "Error reading joystick map element, skipping");
|
|
}
|
|
pButton = pButton->NextSiblingElement();
|
|
}
|
|
vector<string>::iterator it = joynames.begin();
|
|
while (it!=joynames.end())
|
|
{
|
|
m_joystickButtonMap[*it][windowID] = buttonMap;
|
|
m_joystickAxisMap[*it][windowID] = axisMap;
|
|
// CLog::Log(LOGDEBUG, "Found Joystick map for window %d using %s", WindowID, it->c_str());
|
|
it++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
bool CButtonTranslator::TranslateJoystickString(int window, const char* szDevice, int id, bool axis, int& action, CStdString& strAction, bool &fullrange)
|
|
{
|
|
bool found = false;
|
|
|
|
map<string, JoystickMap>::iterator it;
|
|
map<string, JoystickMap> *jmap;
|
|
|
|
fullrange = false;
|
|
|
|
if (axis)
|
|
{
|
|
jmap = &m_joystickAxisMap;
|
|
}
|
|
else
|
|
{
|
|
jmap = &m_joystickButtonMap;
|
|
}
|
|
|
|
it = jmap->find(szDevice);
|
|
if (it==jmap->end())
|
|
return false;
|
|
|
|
JoystickMap wmap = it->second;
|
|
JoystickMap::iterator it2;
|
|
map<int, string> windowbmap;
|
|
map<int, string> globalbmap;
|
|
map<int, string>::iterator it3;
|
|
|
|
it2 = wmap.find(window);
|
|
|
|
// first try local window map
|
|
if (it2!=wmap.end())
|
|
{
|
|
windowbmap = it2->second;
|
|
it3 = windowbmap.find(id);
|
|
if (it3 != windowbmap.end())
|
|
{
|
|
strAction = (it3->second).c_str();
|
|
found = true;
|
|
}
|
|
it3 = windowbmap.find(abs(id)|0xFFFF0000);
|
|
if (it3 != windowbmap.end())
|
|
{
|
|
strAction = (it3->second).c_str();
|
|
found = true;
|
|
fullrange = true;
|
|
}
|
|
}
|
|
|
|
// if not found, try global map
|
|
if (!found)
|
|
{
|
|
it2 = wmap.find(-1);
|
|
if (it2 != wmap.end())
|
|
{
|
|
globalbmap = it2->second;
|
|
it3 = globalbmap.find(id);
|
|
if (it3 != globalbmap.end())
|
|
{
|
|
strAction = (it3->second).c_str();
|
|
found = true;
|
|
}
|
|
it3 = globalbmap.find(abs(id)|0xFFFF0000);
|
|
if (it3 != globalbmap.end())
|
|
{
|
|
strAction = (it3->second).c_str();
|
|
found = true;
|
|
fullrange = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// translated found action
|
|
if (found)
|
|
{
|
|
return TranslateActionString(strAction.c_str(), action);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
CAction CButtonTranslator::GetAction(int window, const CKey &key)
|
|
{
|
|
CStdString strAction;
|
|
// try to get the action from the current window
|
|
int actionID = GetActionCode(window, key, strAction);
|
|
// if it's invalid, try to get it from the global map
|
|
if (actionID == 0)
|
|
actionID = GetActionCode( -1, key, strAction);
|
|
// Now fill our action structure
|
|
CAction action(actionID, strAction, key);
|
|
return action;
|
|
}
|
|
|
|
int CButtonTranslator::GetActionCode(int window, const CKey &key, CStdString &strAction)
|
|
{
|
|
int code = key.GetButtonCode();
|
|
map<int, buttonMap>::iterator it = translatorMap.find(window);
|
|
if (it == translatorMap.end())
|
|
return 0;
|
|
buttonMap::iterator it2 = (*it).second.find(code);
|
|
int action = 0;
|
|
while (it2 != (*it).second.end())
|
|
{
|
|
action = (*it2).second.id;
|
|
strAction = (*it2).second.strID;
|
|
it2 = (*it).second.end();
|
|
}
|
|
return action;
|
|
}
|
|
|
|
void CButtonTranslator::MapAction(int buttonCode, const char *szAction, buttonMap &map)
|
|
{
|
|
int action = ACTION_NONE;
|
|
if (!TranslateActionString(szAction, action) || !buttonCode)
|
|
return; // no valid action, or an invalid buttoncode
|
|
// have a valid action, and a valid button - map it.
|
|
// check to see if we've already got this (button,action) pair defined
|
|
buttonMap::iterator it = map.find(buttonCode);
|
|
if (it == map.end() || (*it).second.id != action || (*it).second.strID != szAction)
|
|
{
|
|
// NOTE: This multimap is only being used as a normal map at this point (no support
|
|
// for multiple actions per key)
|
|
if (it != map.end())
|
|
map.erase(it);
|
|
CButtonAction button;
|
|
button.id = action;
|
|
button.strID = szAction;
|
|
map.insert(pair<int, CButtonAction>(buttonCode, button));
|
|
}
|
|
}
|
|
|
|
void CButtonTranslator::MapWindowActions(TiXmlNode *pWindow, int windowID)
|
|
{
|
|
if (!pWindow || windowID == WINDOW_INVALID) return;
|
|
buttonMap map;
|
|
std::map<int, buttonMap>::iterator it = translatorMap.find(windowID);
|
|
if (it != translatorMap.end())
|
|
{
|
|
map = it->second;
|
|
translatorMap.erase(it);
|
|
}
|
|
TiXmlNode* pDevice;
|
|
if ((pDevice = pWindow->FirstChild("gamepad")) != NULL)
|
|
{ // map gamepad actions
|
|
TiXmlElement *pButton = pDevice->FirstChildElement();
|
|
while (pButton)
|
|
{
|
|
int buttonCode = TranslateGamepadString(pButton->Value());
|
|
if (pButton->FirstChild())
|
|
MapAction(buttonCode, pButton->FirstChild()->Value(), map);
|
|
pButton = pButton->NextSiblingElement();
|
|
}
|
|
}
|
|
if ((pDevice = pWindow->FirstChild("remote")) != NULL)
|
|
{ // map remote actions
|
|
bool bUseMCE = g_guiSettings.GetBool("system.mceremote");
|
|
TiXmlElement *pRemote;
|
|
CStdString remoteName;
|
|
while (pDevice)
|
|
{
|
|
remoteName = "";
|
|
pRemote = pDevice->ToElement();
|
|
if (pRemote && pRemote->Attribute("name"))
|
|
remoteName = pRemote->Attribute("name");
|
|
if (bUseMCE && remoteName == "mce")
|
|
break;
|
|
else if (!bUseMCE && !pRemote)
|
|
break;
|
|
else
|
|
pDevice = pDevice->NextSibling("remote");
|
|
}
|
|
if (!pDevice)
|
|
pDevice = pWindow->FirstChild("remote");
|
|
|
|
TiXmlElement *pButton = pDevice->FirstChildElement();
|
|
while (pButton)
|
|
{
|
|
int buttonCode = TranslateRemoteString(pButton->Value());
|
|
if (pButton->FirstChild())
|
|
MapAction(buttonCode, pButton->FirstChild()->Value(), map);
|
|
pButton = pButton->NextSiblingElement();
|
|
}
|
|
}
|
|
if ((pDevice = pWindow->FirstChild("universalremote")) != NULL)
|
|
{ // map universal remote actions
|
|
TiXmlElement *pButton = pDevice->FirstChildElement();
|
|
while (pButton)
|
|
{
|
|
int buttonCode = TranslateUniversalRemoteString(pButton->Value());
|
|
if (pButton->FirstChild())
|
|
MapAction(buttonCode, pButton->FirstChild()->Value(), map);
|
|
pButton = pButton->NextSiblingElement();
|
|
}
|
|
}
|
|
if ((pDevice = pWindow->FirstChild("keyboard")) != NULL)
|
|
{ // map keyboard actions
|
|
TiXmlElement *pButton = pDevice->FirstChildElement();
|
|
while (pButton)
|
|
{
|
|
int buttonCode = TranslateKeyboardButton(pButton);
|
|
if (pButton->FirstChild())
|
|
MapAction(buttonCode, pButton->FirstChild()->Value(), map);
|
|
pButton = pButton->NextSiblingElement();
|
|
}
|
|
}
|
|
#if defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
|
|
if ((pDevice = pWindow->FirstChild("joystick")) != NULL)
|
|
{
|
|
// map joystick actions
|
|
while (pDevice)
|
|
{
|
|
MapJoystickActions(windowID, pDevice);
|
|
pDevice = pDevice->NextSibling("joystick");
|
|
}
|
|
}
|
|
#endif
|
|
// add our map to our table
|
|
if (map.size() > 0)
|
|
translatorMap.insert(pair<int, buttonMap>( windowID, map));
|
|
}
|
|
|
|
bool CButtonTranslator::TranslateActionString(const char *szAction, int &action)
|
|
{
|
|
action = ACTION_NONE;
|
|
CStdString strAction = szAction;
|
|
strAction.ToLower();
|
|
if (CBuiltins::HasCommand(strAction)) action = ACTION_BUILT_IN_FUNCTION;
|
|
|
|
if (strAction.Equals("noop"))
|
|
return true;
|
|
|
|
for (unsigned int index=0;index < sizeof(actions)/sizeof(actions[0]);++index)
|
|
{
|
|
if (strAction.Equals(actions[index].name))
|
|
{
|
|
action = actions[index].action;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (action == ACTION_NONE)
|
|
{
|
|
CLog::Log(LOGERROR, "Keymapping error: no such action '%s' defined", strAction.c_str());
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
CStdString CButtonTranslator::TranslateWindow(int windowID)
|
|
{
|
|
for (unsigned int index = 0; index < sizeof(windows) / sizeof(windows[0]); ++index)
|
|
{
|
|
if (windows[index].action == windowID)
|
|
return windows[index].name;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
int CButtonTranslator::TranslateWindow(const CStdString &window)
|
|
{
|
|
CStdString strWindow(window);
|
|
if (strWindow.IsEmpty()) return WINDOW_INVALID;
|
|
strWindow.ToLower();
|
|
// eliminate .xml
|
|
if (strWindow.Mid(strWindow.GetLength() - 4) == ".xml" )
|
|
strWindow = strWindow.Mid(0, strWindow.GetLength() - 4);
|
|
|
|
// window12345, for custom window to be keymapped
|
|
if (strWindow.length() > 6 && strWindow.Left(6).Equals("window"))
|
|
strWindow = strWindow.Mid(6);
|
|
if (strWindow.Left(2) == "my") // drop "my" prefix
|
|
strWindow = strWindow.Mid(2);
|
|
if (StringUtils::IsNaturalNumber(strWindow))
|
|
{
|
|
// allow a full window id or a delta id
|
|
int iWindow = atoi(strWindow.c_str());
|
|
if (iWindow > WINDOW_INVALID)
|
|
return iWindow;
|
|
return WINDOW_HOME + iWindow;
|
|
}
|
|
|
|
// run through the window structure
|
|
for (unsigned int index = 0; index < sizeof(windows) / sizeof(windows[0]); ++index)
|
|
{
|
|
if (strWindow.Equals(windows[index].name))
|
|
return windows[index].action;
|
|
}
|
|
|
|
CLog::Log(LOGERROR, "Window Translator: Can't find window %s", strWindow.c_str());
|
|
return WINDOW_INVALID;
|
|
}
|
|
|
|
int CButtonTranslator::TranslateGamepadString(const char *szButton)
|
|
{
|
|
if (!szButton) return 0;
|
|
int buttonCode = 0;
|
|
CStdString strButton = szButton;
|
|
strButton.ToLower();
|
|
if (strButton.Equals("a")) buttonCode = KEY_BUTTON_A;
|
|
else if (strButton.Equals("b")) buttonCode = KEY_BUTTON_B;
|
|
else if (strButton.Equals("x")) buttonCode = KEY_BUTTON_X;
|
|
else if (strButton.Equals("y")) buttonCode = KEY_BUTTON_Y;
|
|
else if (strButton.Equals("white")) buttonCode = KEY_BUTTON_WHITE;
|
|
else if (strButton.Equals("black")) buttonCode = KEY_BUTTON_BLACK;
|
|
else if (strButton.Equals("start")) buttonCode = KEY_BUTTON_START;
|
|
else if (strButton.Equals("back")) buttonCode = KEY_BUTTON_BACK;
|
|
else if (strButton.Equals("leftthumbbutton")) buttonCode = KEY_BUTTON_LEFT_THUMB_BUTTON;
|
|
else if (strButton.Equals("rightthumbbutton")) buttonCode = KEY_BUTTON_RIGHT_THUMB_BUTTON;
|
|
else if (strButton.Equals("leftthumbstick")) buttonCode = KEY_BUTTON_LEFT_THUMB_STICK;
|
|
else if (strButton.Equals("leftthumbstickup")) buttonCode = KEY_BUTTON_LEFT_THUMB_STICK_UP;
|
|
else if (strButton.Equals("leftthumbstickdown")) buttonCode = KEY_BUTTON_LEFT_THUMB_STICK_DOWN;
|
|
else if (strButton.Equals("leftthumbstickleft")) buttonCode = KEY_BUTTON_LEFT_THUMB_STICK_LEFT;
|
|
else if (strButton.Equals("leftthumbstickright")) buttonCode = KEY_BUTTON_LEFT_THUMB_STICK_RIGHT;
|
|
else if (strButton.Equals("rightthumbstick")) buttonCode = KEY_BUTTON_RIGHT_THUMB_STICK;
|
|
else if (strButton.Equals("rightthumbstickup")) buttonCode = KEY_BUTTON_RIGHT_THUMB_STICK_UP;
|
|
else if (strButton.Equals("rightthumbstickdown")) buttonCode = KEY_BUTTON_RIGHT_THUMB_STICK_DOWN;
|
|
else if (strButton.Equals("rightthumbstickleft")) buttonCode = KEY_BUTTON_RIGHT_THUMB_STICK_LEFT;
|
|
else if (strButton.Equals("rightthumbstickright")) buttonCode = KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT;
|
|
else if (strButton.Equals("lefttrigger")) buttonCode = KEY_BUTTON_LEFT_TRIGGER;
|
|
else if (strButton.Equals("righttrigger")) buttonCode = KEY_BUTTON_RIGHT_TRIGGER;
|
|
else if (strButton.Equals("leftanalogtrigger")) buttonCode = KEY_BUTTON_LEFT_ANALOG_TRIGGER;
|
|
else if (strButton.Equals("rightanalogtrigger")) buttonCode = KEY_BUTTON_RIGHT_ANALOG_TRIGGER;
|
|
else if (strButton.Equals("dpadleft")) buttonCode = KEY_BUTTON_DPAD_LEFT;
|
|
else if (strButton.Equals("dpadright")) buttonCode = KEY_BUTTON_DPAD_RIGHT;
|
|
else if (strButton.Equals("dpadup")) buttonCode = KEY_BUTTON_DPAD_UP;
|
|
else if (strButton.Equals("dpaddown")) buttonCode = KEY_BUTTON_DPAD_DOWN;
|
|
else CLog::Log(LOGERROR, "Gamepad Translator: Can't find button %s", strButton.c_str());
|
|
return buttonCode;
|
|
}
|
|
|
|
int CButtonTranslator::TranslateRemoteString(const char *szButton)
|
|
{
|
|
if (!szButton) return 0;
|
|
int buttonCode = 0;
|
|
CStdString strButton = szButton;
|
|
strButton.ToLower();
|
|
if (strButton.Equals("left")) buttonCode = XINPUT_IR_REMOTE_LEFT;
|
|
else if (strButton.Equals("right")) buttonCode = XINPUT_IR_REMOTE_RIGHT;
|
|
else if (strButton.Equals("up")) buttonCode = XINPUT_IR_REMOTE_UP;
|
|
else if (strButton.Equals("down")) buttonCode = XINPUT_IR_REMOTE_DOWN;
|
|
else if (strButton.Equals("select")) buttonCode = XINPUT_IR_REMOTE_SELECT;
|
|
else if (strButton.Equals("back")) buttonCode = XINPUT_IR_REMOTE_BACK;
|
|
else if (strButton.Equals("menu")) buttonCode = XINPUT_IR_REMOTE_MENU;
|
|
else if (strButton.Equals("info")) buttonCode = XINPUT_IR_REMOTE_INFO;
|
|
else if (strButton.Equals("display")) buttonCode = XINPUT_IR_REMOTE_DISPLAY;
|
|
else if (strButton.Equals("title")) buttonCode = XINPUT_IR_REMOTE_TITLE;
|
|
else if (strButton.Equals("play")) buttonCode = XINPUT_IR_REMOTE_PLAY;
|
|
else if (strButton.Equals("pause")) buttonCode = XINPUT_IR_REMOTE_PAUSE;
|
|
else if (strButton.Equals("reverse")) buttonCode = XINPUT_IR_REMOTE_REVERSE;
|
|
else if (strButton.Equals("forward")) buttonCode = XINPUT_IR_REMOTE_FORWARD;
|
|
else if (strButton.Equals("skipplus")) buttonCode = XINPUT_IR_REMOTE_SKIP_PLUS;
|
|
else if (strButton.Equals("skipminus")) buttonCode = XINPUT_IR_REMOTE_SKIP_MINUS;
|
|
else if (strButton.Equals("stop")) buttonCode = XINPUT_IR_REMOTE_STOP;
|
|
else if (strButton.Equals("zero")) buttonCode = XINPUT_IR_REMOTE_0;
|
|
else if (strButton.Equals("one")) buttonCode = XINPUT_IR_REMOTE_1;
|
|
else if (strButton.Equals("two")) buttonCode = XINPUT_IR_REMOTE_2;
|
|
else if (strButton.Equals("three")) buttonCode = XINPUT_IR_REMOTE_3;
|
|
else if (strButton.Equals("four")) buttonCode = XINPUT_IR_REMOTE_4;
|
|
else if (strButton.Equals("five")) buttonCode = XINPUT_IR_REMOTE_5;
|
|
else if (strButton.Equals("six")) buttonCode = XINPUT_IR_REMOTE_6;
|
|
else if (strButton.Equals("seven")) buttonCode = XINPUT_IR_REMOTE_7;
|
|
else if (strButton.Equals("eight")) buttonCode = XINPUT_IR_REMOTE_8;
|
|
else if (strButton.Equals("nine")) buttonCode = XINPUT_IR_REMOTE_9;
|
|
// additional keys from the media center extender for xbox remote
|
|
else if (strButton.Equals("power")) buttonCode = XINPUT_IR_REMOTE_POWER;
|
|
else if (strButton.Equals("mytv")) buttonCode = XINPUT_IR_REMOTE_MY_TV;
|
|
else if (strButton.Equals("mymusic")) buttonCode = XINPUT_IR_REMOTE_MY_MUSIC;
|
|
else if (strButton.Equals("mypictures")) buttonCode = XINPUT_IR_REMOTE_MY_PICTURES;
|
|
else if (strButton.Equals("myvideo")) buttonCode = XINPUT_IR_REMOTE_MY_VIDEOS;
|
|
else if (strButton.Equals("record")) buttonCode = XINPUT_IR_REMOTE_RECORD;
|
|
else if (strButton.Equals("start")) buttonCode = XINPUT_IR_REMOTE_START;
|
|
else if (strButton.Equals("volumeplus")) buttonCode = XINPUT_IR_REMOTE_VOLUME_PLUS;
|
|
else if (strButton.Equals("volumeminus")) buttonCode = XINPUT_IR_REMOTE_VOLUME_MINUS;
|
|
else if (strButton.Equals("channelplus")) buttonCode = XINPUT_IR_REMOTE_CHANNEL_PLUS;
|
|
else if (strButton.Equals("channelminus")) buttonCode = XINPUT_IR_REMOTE_CHANNEL_MINUS;
|
|
else if (strButton.Equals("pageplus")) buttonCode = XINPUT_IR_REMOTE_CHANNEL_PLUS;
|
|
else if (strButton.Equals("pageminus")) buttonCode = XINPUT_IR_REMOTE_CHANNEL_MINUS;
|
|
else if (strButton.Equals("mute")) buttonCode = XINPUT_IR_REMOTE_MUTE;
|
|
else if (strButton.Equals("recordedtv")) buttonCode = XINPUT_IR_REMOTE_RECORDED_TV;
|
|
else if (strButton.Equals("guide")) buttonCode = XINPUT_IR_REMOTE_TITLE; // same as title
|
|
else if (strButton.Equals("livetv")) buttonCode = XINPUT_IR_REMOTE_LIVE_TV;
|
|
else if (strButton.Equals("star")) buttonCode = XINPUT_IR_REMOTE_STAR;
|
|
else if (strButton.Equals("hash")) buttonCode = XINPUT_IR_REMOTE_HASH;
|
|
else if (strButton.Equals("clear")) buttonCode = XINPUT_IR_REMOTE_CLEAR;
|
|
else if (strButton.Equals("enter")) buttonCode = XINPUT_IR_REMOTE_SELECT; // same as select
|
|
else if (strButton.Equals("xbox")) buttonCode = XINPUT_IR_REMOTE_DISPLAY; // same as display
|
|
else CLog::Log(LOGERROR, "Remote Translator: Can't find button %s", strButton.c_str());
|
|
return buttonCode;
|
|
}
|
|
|
|
int CButtonTranslator::TranslateUniversalRemoteString(const char *szButton)
|
|
{
|
|
if (!szButton || strlen(szButton) < 4 || strnicmp(szButton, "obc", 3)) return 0;
|
|
const char *szCode = szButton + 3;
|
|
// Button Code is 255 - OBC (Original Button Code) of the button
|
|
int buttonCode = 255 - atol(szCode);
|
|
if (buttonCode > 255) buttonCode = 0;
|
|
return buttonCode;
|
|
}
|
|
|
|
int CButtonTranslator::TranslateKeyboardString(const char *szButton)
|
|
{
|
|
int buttonCode = 0;
|
|
if (strlen(szButton) == 1)
|
|
{ // single character
|
|
buttonCode = (int)toupper(szButton[0]) | KEY_VKEY;
|
|
// FIXME It is a printable character, printable should be ASCII not VKEY! Till now it works, but how (long)?
|
|
// FIXME support unicode: additional parameter necessary since unicode can not be embedded into key/action-ID.
|
|
}
|
|
else
|
|
{ // for keys such as return etc. etc.
|
|
CStdString strKey = szButton;
|
|
strKey.ToLower();
|
|
if (strKey.Equals("return")) buttonCode = 0xF00D;
|
|
else if (strKey.Equals("enter")) buttonCode = 0xF06C;
|
|
else if (strKey.Equals("escape")) buttonCode = 0xF01B;
|
|
else if (strKey.Equals("esc")) buttonCode = 0xF01B;
|
|
else if (strKey.Equals("tab")) buttonCode = 0xF009;
|
|
else if (strKey.Equals("space")) buttonCode = 0xF020;
|
|
else if (strKey.Equals("left")) buttonCode = 0xF025;
|
|
else if (strKey.Equals("right")) buttonCode = 0xF027;
|
|
else if (strKey.Equals("up")) buttonCode = 0xF026;
|
|
else if (strKey.Equals("down")) buttonCode = 0xF028;
|
|
else if (strKey.Equals("insert")) buttonCode = 0xF02D;
|
|
else if (strKey.Equals("delete")) buttonCode = 0xF02E;
|
|
else if (strKey.Equals("home")) buttonCode = 0xF024;
|
|
else if (strKey.Equals("end")) buttonCode = 0xF023;
|
|
else if (strKey.Equals("f1")) buttonCode = 0xF070;
|
|
else if (strKey.Equals("f2")) buttonCode = 0xF071;
|
|
else if (strKey.Equals("f3")) buttonCode = 0xF072;
|
|
else if (strKey.Equals("f4")) buttonCode = 0xF073;
|
|
else if (strKey.Equals("f5")) buttonCode = 0xF074;
|
|
else if (strKey.Equals("f6")) buttonCode = 0xF075;
|
|
else if (strKey.Equals("f7")) buttonCode = 0xF076;
|
|
else if (strKey.Equals("f8")) buttonCode = 0xF077;
|
|
else if (strKey.Equals("f9")) buttonCode = 0xF078;
|
|
else if (strKey.Equals("f10")) buttonCode = 0xF079;
|
|
else if (strKey.Equals("f11")) buttonCode = 0xF07A;
|
|
else if (strKey.Equals("f12")) buttonCode = 0xF07B;
|
|
else if (strKey.Equals("numpadzero") || strKey.Equals("zero")) buttonCode = 0xF060;
|
|
else if (strKey.Equals("numpadone") || strKey.Equals("one")) buttonCode = 0xF061;
|
|
else if (strKey.Equals("numpadtwo") || strKey.Equals("two")) buttonCode = 0xF062;
|
|
else if (strKey.Equals("numpadthree") || strKey.Equals("three")) buttonCode = 0xF063;
|
|
else if (strKey.Equals("numpadfour") || strKey.Equals("four")) buttonCode = 0xF064;
|
|
else if (strKey.Equals("numpadfive") || strKey.Equals("five")) buttonCode = 0xF065;
|
|
else if (strKey.Equals("numpadsix") || strKey.Equals("six")) buttonCode = 0xF066;
|
|
else if (strKey.Equals("numpadseven") || strKey.Equals("seven")) buttonCode = 0xF067;
|
|
else if (strKey.Equals("numpadeight") || strKey.Equals("eight")) buttonCode = 0xF068;
|
|
else if (strKey.Equals("numpadnine") || strKey.Equals("nine")) buttonCode = 0xF069;
|
|
else if (strKey.Equals("numpadtimes")) buttonCode = 0xF06A;
|
|
else if (strKey.Equals("numpadplus")) buttonCode = 0xF06B;
|
|
else if (strKey.Equals("numpadminus")) buttonCode = 0xF06D;
|
|
else if (strKey.Equals("numpadperiod")) buttonCode = 0xF06E;
|
|
else if (strKey.Equals("numpaddivide")) buttonCode = 0xF06F;
|
|
else if (strKey.Equals("pageup")) buttonCode = 0xF021;
|
|
else if (strKey.Equals("pagedown")) buttonCode = 0xF022;
|
|
else if (strKey.Equals("printscreen")) buttonCode = 0xF02A;
|
|
else if (strKey.Equals("backspace")) buttonCode = 0xF008;
|
|
else if (strKey.Equals("menu")) buttonCode = 0xF05D;
|
|
else if (strKey.Equals("pause")) buttonCode = 0xF013;
|
|
else if (strKey.Equals("leftshift")) buttonCode = 0xF0A0;
|
|
else if (strKey.Equals("rightshift")) buttonCode = 0xF0A1;
|
|
else if (strKey.Equals("leftctrl")) buttonCode = 0xF0A2;
|
|
else if (strKey.Equals("rightctrl")) buttonCode = 0xF0A3;
|
|
else if (strKey.Equals("leftalt")) buttonCode = 0xF0A4;
|
|
else if (strKey.Equals("rightalt")) buttonCode = 0xF0A5;
|
|
else if (strKey.Equals("leftwindows")) buttonCode = 0xF05B;
|
|
else if (strKey.Equals("rightwindows")) buttonCode = 0xF05C;
|
|
else if (strKey.Equals("capslock")) buttonCode = 0xF020;
|
|
else if (strKey.Equals("numlock")) buttonCode = 0xF090;
|
|
else if (strKey.Equals("scrolllock")) buttonCode = 0xF091;
|
|
else if (strKey.Equals("semicolon") || strKey.Equals("colon")) buttonCode = 0xF0BA;
|
|
else if (strKey.Equals("equals") || strKey.Equals("plus")) buttonCode = 0xF0BB;
|
|
else if (strKey.Equals("comma") || strKey.Equals("lessthan")) buttonCode = 0xF0BC;
|
|
else if (strKey.Equals("minus") || strKey.Equals("underline")) buttonCode = 0xF0BD;
|
|
else if (strKey.Equals("period") || strKey.Equals("greaterthan")) buttonCode = 0xF0BE;
|
|
else if (strKey.Equals("forwardslash") || strKey.Equals("questionmark")) buttonCode = 0xF0BF;
|
|
else if (strKey.Equals("leftquote") || strKey.Equals("tilde")) buttonCode = 0xF0C0;
|
|
else if (strKey.Equals("opensquarebracket") || strKey.Equals("openbrace")) buttonCode = 0xF0EB;
|
|
else if (strKey.Equals("backslash") || strKey.Equals("pipe")) buttonCode = 0xF0EC;
|
|
else if (strKey.Equals("closesquarebracket") || strKey.Equals("closebrace")) buttonCode = 0xF0ED;
|
|
else if (strKey.Equals("quote") || strKey.Equals("doublequote")) buttonCode = 0xF0EE;
|
|
else CLog::Log(LOGERROR, "Keyboard Translator: Can't find button %s", strKey.c_str());
|
|
}
|
|
return buttonCode;
|
|
}
|
|
|
|
int CButtonTranslator::TranslateKeyboardButton(TiXmlElement *pButton)
|
|
{
|
|
const char *szButton = pButton->Value();
|
|
|
|
if (!szButton) return 0;
|
|
CStdString strKey = szButton;
|
|
if (strKey.Equals("key"))
|
|
{
|
|
int id = 0;
|
|
if (pButton->QueryIntAttribute("id", &id) == TIXML_SUCCESS)
|
|
return id;
|
|
else
|
|
CLog::Log(LOGERROR, "Keyboard Translator: `key' button has no id");
|
|
}
|
|
else
|
|
{
|
|
return TranslateKeyboardString(szButton);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CButtonTranslator::Clear()
|
|
{
|
|
translatorMap.clear();
|
|
}
|
|
|