changeset 25263:96d0992c7920

Remove hardcoded key->cmd bindings in libmenu, support custom key bindings by menu config file.
author ulion
date Tue, 04 Dec 2007 10:42:59 +0000
parents f1922d2b1925
children 42aa06653705
files etc/menu.conf input/input.c input/input.h libmenu/menu.c libmenu/menu.h libmenu/menu_cmdlist.c libmenu/menu_console.c libmenu/menu_filesel.c libmenu/menu_list.c libmenu/menu_list.h libmenu/menu_param.c libmenu/menu_pt.c libmenu/menu_txt.c libmenu/vf_menu.c
diffstat 14 files changed, 202 insertions(+), 126 deletions(-) [+]
line wrap: on
line diff
--- a/etc/menu.conf	Mon Dec 03 23:38:51 2007 +0000
+++ b/etc/menu.conf	Tue Dec 04 10:42:59 2007 +0000
@@ -1,3 +1,23 @@
+<keybindings name="default">
+    <binding key="UP" cmd="menu up" />
+    <binding key="DOWN" cmd="menu down" />
+    <binding key="LEFT" cmd="menu left" />
+    <binding key="RIGHT" cmd="menu right" />
+    <binding key="ENTER" cmd="menu ok" />
+    <binding key="ESC" cmd="menu cancel" />
+    <binding key="HOME" cmd="menu home" />
+    <binding key="END" cmd="menu end" />
+    <binding key="PGUP" cmd="menu pageup" />
+    <binding key="PGDWN" cmd="menu pagedown" />
+</keybindings>
+<keybindings name="list" parent="default" />
+<keybindings name="filesel" parent="list">
+    <binding key="BS" cmd="menu left" />
+</keybindings>
+<keybindings name="cmdlist" parent="list" />
+<keybindings name="txt" parent="list" />
+<keybindings name="pt" parent="list" />
+<keybindings name="pref" parent="list" />
 
 <txt name="man" file="manpage.txt"/>
 
--- a/input/input.c	Mon Dec 03 23:38:51 2007 +0000
+++ b/input/input.c	Tue Dec 04 10:42:59 2007 +0000
@@ -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
--- a/input/input.h	Mon Dec 03 23:38:51 2007 +0000
+++ b/input/input.h	Tue Dec 04 10:42:59 2007 +0000
@@ -238,6 +238,9 @@
 
 void mp_input_rm_event_fd(int fd);
 
+/// Get input key from its 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.
--- a/libmenu/menu.c	Mon Dec 03 23:38:51 2007 +0000
+++ b/libmenu/menu.c	Tue Dec 04 10:42:59 2007 +0000
@@ -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,18 @@
   NULL
 };
 
+typedef struct key_cmd_s {
+  int key;
+  char *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 +69,18 @@
 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;
 
 
+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 +107,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;
+        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) {
+            mp_msg(MSGT_GLOBAL,MSGL_V,
+                   "[libmenu] got keybinding element %s %s=>[%s].\n",
+                   element, key, cmd ? cmd : "");
+            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 = cmd ? strdup(cmd)
+                                                                : NULL;
+            ++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 +254,34 @@
   }
   free(menu_list);
   menu_count = 0;
+  for (i = 0; i < cmd_bindings_num; ++i) {
+    free(cmd_bindings[i].name);
+    while(cmd_bindings[i].binding_num > 0)
+      free(cmd_bindings[i].bindings[--cmd_bindings[i].binding_num].cmd);
+    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)
+          mp_input_queue_cmd(mp_input_parse_cmd(bindings->bindings[i].cmd));
+        return 1;
+      }
+    }
+    bindings = bindings->parent;
   }
+  return 0;
 }
 
 menu_t* menu_open(char *name) {
--- a/libmenu/menu.h	Mon Dec 03 23:38:51 2007 +0000
+++ b/libmenu/menu.h	Tue Dec 04 10:42:59 2007 +0000
@@ -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
 
--- a/libmenu/menu_cmdlist.c	Mon Dec 03 23:38:51 2007 +0000
+++ b/libmenu/menu_cmdlist.c	Tue Dec 04 10:42:59 2007 +0000
@@ -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) {
--- a/libmenu/menu_console.c	Mon Dec 03 23:38:51 2007 +0000
+++ b/libmenu/menu_console.c	Tue Dec 04 10:42:59 2007 +0000
@@ -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,27 +408,31 @@
     }
     return;
   }
