[Mplayer-cvslog] CVS: main/libmenu Makefile,NONE,1.1 menu.c,NONE,1.1 menu.h,NONE,1.1 menu_cmdlist.c,NONE,1.1 menu_console.c,NONE,1.1 menu_filesel.c,NONE,1.1 menu_list.c,NONE,1.1 menu_list.h,NONE,1.1 menu_param.c,NONE,1.1 menu_pt.c,NONE,1.1 menu_txt.c,NONE,1.1 vf_menu.c,NONE,1.1
Alban Bedel CVS
albeu at mplayerhq.hu
Fri Nov 15 00:47:14 CET 2002
Update of /cvsroot/mplayer/main/libmenu
In directory mail:/var/tmp.root/cvs-serv15428/libmenu
Added Files:
Makefile menu.c menu.h menu_cmdlist.c menu_console.c
menu_filesel.c menu_list.c menu_list.h menu_param.c menu_pt.c
menu_txt.c vf_menu.c
Log Message:
OSD menus initial version
--- NEW FILE ---
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
--- NEW FILE ---
#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;
}
--- NEW FILE ---
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);
--- NEW FILE ---
#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
};
--- NEW FILE ---
#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,
};
--- NEW FILE ---
#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_close), CONF_TYPE_FLAG, 0, 0, 1, NULL },
{ NULL, NULL, NULL, 0,0,0,NULL }
};
#define mpriv (menu->priv)
static void free_entry(list_entry_t* entry) {
free(entry->p.txt);
free(entry);
}
static char* replace_path(char* title , char* dir) {
char *p = strstr(title,"%p");
if(p) {
int tl = strlen(title);
int dl = strlen(dir);
int t1l = p-title;
int l = tl - 2 + dl;
char*r = malloc(l + 1);
memcpy(r,title,t1l);
memcpy(r+t1l,dir,dl);
if(tl - t1l - 2 > 0)
memcpy(r+t1l+dl,p+2,tl - t1l - 2);
r[l] = '\0';
return r;
} else
return title;
}
typedef int (*kill_warn)(const void*, const void*);
static int open_dir(menu_t* menu,char* args) {
struct dirent **namelist;
struct stat st;
int n;
char* p = NULL;
list_entry_t* e;
int mylstat(char *dir, char *file,struct stat* st) {
int l = strlen(dir) + strlen(file);
char s[l+1];
sprintf(s,"%s%s",args,file);
return lstat(s,st);
}
int compare(struct dirent **a,struct dirent **b) {
struct stat as,bs;
mylstat(args,(*a)->d_name,&as);
mylstat(args,(*b)->d_name,&bs);
if(S_ISDIR(as.st_mode)) {
if(S_ISDIR(bs.st_mode))
return alphasort(b,a);
else
return 1;
} else {
if(S_ISDIR(bs.st_mode))
return -1;
else
return alphasort(b,a);
}
}
int select_f(const struct dirent *d) {
if(d->d_name[0] != '.' || strcmp(d->d_name,"..") == 0)
return 1;
return 0;
}
menu_list_init(menu);
if(mpriv->dir)
free(mpriv->dir);
mpriv->dir = strdup(args);
if(mpriv->p.title && mpriv->p.title != mpriv->title && mpriv->p.title != cfg_dflt.p.title)
free(mpriv->p.title);
p = strstr(mpriv->title,"%p");
mpriv->p.title = replace_path(mpriv->title,mpriv->dir);
n = scandir(mpriv->dir, &namelist, select_f, (kill_warn)compare);
if (n < 0) {
printf("scandir error: %s\n",strerror(errno));
return 0;
}
while(n--) {
e = calloc(1,sizeof(list_entry_t));
mylstat(args,namelist[n]->d_name,&st);
if(S_ISDIR(st.st_mode)) {
int sl =strlen(namelist[n]->d_name);
e->p.txt = malloc(sl + 2);
strncpy(e->p.txt,namelist[n]->d_name,sl);
e->p.txt[sl] = '/';
e->p.txt[sl+1] = '\0';
e->d = 1;
menu_list_add_entry(menu,e);
} else if(strcmp(namelist[n]->d_name,"..") == 0 || namelist[n]->d_name[0] != '.') {
e->p.txt = strdup(namelist[n]->d_name);
menu_list_add_entry(menu,e);
}
free(namelist[n]);
}
free(namelist);
return 1;
}
static void read_cmd(menu_t* menu,int cmd) {
mp_cmd_t* c = NULL;
switch(cmd) {
case MENU_CMD_OK: {
// Directory
if(mpriv->p.current->d) {
if(mpriv->dir_action) {
int fname_len = strlen(mpriv->dir) + strlen(mpriv->p.current->p.txt) + 1;
char filename[fname_len];
char* str;
sprintf(filename,"%s%s",mpriv->dir,mpriv->p.current->p.txt);
str = replace_path(mpriv->dir_action,filename);
c = mp_input_parse_cmd(str);
if(str != mpriv->dir_action)
free(str);
} else { // Default action : open this dirctory ourself
int l = strlen(mpriv->dir);
char *slash = NULL, *p = NULL;
if(strcmp(mpriv->p.current->p.txt,"../") == 0) {
if(l <= 1) break;
mpriv->dir[l-1] = '\0';
slash = strrchr(mpriv->dir,'/');
if(!slash) break;
slash[1] = '\0';
p = strdup(mpriv->dir);
} else {
p = malloc(l + strlen(mpriv->p.current->p.txt) + 1);
sprintf(p,"%s%s",mpriv->dir,mpriv->p.current->p.txt);
}
menu_list_uninit(menu,free_entry);
if(!open_dir(menu,p)) {
printf("Can't open directory %s\n",p);
menu->cl = 1;
}
free(p);
}
} else { // Files
int fname_len = strlen(mpriv->dir) + strlen(mpriv->p.current->p.txt) + 1;
char filename[fname_len];
char *str;
sprintf(filename,"%s%s",mpriv->dir,mpriv->p.current->p.txt);
str = replace_path(mpriv->file_action,filename);
c = mp_input_parse_cmd(str);
if(str != mpriv->file_action)
free(str);
}
if(c) {
mp_input_queue_cmd(c);
if(mpriv->auto_close)
menu->cl = 1;
}
} break;
default:
menu_list_read_cmd(menu,cmd);
}
}
static void read_key(menu_t* menu,int c){
if(c == KEY_BS) {
mpriv->p.current = mpriv->p.menu; // Hack : we consider that the first entry is ../
read_cmd(menu,MENU_CMD_OK);
} else
menu_list_read_key(menu,c,1);
}
static void clos(menu_t* menu) {
menu_list_uninit(menu,free_entry);
free(mpriv->dir);
}
static int open_fs(menu_t* menu, char* args) {
char *path = mpriv->path;
int r = 0;
char wd[PATH_MAX+1];
args = NULL; // Warning kill
menu->draw = menu_list_draw;
menu->read_cmd = read_cmd;
menu->read_key = read_key;
menu->close = clos;
getcwd(wd,PATH_MAX);
if(!path || path[0] == '\0') {
int l = strlen(wd) + 2;
char b[l];
sprintf(b,"%s/",wd);
r = open_dir(menu,b);
} else if(path[0] != '/') {
int al = strlen(path);
int l = strlen(wd) + al + 3;
char b[l];
if(b[al-1] != '/')
sprintf(b,"%s/%s/",wd,path);
else
sprintf(b,"%s/%s",wd,path);
r = open_dir(menu,b);
} else
r = open_dir(menu,path);
return r;
}
const menu_info_t menu_info_filesel = {
"File seletor menu",
"filesel",
"Albeu",
"",
{
"fs_cfg",
sizeof(struct menu_priv_s),
&cfg_dflt,
cfg_fields
},
open_fs
};
--- NEW FILE ---
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "../config.h"
#include "img_format.h"
#include "mp_image.h"
#include "m_struct.h"
#include "menu.h"
#include "../libvo/font_load.h"
#include "../linux/keycodes.h"
#define IMPL 1
#include "menu_list.h"
#define mpriv (menu->priv)
void menu_list_draw(menu_t* menu,mp_image_t* mpi) {
int x = mpriv->x;
int y = mpriv->y;
int i;
int h = mpriv->h;
int w = mpriv->w;
int dh = 0,dw = 0;
int dy = 0;
int need_h = 0,need_w = 0,ptr_l = menu_text_length(mpriv->ptr) + 10,sidx = 0;
int th;
list_entry_t* m;
if(mpriv->count < 1)
return;
if(h <= 0) h = mpi->height;
if(w <= 0) w = mpi->width;
dh = h - 2*mpriv->minb;
dw = w - 2*mpriv->minb;
ptr_l = menu_text_length(mpriv->ptr);
// mpi is too small
if(h - vo_font->height <= 0 || w - ptr_l <= 0 || dw <= 0 || dh <= 0)
return;
th = menu_text_num_lines(mpriv->title,dw) * (mpriv->vspace + vo_font->height) + mpriv->vspace;
for(i = 0, m = mpriv->menu ; m ; m = m->next, i++) {
int ll = menu_text_length(m->txt);
if(ptr_l + ll > need_w) need_w = ptr_l + ll;
if(m == mpriv->current) sidx = i;
}
if(need_w > dw) need_w = dw;
if(x > 0)
x += mpriv->minb;
if(y > 0)
y += mpriv->minb;
else
y = mpriv->minb;
need_h = mpriv->count * (mpriv->vspace + vo_font->height) - mpriv->vspace;
if( need_h + th > dh) {
int start,end;
int maxl = (dh + mpriv->vspace - th) / (mpriv->vspace + vo_font->height);
if(maxl < 4) {
th = 0;
maxl = (dh + mpriv->vspace) / ( vo_font->height + mpriv->vspace);
}
// Too smoll
if(maxl < 1) return;
need_h = maxl*(mpriv->vspace + vo_font->height) - mpriv->vspace;
start = sidx - (maxl/2);
if(start < 0) start = 0;
end = start + maxl;
if(end > mpriv->count) {
end = mpriv->count;
if(end - start < maxl)
start = end - maxl < 0 ? 0 : end - maxl;
}
m = mpriv->menu;
for(i = 0 ; m->next && i < start ; i++)
m = m->next;
} else
m = mpriv->menu;
if(th > 0) {
menu_draw_text_full(mpi,mpriv->title,
x < 0 ? mpi->w / 2 : x,
dy+y,dw,0,
mpriv->vspace,1,
MENU_TEXT_TOP|MENU_TEXT_HCENTER,
MENU_TEXT_TOP|(x < 0 ? MENU_TEXT_HCENTER :MENU_TEXT_LEFT));
dy += th;
}
for( ; m != NULL && dy + vo_font->height < dh ; m = m->next ) {
if(m == mpriv->current)
menu_draw_text_full(mpi,mpriv->ptr,
x < 0 ? (mpi->w - need_w) / 2 + ptr_l : x,
dy+y,dw,dh - dy,
mpriv->vspace,0,
MENU_TEXT_TOP|(x < 0 ? MENU_TEXT_RIGHT :MENU_TEXT_LEFT) ,
MENU_TEXT_TOP|(x < 0 ? MENU_TEXT_RIGHT :MENU_TEXT_LEFT));
menu_draw_text_full(mpi,m->txt,
x < 0 ? (mpi->w - need_w) / 2 + ptr_l : x + ptr_l,
dy+y,dw-ptr_l,dh - dy,
mpriv->vspace,0,
MENU_TEXT_TOP|MENU_TEXT_LEFT,
MENU_TEXT_TOP|MENU_TEXT_LEFT);
dy += vo_font->height + mpriv->vspace;
}
}
void menu_list_read_cmd(menu_t* menu,int cmd) {
switch(cmd) {
case MENU_CMD_UP:
if(mpriv->current->prev) {
mpriv->current = mpriv->current->prev;
} else {
for( ; mpriv->current->next != NULL ; mpriv->current = mpriv->current->next)
/* NOTHING */;
} break;
case MENU_CMD_DOWN:
if(mpriv->current->next) {
mpriv->current = mpriv->current->next;
} else {
mpriv->current = mpriv->menu;
} break;
case MENU_CMD_CANCEL:
menu->show = 0;
menu->cl = 1;
break;
}
}
void menu_list_jump_to_key(menu_t* menu,int c) {
if(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;
}
}
for(e = mpriv->menu ; e ; e = e->next) {
if(e->txt[0] == c) {
mpriv->current = e;
return;
}
}
} 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 < 10 ; m = m->prev, i++)
/**/;
if(m)
mpriv->current = m;
break;
case KEY_PAGE_DOWN:
for(i = 0, m = mpriv->current ; m && m->next && i < 10 ; 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++;
if(mpriv->menu == NULL) {
mpriv->menu = mpriv->current = entry;
return;
}
for(l = mpriv->menu ; l->next != NULL ; l = l->next)
/* NOP */;
l->next = entry;
entry->prev = l;
}
void menu_list_init(menu_t* menu) {
if(!mpriv)
mpriv = calloc(1,sizeof(struct menu_priv_s));
}
void menu_list_uninit(menu_t* menu,free_entry_t free_func) {
list_entry_t *i,*j;
if(!free_func) free_func = (free_entry_t)free;
for(i = mpriv->menu ; i != NULL ; ) {
j = i->next;
free_func(i);
i = j;
}
mpriv->menu = mpriv->current = NULL;
}
--- NEW FILE ---
typedef struct list_entry_s list_entry_t;
#ifdef IMPL
struct list_entry_s {
#else
struct list_entry {
#endif
list_entry_t* prev;
list_entry_t* next;
char* txt;
};
#ifndef IMPL
typedef struct menu_list_priv_s {
#else
typedef struct menu_priv_s {
#endif
list_entry_t* menu;
list_entry_t* current;
int count;
char* title;
int x,y;
int w,h;
int vspace, minb;
char* ptr;
} menu_list_priv_t;
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);
extern const menu_list_priv_t menu_list_priv_dflt;
#define MENU_LIST_PRIV_DFLT { \
NULL, \
NULL, \
0, \
\
"MPlayer", \
-1,-1, \
0,0, \
5, 3, \
">" \
}
#define MENU_LIST_PRIV_FIELDS \
{ "minbor", M_ST_OFF(menu_list_priv_t,minb), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL }, \
{ "vspace", M_ST_OFF(menu_list_priv_t,vspace), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL }, \
{ "x", M_ST_OFF(menu_list_priv_t,x), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL }, \
{ "y", M_ST_OFF(menu_list_priv_t,y), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL }, \
{ "w", M_ST_OFF(menu_list_priv_t,w), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL }, \
{ "h", M_ST_OFF(menu_list_priv_t,h), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL }, \
{ "ptr", M_ST_OFF(menu_list_priv_t,ptr), CONF_TYPE_STRING, 0, 0, 0, NULL }
--- NEW FILE ---
#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 "../config.h"
#include "../m_struct.h"
#include "../m_option.h"
#include "../m_config.h"
#include "../asxparser.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;
m_option_t* opt;
};
struct menu_priv_s {
menu_list_priv_t p;
char* edit;
int edit_len;
/// Cfg fields
};
static struct menu_priv_s cfg_dflt = {
MENU_LIST_PRIV_DFLT,
NULL,
0
};
static m_option_t cfg_fields[] = {
MENU_LIST_PRIV_FIELDS,
{ "title", M_ST_OFF(menu_list_priv_t,title), CONF_TYPE_STRING, 0, 0, 0, NULL },
{ NULL, NULL, NULL, 0,0,0,NULL }
};
#define mpriv (menu->priv)
extern m_config_t* mconfig;
static int parse_args(menu_t* menu,char* args) {
char *element,*body, **attribs, *name, *ok, *cancel;
list_entry_t* m = NULL;
int r;
m_option_t* opt;
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);
opt = name ? m_config_get_option(mconfig,name) : NULL;
if(!opt) {
printf("Pref menu entry definitions need a valid name attribut (line %d)\n",parser->line);
free(element);
if(name) free(name);
if(body) free(body);
asx_free_attribs(attribs);
continue;
}
m = calloc(1,sizeof(struct list_entry_s));
m->p.txt = name;
m->opt = opt;
menu_list_add_entry(menu,m);
free(element);
if(body) free(body);
asx_free_attribs(attribs);
}
}
static void read_key(menu_t* menu,int c) {
menu_list_read_key(menu,c,0);
}
static void free_entry(list_entry_t* entry) {
free(entry->p.txt);
free(entry);
}
static void close(menu_t* menu) {
menu_list_uninit(menu,free_entry);
if(mpriv->edit)
free(mpriv->edit);
}
static int open(menu_t* menu, char* args) {
list_entry_t* e;
menu->draw = menu_list_draw;
menu->read_cmd = menu_list_read_cmd;
menu->read_key = read_key;
menu->close = close;
if(!args) {
printf("Pref menu need an argument\n");
return 0;
}
menu_list_init(menu);
if(!parse_args(menu,args))
return 0;
for(e = mpriv->p.menu ; e ; e = e->p.next) {
int l;
char* val = m_option_print(e->opt,e->opt->p);
if((int)val == -1) {
printf("Can't get value of option %s\n",e->opt->name);
continue;
} else if(!val)
val = strdup("NULL");
l = strlen(e->opt->name) + 2 + strlen(val) + 1;
e->p.txt = malloc(l);
sprintf(e->p.txt,"%s: %s",e->opt->name,val);
free(val);
}
return 1;
}
const menu_info_t menu_info_pref = {
"Preferences menu",
"pref",
"Albeu",
"",
{
"pref_cfg",
sizeof(struct menu_priv_s),
&cfg_dflt,
cfg_fields
},
open
};
--- NEW FILE ---
#include <stdlib.h>
#include <stdio.h>
#include <libgen.h>
#include "../config.h"
#include "img_format.h"
#include "mp_image.h"
#include "../m_struct.h"
#include "../m_option.h"
#include "menu.h"
#include "menu_list.h"
#include "../playtree.h"
#include "../input/input.h"
extern play_tree_iter_t* playtree_iter;
struct list_entry_s {
struct list_entry p;
play_tree_t* pt;
};
struct menu_priv_s {
menu_list_priv_t p;
char* title;
};
static struct menu_priv_s cfg_dflt = {
MENU_LIST_PRIV_DFLT,
"Jump to"
};
#define ST_OFF(m) M_ST_OFF(struct menu_priv_s,m)
static m_option_t cfg_fields[] = {
MENU_LIST_PRIV_FIELDS,
{ "title", ST_OFF(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: {
int d = 1;
char str[15];
play_tree_t* i;
mp_cmd_t* c;
if(playtree_iter->tree == mpriv->p.current->pt)
break;
if(playtree_iter->tree->parent && mpriv->p.current->pt == playtree_iter->tree->parent)
snprintf(str,15,"pt_up_step 1");
else {
for(i = playtree_iter->tree->next; i != NULL ; i = i->next) {
if(i == mpriv->p.current->pt)
break;
d++;
}
if(i == NULL) {
d = -1;
for(i = playtree_iter->tree->prev; i != NULL ; i = i->prev) {
if(i == mpriv->p.current->pt)
break;
d--;
}
if(i == NULL) {
printf("Can't find the target item ????\n");
break;
}
}
snprintf(str,15,"pt_step %d",d);
}
c = mp_input_parse_cmd(str);
if(c)
mp_input_queue_cmd(c);
else
printf("Failed to build command %s\n",str);
} break;
default:
menu_list_read_cmd(menu,cmd);
}
}
static void read_key(menu_t* menu,int c){
menu_list_read_key(menu,c,1);
}
static void close(menu_t* menu) {
menu_list_uninit(menu,NULL);
}
static int op(menu_t* menu, char* args) {
play_tree_t* i;
list_entry_t* e;
args = NULL; // Warning kill
menu->draw = menu_list_draw;
menu->read_cmd = read_cmd;
menu->read_key = read_key;
menu->close = close;
menu_list_init(menu);
mpriv->p.title = mpriv->title;
if(playtree_iter->tree->parent != playtree_iter->root) {
e = calloc(1,sizeof(list_entry_t));
e->p.txt = "..";
e->pt = playtree_iter->tree->parent;
menu_list_add_entry(menu,e);
}
for(i = playtree_iter->tree ; i->prev != NULL ; i = i->prev)
/* NOP */;
for( ; i != NULL ; i = i->next ) {
e = calloc(1,sizeof(list_entry_t));
if(i->files)
e->p.txt = basename(i->files[0]);
else
e->p.txt = "Group ...";
e->pt = i;
menu_list_add_entry(menu,e);
}
return 1;
}
const menu_info_t menu_info_pt = {
"Playtree menu",
"pt",
"Albeu",
"",
{
"pt_cfg",
sizeof(struct menu_priv_s),
&cfg_dflt,
cfg_fields
},
op
};
--- NEW FILE ---
#include "../config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.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"
struct menu_priv_s {
char** lines;
int num_lines;
int cur_line;
int disp_lines;
int minb;
int hspace;
char* file;
};
static struct menu_priv_s cfg_dflt = {
NULL,
0,
0,
0,
0,
3,
NULL
};
#define ST_OFF(m) M_ST_OFF(struct menu_priv_s,m)
static m_option_t cfg_fields[] = {
{ "minbor", ST_OFF(minb), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL },
{ "hspace", ST_OFF(hspace), CONF_TYPE_INT, M_OPT_MIN, 0, 0, NULL },
{ "file", ST_OFF(file), 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_UP:
mpriv->cur_line -= mpriv->disp_lines / 2;
if(mpriv->cur_line < 0)
mpriv->cur_line = 0;
break;
case MENU_CMD_DOWN:
case MENU_CMD_OK:
mpriv->cur_line += mpriv->disp_lines / 2;
if(mpriv->cur_line >= mpriv->num_lines)
mpriv->cur_line = mpriv->num_lines - 1;
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_HOME:
mpriv->cur_line = 0;
break;
case KEY_END:
mpriv->cur_line = mpriv->num_lines - 1;
break;
case KEY_PAGE_UP:
mpriv->cur_line = mpriv->cur_line > mpriv->disp_lines ?
mpriv->cur_line - mpriv->disp_lines : 0;
break;
case KEY_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);
}
}
static void draw(menu_t* menu,mp_image_t* mpi) {
int x = mpriv->minb;
int y = mpriv->minb;
//int th = 2*mpriv->hspace + vo_font->height;
int i,end;
if(x < 0) x = 8;
if(y < 0) y = 8;
mpriv->disp_lines = (mpi->h + mpriv->hspace - 2*mpriv->minb) / ( vo_font->height + mpriv->hspace);
if(mpriv->num_lines - mpriv->cur_line < mpriv->disp_lines) {
i = mpriv->num_lines - 1 - mpriv->disp_lines;
if(i < 0) i = 0;
end = mpriv->num_lines - 1;
} else {
i = mpriv->cur_line;
end = i + mpriv->disp_lines;
if(end >= mpriv->num_lines) end = mpriv->num_lines - 1;
}
for( ; i < end ; i++) {
menu_draw_text(mpi,mpriv->lines[i],x,y);
y += vo_font->height + mpriv->hspace;
}
}
#define BUF_SIZE 1024
static int open(menu_t* menu, char* args) {
FILE* fd;
char buf[BUF_SIZE];
char *l;
int s;
int pos = 0, r = 0;
args = NULL; // Warning kill
menu->draw = draw;
menu->read_cmd = read_cmd;
menu->read_key = read_key;
if(!mpriv->file) {
printf("Menu txt need a txt file name (param file)\n");
return 0;
}
fd = fopen(mpriv->file,"r");
if(!fd) {
printf("Menu txt can't open: %s\n",mpriv->file);
return 0;
}
while(1) {
r = fread(buf+pos,1,BUF_SIZE-pos-1,fd);
if(r <= 0) {
if(pos > 0) {
mpriv->lines = realloc(mpriv->lines,(mpriv->num_lines + 1)*sizeof(char*));
mpriv->lines[mpriv->num_lines] = strdup(buf);
mpriv->num_lines++;
}
fclose(fd);
break;
}
pos += r;
buf[pos] = '\0';
while((l = strchr(buf,'\n')) != NULL) {
s = l-buf;
mpriv->lines = realloc(mpriv->lines,(mpriv->num_lines + 1)*sizeof(char*));
mpriv->lines[mpriv->num_lines] = malloc(s+1);
memcpy(mpriv->lines[mpriv->num_lines],buf,s);
mpriv->lines[mpriv->num_lines][s] = '\0';
pos -= s + 1;
if(pos > 0)
memmove(buf,l+1,pos);
buf[pos] = '\0';
mpriv->num_lines++;
}
if(pos >= BUF_SIZE-1) {
printf("Warning too long line, splitting it\n");
mpriv->lines = realloc(mpriv->lines,(mpriv->num_lines + 1)*sizeof(char*));
mpriv->lines[mpriv->num_lines] = strdup(buf);
mpriv->num_lines++;
pos = 0;
}
}
printf("Parsed %d lines\n",mpriv->num_lines);
return 1;
}
const menu_info_t menu_info_txt = {
"Text file viewer",
"txt",
"Albeu",
"",
{
"txt_cfg",
sizeof(struct menu_priv_s),
&cfg_dflt,
cfg_fields
},
open,
};
--- NEW FILE ---
#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../mp_msg.h"
#include "../libmpcodecs/img_format.h"
#include "../libmpcodecs/mp_image.h"
#include "../libmpcodecs/vf.h"
#include "../libvo/fastmemcpy.h"
#include "../libvo/video_out.h"
#include "../input/input.h"
#include "../m_struct.h"
#include "menu.h"
extern vo_functions_t* video_out;
static struct vf_priv_s* st_priv = NULL;
static mp_image_t* pause_mpi = NULL;
static int go2pause = 0;
struct vf_priv_s {
menu_t* root;
menu_t* current;
};
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi);
static mp_image_t* alloc_mpi(int w, int h, uint32_t fmt) {
mp_image_t* mpi = new_mp_image(w,h);
mp_image_setfmt(mpi,fmt);
// IF09 - allocate space for 4. plane delta info - unused
if (mpi->imgfmt == IMGFMT_IF09)
{
mpi->planes[0]=memalign(64, mpi->bpp*mpi->width*(mpi->height+2)/8+
mpi->chroma_width*mpi->chroma_height);
/* delta table, just for fun ;) */
mpi->planes[3]=mpi->planes[0]+2*(mpi->chroma_width*mpi->chroma_height);
}
else
mpi->planes[0]=memalign(64, mpi->bpp*mpi->width*(mpi->height+2)/8);
if(mpi->flags&MP_IMGFLAG_PLANAR){
// YV12/I420/YVU9/IF09. feel free to add other planar formats here...
if(!mpi->stride[0]) mpi->stride[0]=mpi->width;
if(!mpi->stride[1]) mpi->stride[1]=mpi->stride[2]=mpi->chroma_width;
if(mpi->flags&MP_IMGFLAG_SWAPPED){
// I420/IYUV (Y,U,V)
mpi->planes[1]=mpi->planes[0]+mpi->width*mpi->height;
mpi->planes[2]=mpi->planes[1]+mpi->chroma_width*mpi->chroma_height;
} else {
// YV12,YVU9,IF09 (Y,V,U)
mpi->planes[2]=mpi->planes[0]+mpi->width*mpi->height;
mpi->planes[1]=mpi->planes[2]+mpi->chroma_width*mpi->chroma_height;
}
} else {
if(!mpi->stride[0]) mpi->stride[0]=mpi->width*mpi->bpp/8;
}
mpi->flags|=MP_IMGFLAG_ALLOCATED;
return mpi;
}
void vf_menu_pause_update(struct vf_instance_s* vf) {
if(pause_mpi) {
put_image(vf,pause_mpi);
// Don't draw the osd atm
//vf->control(vf,VFCTRL_DRAW_OSD,NULL);
video_out->flip_page();
}
}
static int cmd_filter(mp_cmd_t* cmd, int paused, struct vf_priv_s * priv) {
switch(cmd->id) {
case MP_CMD_PAUSE :
if(!paused && !go2pause) { // Initial pause cmd -> wait the next put_image
go2pause = 1;
return 1;
}
if(go2pause == 2) // Msg resent by put_image after saving the image
go2pause = 0;
break;
case MP_CMD_MENU : { // Convert txt cmd from the users into libmenu stuff
char* arg = cmd->args[0].v.s;
if(!priv->current->show)
priv->current->show = 1;
else if(strcmp(arg,"up") == 0)
menu_read_cmd(priv->current,MENU_CMD_UP);
else if(strcmp(arg,"down") == 0)
menu_read_cmd(priv->current,MENU_CMD_DOWN);
else if(strcmp(arg,"ok") == 0)
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,"hide") == 0)
priv->current->show = 0;
else
printf("Unknow menu command: '%s'\n",arg);
return 1;
}
case MP_CMD_SET_MENU : {
char* menu = cmd->args[0].v.s;
menu_t* l = priv->current;
priv->current = menu_open(menu);
if(!priv->current) {
printf("Failed to open menu '%s'\n",menu);
priv->current = l;
priv->current->show = 0;
} else {
priv->current->show = 1;
priv->current->parent = l;
}
return 1;
}
}
return 0;
}
static void get_image(struct vf_instance_s* vf, mp_image_t *mpi){
mp_image_t *dmpi;
if(mpi->type == MP_IMGTYPE_TEMP && (!(mpi->flags&MP_IMGFLAG_PRESERVE)) ) {
dmpi = vf_get_image(vf->next,mpi->imgfmt,mpi->type, mpi->flags, mpi->w, mpi->h);
memcpy(mpi->planes,dmpi->planes,MP_MAX_PLANES*sizeof(unsigned char*));
memcpy(mpi->stride,dmpi->stride,MP_MAX_PLANES*sizeof(unsigned int));
mpi->flags|=MP_IMGFLAG_DIRECT;
mpi->priv=(void*)dmpi;
return;
}
}
static void key_cb(int code) {
menu_read_key(st_priv->current,code);
}
inline static void copy_mpi(mp_image_t *dmpi, mp_image_t *mpi) {
if(mpi->flags&MP_IMGFLAG_PLANAR){
memcpy_pic(dmpi->planes[0],mpi->planes[0], mpi->w, mpi->h,
dmpi->stride[0],mpi->stride[0]);
memcpy_pic(dmpi->planes[1],mpi->planes[1], mpi->chroma_width, mpi->chroma_height,
dmpi->stride[1],mpi->stride[1]);
memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->chroma_width, mpi->chroma_height,
dmpi->stride[2],mpi->stride[2]);
} else {
memcpy_pic(dmpi->planes[0],mpi->planes[0],
mpi->w*(dmpi->bpp/8), mpi->h,
dmpi->stride[0],mpi->stride[0]);
}
}
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi){
mp_image_t *dmpi = NULL;
// Close all menu who requested it
while(vf->priv->current->cl && vf->priv->current != vf->priv->root) {
menu_t* m = vf->priv->current;
vf->priv->current = m->parent ? m->parent : vf->priv->root;
menu_close(m);
}
// Step 1 : save the picture
while(go2pause == 1) {
static char delay = 0; // Hack : wait the 2 frame to be sure to show the right picture
delay ^= 1; // after a seek
if(!delay) break;
if(pause_mpi && (mpi->w != pause_mpi->w || mpi->h != pause_mpi->h ||
mpi->imgfmt != pause_mpi->imgfmt)) {
free_mp_image(pause_mpi);
pause_mpi = NULL;
}
if(!pause_mpi)
pause_mpi = alloc_mpi(mpi->w,mpi->h,mpi->imgfmt);
copy_mpi(pause_mpi,mpi);
mp_input_queue_cmd(mp_input_parse_cmd("pause"));
go2pause = 2;
break;
}
// Grab // Ungrab the keys
if(!mp_input_key_cb && vf->priv->current->show)
mp_input_key_cb = key_cb;
if(mp_input_key_cb && !vf->priv->current->show)
mp_input_key_cb = NULL;
if(mpi->flags&MP_IMGFLAG_DIRECT)
dmpi = mpi->priv;
else {
dmpi = vf_get_image(vf->next,mpi->imgfmt,
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
mpi->w,mpi->h);
copy_mpi(dmpi,mpi);
}
menu_draw(vf->priv->current,dmpi);
return vf_next_put_image(vf,dmpi);
}
static void uninit(vf_instance_t *vf) {
vf->priv=NULL;
if(pause_mpi) {
free_mp_image(pause_mpi);
pause_mpi = NULL;
}
}
static int open(vf_instance_t *vf, char* args){
if(!st_priv) {
st_priv = calloc(1,sizeof(struct vf_priv_s));
st_priv->root = st_priv->current = menu_open(args);
if(!st_priv->current) {
free(st_priv);
st_priv = NULL;
return 0;
}
mp_input_add_cmd_filter((mp_input_cmd_filter)cmd_filter,st_priv);
}
vf->put_image = put_image;
vf->get_image = get_image;
vf->uninit=uninit;
vf->priv=st_priv;
go2pause=0;
return 1;
}
vf_info_t vf_info_menu = {
"Internal filter for libmenu",
"menu",
"Albeu",
"",
open
};
More information about the MPlayer-cvslog
mailing list