summaryrefslogtreecommitdiffstats
path: root/libmenu
diff options
context:
space:
mode:
authoralbeu <albeu@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-11-14 23:47:11 +0000
committeralbeu <albeu@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-11-14 23:47:11 +0000
commitc83ebc0b7df94135390661a0d7a1a7b9bda57462 (patch)
tree5c1a489baddf23a95de12d1a678599f0da04f399 /libmenu
parent54e31581a3cc8cd5501baa8553ab0a1cf2a75bee (diff)
downloadmpv-c83ebc0b7df94135390661a0d7a1a7b9bda57462.tar.bz2
mpv-c83ebc0b7df94135390661a0d7a1a7b9bda57462.tar.xz
OSD menus initial version
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8198 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmenu')
-rw-r--r--libmenu/Makefile38
-rw-r--r--libmenu/menu.c515
-rw-r--r--libmenu/menu.h72
-rw-r--r--libmenu/menu_cmdlist.c155
-rw-r--r--libmenu/menu_console.c234
-rw-r--r--libmenu/menu_filesel.c283
-rw-r--r--libmenu/menu_list.c225
-rw-r--r--libmenu/menu_list.h66
-rw-r--r--libmenu/menu_param.c159
-rw-r--r--libmenu/menu_pt.c151
-rw-r--r--libmenu/menu_txt.c194
-rw-r--r--libmenu/vf_menu.c251
12 files changed, 2343 insertions, 0 deletions
diff --git a/libmenu/Makefile b/libmenu/Makefile
new file mode 100644
index 0000000000..7886c13679
--- /dev/null
+++ b/libmenu/Makefile
@@ -0,0 +1,38 @@
+
+include ../config.mak
+
+LIBNAME = libmenu.a
+
+SRCS= menu.c vf_menu.c menu_cmdlist.c menu_pt.c menu_list.c menu_filesel.c menu_txt.c menu_console.c menu_param.c
+OBJS=$(SRCS:.c=.o)
+
+CFLAGS = $(OPTFLAGS) -I. -I.. -I../libmpcodecs $(EXTRA_INC) -Wall
+
+.SUFFIXES: .c .o
+
+
+.c.o:
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+$(LIBNAME): $(OBJS)
+ $(AR) r $(LIBNAME) $(OBJS)
+
+all: $(LIBNAME)
+
+clean:
+ rm -f *.o *.a *~
+
+distclean:
+ rm -f Makefile.bak *.o *.a *~ .depend
+
+dep: depend
+
+depend:
+ $(CC) -MM $(CFLAGS) $(SRCS) 1>.depend
+
+#
+# include dependency files if they exist
+#
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/libmenu/menu.c b/libmenu/menu.c
new file mode 100644
index 0000000000..89842f5c6e
--- /dev/null
+++ b/libmenu/menu.c
@@ -0,0 +1,515 @@
+
+#include "../config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../libvo/osd.h"
+#include "../libvo/font_load.h"
+#include "../linux/keycodes.h"
+#include "../asxparser.h"
+#include "../libmpdemux/stream.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "../m_option.h"
+#include "../m_struct.h"
+#include "menu.h"
+
+extern menu_info_t menu_info_cmdlist;
+extern menu_info_t menu_info_pt;
+extern menu_info_t menu_info_filesel;
+extern menu_info_t menu_info_txt;
+extern menu_info_t menu_info_console;
+extern menu_info_t menu_info_pref;
+
+menu_info_t* menu_info_list[] = {
+ &menu_info_pt,
+ &menu_info_cmdlist,
+ &menu_info_filesel,
+ &menu_info_txt,
+ &menu_info_console,
+ &menu_info_pref,
+ NULL
+};
+
+typedef struct menu_def_st {
+ char* name;
+ menu_info_t* type;
+ void* cfg;
+ char* args;
+} menu_def_t;
+
+static menu_def_t* menu_list = NULL;
+static int mcount = 0;
+
+
+static int menu_parse_config(char* buffer) {
+ char *element,*body, **attribs, *name;
+ menu_info_t* minfo = NULL;
+ int r,i;
+ ASX_Parser_t* parser = asx_parser_new();
+
+ while(1) {
+ r = asx_get_element(parser,&buffer,&element,&body,&attribs);
+ if(r < 0) {
+ printf("Syntax error at line %d\n",parser->line);
+ asx_parser_free(parser);
+ return 0;
+ } else if(r == 0) {
+ asx_parser_free(parser);
+ return 1;
+ }
+ // Has it a name ?
+ name = asx_get_attrib("name",attribs);
+ if(!name) {
+ printf("Menu definitions need a name attrib (line %d)\n",parser->line);
+ free(element);
+ if(body) free(body);
+ asx_free_attribs(attribs);
+ 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) {
+ minfo = menu_info_list[i];
+ break;
+ }
+ }
+ // Got it : add this to our list
+ if(minfo) {
+ menu_list = realloc(menu_list,(mcount+2)*sizeof(menu_def_t));
+ menu_list[mcount].name = name;
+ menu_list[mcount].type = minfo;
+ menu_list[mcount].cfg = m_struct_alloc(&minfo->priv_st);
+ menu_list[mcount].args = body;
+ // Setup the attribs
+ for(i = 0 ; attribs[2*i] ; i++) {
+ if(strcasecmp(attribs[2*i],"name") == 0) continue;
+ if(!m_struct_set(&minfo->priv_st,menu_list[mcount].cfg,attribs[2*i], attribs[2*i+1]))
+ printf("Bad attrib %s=%s in menu %s at line %d\n",attribs[2*i],attribs[2*i+1],
+ name,parser->line);
+ }
+ mcount++;
+ memset(&menu_list[mcount],0,sizeof(menu_def_t));
+ } else {
+ printf("Unknow menu type %s at line %d\n",element,parser->line);
+ free(name);
+ if(body) free(body);
+ }
+
+ free(element);
+ asx_free_attribs(attribs);
+ }
+
+}
+
+
+/// This will build the menu_defs list from the cfg file
+#define BUF_STEP 1024
+#define BUF_MIN 128
+#define BUF_MAX BUF_STEP*1024
+int menu_init(char* cfg_file) {
+ char* buffer = NULL;
+ int bl = BUF_STEP, br = 0;
+ int f;
+ stream_t* stream = open_stream(cfg_file,0,&f);
+ if(!stream) {
+ printf("Can't open menu config file: %s\n",cfg_file);
+ return 0;
+ }
+ buffer = malloc(bl);
+ while(1) {
+ int r;
+ if(bl - br < BUF_MIN) {
+ if(bl >= BUF_MAX) {
+ printf("Menu config file is too big (> %d KB)\n",BUF_MAX/1024);
+ free_stream(stream);
+ free(buffer);
+ return 0;
+ }
+ bl += BUF_STEP;
+ buffer = realloc(buffer,bl);
+ }
+ r = stream_read(stream,buffer+br,bl-br);
+ if(r == 0) break;
+ br += r;
+ }
+ if(!br) {
+ printf("Menu config file is empty\n");
+ return 0;
+ }
+ buffer[br-1] = '\0';
+
+ f = menu_parse_config(buffer);
+ free(buffer);
+ return f;
+}
+
+// Destroy all this stuff
+void menu_unint(void) {
+ int i;
+ for(i = 0 ; menu_list && menu_list[i].name ; i++) {
+ free(menu_list[i].name);
+ m_struct_free(&menu_list[i].type->priv_st,menu_list[i].cfg);
+ if(menu_list[i].args) free(menu_list[i].args);
+ }
+ free(menu_list);
+ mcount = 0;
+}
+
+/// 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:
+ case KEY_ESC:
+ menu->read_cmd(menu,MENU_CMD_CANCEL);
+ break;
+ case KEY_RIGHT:
+ case KEY_ENTER:
+ menu->read_cmd(menu,MENU_CMD_OK);
+ break;
+ }
+}
+
+menu_t* menu_open(char *name) {
+ menu_t* m;
+ int i;
+
+ for(i = 0 ; menu_list[i].name != NULL ; i++) {
+ if(strcmp(name,menu_list[i].name) == 0)
+ break;
+ }
+ if(menu_list[i].name == NULL) {
+ printf("Menu %s not found\n",name);
+ return NULL;
+ }
+ m = calloc(1,sizeof(menu_t));
+ m->priv_st = &(menu_list[i].type->priv_st);
+ m->priv = m_struct_copy(m->priv_st,menu_list[i].cfg);
+ if(menu_list[i].type->open(m,menu_list[i].args))
+ return m;
+ if(m->priv)
+ m_struct_free(m->priv_st,m->priv);
+ free(m);
+ printf("Menu %s: init failed\n",name);
+ return NULL;
+}
+
+void menu_draw(menu_t* menu,mp_image_t* mpi) {
+ if(menu->show && menu->draw)
+ menu->draw(menu,mpi);
+}
+
+void menu_read_cmd(menu_t* menu,int cmd) {
+ if(menu->read_cmd)
+ menu->read_cmd(menu,cmd);
+}
+
+void menu_close(menu_t* menu) {
+ if(menu->close)
+ menu->close(menu);
+ if(menu->priv)
+ m_struct_free(menu->priv_st,menu->priv);
+ free(menu);
+}
+
+void menu_read_key(menu_t* menu,int cmd) {
+ if(menu->read_key)
+ menu->read_key(menu,cmd);
+ else
+ menu_dflt_read_key(menu,cmd);
+}
+
+///////////////////////////// Helpers ////////////////////////////////////
+
+typedef void (*draw_alpha_f)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
+
+inline static draw_alpha_f get_draw_alpha(uint32_t fmt) {
+ switch(fmt) {
+ case IMGFMT_BGR15:
+ case IMGFMT_RGB15:
+ return vo_draw_alpha_rgb15;
+ case IMGFMT_BGR16:
+ case IMGFMT_RGB16:
+ return vo_draw_alpha_rgb16;
+ case IMGFMT_BGR24:
+ case IMGFMT_RGB24:
+ return vo_draw_alpha_rgb24;
+ case IMGFMT_BGR32:
+ case IMGFMT_RGB32:
+ return vo_draw_alpha_rgb32;
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ case IMGFMT_IYUV:
+ case IMGFMT_YVU9:
+ case IMGFMT_IF09:
+ case IMGFMT_Y800:
+ case IMGFMT_Y8:
+ return vo_draw_alpha_yv12;
+ case IMGFMT_YUY2:
+ return vo_draw_alpha_yuy2;
+ }
+
+ return NULL;
+}
+
+
+void menu_draw_text(mp_image_t* mpi,char* txt, int x, int y) {
+ draw_alpha_f draw_alpha = get_draw_alpha(mpi->imgfmt);
+ int font;
+
+ if(!draw_alpha) {
+ printf("Unsupported outformat !!!!\n");
+ return;
+ }
+
+ while (*txt) {
+ unsigned char c=*txt++;
+ if ((font=vo_font->font[c])>=0 && (x + vo_font->width[c] <= mpi->w) && (y + vo_font->pic_a[font]->h <= mpi->h))
+ draw_alpha(vo_font->width[c], vo_font->pic_a[font]->h,
+ vo_font->pic_b[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->w,
+ mpi->planes[0] + y * mpi->stride[0] + x * (mpi->bpp>>3),
+ mpi->stride[0]);
+ x+=vo_font->width[c]+vo_font->charspace;
+ }
+
+}
+
+void menu_draw_text_full(mp_image_t* mpi,char* txt,
+ int x, int y,int w, int h,
+ int vspace, int warp, int align, int anchor) {
+ int need_w,need_h;
+ int sy, ymin, ymax;
+ int sx, xmin, xmax, xmid, xrmin;
+ int ll = 0;
+ int font;
+ draw_alpha_f draw_alpha = get_draw_alpha(mpi->imgfmt);
+
+ if(!draw_alpha) {
+ printf("Unsupported outformat !!!!\n");
+ return;
+ }
+
+ if(x > mpi->w || y > mpi->h)
+ return;
+
+ if(anchor & MENU_TEXT_VCENTER) {
+ if(h <= 0) h = mpi->h;
+ ymin = y - h/2;
+ ymax = y + h/2;
+ } else if(anchor & MENU_TEXT_BOT) {
+ if(h <= 0) h = mpi->h - y;
+ ymin = y - h;
+ ymax = y;
+ } else {
+ if(h <= 0) h = mpi->h - y;
+ ymin = y;
+ ymax = y + h;
+ }
+
+ if(anchor & MENU_TEXT_HCENTER) {
+ if(w <= 0) w = mpi->w;
+ xmin = x - w/2;
+ xmax = x + w/2;
+ } else if(anchor & MENU_TEXT_RIGHT) {
+ if(w <= 0) w = mpi->w -x;
+ xmin = x - w;
+ xmax = x;
+ } else {
+ if(w <= 0) w = mpi->w -x;
+ xmin = x;
+ xmax = x + w;
+ }
+
+ // How many space do we need to draw this ?
+ menu_text_size(txt,w,vspace,warp,&need_w,&need_h);
+
+ // Find the first line
+ if(align & MENU_TEXT_VCENTER)
+ sy = ymin + ((h - need_h)/2);
+ else if(align & MENU_TEXT_BOT)
+ sy = ymax - need_h;
+ else
+ sy = y;
+
+#if 0
+ // Find the first col
+ if(align & MENU_TEXT_HCENTER)
+ sx = xmin + ((w - need_w)/2);
+ else if(align & MENU_TEXT_RIGHT)
+ sx = xmax - need_w;
+#endif
+
+ xmid = xmin + (xmax - xmin) / 2;
+ xrmin = xmin;
+ // Clamp the bb to the mpi size
+ if(ymin < 0) ymin = 0;
+ if(xmin < 0) xmin = 0;
+ if(ymax > mpi->h) ymax = mpi->h;
+ if(xmax > mpi->w) xmax = mpi->w;
+
+ // Jump some the beginnig text if needed
+ while(sy < ymin && *txt) {
+ unsigned char c=*txt++;
+ if(c == '\n' || (warp && ll + vo_font->width[c] > w)) {
+ ll = 0;
+ sy += vo_font->height + vspace;
+ if(c == '\n') continue;
+ }
+ ll += vo_font->width[c]+vo_font->charspace;
+ }
+ if(*txt == '\0') // Nothing left to draw
+ return;
+
+ while(sy < ymax && *txt) {
+ char* line_end = NULL;
+ int n;
+
+ if(txt[0] == '\n') { // New line
+ sy += vo_font->height + vspace;
+ txt++;
+ continue;
+ }
+
+ // Get the length and end of this line
+ for(n = 0, ll = 0 ; txt[n] != '\0' && txt[n] != '\n' ; n++) {
+ unsigned char c = txt[n];
+ if(warp && ll + vo_font->width[c] > w) break;
+ ll += vo_font->width[c]+vo_font->charspace;
+ }
+ line_end = &txt[n];
+ ll -= vo_font->charspace;
+
+
+ if(align & (MENU_TEXT_HCENTER|MENU_TEXT_RIGHT)) {
+ // Too long line
+ if(ll > xmax-xmin) {
+ if(align & MENU_TEXT_HCENTER) {
+ int mid = ll/2;
+ // Find the middle point
+ for(n--, ll = 0 ; n <= 0 ; n--) {
+ ll += vo_font->width[(int)txt[n]]+vo_font->charspace;
+ if(ll - vo_font->charspace > mid) break;
+ }
+ ll -= vo_font->charspace;
+ sx = xmid + mid - ll;
+ } else// MENU_TEXT_RIGHT)
+ sx = xmax + vo_font->charspace;
+
+ // We are after the start point -> go back
+ if(sx > xmin) {
+ for(n-- ; n <= 0 ; n--) {
+ unsigned char c = txt[n];
+ if(sx - vo_font->width[c] - vo_font->charspace < xmin) break;
+ sx -= vo_font->width[c]+vo_font->charspace;
+ }
+ } else { // We are before the start point -> go forward
+ for( ; sx < xmin && (&txt[n]) != line_end ; n++) {
+ unsigned char c = txt[n];
+ sx += vo_font->width[c]+vo_font->charspace;
+ }
+ }
+ txt = &txt[n]; // Jump to the new start char
+ } else {
+ if(align & MENU_TEXT_HCENTER)
+ sx = xmid - ll/2;
+ else
+ sx = xmax - ll;
+ }
+ } else {
+ for(sx = xrmin ; sx < xmin && txt != line_end ; txt++) {
+ unsigned char c = txt[n];
+ sx += vo_font->width[c]+vo_font->charspace;
+ }
+ }
+
+ while(sx < xmax && txt != line_end) {
+ unsigned char c = *txt++;
+ font = vo_font->font[c];
+ if ( (font >= 0) && (sx + vo_font->width[c] <= xmax) /*&& (sy + vo_font->pic_a[font]->h <= ymax)*/)
+ draw_alpha(vo_font->width[c], vo_font->pic_a[font]->h,
+ vo_font->pic_b[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->w,
+ mpi->planes[0] + sy * mpi->stride[0] + sx * (mpi->bpp>>3),
+ mpi->stride[0]);
+/* else */
+/* printf("Can't draw '%c'\n",c); */
+ sx+=vo_font->width[c]+vo_font->charspace;
+ }
+ txt = line_end;
+ if(txt[0] == '\0') break;
+ sy += vo_font->height + vspace;
+ }
+}
+
+int menu_text_length(char* txt) {
+ int l = 0;
+ while (*txt) {
+ unsigned char c=*txt++;
+ l += vo_font->width[c]+vo_font->charspace;
+ }
+ return l - vo_font->charspace;
+}
+
+void menu_text_size(char* txt,int max_width, int vspace, int warp, int* _w, int* _h) {
+ int l = 1, i = 0;
+ int w = 0;
+
+ while (*txt) {
+ unsigned char c=*txt++;
+ if(c == '\n' || (warp && i + vo_font->width[c] >= max_width)) {
+ if(*txt)
+ l++;
+ i = 0;
+ if(c == '\n') continue;
+ }
+ i += vo_font->width[c]+vo_font->charspace;
+ if(i > w) w = i;
+ }
+
+ *_w = w;
+ *_h = (l-1) * (vo_font->height + vspace) + vo_font->height;
+}
+
+
+int menu_text_num_lines(char* txt, int max_width) {
+ int l = 1, i = 0;
+ while (*txt) {
+ unsigned char c=*txt++;
+ if(c == '\n' || i + vo_font->width[c] > max_width) {
+ l++;
+ i = 0;
+ if(c == '\n') continue;
+ }
+ i += vo_font->width[c]+vo_font->charspace;
+ }
+ return l;
+}
+
+char* menu_text_get_next_line(char* txt, int max_width) {
+ int i = 0;
+ while (*txt) {
+ unsigned char c=*txt;
+ if(c == '\n') {
+ txt++;
+ break;
+ }
+ i += vo_font->width[c];
+ if(i >= max_width)
+ break;
+ i += vo_font->charspace;
+ }
+ return txt;
+}
diff --git a/libmenu/menu.h b/libmenu/menu.h
new file mode 100644
index 0000000000..225326a40b
--- /dev/null
+++ b/libmenu/menu.h
@@ -0,0 +1,72 @@
+
+struct menu_priv_s;
+typedef struct menu_s menu_t;
+
+struct menu_s {
+ void (*draw)(menu_t* menu,mp_image_t* mpi);
+ void (*read_cmd)(menu_t* menu,int cmd);
+ void (*read_key)(menu_t* menu,int cmd);
+ void (*close)(menu_t* menu);
+ m_struct_t* priv_st;
+ struct menu_priv_s* priv;
+ int show; // Draw it ?
+ int cl; // Close request (user sent a close cmd or
+ menu_t* parent;
+};
+
+typedef struct menu_info_s {
+ const char *info;
+ const char *name;
+ const char *author;
+ const char *comment;
+ m_struct_t priv_st; // Config struct definition
+ // cfg is a config struct as defined in cfg_st, it may be used as a priv struct
+ // cfg is filled from the attributs found in the cfg file
+ // the args param hold the content of the balise in the cfg file (if any)
+ int (*open)(menu_t* menu, char* args);
+} menu_info_t;
+
+
+#define MENU_CMD_UP 0
+#define MENU_CMD_DOWN 1
+#define MENU_CMD_OK 2
+#define MENU_CMD_CANCEL 3
+
+/// Global init/uninit
+int menu_init(char* cfg_file);
+void menu_unint(void);
+
+/// Open a menu defined in the config file
+menu_t* menu_open(char *name);
+
+void menu_draw(menu_t* menu,mp_image_t* mpi);
+void menu_read_cmd(menu_t* menu,int cmd);
+void menu_close(menu_t* menu);
+void menu_read_key(menu_t* menu,int cmd);
+
+//// Default implementation
+void menu_dflt_read_key(menu_t* menu,int cmd);
+
+/////////// Helpers
+
+#define MENU_TEXT_TOP (1<<0)
+#define MENU_TEXT_VCENTER (1<<1)
+#define MENU_TEXT_BOT (1<<2)
+#define MENU_TEXT_VMASK (MENU_TEXT_TOP|MENU_TEXT_VCENTER|MENU_TEXT_BOT)
+#define MENU_TEXT_LEFT (1<<3)
+#define MENU_TEXT_HCENTER (1<<4)
+#define MENU_TEXT_RIGHT (1<<5)
+#define MENU_TEXT_HMASK (MENU_TEXT_LEFT|MENU_TEXT_HCENTER|MENU_TEXT_RIGHT)
+#define MENU_TEXT_CENTER (MENU_TEXT_VCENTER|MENU_TEXT_HCENTER)
+
+void menu_draw_text(mp_image_t* mpi, char* txt, int x, int y);
+int menu_text_length(char* txt);
+int menu_text_num_lines(char* txt, int max_width);
+
+void menu_text_size(char* txt,int max_width,
+ int vspace, int warp,
+ int* _w, int* _h);
+
+void menu_draw_text_full(mp_image_t* mpi,char* txt,
+ int x, int y,int w, int h,
+ int vspace, int warp, int align, int anchor);
diff --git a/libmenu/menu_cmdlist.c b/libmenu/menu_cmdlist.c
new file mode 100644
index 0000000000..44e12364cd
--- /dev/null
+++ b/libmenu/menu_cmdlist.c
@@ -0,0 +1,155 @@
+
+#include "../config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "img_format.h"
+#include "mp_image.h"
+
+#include "../m_option.h"
+#include "../m_struct.h"
+#include "../asxparser.h"
+#include "menu.h"
+#include "menu_list.h"
+
+#include "../libvo/font_load.h"
+
+#include "../input/input.h"
+#include "../version.h"
+
+
+
+struct list_entry_s {
+ struct list_entry p;
+
+ char* ok;
+ char* cancel;
+};
+
+struct menu_priv_s {
+ menu_list_priv_t p;
+};
+
+static struct menu_priv_s cfg_dflt = {
+ MENU_LIST_PRIV_DFLT
+};
+
+static m_option_t cfg_fields[] = {
+ MENU_LIST_PRIV_FIELDS,
+ { "title",M_ST_OFF(struct menu_priv_s,p.title), CONF_TYPE_STRING, 0, 0, 0, NULL },
+ { NULL, NULL, NULL, 0,0,0,NULL }
+};
+
+#define mpriv (menu->priv)
+
+static void read_cmd(menu_t* menu,int cmd) {
+ switch(cmd) {
+ case MENU_CMD_OK: {
+ if(mpriv->p.current->ok) {
+ mp_cmd_t* c = mp_input_parse_cmd(mpriv->p.current->ok);
+ if(c)
+ mp_input_queue_cmd(c);
+ }
+ } break;
+ case MENU_CMD_CANCEL:
+ if(mpriv->p.current->cancel) {
+ mp_cmd_t* c = mp_input_parse_cmd(mpriv->p.current->cancel);
+ if(c)
+ mp_input_queue_cmd(c);
+ break;
+ }
+ default:
+ menu_list_read_cmd(menu,cmd);
+ }
+}
+
+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);
+ if(entry->cancel)
+ free(entry->cancel);
+ free(entry->p.txt);
+ free(entry);
+}
+
+static void close(menu_t* menu) {
+ menu_list_uninit(menu,free_entry);
+}
+
+static int parse_args(menu_t* menu,char* args) {
+ char *element,*body, **attribs, *name, *ok, *cancel;
+ list_entry_t* m = NULL;
+ int r;
+ ASX_Parser_t* parser = asx_parser_new();
+
+ while(1) {
+ r = asx_get_element(parser,&args,&element,&body,&attribs);
+ if(r < 0) {
+ printf("Syntax error at line %d\n",parser->line);
+ asx_parser_free(parser);
+ return -1;
+ } else if(r == 0) {
+ asx_parser_free(parser);
+ if(!m)
+ printf("No entry found in the menu definition\n");
+ return m ? 1 : 0;
+ }
+ // Has it a name ?
+ name = asx_get_attrib("name",attribs);
+ if(!name) {
+ printf("List menu entry definitions need a name (line %d)\n",parser->line);
+ free(element);
+ if(body) free(body);
+ asx_free_attribs(attribs);
+ continue;
+ }
+ ok = asx_get_attrib("ok",attribs);
+ cancel = asx_get_attrib("cancel",attribs);
+ m = calloc(1,sizeof(struct list_entry_s));
+ m->p.txt = name;
+ m->ok = ok;
+ m->cancel = cancel;
+ menu_list_add_entry(menu,m);
+
+ free(element);
+ if(body) free(body);
+ asx_free_attribs(attribs);
+ }
+}
+
+static int open(menu_t* menu, char* args) {
+ menu->draw = menu_list_draw;
+ menu->read_cmd = read_cmd;
+ menu->read_key = read_key;
+ menu->close = close;
+
+ if(!args) {
+ printf("List menu need an argument\n");
+ return 0;
+ }
+
+ menu_list_init(menu);
+ if(!parse_args(menu,args))
+ return 0;
+ return 1;
+}
+
+const menu_info_t menu_info_cmdlist = {
+ "Command list menu",
+ "cmdlist",
+ "Albeu",
+ "",
+ {
+ "cmdlist_cfg",
+ sizeof(struct menu_priv_s),
+ &cfg_dflt,
+ cfg_fields
+ },
+ open
+};
diff --git a/libmenu/menu_console.c b/libmenu/menu_console.c
new file mode 100644
index 0000000000..cc30568338
--- /dev/null
+++ b/libmenu/menu_console.c
@@ -0,0 +1,234 @@
+
+#include "../config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "img_format.h"
+#include "mp_image.h"
+
+#include "../m_struct.h"
+#include "../m_option.h"
+#include "menu.h"
+
+#include "../libvo/font_load.h"
+#include "../linux/keycodes.h"
+#include "../input/input.h"
+#include "../linux/timer.h"
+
+struct menu_priv_s {
+ char** lines; // Our buffer
+ int last_line;
+ int num_lines;
+ char* input; // input buffer
+ int input_size; // size of the input buffer in lines
+ unsigned int hide_ts;
+ unsigned int show_ts;
+
+ //int max_lines; // Max number of lines with the last mpi
+
+ char* prompt;
+ int buf_lines; // Buffer size (in line)
+ int height; // Display size in %
+ int minb;
+ int vspace;
+ unsigned int hide_time;
+ unsigned int show_time;
+};
+
+static struct menu_priv_s cfg_dflt = {
+ NULL,
+ 0,
+ 0,
+ NULL,
+ 0,
+ 0,
+ 0,
+
+ "# ",
+ 50, // lines
+ 33, // %
+ 3,
+ 3,
+ 500,
+ 500,
+};
+
+#define ST_OFF(m) M_ST_OFF(struct menu_priv_s,m)
+
+static m_option_t cfg_fields[] = {
+ { "prompt", ST_OFF(prompt), CONF_TYPE_STRING, M_OPT_MIN, 1, 0, NULL },
+ { "buffer-lines", ST_OFF(buf_lines), CONF_TYPE_INT, M_OPT_MIN, 5, 0, NULL },
+ { "height", ST_OFF(height), CONF_TYPE_INT, M_OPT_RANGE, 1, 100, NULL },
+ { "minbor", ST_OFF(minb), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL },
+ { "vspace", ST_OFF(vspace), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL },
+ { "show-time",ST_OFF(show_time), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL },
+ { "hide-time",ST_OFF(hide_time), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL },
+ { NULL, NULL, NULL, 0,0,0,NULL }
+};
+
+#define mpriv (menu->priv)
+
+static void add_line(struct menu_priv_s* priv, char* l) {
+
+ if(priv->num_lines >= priv->buf_lines && priv->lines[priv->last_line])
+ free(priv->lines[priv->last_line]);
+ else
+ priv->num_lines++;
+
+ priv->lines[priv->last_line] = strdup(l);
+ priv->last_line = (priv->last_line + 1) % priv->buf_lines;
+}
+
+static void draw(menu_t* menu, mp_image_t* mpi) {
+ int h = mpi->h*mpriv->height/100;
+ int w = mpi->w - 2* mpriv->minb;
+ int x = mpriv->minb, y;
+ int lw,lh,i, ll = mpriv->last_line - 1;
+
+ if(mpriv->hide_ts) {
+ unsigned int t = GetTimerMS() - mpriv->hide_ts;
+ if(t >= mpriv->hide_time) {
+ mpriv->hide_ts = 0;
+ menu->show = 0;
+ return;
+ }
+ h = mpi->h*(mpriv->height - (mpriv->height * t /mpriv->hide_time))/100;
+ } else if(mpriv->show_time && mpriv->show_ts == 0) {
+ mpriv->show_ts = GetTimerMS();
+ return;
+ } else if(mpriv->show_ts > 0) {
+ unsigned int t = GetTimerMS() - mpriv->show_ts;
+ if(t > mpriv->show_time)
+ mpriv->show_ts = -1;
+ else
+ h = mpi->h*(mpriv->height * t /mpriv->hide_time)/100;
+ }
+
+ y = h - mpriv->vspace;
+
+ if(x < 0 || y < 0 || w <= 0 || h <= 0 )
+ return;
+
+ menu_text_size(mpriv->input,w,mpriv->vspace,1,&lw,&lh);
+ menu_draw_text_full(mpi,mpriv->input,x,y,w,h,mpriv->vspace,1,
+ MENU_TEXT_BOT|MENU_TEXT_LEFT,
+ MENU_TEXT_BOT|MENU_TEXT_LEFT);
+ y -= lh + mpriv->vspace;
+
+ for( i = 0 ; y > mpriv->minb && i < mpriv->num_lines ; i++){
+ int c = (ll - i) >= 0 ? ll - i : mpriv->buf_lines + ll - i;
+ menu_text_size(mpriv->lines[c],w,mpriv->vspace,1,&lw,&lh);
+ menu_draw_text_full(mpi,mpriv->lines[c],x,y,w,h,mpriv->vspace,1,
+ MENU_TEXT_BOT|MENU_TEXT_LEFT,
+ MENU_TEXT_BOT|MENU_TEXT_LEFT);
+ y -= lh + mpriv->vspace;
+ }
+ 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 read_key(menu_t* menu,int c) {
+ switch(c) {
+ case KEY_ESC:
+ if(mpriv->hide_time)
+ mpriv->hide_ts = GetTimerMS();
+ else
+ menu->show = 0;
+ mpriv->show_ts = 0;
+ return;
+ case KEY_ENTER: {
+ mp_cmd_t* c = mp_input_parse_cmd(&mpriv->input[strlen(mpriv->prompt)]);
+ add_line(mpriv,mpriv->input);
+ if(!c)
+ add_line(mpriv,"Invalid command try help");
+ else {
+ switch(c->id) {
+ case MP_CMD_CHELP:
+ add_line(mpriv,"Mplayer console 0.01");
+ add_line(mpriv,"TODO: Write some mainful help msg ;)");
+ add_line(mpriv,"Enter any mplayer command");
+ add_line(mpriv,"exit close this console");
+ break;
+ case MP_CMD_CEXIT:
+ menu->show = 0;
+ menu->cl = 1;
+ break;
+ case MP_CMD_CHIDE:
+ if(mpriv->hide_time)
+ mpriv->hide_ts = GetTimerMS();
+ else
+ menu->show = 0;
+ mpriv->show_ts = 0;
+ break;
+ default: // Send the other commands to mplayer
+ mp_input_queue_cmd(c);
+ }
+ }
+ mpriv->input[strlen(mpriv->prompt)] = '\0';
+ return;
+ }
+ case KEY_DELETE:
+ case KEY_BS: {
+ unsigned int i = strlen(mpriv->input);
+ if(i > strlen(mpriv->prompt))
+ mpriv->input[i-1] = '\0';
+ return;
+ }
+ }
+
+ if(isascii(c)) {
+ int l = strlen(mpriv->input);
+ mpriv->input[l] = (char)c;
+ mpriv->input[l+1] = '\0';
+ }
+
+}
+
+
+static int open(menu_t* menu, char* args) {
+
+
+ menu->draw = draw;
+ menu->read_cmd = read_cmd;
+ menu->read_key = read_key;
+
+ mpriv->lines = calloc(mpriv->buf_lines,sizeof(char*));
+ mpriv->input_size = 1024;
+ mpriv->input = calloc(mpriv->input_size,sizeof(char));
+ strcpy(mpriv->input,mpriv->prompt);
+
+ if(args)
+ add_line(mpriv,args);
+
+ return 1;
+}
+
+const menu_info_t menu_info_console = {
+ "MPlayer console",
+ "console",
+ "Albeu",
+ "",
+ {
+ "console_cfg",
+ sizeof(struct menu_priv_s),
+ &cfg_dflt,
+ cfg_fields
+ },
+ open,
+};
diff --git a/libmenu/menu_filesel.c b/libmenu/menu_filesel.c
new file mode 100644
index 0000000000..83eaa34881
--- /dev/null
+++ b/libmenu/menu_filesel.c
@@ -0,0 +1,283 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <unistd.h>
+
+
+#include "../config.h"
+
+#include "../m_struct.h"
+#include "../m_option.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+
+#include "menu.h"
+#include "menu_list.h"
+#include "../input/input.h"
+#include "../linux/keycodes.h"
+
+struct list_entry_s {
+ struct list_entry p;
+ int d;
+};
+
+struct menu_priv_s {
+ menu_list_priv_t p;
+ char* dir; // current dir
+ /// Cfg fields
+ char* path;
+ char* title;
+ char* file_action;
+ char* dir_action;
+ int auto_close;
+};
+
+static struct menu_priv_s cfg_dflt = {
+ MENU_LIST_PRIV_DFLT,
+ NULL,
+
+ NULL,
+ "Select a file: %p",
+ "loadfile %p",
+ NULL,
+ 0
+};
+
+#define ST_OFF(m) M_ST_OFF(struct menu_priv_s,m)
+
+static m_option_t cfg_fields[] = {
+ MENU_LIST_PRIV_FIELDS,
+ { "path", ST_OFF(path), CONF_TYPE_STRING, 0, 0, 0, NULL },
+ { "title", ST_OFF(title), CONF_TYPE_STRING, 0, 0, 0, NULL },
+ { "file-action", ST_OFF(file_action), CONF_TYPE_STRING, 0, 0, 0, NULL },
+ { "dir-action", ST_OFF(dir_action), CONF_TYPE_STRING, 0, 0, 0, NULL },
+ { "auto-close", ST_OFF(auto_clo