-  case KEY_DELETE:
-  case KEY_BS: {
+  case MENU_CMD_UP:
+    if(mpriv->cur_history->prev)
+      mpriv->cur_history = mpriv->cur_history->prev;
+    break;
+  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;
   }
-  case KEY_UP:
-    if(mpriv->cur_history->prev)
-      mpriv->cur_history = mpriv->cur_history->prev;
-    break;
-  case KEY_DOWN:
-    if(mpriv->cur_history->next)
-      mpriv->cur_history = mpriv->cur_history->next;
-    break;
-  }
-
-  if(mpriv->child && mpriv->raw_child) {
-    write(mpriv->child_fd[0],&c,sizeof(int));
+  if (menu_dflt_read_key(menu, c))
     return;
-  }
 
   if(isascii(c)) {
     int l = strlen(mpriv->cur_history->buffer);
@@ -453,7 +443,7 @@
     mpriv->cur_history->buffer[l] = (char)c;
     mpriv->cur_history->buffer[l+1] = '\0';
   }
-
+  return;
 }
 
 
--- a/libmenu/menu_filesel.c	Mon Dec 03 23:38:51 2007 +0000
+++ b/libmenu/menu_filesel.c	Tue Dec 04 10:42:59 2007 +0000
@@ -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) {
--- a/libmenu/menu_list.c	Mon Dec 03 23:38:51 2007 +0000
+++ b/libmenu/menu_list.c	Tue Dec 04 10:42:59 2007 +0000
@@ -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,57 +210,25 @@
   }    
 }
 
-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);
-}
-
-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);
-  }    
+    return 1;
+  }
+  return 0;
 }
 
 void menu_list_add_entry(menu_t* menu,list_entry_t* entry) {
--- a/libmenu/menu_list.h	Mon Dec 03 23:38:51 2007 +0000
+++ b/libmenu/menu_list.h	Tue Dec 04 10:42:59 2007 +0000
@@ -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;
 
--- a/libmenu/menu_param.c	Mon Dec 03 23:38:51 2007 +0000
+++ b/libmenu/menu_param.c	Tue Dec 04 10:42:59 2007 +0000
@@ -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;
 
 
--- a/libmenu/menu_pt.c	Mon Dec 03 23:38:51 2007 +0000
+++ b/libmenu/menu_pt.c	Tue Dec 04 10:42:59 2007 +0000
@@ -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) {
--- a/libmenu/menu_txt.c	Mon Dec 03 23:38:51 2007 +0000
+++ b/libmenu/menu_txt.c	Tue Dec 04 10:42:59 2007 +0000
@@ -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);
--- a/libmenu/vf_menu.c	Mon Dec 03 23:38:51 2007 +0000
+++ b/libmenu/vf_menu.c	Tue Dec 04 10:42:59 2007 +0000
@@ -73,6 +73,14 @@
       menu_read_cmd(priv->current,MENU_CMD_OK);
     else if(strcmp(arg,"cancel") == 0)
       menu_read_cmd(priv->current,MENU_CMD_CANCEL);
+    else if(strcmp(arg,"home") == 0)
+      menu_read_cmd(priv->current,MENU_CMD_HOME);
+    else if(strcmp(arg,"end") == 0)
+      menu_read_cmd(priv->current,MENU_CMD_END);
+    else if(strcmp(arg,"pageup") == 0)
+      menu_read_cmd(priv->current,MENU_CMD_PAGE_UP);
+    else if(strcmp(arg,"pagedown") == 0)
+      menu_read_cmd(priv->current,MENU_CMD_PAGE_DOWN);
     else if(strcmp(arg,"hide") == 0 || strcmp(arg,"toggle") == 0)
       priv->current->show = 0;
     else