diff --git a/KeyConfig.cpp b/KeyConfig.cpp index 4e67a54f..cddd1f54 100644 --- a/KeyConfig.cpp +++ b/KeyConfig.cpp @@ -1,5 +1,4 @@ -#include -#include +#include #include #include "KeyConfig.h" @@ -86,9 +85,7 @@ string getKeyFromString(string line){ /* Returns a keymap consisting of the default * keybinds specified with the -k option */ -map KeyConfig::buildDefaultKeymap(){ - map keymap; - +void KeyConfig::buildDefaultKeymap(){ keymap['1'] = ACTION_DECREASE_SPEED; keymap['2'] = ACTION_INCREASE_SPEED; keymap['<'] = ACTION_REWIND; @@ -106,28 +103,26 @@ map KeyConfig::buildDefaultKeymap(){ keymap['d'] = ACTION_DECREASE_SUBTITLE_DELAY; keymap['f'] = ACTION_INCREASE_SUBTITLE_DELAY; keymap['q'] = ACTION_EXIT; - keymap[KEY_ESC] = ACTION_EXIT; + keymap[KEY_ESC_HEX] = ACTION_EXIT; keymap['p'] = ACTION_PAUSE; keymap[' '] = ACTION_PAUSE; keymap['-'] = ACTION_DECREASE_VOLUME; keymap['+'] = ACTION_INCREASE_VOLUME; keymap['='] = ACTION_INCREASE_VOLUME; - keymap[KEY_LEFT] = ACTION_SEEK_BACK_SMALL; - keymap[KEY_RIGHT] = ACTION_SEEK_FORWARD_SMALL; - keymap[KEY_DOWN] = ACTION_SEEK_BACK_LARGE; - keymap[KEY_UP] = ACTION_SEEK_FORWARD_LARGE; + keymap[KEY_LEFT_HEX] = ACTION_SEEK_BACK_SMALL; + keymap[KEY_RIGHT_HEX] = ACTION_SEEK_FORWARD_SMALL; + keymap[KEY_DOWN_HEX] = ACTION_SEEK_BACK_LARGE; + keymap[KEY_UP_HEX] = ACTION_SEEK_FORWARD_LARGE; keymap['v'] = ACTION_STEP; - - return keymap; } -/* Parses the supplied config file and turns it into a map object. +/* Parses the supplied config file and adds the values to the map objects. * NOTE: Does not work with certain filepath shortcuts (e.g. ~ as user's home) */ -map KeyConfig::parseConfigFile(string filepath){ - ifstream config_file(filepath.c_str()); - map keymap; +void KeyConfig::parseConfigFile(char* filepath){ + ifstream config_file(filepath); string line; + std::set jsset; while(getline(config_file, line)){ string str_action = getActionFromString(line); @@ -136,27 +131,86 @@ map KeyConfig::parseConfigFile(string filepath){ if(str_action != "" && key != "" && str_action[0] != '#'){ int key_action = convertStringToAction(str_action); if(key.substr(0,4) == "left"){ - keymap[KEY_LEFT] = key_action; + keymap[KEY_LEFT_HEX] = key_action; } else if(key.substr(0,5) == "right"){ - keymap[KEY_RIGHT] = key_action; + keymap[KEY_RIGHT_HEX] = key_action; } else if(key.substr(0,2) == "up"){ - keymap[KEY_UP] = key_action; + keymap[KEY_UP_HEX] = key_action; } else if(key.substr(0,4) == "down"){ - keymap[KEY_DOWN] = key_action; + keymap[KEY_DOWN_HEX] = key_action; } else if(key.substr(0,3) == "esc"){ - keymap[KEY_ESC] = key_action; + keymap[KEY_ESC_HEX] = key_action; } else if(key.substr(0,3) == "hex"){ const char *hex = key.substr(4).c_str(); if (hex) keymap[strtoul(hex,0,0)] = key_action; } + else if(key.substr(0,3) == "js "){ + string js_key = key.substr(3); + jsmap[js_key] = key_action; + string js_path = js_key.substr(0, js_key.find(' ')); + jsset.insert(js_path); + } else keymap[key[0]] = key_action; } } - return keymap; + + //Turn the set of joysticks into a vector because it is more convenient to work with later + joysticks.assign(jsset.begin(), jsset.end()); +} + +/* Default constructor that builds the default keymap */ +KeyConfig::KeyConfig(){ + buildDefaultKeymap(); + num_joysticks = 0; +} + +/* Constructor that takes a path to a config file. Falls back on the + * default keymap in case of trouble. + */ +KeyConfig::KeyConfig(char* filepath){ + parseConfigFile(filepath); + + // true if config file is empty or there was an error reading it + if(keymap.size() + jsmap.size() < 1){ + buildDefaultKeymap(); + num_joysticks = 0; + } + else if(jsmap.size() > 0){ + num_joysticks = joysticks.size(); + } +} + +/* Finds the action associated with the provided keyboard event */ +int KeyConfig::getAction(int key_pressed){ + return keymap[key_pressed]; +} + +/* Finds the action associated with the provided joystick/joystick event */ +int KeyConfig::getAction(std::string joystick, struct js_event *jse){ + //value of 0 is either a button release or a dead joystick + if(jse->value == 0) + return -1; + + std::string key_string = joystick; + + if((jse->type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON){ + key_string.append(" b"); + key_string.append(to_string(jse->number)); + } + else if((jse->type & ~JS_EVENT_INIT) == JS_EVENT_AXIS){ + key_string.append(" a"); + key_string.append(to_string(jse->number)); + + if(jse->value > 0) + key_string.append("+"); + else if(jse->value < 0) + key_string.append("-"); + } + return jsmap[key_string]; } diff --git a/KeyConfig.h b/KeyConfig.h index c59e1414..966d4fd5 100644 --- a/KeyConfig.h +++ b/KeyConfig.h @@ -1,5 +1,8 @@ #include +#include #include +#include +#include class KeyConfig{ @@ -30,12 +33,27 @@ class KeyConfig{ ACTION_STEP }; - #define KEY_LEFT 0x5b44 - #define KEY_RIGHT 0x5b43 - #define KEY_UP 0x5b41 - #define KEY_DOWN 0x5b42 - #define KEY_ESC 27 + #define KEY_LEFT_HEX 0x5b44 + #define KEY_RIGHT_HEX 0x5b43 + #define KEY_UP_HEX 0x5b41 + #define KEY_DOWN_HEX 0x5b42 + #define KEY_ESC_HEX 27 - static std::map buildDefaultKeymap(); - static std::map parseConfigFile(std::string filepath); + KeyConfig(); + KeyConfig(char*); + + int getAction(int key); + int getAction(std::string joystick, struct js_event *jse); + + std::vector getJoysticks(){ return joysticks; } + int getNumJoysticks(){ return joysticks.size(); } + + private: + std::map keymap; + std::map jsmap; + std::vector joysticks; + int num_joysticks; + + void buildDefaultKeymap(); + void parseConfigFile(char* filepath); }; diff --git a/README.md b/README.md index 05e14e15..4bd69f5e 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,8 @@ While playing you can use the following keys to control omxplayer: Key Config Syntax ----------------- -A key config file is a series of rules of the form [action]:[key]. Multiple keys can be bound +A key config file is a series of rules of the form [action]:[key]. Keyboard input +is supported as well as input from multiple joysticks. Multiple keys can be bound to the same action, and comments are supported by adding a # in front of the line. The list of valid [action]s roughly corresponds to the list of default key bindings above and are: @@ -146,6 +147,7 @@ The list of valid [action]s roughly corresponds to the list of default key bindi STEP Valid [key]s include all alpha-numeric characters and most symbols, as well as: + left right up @@ -153,8 +155,22 @@ Valid [key]s include all alpha-numeric characters and most symbols, as well as: esc hex [keycode] +Joystick inputs are defined of the form: + + js /path/to/js a[number][+-] + js /path/to/js b[number] + +Where /path/to/js is the path to the joystick (usually something like /dev/input/js0), +a denotes an axis is being bound, b denotes a button being bound, [number] is the +number of the joystick axis or button, and [+-] designates which direction (positive or +negative) of motion on the axis will trigger the event. Joystick axis and button +numbers can easily be discovered by using jstest. You do not need to declare the +joysticks anywhere in the file; the parser will build the list of joysticks +from the ones it finds that have buttons/axes bound. + For example: + #Keyboard bindings EXIT:esc PAUSE:p #Note that this next line has a space after the : @@ -162,3 +178,9 @@ For example: REWIND:left SEEK_FORWARD_SMALL:hex 0x4f43 EXIT:q + + #Joystick bindings + SEEK_FORWARD_SMALL:js /dev/input/js0 a0+ + SEEK_BACK_SMALL:js /dev/input/js0 a0- + EXIT:js /dev/input/js0 b6 + PAUSE:js /dev/input/js1 b0 diff --git a/omxplayer.cpp b/omxplayer.cpp index d224c2f2..802e5865 100644 --- a/omxplayer.cpp +++ b/omxplayer.cpp @@ -558,6 +558,8 @@ int main(int argc, char *argv[]) float video_queue_size = 0.0; float m_threshold = 0.1f; // amount of audio/video required to come out of buffering TV_DISPLAY_STATE_T tv_state; + int *joystick_fds = 0; + vector joysticks; const int font_opt = 0x100; const int italic_font_opt = 0x201; @@ -622,7 +624,7 @@ int main(int argc, char *argv[]) std::string mode; //Build default keymap just in case the --key-config option isn't used - map keymap = KeyConfig::buildDefaultKeymap(); + KeyConfig * keymap = new KeyConfig; while ((c = getopt_long(argc, argv, "wihvkn:l:o:cslbpd3:yzt:rg", longopts, NULL)) != -1) { @@ -747,7 +749,8 @@ int main(int argc, char *argv[]) m_blank_background = true; break; case key_config_opt: - keymap = KeyConfig::parseConfigFile(optarg); + keymap = new KeyConfig(optarg); + joysticks = keymap->getJoysticks(); break; case 0: break; @@ -974,10 +977,27 @@ int main(int argc, char *argv[]) PrintSubtitleInfo(); + // Open joystick file descriptors + if(keymap->getNumJoysticks() > 0){ + joystick_fds = (int*) malloc(keymap->getNumJoysticks() * sizeof(int)); + for(unsigned int i=0; i < joysticks.size(); i++){ + joystick_fds[i] = open(joysticks[i].c_str(), O_RDONLY | O_NONBLOCK); + } + } + while(!m_stop) { int ch[8]; int chnum = 0; + struct js_event jse; + memset(&jse, 0, sizeof(struct js_event)); + + int num_actions = 1 + keymap->getNumJoysticks(); + int current_actions[num_actions]; // 0 = stdin, 1-n are joysticks + + for(int i = 0; i < num_actions; i++){ + current_actions[i] = -1; + } if(g_abort) goto do_exit; @@ -988,7 +1008,20 @@ int main(int argc, char *argv[]) if (chnum > 1) ch[0] = ch[chnum - 1] | (ch[chnum - 2] << 8); - switch(keymap[ch[0]]) + current_actions[0] = keymap->getAction(ch[0]); + + // skip stdin + for(int i=0; i < num_actions-1; i++){ + if(joystick_fds[i] > 0){ + int bytes = read(joystick_fds[i], &jse, sizeof(struct js_event)); + if(bytes == sizeof(struct js_event)){ + current_actions[i+1] = keymap->getAction(joysticks[i], &jse); + } + } + } + + for(int i=0; i < num_actions; i++){ + switch(current_actions[i]) { case KeyConfig::ACTION_SHOW_INFO: m_tv_show_info = !m_tv_show_info; @@ -1187,6 +1220,7 @@ int main(int argc, char *argv[]) default: break; } + } if(m_seek_flush || m_incr != 0) { @@ -1448,6 +1482,9 @@ int main(int argc, char *argv[]) g_OMX.Deinitialize(); g_RBP.Deinitialize(); + free(joystick_fds); + delete keymap; + printf("have a nice day ;)\n"); return 1; }