mirror of
https://github.com/mpv-player/mpv.git
synced 2024-09-20 20:03:10 +02:00
OSD menus initial version
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8198 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
54e31581a3
commit
c83ebc0b7d
38
libmenu/Makefile
Normal file
38
libmenu/Makefile
Normal file
@ -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
|
515
libmenu/menu.c
Normal file
515
libmenu/menu.c
Normal file
@ -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;
|
||||||
|
}
|
72
libmenu/menu.h
Normal file
72
libmenu/menu.h
Normal file
@ -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);
|
155
libmenu/menu_cmdlist.c
Normal file
155
libmenu/menu_cmdlist.c
Normal file
@ -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
|
||||||
|
};
|
234
libmenu/menu_console.c
Normal file
234
libmenu/menu_console.c
Normal file
@ -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,
|
||||||
|
};
|
283
libmenu/menu_filesel.c
Normal file
283
libmenu/menu_filesel.c
Normal file
@ -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_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
|
||||||
|
};
|
225
libmenu/menu_list.c
Normal file
225
libmenu/menu_list.c
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
}
|
66
libmenu/menu_list.h
Normal file
66
libmenu/menu_list.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
|
||||||
|
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 }
|
||||||
|
|
159
libmenu/menu_param.c
Normal file
159
libmenu/menu_param.c
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
|
||||||
|
#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
|
||||||
|
};
|
151
libmenu/menu_pt.c
Normal file
151
libmenu/menu_pt.c
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
|
||||||
|
#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
|
||||||
|
};
|
194
libmenu/menu_txt.c
Normal file
194
libmenu/menu_txt.c
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
|
||||||
|
#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,
|
||||||
|
};
|
251
libmenu/vf_menu.c
Normal file
251
libmenu/vf_menu.c
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
|
||||||
|
#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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user