Index: etc/menu.conf
===================================================================
--- etc/menu.conf (revision 25213)
+++ etc/menu.conf (working copy)
@@ -1,3 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: input/input.c
===================================================================
--- input/input.c (revision 25213)
+++ input/input.c (working copy)
@@ -1373,7 +1373,7 @@
}
-static int
+int
mp_input_get_key_from_name(const char *name) {
int i,ret = 0,len = strlen(name);
if(len == 1) { // Direct key code
Index: input/input.h
===================================================================
--- input/input.h (revision 25213)
+++ input/input.h (working copy)
@@ -238,6 +238,9 @@
void mp_input_rm_event_fd(int fd);
+/// Get cmd from name.
+int mp_input_get_key_from_name(const char *name);
+
// This function can be used to put a command in the system again. It's used by libmpdemux
// when it performs a blocking operation to resend the command it received to the main
// loop.
Index: libmenu/menu_list.c
===================================================================
--- libmenu/menu_list.c (revision 25213)
+++ libmenu/menu_list.c (working copy)
@@ -153,6 +153,8 @@
}
void menu_list_read_cmd(menu_t* menu,int cmd) {
+ list_entry_t* m;
+ int i;
switch(cmd) {
case MENU_CMD_UP:
while(mpriv->current->prev) {
@@ -179,6 +181,27 @@
if(!mpriv->current->hide) return;
}
break;
+ case MENU_CMD_HOME:
+ mpriv->current = mpriv->menu;
+ break;
+ case MENU_CMD_END:
+ for(m = mpriv->current ; m && m->next ; m = m->next)
+ /**/;
+ if(m)
+ mpriv->current = m;
+ break;
+ case MENU_CMD_PAGE_UP:
+ for(i = 0, m = mpriv->current ; m && m->prev && i < mpriv->disp_lines ; m = m->prev, i++)
+ /**/;
+ if(m)
+ mpriv->current = m;
+ break;
+ case MENU_CMD_PAGE_DOWN:
+ for(i = 0, m = mpriv->current ; m && m->next && i < mpriv->disp_lines ; m = m->next, i++)
+ /**/;
+ if(m)
+ mpriv->current = m;
+ break;
case MENU_CMD_LEFT:
case MENU_CMD_CANCEL:
menu->show = 0;
@@ -187,59 +210,27 @@
}
}
-void menu_list_jump_to_key(menu_t* menu,int c) {
+int menu_list_jump_to_key(menu_t* menu,int c) {
if(c < 256 && isalnum(c)) {
list_entry_t* e = mpriv->current;
if(e->txt[0] == c) e = e->next;
for( ; e ; e = e->next) {
if(e->txt[0] == c) {
mpriv->current = e;
- return;
+ return 1;
}
}
for(e = mpriv->menu ; e ; e = e->next) {
if(e->txt[0] == c) {
mpriv->current = e;
- return;
+ return 1;
}
}
- } else
- menu_dflt_read_key(menu,c);
+ return 1;
+ }
+ return 0;
}
-void menu_list_read_key(menu_t* menu,int c,int jump_to) {
- list_entry_t* m;
- int i;
- switch(c) {
- case KEY_HOME:
- mpriv->current = mpriv->menu;
- break;
- case KEY_END:
- for(m = mpriv->current ; m && m->next ; m = m->next)
- /**/;
- if(m)
- mpriv->current = m;
- break;
- case KEY_PAGE_UP:
- for(i = 0, m = mpriv->current ; m && m->prev && i < mpriv->disp_lines ; m = m->prev, i++)
- /**/;
- if(m)
- mpriv->current = m;
- break;
- case KEY_PAGE_DOWN:
- for(i = 0, m = mpriv->current ; m && m->next && i < mpriv->disp_lines ; m = m->next, i++)
- /**/;
- if(m)
- mpriv->current = m;
- break;
- default:
- if(jump_to)
- menu_list_jump_to_key(menu,c);
- else
- menu_dflt_read_key(menu,c);
- }
-}
-
void menu_list_add_entry(menu_t* menu,list_entry_t* entry) {
list_entry_t* l;
mpriv->count++;
Index: libmenu/menu_cmdlist.c
===================================================================
--- libmenu/menu_cmdlist.c (revision 25213)
+++ libmenu/menu_cmdlist.c (working copy)
@@ -91,10 +91,6 @@
}
}
-static void read_key(menu_t* menu,int c){
- menu_list_read_key(menu,c,0);
-}
-
static void free_entry(list_entry_t* entry) {
if(entry->ok)
free(entry->ok);
@@ -152,7 +148,6 @@
static int open_cmdlist(menu_t* menu, char* args) {
menu->draw = menu_list_draw;
menu->read_cmd = read_cmd;
- menu->read_key = read_key;
menu->close = close_menu;
if(!args) {
Index: libmenu/menu_txt.c
===================================================================
--- libmenu/menu_txt.c (revision 25213)
+++ libmenu/menu_txt.c (working copy)
@@ -66,26 +66,19 @@
menu->show = 0;
menu->cl = 1;
break;
- }
-}
-
-static void read_key(menu_t* menu,int c) {
- switch (c) {
- case KEY_HOME:
+ case MENU_CMD_HOME:
mpriv->cur_line = 0;
break;
- case KEY_END:
+ case MENU_CMD_END:
mpriv->cur_line = mpriv->num_lines - 1;
break;
- case KEY_PAGE_UP:
+ case MENU_CMD_PAGE_UP:
mpriv->cur_line = mpriv->cur_line > mpriv->disp_lines ?
mpriv->cur_line - mpriv->disp_lines : 0;
break;
- case KEY_PAGE_DOWN:
+ case MENU_CMD_PAGE_DOWN:
mpriv->cur_line = mpriv->cur_line + mpriv->disp_lines > mpriv->num_lines - 1 ? mpriv->num_lines - 1 : mpriv->cur_line + mpriv->disp_lines;
break;
- default:
- menu_dflt_read_key(menu,c);
}
}
@@ -129,7 +122,6 @@
menu->draw = draw;
menu->read_cmd = read_cmd;
- menu->read_key = read_key;
if(!mpriv->file) {
mp_msg(MSGT_GLOBAL,MSGL_WARN,MSGTR_LIBMENU_MenuTxtNeedATxtFileName);
Index: libmenu/menu.c
===================================================================
--- libmenu/menu.c (revision 25236)
+++ libmenu/menu.c (working copy)
@@ -15,6 +15,7 @@
#include "osdep/keycodes.h"
#include "asxparser.h"
#include "stream/stream.h"
+#include "input/input.h"
#include "libmpcodecs/img_format.h"
#include "libmpcodecs/mp_image.h"
@@ -46,6 +47,32 @@
NULL
};
+static mp_key_name_t menu_cmd_names[] = {
+ { MENU_CMD_UP, "menu up" },
+ { MENU_CMD_DOWN, "menu down" },
+ { MENU_CMD_OK, "menu ok" },
+ { MENU_CMD_CANCEL, "menu cancel" },
+ { MENU_CMD_LEFT, "menu left" },
+ { MENU_CMD_RIGHT, "menu right" },
+ { MENU_CMD_HOME, "menu home" },
+ { MENU_CMD_END, "menu end" },
+ { MENU_CMD_PAGE_UP, "menu pageup" },
+ { MENU_CMD_PAGE_DOWN, "menu pagedown" },
+ { -1, NULL },
+};
+
+typedef struct key_cmd_s {
+ int key;
+ int cmd;
+} key_cmd_t;
+
+typedef struct menu_cmd_bindings_s {
+ char *name;
+ key_cmd_t *bindings;
+ int binding_num;
+ struct menu_cmd_bindings_s *parent;
+} menu_cmd_bindings_t;
+
struct menu_def_st {
char* name;
menu_info_t* type;
@@ -56,8 +83,27 @@
static struct MPContext *menu_ctx = NULL;
static menu_def_t* menu_list = NULL;
static int menu_count = 0;
+static menu_cmd_bindings_t *cmd_bindings = NULL;
+static int cmd_bindings_num = 0;
+static int get_menu_cmd_from_name(const char *name) {
+ int i;
+ if (!name)
+ return -1;
+ for(i = 0; menu_cmd_names[i].name != NULL; i++)
+ if(strcasecmp(menu_cmd_names[i].name,name) == 0)
+ return menu_cmd_names[i].key;
+ return -2;
+}
+menu_cmd_bindings_t *get_cmd_bindings(const char *name) {
+ int i;
+ for (i = 0; i < cmd_bindings_num; ++i)
+ if (!strcasecmp(cmd_bindings[i].name, name))
+ return &cmd_bindings[i];
+ return NULL;
+}
+
static int menu_parse_config(char* buffer) {
char *element,*body, **attribs, *name;
menu_info_t* minfo = NULL;
@@ -84,6 +130,59 @@
continue;
}
+ if (!strcasecmp(element, "keybindings")) {
+ menu_cmd_bindings_t *bindings = cmd_bindings;
+ const char *parent_bindings;
+ cmd_bindings = realloc(cmd_bindings,
+ (cmd_bindings_num+1)*sizeof(menu_cmd_bindings_t));
+ for (i = 0; i < cmd_bindings_num; ++i)
+ if (cmd_bindings[i].parent)
+ cmd_bindings[i].parent = cmd_bindings[i].parent-bindings+cmd_bindings;
+ bindings = &cmd_bindings[cmd_bindings_num];
+ memset(bindings, 0, sizeof(menu_cmd_bindings_t));
+ bindings->name = strdup(name);
+ parent_bindings = asx_get_attrib("parent",attribs);
+ if (parent_bindings)
+ bindings->parent = get_cmd_bindings(parent_bindings);
+ free(element);
+ asx_free_attribs(attribs);
+ if (body) {
+ char *bd = body;
+ char *b, *key, *cmd;
+ int keycode, cmdcode;
+ for(;;) {
+ r = asx_get_element(parser,&bd,&element,&b,&attribs);
+ if(r < 0) {
+ mp_msg(MSGT_GLOBAL,MSGL_WARN,MSGTR_LIBMENU_SyntaxErrorAtLine,
+ parser->line);
+ free(body);
+ asx_parser_free(parser);
+ return 0;
+ }
+ if(r == 0)
+ break;
+ key = asx_get_attrib("key",attribs);
+ cmd = asx_get_attrib("cmd",attribs);
+ if (key && (keycode = mp_input_get_key_from_name(key)) >= 0
+ && (cmdcode = get_menu_cmd_from_name(cmd)) >= -1) {
+ mp_msg(MSGT_GLOBAL,MSGL_V,
+ "[libmenu] got keybinding element %s %d=>%d\n",
+ element, keycode, cmdcode);
+ bindings->bindings = realloc(bindings->bindings,
+ (bindings->binding_num+1)*sizeof(key_cmd_t));
+ bindings->bindings[bindings->binding_num].key = keycode;
+ bindings->bindings[bindings->binding_num].cmd = cmdcode;
+ ++bindings->binding_num;
+ }
+ free(element);
+ asx_free_attribs(attribs);
+ free(b);
+ }
+ free(body);
+ }
+ ++cmd_bindings_num;
+ continue;
+ }
// Try to find this menu type in our list
for(i = 0, minfo = NULL ; menu_info_list[i] ; i++) {
if(strcasecmp(element,menu_info_list[i]->name) == 0) {
@@ -178,30 +277,32 @@
}
free(menu_list);
menu_count = 0;
+ for (i = 0; i < cmd_bindings_num; ++i) {
+ free(cmd_bindings[i].name);
+ free(cmd_bindings[i].bindings);
+ }
+ free(cmd_bindings);
}
/// Default read_key function
-void menu_dflt_read_key(menu_t* menu,int cmd) {
- switch(cmd) {
- case KEY_UP:
- menu->read_cmd(menu,MENU_CMD_UP);
- break;
- case KEY_DOWN:
- menu->read_cmd(menu,MENU_CMD_DOWN);
- break;
- case KEY_LEFT:
- menu->read_cmd(menu,MENU_CMD_LEFT);
- break;
- case KEY_ESC:
- menu->read_cmd(menu,MENU_CMD_CANCEL);
- break;
- case KEY_RIGHT:
- menu->read_cmd(menu,MENU_CMD_RIGHT);
- break;
- case KEY_ENTER:
- menu->read_cmd(menu,MENU_CMD_OK);
- break;
+int menu_dflt_read_key(menu_t* menu,int cmd) {
+ int i;
+ menu_cmd_bindings_t *bindings = get_cmd_bindings(menu->type->name);
+ if (!bindings)
+ bindings = get_cmd_bindings(menu->type->type->name);
+ if (!bindings)
+ bindings = get_cmd_bindings("default");
+ while (bindings) {
+ for (i = 0; i < bindings->binding_num; ++i) {
+ if (bindings->bindings[i].key == cmd) {
+ if (bindings->bindings[i].cmd >= 0)
+ menu->read_cmd(menu, bindings->bindings[i].cmd);
+ return 1;
+ }
+ }
+ bindings = bindings->parent;
}
+ return 0;
}
menu_t* menu_open(char *name) {
Index: libmenu/menu_list.h
===================================================================
--- libmenu/menu_list.h (revision 25213)
+++ libmenu/menu_list.h (working copy)
@@ -38,12 +38,11 @@
typedef void (*free_entry_t)(list_entry_t* entry);
void menu_list_read_cmd(menu_t* menu,int cmd);
-void menu_list_read_key(menu_t* menu,int c,int jump_to);
void menu_list_draw(menu_t* menu,mp_image_t* mpi);
void menu_list_add_entry(menu_t* menu,list_entry_t* entry);
void menu_list_init(menu_t* menu);
void menu_list_uninit(menu_t* menu,free_entry_t free_func);
-void menu_list_jump_to_key(menu_t* menu,int c);
+int menu_list_jump_to_key(menu_t* menu,int c);
extern const menu_list_priv_t menu_list_priv_dflt;
Index: libmenu/menu_param.c
===================================================================
--- libmenu/menu_param.c (revision 25213)
+++ libmenu/menu_param.c (working copy)
@@ -157,10 +157,6 @@
}
}
-static void read_key(menu_t* menu,int c) {
- menu_list_read_key(menu,c,0);
-}
-
static void read_cmd(menu_t* menu,int cmd) {
list_entry_t* e = mpriv->p.current;
@@ -247,7 +243,6 @@
menu->draw = menu_list_draw;
menu->read_cmd = read_cmd;
- menu->read_key = read_key;
menu->close = closeMenu;
Index: libmenu/menu_console.c
===================================================================
--- libmenu/menu_console.c (revision 25213)
+++ libmenu/menu_console.c (working copy)
@@ -221,20 +221,6 @@
return;
}
-static void read_cmd(menu_t* menu,int cmd) {
- switch(cmd) {
- case MENU_CMD_UP:
- break;
- case MENU_CMD_DOWN:
- case MENU_CMD_OK:
- break;
- case MENU_CMD_CANCEL:
- menu->show = 0;
- menu->cl = 1;
- break;
- }
-}
-
static void check_child(menu_t* menu) {
#ifndef __MINGW32__
fd_set rfd;
@@ -362,16 +348,16 @@
//mpriv->input = mpriv->cur_history->buffer;
}
-static void read_key(menu_t* menu,int c) {
- if(!mpriv->child || !mpriv->raw_child) switch(c) {
- case KEY_ESC:
+static void read_cmd(menu_t* menu,int cmd) {
+ switch(cmd) {
+ case MENU_CMD_CANCEL:
if(mpriv->hide_time)
mpriv->hide_ts = GetTimerMS();
else
menu->show = 0;
mpriv->show_ts = 0;
return;
- case KEY_ENTER: {
+ case MENU_CMD_OK: {
mp_cmd_t* c;
if(mpriv->child) {
char *str = mpriv->cur_history->buffer;
@@ -422,28 +408,32 @@
}
return;
}
- case KEY_DELETE:
- case KEY_BS: {
- unsigned int i = strlen(mpriv->cur_history->buffer);
- if(i > 0)
- mpriv->cur_history->buffer[i-1] = '\0';
- return;
- }
- case KEY_UP:
+ case MENU_CMD_UP:
if(mpriv->cur_history->prev)
mpriv->cur_history = mpriv->cur_history->prev;
break;
- case KEY_DOWN:
+ case MENU_CMD_DOWN:
if(mpriv->cur_history->next)
mpriv->cur_history = mpriv->cur_history->next;
break;
}
+}
+static void read_key(menu_t* menu,int c) {
if(mpriv->child && mpriv->raw_child) {
write(mpriv->child_fd[0],&c,sizeof(int));
return;
}
+ if (c == KEY_DELETE || c == KEY_BS) {
+ unsigned int i = strlen(mpriv->cur_history->buffer);
+ if(i > 0)
+ mpriv->cur_history->buffer[i-1] = '\0';
+ return;
+ }
+ if (menu_dflt_read_key(menu, c))
+ return;
+
if(isascii(c)) {
int l = strlen(mpriv->cur_history->buffer);
if(l >= mpriv->cur_history->size) {
@@ -453,7 +443,7 @@
mpriv->cur_history->buffer[l] = (char)c;
mpriv->cur_history->buffer[l+1] = '\0';
}
-
+ return;
}
Index: libmenu/menu_filesel.c
===================================================================
--- libmenu/menu_filesel.c (revision 25213)
+++ libmenu/menu_filesel.c (working copy)
@@ -370,19 +370,16 @@
}
static void read_key(menu_t* menu,int c){
- if(c == KEY_BS)
- read_cmd(menu,MENU_CMD_LEFT);
- else {
char **str;
for (str=mpriv->actions; str && *str; str++)
if (c == (*str)[0]) {
action = &(*str)[2];
read_cmd(menu,MENU_CMD_ACTION);
- break;
+ return;
}
- if (!str || !*str)
- menu_list_read_key(menu,c,1);
- }
+ if (menu_dflt_read_key(menu, c))
+ return;
+ menu_list_jump_to_key(menu, c);
}
static void clos(menu_t* menu) {
Index: libmenu/menu_pt.c
===================================================================
--- libmenu/menu_pt.c (revision 25213)
+++ libmenu/menu_pt.c (working copy)
@@ -96,7 +96,9 @@
}
static void read_key(menu_t* menu,int c){
- menu_list_read_key(menu,c,1);
+ if (menu_dflt_read_key(menu, c))
+ return;
+ menu_list_jump_to_key(menu, c);
}
static void close_menu(menu_t* menu) {
Index: libmenu/menu.h
===================================================================
--- libmenu/menu.h (revision 25236)
+++ libmenu/menu.h (working copy)
@@ -38,6 +38,10 @@
#define MENU_CMD_LEFT 4
#define MENU_CMD_RIGHT 5
#define MENU_CMD_ACTION 6
+#define MENU_CMD_HOME 7
+#define MENU_CMD_END 8
+#define MENU_CMD_PAGE_UP 9
+#define MENU_CMD_PAGE_DOWN 10
/// Global init/uninit
int menu_init(struct MPContext *mpctx, char* cfg_file);
@@ -52,7 +56,7 @@
void menu_read_key(menu_t* menu,int cmd);
//// Default implementation
-void menu_dflt_read_key(menu_t* menu,int cmd);
+int menu_dflt_read_key(menu_t* menu,int cmd);
/////////// Helpers