# HG changeset patch # User albeu # Date 1037066202 0 # Node ID 487cfc28525d56e888a0b5758122c7f57ff23a52 # Parent 51e5033ee687c80c6adbf9f4c634dbff403b5494 New config system + cleanup of header inter dependency diff -r 51e5033ee687 -r 487cfc28525d Makefile --- a/Makefile Tue Nov 12 00:19:14 2002 +0000 +++ b/Makefile Tue Nov 12 01:56:42 2002 +0000 @@ -26,9 +26,9 @@ # a BSD compatible 'install' program INSTALL = install -SRCS_COMMON = cpudetect.c codec-cfg.c cfgparser.c my_profile.c spudec.c playtree.c playtreeparser.c asxparser.c vobsub.c subreader.c sub_cc.c find_sub.c -SRCS_MENCODER = mencoder.c mp_msg-mencoder.c $(SRCS_COMMON) libao2/afmt.c divx4_vbr.c libvo/aclib.c libvo/osd.c libvo/sub.c libvo/font_load.c libvo/font_load_ft.c xvid_vbr.c -SRCS_MPLAYER = mplayer.c mp_msg.c $(SRCS_COMMON) mixer.c +SRCS_COMMON = cpudetect.c codec-cfg.c cfgparser.c my_profile.c spudec.c playtree.c playtreeparser.c asxparser.c vobsub.c subreader.c sub_cc.c find_sub.c m_config.c m_option.c parser-cfg.c +SRCS_MENCODER = mencoder.c mp_msg-mencoder.c $(SRCS_COMMON) libao2/afmt.c divx4_vbr.c libvo/aclib.c libvo/osd.c libvo/sub.c libvo/font_load.c libvo/font_load_ft.c xvid_vbr.c parser-mecmd.c +SRCS_MPLAYER = mplayer.c mp_msg.c $(SRCS_COMMON) mixer.c parser-mpcmd.c ifeq ($(UNRARLIB),yes) SRCS_COMMON += unrarlib.c diff -r 51e5033ee687 -r 487cfc28525d asxparser.c --- a/asxparser.c Tue Nov 12 00:19:14 2002 +0000 +++ b/asxparser.c Tue Nov 12 01:56:42 2002 +0000 @@ -1,3 +1,4 @@ +#include "config.h" #include #include @@ -5,7 +6,9 @@ #include #include +#include "playtree.h" #include "playtreeparser.h" +#include "libmpdemux/stream.h" #include "asxparser.h" #include "mp_msg.h" #include "cfgparser.h" diff -r 51e5033ee687 -r 487cfc28525d asxparser.h --- a/asxparser.h Tue Nov 12 00:19:14 2002 +0000 +++ b/asxparser.h Tue Nov 12 01:56:42 2002 +0000 @@ -1,5 +1,4 @@ -#include "playtree.h" typedef struct _ASX_Parser_t ASX_Parser_t; diff -r 51e5033ee687 -r 487cfc28525d cfg-mplayer.h --- a/cfg-mplayer.h Tue Nov 12 00:19:14 2002 +0000 +++ b/cfg-mplayer.h Tue Nov 12 01:56:42 2002 +0000 @@ -252,8 +252,8 @@ {"x", &opt_screen_size_x, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, {"y", &opt_screen_size_y, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, // set screen dimensions (when not detectable or virtual!=visible) - {"screenw", &vo_screenwidth, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, - {"screenh", &vo_screenheight, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, + {"screenw", &vo_screenwidth, CONF_TYPE_INT, CONF_RANGE|CONF_OLD, 0, 4096, NULL}, + {"screenh", &vo_screenheight, CONF_TYPE_INT, CONF_RANGE|CONF_OLD, 0, 4096, NULL}, // Geometry string {"geometry", &vo_geometry, CONF_TYPE_STRING, 0, 0, 0, NULL}, // set aspect ratio of monitor - usefull for 16:9 TVout diff -r 51e5033ee687 -r 487cfc28525d cfgparser.c --- a/cfgparser.c Tue Nov 12 00:19:14 2002 +0000 +++ b/cfgparser.c Tue Nov 12 01:56:42 2002 +0000 @@ -19,6 +19,8 @@ #include "config.h" +#ifndef NEW_CONFIG + #ifdef USE_SETLOCALE #include #endif @@ -50,6 +52,7 @@ #endif #include "cfgparser.h" +#include "playtree.h" static void m_config_list_options(m_config_t *config); static void m_config_error(int err,char* opt,char* val); @@ -1536,3 +1539,5 @@ break; } } + +#endif diff -r 51e5033ee687 -r 487cfc28525d cfgparser.h --- a/cfgparser.h Tue Nov 12 00:19:14 2002 +0000 +++ b/cfgparser.h Tue Nov 12 01:56:42 2002 +0000 @@ -2,6 +2,14 @@ * command line and config file parser */ +#ifdef NEW_CONFIG +#ifdef MP_DEBUG +#warning "NEW_CONFIG defined but still using the old cfgparser.h" +#endif +#include "m_config.h" +#include "m_option.h" +#else + #ifndef __CONFIG_H #define __CONFIG_H @@ -32,13 +40,14 @@ #define CONF_NOCMD (1<<3) #define CONF_GLOBAL (1<<4) #define CONF_NOSAVE (1<<5) +#define CONF_OLD (1<<6) typedef struct config config_t; typedef struct m_config m_config_t; typedef struct config_save config_save_t; -#include "playtree.h" +struct play_tree; typedef void (*cfg_default_func_t)(config_t *, char*); @@ -62,9 +71,9 @@ int parser_mode; /* COMMAND_LINE or CONFIG_FILE */ int flags; char* sub_conf; // When we save a subconfig - play_tree_t* pt; // play tree we use for playlist option, etc - play_tree_t* last_entry; // last added entry - play_tree_t* last_parent; // if last_entry is NULL we must create child of this + struct play_tree* pt; // play tree we use for playlist option, etc + struct play_tree* last_entry; // last added entry + struct play_tree* last_parent; // if last_entry is NULL we must create child of this int recursion_depth; }; @@ -97,7 +106,7 @@ */ int m_config_parse_command_line(m_config_t* config, int argc, char **argv); -m_config_t* m_config_new(play_tree_t* pt); +m_config_t* m_config_new(struct play_tree* pt); void m_config_free(m_config_t* config); @@ -190,3 +199,5 @@ m_config_get_float (m_config_t *config, char* arg,int* err_ret); #endif /* __CONFIG_H */ + +#endif /* NEW_CONFIG */ diff -r 51e5033ee687 -r 487cfc28525d configure --- a/configure Tue Nov 12 00:19:14 2002 +0000 +++ b/configure Tue Nov 12 01:56:42 2002 +0000 @@ -151,6 +151,7 @@ --disable-cdparanoia Disable cdparanoia support [autodetect] --enable-freetype Enable freetype2 font rendering support [disabled] --disable-unrarlib Disable Unique RAR File Library [enabled] + --enable-new-conf Enable new config stuff [disabled] Codecs: --enable-gif enable gif89a output support [autodetect] @@ -1013,6 +1014,7 @@ _big_endian=auto _freetype=no _shared_pp=no +_new_conf=no for ac_option do case "$ac_option" in @@ -1193,6 +1195,9 @@ --enable-shared-pp) _shared_pp=yes ;; --disable-shared-pp) _shared_pp=no ;; + --enable-new-conf) _new_conf=yes ;; + --disable-new-conf) _new_conf=no ;; + --language=*) LINGUAS=`echo $ac_option | cut -d '=' -f 2` ;; @@ -4235,6 +4240,14 @@ fi echores "$_shared_pp" +echocheck "New config" +if test "$_new_conf" = yes ; then + _def_new_conf='#define NEW_CONFIG 1' +else + _def_new_conf='#undef NEW_CONFIG' +fi +echores "$_new_conf" + # --------------- GUI specific tests begin ------------------- echocheck "GUI" echo "$_gui" @@ -4969,6 +4982,9 @@ /* enables / disables new input joystick support */ $_def_joystick +/* enables / disables new config */ +$_def_new_conf + /* Extension defines */ $_def_3dnow // only define if you have 3DNOW (AMD k6-2, AMD Athlon, iDT WinChip, etc.) $_def_3dnowex // only define if you have 3DNOWEX (AMD Athlon, etc.) diff -r 51e5033ee687 -r 487cfc28525d input/input.c --- a/input/input.c Tue Nov 12 00:19:14 2002 +0000 +++ b/input/input.c Tue Nov 12 01:56:42 2002 +0000 @@ -24,6 +24,7 @@ #include "../linux/getch2.h" #include "../linux/keycodes.h" #include "../linux/timer.h" +#include "../mp_msg.h" #include "../cfgparser.h" #include "joystick.h" diff -r 51e5033ee687 -r 487cfc28525d libmpdemux/stream.h --- a/libmpdemux/stream.h Tue Nov 12 00:19:14 2002 +0000 +++ b/libmpdemux/stream.h Tue Nov 12 01:56:42 2002 +0000 @@ -31,7 +31,7 @@ int vcd_seek_to_track(int fd,int track); void vcd_read_toc(int fd); -typedef struct { +typedef struct stream_st { int fd; // file descriptor, see man open(2) int type; // see STREAMTYPE_* unsigned int buf_pos,buf_len; diff -r 51e5033ee687 -r 487cfc28525d libvo/vo_aa.c --- a/libvo/vo_aa.c Tue Nov 12 00:19:14 2002 +0000 +++ b/libvo/vo_aa.c Tue Nov 12 01:56:42 2002 +0000 @@ -510,7 +510,7 @@ if (strstr(c->driver->name,"Curses") || strstr(c->driver->name,"Linux")){ freopen("/dev/tty", "w", stderr); - m_config_set_flag(mconfig,"quiet",0); /* enable mplayer outputs */ + m_config_set_option(mconfig,"quiet",NULL); /* enable mplayer outputs */ } #ifdef USE_OSD if(vo_font_save) { @@ -729,7 +729,7 @@ if ((strstr(c->driver->name,"Curses")) || (strstr(c->driver->name,"Linux"))){ freopen("/dev/null", "w", stderr); - m_config_set_flag(mconfig,"quiet",0); /* disable mplayer outputs */ + m_config_set_option(mconfig,"noquiet",NULL); /* disable mplayer outputs */ /* disable console blanking */ printf("\033[9;0]"); } diff -r 51e5033ee687 -r 487cfc28525d m_config.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m_config.c Tue Nov 12 01:56:42 2002 +0000 @@ -0,0 +1,347 @@ + +#include "config.h" + +#ifdef NEW_CONFIG + +#include +#include +#include +#include +#ifdef MP_DEBUG +#include +#endif + + +#include "m_config.h" +#include "m_option.h" +#include "mp_msg.h" + +m_config_t* +m_config_new(void) { + m_config_t* config; + + config = (m_config_t*)calloc(1,sizeof(m_config_t)); + config->lvl = 1; // 0 Is the defaults + return config; +} + +void +m_config_free(m_config_t* config) { + m_config_option_t *i = config->opts, *ct; + m_config_save_slot_t *sl,*st; + +#ifdef MP_DEBUG + assert(config != NULL); +#endif + + while(i) { + sl = i->slots; + while(sl) { + m_option_free(i->opt,sl->data); + st = sl->prev; + free(sl); + sl = st; + } + if(i->name != i->opt->name) + free(i->name); + ct = i->next; + free(i); + ct = i; + } + free(config); +} + +void +m_config_push(m_config_t* config) { + m_config_option_t *co; + m_config_save_slot_t *slot; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 0); +#endif + + config->lvl++; + + for(co = config->opts ; co ; co = co->next ) { + if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) + continue; + if(co->opt->flags & (M_OPT_GLOBAL|M_OPT_NOSAVE)) + continue; + if((co->opt->flags & M_OPT_OLD) && !co->flags) + continue; + + // Update the current status + m_option_save(co->opt,co->slots->data,co->opt->p); + + // Allocate a new slot + slot = (m_config_save_slot_t*)calloc(1,sizeof(m_config_save_slot_t) + co->opt->type->size); + slot->lvl = config->lvl; + slot->prev = co->slots; + co->slots = slot; + m_option_copy(co->opt,co->slots->data,co->slots->prev->data); + // Reset our flags + co->flags=0; + } + + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config pushed level is now %d\n",config->lvl); +} + +void +m_config_pop(m_config_t* config) { + m_config_option_t *co; + m_config_save_slot_t *slot; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 1); +#endif + + for(co = config->opts ; co ; co = co->next ) { + int pop = 0; + if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) + continue; + if(co->opt->flags & (M_OPT_GLOBAL|M_OPT_NOSAVE)) + continue; + if(co->slots->lvl > config->lvl) + mp_msg(MSGT_CFGPARSER, MSGL_WARN,"Too old save slot found from lvl %d : %d !!!\n",config->lvl,co->slots->lvl); + + while(co->slots->lvl >= config->lvl) { + m_option_free(co->opt,co->slots->data); + slot = co->slots; + co->slots = slot->prev; + free(slot); + pop++; + } + if(pop) // We removed some ctx -> set the previous value + m_option_set(co->opt,co->opt->p,co->slots->data); + } + + config->lvl--; + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config poped level=%d\n",config->lvl); +} + +static void +m_config_add_option(m_config_t *config, m_option_t *arg, char* prefix) { + m_config_option_t *co; + m_config_save_slot_t* sl; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 0); + assert(arg != NULL); +#endif + + // Allocate a new entry for this option + co = (m_config_option_t*)calloc(1,sizeof(m_config_option_t) + arg->type->size); + co->opt = arg; + + // Fill in the full name + if(prefix && strlen(prefix) > 0) { + int l = strlen(prefix) + 1 + strlen(arg->name) + 1; + co->name = (char*) malloc(l); + sprintf(co->name,"%s:%s",prefix,arg->name); + } else + co->name = arg->name; + + // Option with childs -> add them + if(arg->type->flags & M_OPT_TYPE_HAS_CHILD) { + m_option_t *ol = arg->p; + int i; + for(i = 0 ; ol[i].name != NULL ; i++) + m_config_add_option(config,&ol[i], co->name); + } else { + // Allocate a slot for the defaults + sl = (m_config_save_slot_t*)calloc(1,sizeof(m_config_save_slot_t) + arg->type->size); + m_option_save(arg,sl->data,(void**)arg->p); + // Hack to avoid too much trouble with dynamicly allocated data : + // We always use a dynamic version + if((arg->type->flags & M_OPT_TYPE_DYNAMIC) && arg->p && (*(void**)arg->p)) { + *(void**)arg->p = NULL; + m_option_set(arg,arg->p,sl->data); + } + sl->lvl = 0; + co->slots = (m_config_save_slot_t*)calloc(1,sizeof(m_config_save_slot_t) + arg->type->size); + co->slots->prev = sl; + co->slots->lvl = config->lvl; + m_option_copy(co->opt,co->slots->data,sl->data); + } + co->next = config->opts; + config->opts = co; +} + +int +m_config_register_options(m_config_t *config, m_option_t *args) { + int i; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 0); + assert(args != NULL); +#endif + + for(i = 0 ; args[i].name != NULL ; i++) + m_config_add_option(config,&args[i],NULL); + + return 1; +} + +static m_config_option_t* +m_config_get_co(m_config_t *config, char* arg) { + m_config_option_t *co; + + for(co = config->opts ; co ; co = co->next ) { + int l = strlen(co->name) - 1; + if((co->opt->type->flags & M_OPT_TYPE_ALLOW_WILDCARD) && + (co->name[l] == '*')) { + if(strncasecmp(co->name,arg,l) == 0) + return co; + } else if(strcasecmp(co->name,arg) == 0) + return co; + } + return NULL; +} + +static int +m_config_parse_option(m_config_t *config, char* arg, char* param,int set) { + m_config_option_t *co; + int r = 0; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 0); + assert(arg != NULL); +#endif + + co = m_config_get_co(config,arg); + if(!co) + return M_OPT_UNKNOW; + +#ifdef MP_DEBUG + // This is the only mandatory function + assert(co->opt->type->parse); +#endif + + // Check if this option isn't forbiden in the current mode + if((config->mode == M_CONFIG_FILE) && (co->opt->flags & M_OPT_NOCFG)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR,"The %s option can't be used in a config file\n",config->lvl); + return M_OPT_INVALID; + } + if((config->mode == M_COMMAND_LINE) && (co->opt->flags & M_OPT_NOCMD)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR,"The %s option can't be used on the command line\n",config->lvl); + return M_OPT_INVALID; + } + + // Option with childs are a bit different to parse + if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) { + char** lst = NULL; + int i,sr; + // Parse the child options + r = m_option_parse(co->opt,arg,param,&lst,config->mode); + // Set them now + for(i = 0 ; lst && lst[2*i] ; i++) { + int l = strlen(co->name) + 1 + strlen(lst[2*i]) + 1; + if(r >= 0) { + // Build the full name + char n[l]; + sprintf(n,"%s:%s",co->name,lst[2*i]); + sr = m_config_parse_option(config,n,lst[2*i+1],set); + if(sr < 0) r = sr; + } + free(lst[2*i]); + free(lst[2*i+1]); + } + if(lst) free(lst); + } else + r = m_option_parse(co->opt,arg,param,set ? co->slots->data : NULL,config->mode); + + // Parsing failed ? + if(r < 0) + return r; + // Set the option + if(set) { + m_option_set(co->opt,co->opt->p,co->slots->data); + co->flags = 1; + } + + return r; +} + +int +m_config_set_option(m_config_t *config, char* arg, char* param) { + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Setting %s=%s\n",arg,param); + return m_config_parse_option(config,arg,param,1); +} + +int +m_config_check_option(m_config_t *config, char* arg, char* param) { + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Checking %s=%s\n",arg,param); + return m_config_parse_option(config,arg,param,0); +} + + +m_option_t* +m_config_get_option(m_config_t *config, char* arg) { + m_config_option_t *co; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->lvl > 0); + assert(arg != NULL); +#endif + + co = m_config_get_co(config,arg); + if(co) + return co->opt; + else + return NULL; +} + +void* +m_config_get_option_ptr(m_config_t *config, char* arg) { + m_option_t* conf; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(arg != NULL); +#endif + + conf = m_config_get_option(config,arg); + if(!conf) return NULL; + return conf->p; +} + +void +m_config_print_option_list(m_config_t *config) { + char min[50],max[50]; + m_config_option_t* co; + int count = 0; + + if(!config->opts) return; + + printf("\n Name Type Min Max Global CL Cfg\n\n"); + for(co = config->opts ; co ; co = co->next) { + m_option_t* opt = co->opt; + if(opt->type->flags & M_OPT_TYPE_HAS_CHILD) continue; + if(opt->flags & M_OPT_MIN) + sprintf(min,"%-8.0f",opt->min); + else + strcpy(min,"No"); + if(opt->flags & M_OPT_MAX) + sprintf(max,"%-8.0f",opt->max); + else + strcpy(max,"No"); + printf(" %-20.20s %-15.15s %-10.10s %-10.10s %-3.3s %-3.3s %-3.3s\n", + co->name, + co->opt->type->name, + min, + max, + opt->flags & CONF_GLOBAL ? "Yes" : "No", + opt->flags & CONF_NOCMD ? "No" : "Yes", + opt->flags & CONF_NOCFG ? "No" : "Yes"); + count++; + } + printf("\nTotal: %d options\n",count); +} + +#endif // NEW_CONFIG diff -r 51e5033ee687 -r 487cfc28525d m_config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m_config.h Tue Nov 12 01:56:42 2002 +0000 @@ -0,0 +1,87 @@ + +#ifndef NEW_CONFIG +#warning "Including m_config.h but NEW_CONFIG is disabled" +#else + +typedef struct m_config_option m_config_option_t; +typedef struct m_config_save_slot m_config_save_slot_t; +struct m_option; +struct m_option_type; + +struct m_config_save_slot { + m_config_save_slot_t* prev; + int lvl; + unsigned char data[0]; +}; + +struct m_config_option { + m_config_option_t* next; + char* name; // Full name (ie option:subopt) + struct m_option* opt; + m_config_save_slot_t* slots; + unsigned int flags; // currently it only tell if the option was set +}; + +typedef struct m_config { + m_config_option_t* opts; + int lvl; // Current stack level + int mode; +} m_config_t; + + +//////////////////////////// Functions /////////////////////////////////// + +m_config_t* +m_config_new(void); + +void +m_config_free(m_config_t* config); + +void +m_config_push(m_config_t* config); + +void +m_config_pop(m_config_t* config); + +int +m_config_register_options(m_config_t *config, struct m_option *args); + +int +m_config_set_option(m_config_t *config, char* arg, char* param); + +int +m_config_check_option(m_config_t *config, char* arg, char* param); + +struct m_option* +m_config_get_option(m_config_t *config, char* arg); + +///////////////////////////////////////////////////////////////////////////////////// +/////////////////////////// Backward compat. stuff //////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// + +typedef struct config config_t; +struct config { + char *name; + void *p; + struct m_option_type* type; + unsigned int flags; + float min,max; + void* priv; +}; + + +#define CONF_MIN (1<<0) +#define CONF_MAX (1<<1) +#define CONF_RANGE (CONF_MIN|CONF_MAX) +#define CONF_NOCFG (1<<2) +#define CONF_NOCMD (1<<3) +#define CONF_GLOBAL (1<<4) +#define CONF_NOSAVE (1<<5) +#define CONF_OLD (1<<6) + +#define ERR_NOT_AN_OPTION -1 +#define ERR_MISSING_PARAM -2 +#define ERR_OUT_OF_RANGE -3 +#define ERR_FUNC_ERR -4 + +#endif diff -r 51e5033ee687 -r 487cfc28525d m_option.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m_option.c Tue Nov 12 01:56:42 2002 +0000 @@ -0,0 +1,1008 @@ + +#include "config.h" + +#ifdef NEW_CONFIG + +#include +#include +#include +#include +#include +#include + +#include "m_option.h" +//#include "m_config.h" +#include "mp_msg.h" + +// Default function that just do a memcpy + +static void copy_opt(m_option_t* opt,void* dst,void* src) { + if(dst && src) + memcpy(dst,src,opt->type->size); +} + +// Helper for the print funcs (from man printf) +static char* dup_printf(const char *fmt, ...) { + /* Guess we need no more than 50 bytes. */ + int n, size = 50; + char *p; + va_list ap; + if ((p = malloc (size)) == NULL) + return NULL; + while (1) { + /* Try to print in the allocated space. */ + va_start(ap, fmt); + n = vsnprintf (p, size, fmt, ap); + va_end(ap); + /* If that worked, return the string. */ + if (n > -1 && n < size) + return p; + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n+1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + if ((p = realloc (p, size)) == NULL) + return NULL; + } +} + + +// Flag + +#define VAL(x) (*(int*)(x)) + +static int parse_flag(m_option_t* opt,char *name, char *param, void* dst, int src) { + if (src == M_CONFIG_FILE) { + if (!strcasecmp(param, "yes") || /* any other language? */ + !strcasecmp(param, "ja") || + !strcasecmp(param, "si") || + !strcasecmp(param, "igen") || + !strcasecmp(param, "y") || + !strcasecmp(param, "j") || + !strcasecmp(param, "i") || + !strcmp(param, "1")) { + if(dst) VAL(dst) = opt->max; + } else if (!strcasecmp(param, "no") || + !strcasecmp(param, "nein") || + !strcasecmp(param, "nicht") || + !strcasecmp(param, "nem") || + !strcasecmp(param, "n") || + !strcmp(param, "0")) { + if(dst) VAL(dst) = opt->min; + } else { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid parameter for %s flag: %s\n",name, param); + return M_OPT_INVALID; + } + return 1; + } else { + if(dst) VAL(dst) = opt->max; + return 0; + } +} + +static char* print_flag(m_option_t* opt, void* val) { + if(VAL(val) == opt->min) + return strdup("no"); + else + return strdup("yes"); +} + +m_option_type_t m_option_type_flag = { + "Flag", + "need yes or no in config files", + sizeof(int), + 0, + parse_flag, + print_flag, + copy_opt, + copy_opt, + NULL, + NULL +}; + +// Integer + +static int parse_int(m_option_t* opt,char *name, char *param, void* dst, int src) { + long tmp_int; + char *endptr; + src = 0; + + if (param == NULL) + return M_OPT_MISSING_PARAM; + + tmp_int = strtol(param, &endptr, 0); + if (*endptr) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be an integer: %s\n",name, param); + return M_OPT_INVALID; + } + + if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be >= %d: %s\n", name, (int) opt->min, param); + return M_OPT_OUT_OF_RANGE; + } + + if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be <= %d: %s\n",name, (int) opt->max, param); + return M_OPT_OUT_OF_RANGE; + } + + if(dst) VAL(dst) = tmp_int; + + return 1; +} + +static char* print_int(m_option_t* opt, void* val) { + opt = NULL; + return dup_printf("%d",VAL(val)); +} + +m_option_type_t m_option_type_int = { + "Integer", + "", + sizeof(int), + 0, + parse_int, + print_int, + copy_opt, + copy_opt, + NULL, + NULL +}; + +// Float + +#undef VAL +#define VAL(x) (*(float*)(x)) + +static int parse_float(m_option_t* opt,char *name, char *param, void* dst, int src) { + float tmp_float; + char* endptr; + src = 0; + + if (param == NULL) + return M_OPT_MISSING_PARAM; + + tmp_float = strtod(param, &endptr); + + switch(*endptr) { + case ':': + case '/': + tmp_float /= strtod(endptr+1, &endptr); + break; + case '.': + case ',': + /* we also handle floats specified with + * non-locale decimal point ::atmos + */ + if(tmp_float<0) + tmp_float -= 1.0/pow(10,strlen(endptr+1)) * strtod(endptr+1, &endptr); + else + tmp_float += 1.0/pow(10,strlen(endptr+1)) * strtod(endptr+1, &endptr); + break; + } + + if (*endptr) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be a floating point " + "number or a ratio (numerator[:/]denominator): %s\n",name, param); + return M_OPT_INVALID; + } + + if (opt->flags & M_OPT_MIN) + if (tmp_float < opt->min) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be >= %f: %s\n", name, opt->min, param); + return M_OPT_OUT_OF_RANGE; + } + + if (opt->flags & M_OPT_MAX) + if (tmp_float > opt->max) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be <= %f: %s\n", name, opt->max, param); + return M_OPT_OUT_OF_RANGE; + } + + if(dst) VAL(dst) = tmp_float; + return 1; +} + +static char* print_float(m_option_t* opt, void* val) { + opt = NULL; + return dup_printf("%f",VAL(val)); +} + +m_option_type_t m_option_type_float = { + "Float", + "floating point number or ratio (numerator[:/]denominator)", + sizeof(float), + 0, + parse_float, + print_float, + copy_opt, + copy_opt, + NULL, + NULL +}; + +///////////// Position +#undef VAL +#define VAL(x) (*(off_t*)(x)) + +static int parse_position(m_option_t* opt,char *name, char *param, void* dst, int src) { + off_t tmp_off; + char dummy; + + if (param == NULL) + return M_OPT_MISSING_PARAM; + if (sscanf(param, sizeof(off_t) == sizeof(int) ? + "%d%c" : "%lld%c", &tmp_off, &dummy) != 1) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be an integer: %s\n",opt->name,param); + return M_OPT_INVALID; + } + + if (opt->flags & M_OPT_MIN) + if (tmp_off < opt->min) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + (sizeof(off_t) == sizeof(int) ? + "The %s option must be >= %d: %s\n" : + "The %s option must be >= %lld: %s\n"), + (off_t) opt->min, param); + return M_OPT_OUT_OF_RANGE; + } + + if (opt->flags & M_OPT_MAX) + if (tmp_off > opt->max) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + (sizeof(off_t) == sizeof(int) ? + "The %s option must be <= %d: %s\n" : + "The %s option must be <= %lld: %s\n"), + (off_t) opt->max, param); + return M_OPT_OUT_OF_RANGE; + } + + if(dst) + VAL(dst) = tmp_off; + return 1; +} + +static char* print_position(m_option_t* opt, void* val) { + return dup_printf(sizeof(off_t) == sizeof(int) ? "%d" : "%lld",VAL(val)); +} + +m_option_type_t m_option_type_position = { + "Position", + "Integer (off_t)", + sizeof(off_t), + 0, + parse_position, + print_position, + copy_opt, + copy_opt, + NULL, + NULL +}; + + +///////////// String + +#undef VAL +#define VAL(x) (*(char**)(x)) + +static int parse_str(m_option_t* opt,char *name, char *param, void* dst, int src) { + + + if (param == NULL) + return M_OPT_MISSING_PARAM; + + if ((opt->flags & M_OPT_MIN) && (strlen(param) < opt->min)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %d chars: %s\n", + (int) opt->min, param); + return M_OPT_OUT_OF_RANGE; + } + + if ((opt->flags & M_OPT_MAX) && (strlen(param) > opt->max)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %d chars: %s\n", + (int) opt->max, param); + return M_OPT_OUT_OF_RANGE; + } + + if(dst) { + if(VAL(dst)) + free(VAL(dst)); + VAL(dst) = strdup(param); + } + + return 1; + +} + +static char* print_str(m_option_t* opt, void* val) { + return (val && VAL(val) && strlen(VAL(val)) > 0) ? strdup(VAL(val)) : strdup("(empty)"); +} + +static void copy_str(m_option_t* opt,void* dst, void* src) { + if(dst && src) { + if(VAL(dst)) free(VAL(dst)); + VAL(dst) = VAL(src) ? strdup(VAL(src)) : NULL; + } +} + +static void free_str(void* src) { + if(src && VAL(src)){ + free(VAL(src)); + VAL(src) = NULL; + } +} + +m_option_type_t m_option_type_string = { + "String", + "", + sizeof(char*), + M_OPT_TYPE_DYNAMIC, + parse_str, + print_str, + copy_str, + copy_str, + copy_str, + free_str +}; + +//////////// String list + +#define LIST_SEPARATOR ',' +#undef VAL +#define VAL(x) (*(char***)(x)) + +#define OP_NONE 0 +#define OP_ADD 1 +#define OP_PRE 2 +#define OP_DEL 3 +#define OP_CLR 4 + +static void free_str_list(void* dst) { + char** d; + int i; + + if(!dst || !VAL(dst)) return; + d = VAL(dst); + + + for(i = 0 ; d[i] != NULL ; i++) + free(d[i]); + free(d); + VAL(dst) = NULL; +} + +static int str_list_add(char** add, int n,void* dst,int pre) { + char** lst = VAL(dst); + int ln; + + if(!dst) return M_OPT_PARSER_ERR; + lst = VAL(dst); + + for(ln = 0 ; lst && lst[ln] ; ln++) + /**/; + + lst = realloc(lst,(n+ln+1)*sizeof(char*)); + + if(pre) { + memmove(&lst[n],lst,(ln+1)*sizeof(char*)); + memcpy(lst,add,n*sizeof(char*)); + } else + memcpy(&lst[ln],add,(n+1)*sizeof(char*)); + + free(add); + + VAL(dst) = lst; + + return 1; +} + +static int str_list_del(char** del, int n,void* dst) { + char **lst,*ep,**d; + int i,ln,s; + long idx; + + if(!dst) return M_OPT_PARSER_ERR; + lst = VAL(dst); + + for(ln = 0 ; lst && lst[ln] ; ln++) + /**/; + s = ln; + + for(i = 0 ; del[i] != NULL ; i++) { + idx = strtol(del[i], &ep, 0); + if(*ep) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid index: %s\n",del[i]); + free(del[i]); + continue; + } + free(del[i]); + if(idx < 0 || idx >= ln) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Index %d is out of range\n",idx); + continue; + } else if(!lst[idx]) + continue; + free(lst[idx]); + lst[idx] = NULL; + s--; + } + free(del); + + if(s == 0) { + if(lst) free(lst); + VAL(dst) = NULL; + return 1; + } + + d = calloc(s+1,sizeof(char*)); + for(i = 0, n = 0 ; i < ln ; i++) { + if(!lst[i]) continue; + d[n] = lst[i]; + n++; + } + d[s] = NULL; + + if(lst) free(lst); + VAL(dst) = d; + + return 1; +} + + +static int parse_str_list(m_option_t* opt,char *name, char *param, void* dst, int src) { + int n = 0,len = strlen(opt->name); + char *ptr = param, *last_ptr, **res; + int op = OP_NONE; + + if(opt->name[len-1] == '*' && ((int)strlen(name) > len - 1)) { + char* n = &name[len-1]; + if(strcasecmp(n,"-add") == 0) + op = OP_ADD; + else if(strcasecmp(n,"-pre") == 0) + op = OP_PRE; + else if(strcasecmp(n,"-del") == 0) + op = OP_DEL; + else if(strcasecmp(n,"-clr") == 0) + op = OP_CLR; + else + return M_OPT_UNKNOW; + } + + // Clear the list ?? + if(op == OP_CLR) { + if(dst) + free_str_list(dst); + return 0; + } + + // All other op need a param + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; + + + while(ptr[0] != '\0') { + last_ptr = ptr; + ptr = strchr(ptr,LIST_SEPARATOR); + if(!ptr) { + n++; + break; + } + ptr++; + n++; + } + if(n == 0) + return M_OPT_INVALID; + if( ((opt->flags & M_OPT_MIN) && (n < opt->min)) || + ((opt->flags & M_OPT_MAX) && (n > opt->max)) ) + return M_OPT_OUT_OF_RANGE; + + if(!dst) return 1; + + res = malloc((n+1)*sizeof(char*)); + ptr = param; + n = 0; + + while(1) { + last_ptr = ptr; + ptr = strchr(ptr,LIST_SEPARATOR); + if(!ptr) { + res[n] = strdup(last_ptr); + n++; + break; + } + len = ptr - last_ptr; + res[n] = (char*)malloc(len + 1); + if(len) strncpy(res[n],last_ptr,len); + res[n][len] = '\0'; + ptr++; + n++; + } + res[n] = NULL; + + switch(op) { + case OP_ADD: + return str_list_add(res,n,dst,0); + case OP_PRE: + return str_list_add(res,n,dst,1); + case OP_DEL: + return str_list_del(res,n,dst); + } + + if(VAL(dst)) + free_str_list(dst); + VAL(dst) = res; + + return 1; +} + +static void copy_str_list(m_option_t* opt,void* dst, void* src) { + int n; + char **d,**s; + + if(!(dst && src)) return; + s = VAL(src); + + if(VAL(dst)) + free_str_list(dst); + + if(!s) { + VAL(dst) = NULL; + return; + } + + for(n = 0 ; s[n] != NULL ; n++) + /* NOTHING */; + d = (char**)malloc((n+1)*sizeof(char*)); + for( ; n >= 0 ; n--) + d[n] = s[n] ? strdup(s[n]) : NULL; + + VAL(dst) = d; +} + +static char* print_str_list(m_option_t* opt, void* src) { + return strdup("TODO ;)"); +} + +m_option_type_t m_option_type_string_list = { + "String list", + "A list of string separated by ','\n" + "Option with name that finish by an * allow to use the following suffix : \n" + "\t-add : add the given parameters at the end of list\n" + "\t-pre : add the given parameters at the begining of list\n" + "\t-del : remove the entry at the given indexs\n" + "\t-clr : clear the list\n" + "e.g: -vop-add flip,mirror -vop-del 2,5\n", + sizeof(char**), + M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD, + parse_str_list, + print_str_list, + copy_str_list, + copy_str_list, + copy_str_list, + free_str_list +}; + + +/////////////////// Func based options + +// A chained list to save the various calls for func_param and func_full +typedef struct m_func_save m_func_save_t; +struct m_func_save { + m_func_save_t* next; + char* name; + char* param; +}; + +#undef VAL +#define VAL(x) (*(m_func_save_t**)(x)) + +static void free_func_pf(void* src) { + m_func_save_t *s,*n; + + if(!src) return; + + s = VAL(src); + + while(s) { + n = s->next; + free(s->name); + if(s->param) free(s->param); + free(s); + s = n; + } + VAL(src) = NULL; +} + +// Parser for func_param and func_full +static int parse_func_pf(m_option_t* opt,char *name, char *param, void* dst, int src) { + m_func_save_t *s,*p; + + if(!dst) + return 1; + + s = (m_func_save_t*)calloc(1,sizeof(m_func_save_t)); + s->name = strdup(name); + s->param = param ? strdup(param) : NULL; + + p = VAL(dst); + if(p) { + for( ; p->next != NULL ; p = p->next) + /**/; + p->next = s; + } else + VAL(dst) = s; + + return 1; +} + +static void copy_func_pf(m_option_t* opt,void* dst, void* src) { + m_func_save_t *d = NULL, *s,* last = NULL; + + if(!(dst && src)) return; + s = VAL(src); + + if(VAL(dst)) + free_func_pf(dst); + + while(s) { + d = (m_func_save_t*)malloc(sizeof(m_func_save_t)); + d->name = strdup(s->name); + d->param = s->param ? strdup(s->param) : NULL; + if(last) + last->next = d; + else + VAL(dst) = d; + last = d; + s = s->next; + } + + +} + +/////////////////// Func_param + +static void set_func_param(m_option_t* opt, void* dst, void* src) { + m_func_save_t* s; + + if(!src) return; + s = VAL(src); + + if(!s) return; + + // Revert if needed + if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,opt->name); + for( ; s != NULL ; s = s->next) + ((m_opt_func_param_t) opt->p)(opt,s->param); +} + +m_option_type_t m_option_type_func_param = { + "Func param", + "", + sizeof(m_func_save_t*), + M_OPT_TYPE_INDIRECT, + parse_func_pf, + NULL, + NULL, // Nothing to do on save + set_func_param, + copy_func_pf, + free_func_pf +}; + +/////////////////// Func_full + +static void set_func_full(m_option_t* opt, void* dst, void* src) { + m_func_save_t* s; + + if(!src) return; + + for(s = VAL(src) ; s ; s = s->next) { + // Revert if needed + if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,s->name); + ((m_opt_func_full_t) opt->p)(opt,s->name,s->param); + } +} + +m_option_type_t m_option_type_func_full = { + "Func full", + "", + sizeof(m_func_save_t*), + M_OPT_TYPE_ALLOW_WILDCARD|M_OPT_TYPE_INDIRECT, + parse_func_pf, + NULL, + NULL, // Nothing to do on save + set_func_full, + copy_func_pf, + free_func_pf +}; + +/////////////// Func + +#undef VAL +#define VAL(x) (*(int*)(x)) + +static int parse_func(m_option_t* opt,char *name, char *param, void* dst, int src) { + if(dst) + VAL(dst) += 1; + return 0; +} + +static void set_func(m_option_t* opt,void* dst, void* src) { + int i; + if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,opt->name); + for(i = 0 ; i < VAL(src) ; i++) + ((m_opt_func_t) opt->p)(opt); +} + +m_option_type_t m_option_type_func = { + "Func", + "", + sizeof(int), + M_OPT_TYPE_INDIRECT, + parse_func, + NULL, + NULL, // Nothing to do on save + set_func, + NULL, + NULL +}; + +/////////////////// Print + +static int parse_print(m_option_t* opt,char *name, char *param, void* dst, int src) { + mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", (char *) opt->p); + if(opt->priv == NULL) + exit(1); // Call something else instead ?? + return 1; +} + +m_option_type_t m_option_type_print = { + "Print", + "", + 0, + 0, + parse_print, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +/////////////////////// Subconfig +#undef VAL +#define VAL(x) (*(char***)(x)) + +static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int src) { + char *subparam; + char *subopt; + int nr = 0; + m_option_t *subopts; + char *token; + char *p; + char** lst = NULL; + + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; + + subparam = malloc(strlen(param)+1); + subopt = malloc(strlen(param)+1); + p = strdup(param); // In case that param is a static string (cf man strtok) + + subopts = opt->p; + + token = strtok(p, (char *)&(":")); + while(token) + { + int sscanf_ret; + /* clear out */ + subopt[0] = subparam[0] = 0; + + sscanf_ret = sscanf(token, "%[^=]=%[^:]", subopt, subparam); + + mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "token: '%s', subopt='%s', subparam='%s' (ret: %d)\n", token, subopt, subparam, sscanf_ret); + switch(sscanf_ret) + { + case 1: + subparam[0] = 0; + case 2: + if(dst) { + lst = (char**)realloc(lst,2 * (nr+2) * sizeof(char*)); + lst[2*nr] = strdup(subopt); + lst[2*nr+1] = subparam[0] == 0 ? NULL : strdup(subparam); + memset(&lst[2*(nr+1)],0,2*sizeof(char*)); + nr++; + } + break; + default: + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid subconfig argument! ('%s')\n", token); + return M_OPT_INVALID; + } + token = strtok(NULL, (char *)&(":")); + } + + free(subparam); + free(subopt); + free(p); + VAL(dst) = lst; + + return 1; +} + +m_option_type_t m_option_type_subconfig = { + "Subconfig", + "The syntax is -option opt1=foo:flag:opt2=blah", + sizeof(int), + M_OPT_TYPE_HAS_CHILD, + parse_subconf, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +#include "libmpcodecs/img_format.h" +// TODO : use an array so we parse/print easily + +static int parse_imgfmt(m_option_t* opt,char *name, char *param, void* dst, int src) { + uint32_t fmt = 0; + + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; + + // From vf_format + if(!strcasecmp(param,"444p")) fmt=IMGFMT_444P; else + if(!strcasecmp(param,"422p")) fmt=IMGFMT_422P; else + if(!strcasecmp(param,"411p")) fmt=IMGFMT_411P; else + if(!strcasecmp(param,"yuy2")) fmt=IMGFMT_YUY2; else + if(!strcasecmp(param,"yv12")) fmt=IMGFMT_YV12; else + if(!strcasecmp(param,"i420")) fmt=IMGFMT_I420; else + if(!strcasecmp(param,"yvu9")) fmt=IMGFMT_YVU9; else + if(!strcasecmp(param,"if09")) fmt=IMGFMT_IF09; else + if(!strcasecmp(param,"iyuv")) fmt=IMGFMT_IYUV; else + if(!strcasecmp(param,"uyvy")) fmt=IMGFMT_UYVY; else + if(!strcasecmp(param,"bgr24")) fmt=IMGFMT_BGR24; else + if(!strcasecmp(param,"bgr32")) fmt=IMGFMT_BGR32; else + if(!strcasecmp(param,"bgr16")) fmt=IMGFMT_BGR16; else + if(!strcasecmp(param,"bgr15")) fmt=IMGFMT_BGR15; else + if(!strcasecmp(param,"bgr8")) fmt=IMGFMT_BGR8; else + if(!strcasecmp(param,"bgr4")) fmt=IMGFMT_BGR4; else + if(!strcasecmp(param,"bgr1")) fmt=IMGFMT_BGR1; else + if(!strcasecmp(param,"rgb24")) fmt=IMGFMT_RGB24; else + if(!strcasecmp(param,"rgb32")) fmt=IMGFMT_RGB32; else + if(!strcasecmp(param,"rgb16")) fmt=IMGFMT_RGB16; else + if(!strcasecmp(param,"rgb15")) fmt=IMGFMT_RGB15; else + if(!strcasecmp(param,"rgb8")) fmt=IMGFMT_RGB8; else + if(!strcasecmp(param,"rgb4")) fmt=IMGFMT_RGB4; else + if(!strcasecmp(param,"rgb1")) fmt=IMGFMT_RGB1; else { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: unknown format name: '%s'\n",param); + return M_OPT_INVALID; + } + + if(dst) + *((uint32_t*)dst) = fmt; + + return 1; +} + +m_option_type_t m_option_type_imgfmt = { + "Image format (aka colorspace)", + "Pls report any missing colorspace", + sizeof(uint32_t), + 0, + parse_imgfmt, + NULL, + copy_opt, + copy_opt, + NULL, + NULL +}; + +/// Span stuff : Not finished +static int parse_play_pos(m_play_pos_t* pos,char* opt, char *s) { + char *ep; + long tmp; + int i; + + memset(pos,0,sizeof(m_play_pos_t)); + + if(!s || s[0] == '\0') + return M_OPT_MISSING_PARAM; + + // Track index + tmp = strtol(s, &ep, 0); + if(ep != s) { + if(tmp < 1) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Track/Chapter index must be > 0\n", opt); + return M_OPT_OUT_OF_RANGE; + } + pos->idx = tmp; + if(ep[0] == '\0') + return 1; + s = ep; + } + + // Span + tmp = strlen(s); + if(s[0] != '[' || s[tmp-1] != ']') { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt); + return M_OPT_INVALID; + } + s[tmp-1] = '\0'; + s++; + + // hh:mm:ss + for( i = 2 ; i >= 0 && s[0] != 0 ; i--) { + if(s[0] == ':') { + tmp = 0; + s++; + } else { + tmp = strtol(s, &ep, 0); + if(tmp < 0 || (ep[0] != '\0' && ep[0] != (i > 0 ? ':' : '.') )) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt); + return M_OPT_INVALID; + } + pos->seconds += tmp * pow(60,i); + s = ep; + if(s[0] != '\0') + s++; + + } + } + + // sectors + if(s[0]) { + tmp = strtol(s, &ep, 0); + if(tmp < 0 || ep[0] != '\0') { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt); + return M_OPT_INVALID; + } + pos->sectors = tmp; + } + + return 1; +} + + +static int parse_span(m_option_t* opt,char *name, char *param, void* dst, int src) { + m_span_t* span = dst; + char *s = param,*e = NULL; + int r = M_OPT_INVALID; + + if(param == NULL) + return M_OPT_MISSING_PARAM; + + e = strchr(param,'-'); + if(e) { + e[0] = '\0'; + e++; + } + + if(s[0] == '\0' && e[0] == '\0') { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument\n"); + return M_OPT_INVALID; + } + + if(s[0]) { + r = parse_play_pos(&span->start,name,s); + if(r < 0) return r; + } + if(e && e[0] != '\0') + r = parse_play_pos(&span->end,name,s); + + return r; +} + +m_option_type_t m_option_type_span = { + "Span", + "The syntax is 1[hh:mm:ss.zz]-5[hh:mm:ss.zz]", + sizeof(m_span_t), + 0, + parse_span, + NULL, + copy_opt, + copy_opt, + NULL, + NULL +}; + +#endif diff -r 51e5033ee687 -r 487cfc28525d m_option.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m_option.h Tue Nov 12 01:56:42 2002 +0000 @@ -0,0 +1,222 @@ + +#ifndef NEW_CONFIG +#warning "Including m_option.h but NEW_CONFIG is disabled" +#else + +typedef struct m_option_type m_option_type_t; +typedef struct m_option m_option_t; + +///////////////////////////// Options types declarations //////////////////////////// + +// Simple types +extern m_option_type_t m_option_type_flag; +extern m_option_type_t m_option_type_int; +extern m_option_type_t m_option_type_float; +extern m_option_type_t m_option_type_string; +extern m_option_type_t m_option_type_string_list; +extern m_option_type_t m_option_type_position; + +extern m_option_type_t m_option_type_print; +extern m_option_type_t m_option_type_subconfig; +extern m_option_type_t m_option_type_imgfmt; + +// Func based types +extern m_option_type_t m_option_type_func_full; +extern m_option_type_t m_option_type_func_param; +extern m_option_type_t m_option_type_func; + +typedef void (*m_opt_default_func_t)(m_option_t *, char*); +typedef int (*m_opt_func_full_t)(m_option_t *, char *, char *); +typedef int (*m_opt_func_param_t)(m_option_t *, char *); +typedef int (*m_opt_func_t)(m_option_t *); +///////////// Backward compat +typedef m_opt_default_func_t cfg_default_func_t; +typedef m_opt_func_full_t cfg_func_arg_param_t; +typedef m_opt_func_param_t cfg_func_param_t; +typedef m_opt_func_t cfg_func_t; + +// Track/Chapter range +// accept range in the form 1[hh:mm:ss.zz]-5[hh:mm:ss.zz] +// ommited fields are assumed to be 0 +// Not finished !!!! +typedef struct { + int idx; // in the e.g 1 or 5 + unsigned int seconds; // hh:mm:ss converted in seconds + unsigned int sectors; // zz +} m_play_pos_t; + +typedef struct { + m_play_pos_t start; + m_play_pos_t end; +} m_span_t; +extern m_option_type_t m_option_type_span; + +// Don't be stupid keep tho old names ;-) +#define CONF_TYPE_FLAG (&m_option_type_flag) +#define CONF_TYPE_INT (&m_option_type_int) +#define CONF_TYPE_FLOAT (&m_option_type_float) +#define CONF_TYPE_STRING (&m_option_type_string) +#define CONF_TYPE_FUNC (&m_option_type_func) +#define CONF_TYPE_FUNC_PARAM (&m_option_type_func_param) +#define CONF_TYPE_PRINT (&m_option_type_print) +#define CONF_TYPE_FUNC_FULL (&m_option_type_func_full) +#define CONF_TYPE_SUBCONFIG (&m_option_type_subconfig) +#define CONF_TYPE_STRING_LIST (&m_option_type_string_list) +#define CONF_TYPE_POSITION (&m_option_type_position) +#define CONF_TYPE_IMGFMT (&m_option_type_imgfmt) +#define CONF_TYPE_SPAN (&m_option_type_span) + + +///////////////////////////////////////////////////////////////////////////////////////////// + +struct m_option_type { + char* name; + char* comments; // syntax desc, etc + unsigned int size; // size needed for a save slot + unsigned int flags; + + // parse is the only requiered function all others can be NULL + // If dst if non-NULL it should create/update the save slot + // If dst is NULL it should just test the validity of the arg if possible + // Src tell from where come this setting (ie cfg file, command line, playlist, .... + // It should return 1 if param was used, 0 if not. + // On error it must return 1 of the error code below + int (*parse)(m_option_t* opt,char *name, char *param, void* dst, int src); + // Print back a value in human form + char* (*print)(m_option_t* opt, void* val); + + // These 3 will be a memcpy in 50% of the case, it's called to save/restore the status of + // the var it's there for complex type like CONF_TYPE_FUNC* + // update a save slot (dst) from the current value in the prog (src) + void (*save)(m_option_t* opt,void* dst, void* src); + // set the current value (dst) from a save slot + void (*set)(m_option_t* opt,void* dst, void* src); + // Copy betewen 2 slot (if NULL and size > 0 a memcpy will be used + void (*copy)(m_option_t* opt,void* dst, void* src); + // Free the data allocated for a save slot if needed + void (*free)(void* dst); +}; + +/// This is the same thing as a struct config it have been renamed +/// to remove this config_t, m_config_t mess. Sorry about that, +/// config_t is still provided for backward compat. +struct m_option { + char *name; + void *p; + m_option_type_t* type; + unsigned int flags; + float min,max; + // This used to be function pointer to hold a 'reverse to defaults' func. + // Nom it can be used to pass any type of extra args. + // Passing a 'default func' is still valid for all func based option types + void* priv; // Type dependent data (for all kind of extended setting) +}; + + +//////////////////////////////// Option flags ///////////////////////////////// + +// Option flags +#define M_OPT_MIN (1<<0) +#define M_OPT_MAX (1<<1) +#define M_OPT_RANGE (M_OPT_MIN|M_OPT_MAX) +#define M_OPT_NOCFG (1<<2) +#define M_OPT_NOCMD (1<<3) +// This option is global : it won't be saved on push and the command +// line parser will set it when it's parsed (ie. it won't be set later) +// e.g options : -v, -quiet +#define M_OPT_GLOBAL (1<<4) +// Do not save this option : it won't be saved on push but the command +// line parser will put it with it's entry (ie : it may be set later) +// e.g options : -include +#define M_OPT_NOSAVE (1<<5) +// Emulate old behaviour by pushing the option only if it was set by the user +#define M_OPT_OLD (1<<6) + + +///////////////////////////// Option type flags /////////////////////////////////// + +// These flags are for the parsers. The description here apply to the m_config_t +// based parsers (ie. cmd line and config file parsers) +// Some parser will refuse option types that have some of these flags + +// This flag is used for the subconfig +// When this flag is set, opt->p should point to another m_option_t array +// Only the parse function will be called. If dst is set, it should create/update +// an array of char* containg opt/val pairs. +// Then the options in the child array will then be set automaticly. +// You can only affect the way suboption are parsed. +// Also note that suboptions may be directly accessed by using -option:subopt blah :-) +#define M_OPT_TYPE_HAS_CHILD (1<<0) +// If this flag is set the option type support option name with * at the end (used for -aa*) +// This only affect the option name matching, the option type have to implement +// the needed stuff. +#define M_OPT_TYPE_ALLOW_WILDCARD (1<<1) +// This flag indicate that the data is dynamicly allocated (opt->p point to a pointer) +// It enable a little hack wich replace the initial value by a dynamic copy +// in case the initial value is staticly allocated (pretty common with strings) +#define M_OPT_TYPE_DYNAMIC (1<<2) +/// If this is set the parse function doesn't directly return +// the wanted thing. Options use this if for some reasons they have to wait +// until the set call to be able to correctly set the target var. +// So for those types you have to first parse and then set the target var +// If this flag isn't set you can parse directly to the target var +// It's used for the callback based option as the callback call may append +// later on. +#define M_OPT_TYPE_INDIRECT (1<<3) + + +///////////////////////////// Parser flags //////////////////////////////////////// + +// Config mode : some parser type behave differently depending +// on config->mode value wich is passed in the src param of parse() +#define M_CONFIG_FILE 0 +#define M_COMMAND_LINE 1 + +// Option parser error code +#define M_OPT_UNKNOW -1 +#define M_OPT_MISSING_PARAM -2 +#define M_OPT_INVALID -3 +#define M_OPT_OUT_OF_RANGE -4 +#define M_OPT_PARSER_ERR -5 + + +inline static int +m_option_parse(m_option_t* opt,char *name, char *param, void* dst, int src) { + return opt->type->parse(opt,name,param,dst,src); +} + +inline static char* +m_option_print(m_option_t* opt, void* val_ptr) { + if(opt->type->print) + return opt->type->print(opt,val_ptr); + else + return NULL; +} + +inline static void +m_option_save(m_option_t* opt,void* dst, void* src) { + if(opt->type->save) + opt->type->save(opt,dst,src); +} + +inline static void +m_option_set(m_option_t* opt,void* dst, void* src) { + if(opt->type->set) + opt->type->set(opt,dst,src); +} + +inline static void +m_option_copy(m_option_t* opt,void* dst, void* src) { + if(opt->type->copy) + opt->type->set(opt,dst,src); + else if(opt->type->size > 0) + memcpy(dst,src,opt->type->size); +} + +inline static void +m_option_free(m_option_t* opt,void* dst) { + if(opt->type->free) + opt->type->free(dst); +} + +#endif diff -r 51e5033ee687 -r 487cfc28525d mencoder.c --- a/mencoder.c Tue Nov 12 00:19:14 2002 +0000 +++ b/mencoder.c Tue Nov 12 01:56:42 2002 +0000 @@ -33,7 +33,14 @@ #include "cpudetect.h" #include "codec-cfg.h" +#ifdef NEW_CONFIG +#include "m_option.h" +#include "m_config.h" +#include "parser-mecmd.h" +#else #include "cfgparser.h" +#include "playtree.h" +#endif #include "libmpdemux/stream.h" #include "libmpdemux/demuxer.h" @@ -41,7 +48,6 @@ #include "libmpdemux/mp3_hdr.h" #include "libmpdemux/aviwrite.h" -#include "playtree.h" #include "libvo/video_out.h" @@ -196,6 +202,12 @@ m_config_t* mconfig; +#ifdef NEW_CONFIG +extern int +m_config_parse_config_file(m_config_t* config, char *conffile); +#endif + + static int cfg_inc_verbose(struct config *conf){ ++verbose; return 0;} static int cfg_include(struct config *conf, char *filename){ @@ -326,8 +338,12 @@ double v_pts_corr=0; double v_timer_corr=0; +#ifdef NEW_CONFIG +m_entry_t* filelist = NULL; +#else play_tree_t* playtree; play_tree_iter_t* playtree_iter; +#endif char* filename=NULL; char* frameno_filename="frameno.avi"; @@ -357,13 +373,24 @@ } } - // FIXME: get rid of -dvd and other tricky options and config/playtree + // FIXME: get rid of -dvd and other tricky options stream2=open_stream(frameno_filename,0,&i); if(stream2){ demuxer2=demux_open(stream2,DEMUXER_TYPE_AVI,-1,-1,-2); if(demuxer2) printf(MSGTR_UsingPass3ControllFile,frameno_filename); } + // New config code +#ifdef NEW_CONFIG + mconfig = m_config_new(); + m_config_register_options(mconfig,mencoder_opts); + parse_cfgfiles(mconfig); + filelist = m_config_parse_me_command_line(mconfig, argc, argv); + if(!filelist) mencoder_exit(1, "error parsing cmdline"); + m_entry_set_options(mconfig,&filelist[0]); + filename = filelist[0].name; + // Warn the user if he put more than 1 filename ? +#else playtree = play_tree_new(); mconfig = m_config_new(playtree); m_config_register_options(mconfig,mencoder_opts); @@ -381,6 +408,7 @@ filename = play_tree_iter_get_file(playtree_iter,1); } } +#endif if(!filename && !vcd_track && !dvd_title && !tv_param_on){ printf(MSGTR_MissingFilename); diff -r 51e5033ee687 -r 487cfc28525d mplayer.c --- a/mplayer.c Tue Nov 12 00:19:14 2002 +0000 +++ b/mplayer.c Tue Nov 12 01:56:42 2002 +0000 @@ -26,7 +26,12 @@ #define HELP_MP_DEFINE_STATIC #include "help_mp.h" +#ifdef NEW_CONFIG +#include "m_option.h" +#include "m_config.h" +#else #include "cfgparser.h" +#endif #include "cfg-mplayer-def.h" #ifdef USE_SUB @@ -101,6 +106,13 @@ m_config_t* mconfig; +#ifdef NEW_CONFIG +extern play_tree_t* +m_config_parse_mp_command_line(m_config_t *config, int argc, char **argv); +extern int +m_config_parse_config_file(m_config_t* config, char *conffile); +#endif + //**************************************************************************// // Config file //**************************************************************************// @@ -584,9 +596,13 @@ (strrchr(argv[0],'/') && !strcmp(strrchr(argv[0],'/'),"/gmplayer") ) ) use_gui=1; +#ifdef NEW_CONFIG + mconfig = m_config_new(); +#else playtree = play_tree_new(); mconfig = m_config_new(playtree); +#endif m_config_register_options(mconfig,mplayer_opts); // TODO : add something to let modules register their options mp_input_register_options(mconfig); @@ -596,7 +612,13 @@ if ( use_gui ) cfg_read(); #endif +#ifdef NEW_CONFIG + playtree = m_config_parse_mp_command_line(mconfig, argc, argv); + if(playtree == NULL) + exit(1); +#else if(m_config_parse_command_line(mconfig, argc, argv) < 0) exit(1); // error parsing cmdline +#endif playtree = play_tree_cleanup(playtree); if(playtree) { diff -r 51e5033ee687 -r 487cfc28525d parser-cfg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parser-cfg.c Tue Nov 12 01:56:42 2002 +0000 @@ -0,0 +1,211 @@ + +#include "config.h" + +#ifdef NEW_CONFIG + +#include +#include +#include +#include +#include + +#ifdef MP_DEBUG +#include +#endif + +#include "mp_msg.h" +#include "m_option.h" +#include "m_config.h" + +#define MAX_RECURSION_DEPTH 8 + +static int recursion_depth = 0; + +int m_config_parse_config_file(m_config_t* config, char *conffile) +{ +#define PRINT_LINENUM mp_msg(MSGT_CFGPARSER,MSGL_V,"%s(%d): ", conffile, line_num) +#define MAX_LINE_LEN 1000 +#define MAX_OPT_LEN 100 +#define MAX_PARAM_LEN 100 + FILE *fp; + char *line; + char opt[MAX_OPT_LEN + 1]; + char param[MAX_PARAM_LEN + 1]; + char c; /* for the "" and '' check */ + int tmp; + int line_num = 0; + int line_pos; /* line pos */ + int opt_pos; /* opt pos */ + int param_pos; /* param pos */ + int ret = 1; + int errors = 0; + int prev_mode = config->mode; + +#ifdef MP_DEBUG + assert(config != NULL); + // assert(conf_list != NULL); +#endif + mp_msg(MSGT_CFGPARSER,MSGL_INFO,"Reading config file %s", conffile); + + if (recursion_depth > MAX_RECURSION_DEPTH) { + mp_msg(MSGT_CFGPARSER,MSGL_ERR,": too deep 'include'. check your configfiles\n"); + ret = -1; + goto out; + } else + + config->mode = M_CONFIG_FILE; + + if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) { + mp_msg(MSGT_CFGPARSER,MSGL_FATAL,"\ncan't get memory for 'line': %s", strerror(errno)); + ret = -1; + goto out; + } + + if ((fp = fopen(conffile, "r")) == NULL) { + mp_msg(MSGT_CFGPARSER,MSGL_ERR,": %s\n", strerror(errno)); + free(line); + ret = 0; + goto out; + } + mp_msg(MSGT_CFGPARSER,MSGL_INFO,"\n"); + + while (fgets(line, MAX_LINE_LEN, fp)) { + if (errors >= 16) { + mp_msg(MSGT_CFGPARSER,MSGL_FATAL,"too many errors\n"); + goto out; + } + + line_num++; + line_pos = 0; + + /* skip whitespaces */ + while (isspace(line[line_pos])) + ++line_pos; + + /* EOL / comment */ + if (line[line_pos] == '\0' || line[line_pos] == '#') + continue; + + /* read option. */ + for (opt_pos = 0; isprint(line[line_pos]) && + line[line_pos] != ' ' && + line[line_pos] != '#' && + line[line_pos] != '='; /* NOTHING */) { + opt[opt_pos++] = line[line_pos++]; + if (opt_pos >= MAX_OPT_LEN) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER,MSGL_ERR,"too long option\n"); + errors++; + ret = -1; + goto nextline; + } + } + if (opt_pos == 0) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER,MSGL_ERR,"parse error\n"); + ret = -1; + errors++; + continue; + } + opt[opt_pos] = '\0'; + +#ifdef MP_DEBUG + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER,MSGL_V,"option: %s\n", opt); +#endif + + /* skip whitespaces */ + while (isspace(line[line_pos])) + ++line_pos; + + /* check '=' */ + if (line[line_pos++] != '=') { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER,MSGL_ERR,"option without parameter\n"); + ret = -1; + errors++; + continue; + } + + /* whitespaces... */ + while (isspace(line[line_pos])) + ++line_pos; + + /* read the parameter */ + if (line[line_pos] == '"' || line[line_pos] == '\'') { + c = line[line_pos]; + ++line_pos; + for (param_pos = 0; line[line_pos] != c; /* NOTHING */) { + param[param_pos++] = line[line_pos++]; + if (param_pos >= MAX_PARAM_LEN) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER,MSGL_ERR,"too long parameter\n"); + ret = -1; + errors++; + goto nextline; + } + } + line_pos++; /* skip the closing " or ' */ + } else { + for (param_pos = 0; isprint(line[line_pos]) && !isspace(line[line_pos]) + && line[line_pos] != '#'; /* NOTHING */) { + param[param_pos++] = line[line_pos++]; + if (param_pos >= MAX_PARAM_LEN) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER,MSGL_ERR,"too long parameter\n"); + ret = -1; + errors++; + goto nextline; + } + } + } + param[param_pos] = '\0'; + + /* did we read a parameter? */ + if (param_pos == 0) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER,MSGL_ERR,"option without parameter\n"); + ret = -1; + errors++; + continue; + } + +#ifdef MP_DEBUG + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER,MSGL_V,"parameter: %s\n", param); +#endif + + /* now, check if we have some more chars on the line */ + /* whitespace... */ + while (isspace(line[line_pos])) + ++line_pos; + + /* EOL / comment */ + if (line[line_pos] != '\0' && line[line_pos] != '#') { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER,MSGL_WARN,"extra characters on line: %s\n", line+line_pos); + ret = -1; + } + + tmp = m_config_set_option(config, opt, param); + if (tmp < 0) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER,MSGL_INFO,"%s\n", opt); + ret = -1; + errors++; + continue; + /* break */ + } +nextline: + ; + } + + free(line); + fclose(fp); +out: + config->mode = prev_mode; + --recursion_depth; + return ret; +} + +#endif diff -r 51e5033ee687 -r 487cfc28525d parser-mecmd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parser-mecmd.c Tue Nov 12 01:56:42 2002 +0000 @@ -0,0 +1,153 @@ + +#include "config.h" + +#ifdef NEW_CONFIG + +#include +#include +#include +#include + +#ifdef MP_DEBUG +#include +#endif + +#include "mp_msg.h" +#include "m_option.h" +#include "m_config.h" +#include "parser-mecmd.h" + + +void +m_entry_list_free(m_entry_t* lst) { + int i,j; + + for(i = 0 ; lst[i].name != NULL ; i++){ + free(lst[i].name); + for(j = 0 ; lst[i].opts[2*j] != NULL ; j++) { + free(lst[i].opts[2*j]); + free(lst[i].opts[2*j+1]); + } + free(lst[i].opts); + } + free(lst); +} + +int +m_entry_set_options(m_config_t *config, m_entry_t* entry) { + int i,r; + + for(i = 0 ; entry->opts[2*i] != NULL ; i++){ + r = m_config_set_option(config,entry->opts[2*i],entry->opts[2*i+1]); + if(r < 0) + return 0; + } + return 1; +} + + + + +m_entry_t* +m_config_parse_me_command_line(m_config_t *config, int argc, char **argv) +{ + int i,nf = 0,no = 0; + int tmp; + char *opt; + int no_more_opts = 0; + m_entry_t *lst = NULL, *entry = NULL; + void add_file(char* file) { + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Adding file %s\n",argv[i]); + lst = realloc(lst,(nf+2)*sizeof(m_entry_t)); + lst[nf].name = strdup(file); + lst[nf].opts = calloc(2,sizeof(char*)); + entry = &lst[nf]; + no = 0; + memset(&lst[nf+1],0,sizeof(m_entry_t)); + nf++; + } + +#ifdef MP_DEBUG + assert(config != NULL); + assert(argv != NULL); + assert(argc >= 1); +#endif + + config->mode = M_COMMAND_LINE; + + lst = calloc(1,sizeof(m_entry_t)); + + for (i = 1; i < argc; i++) { + //next: + opt = argv[i]; + /* check for -- (no more options id.) except --help! */ + if ((*opt == '-') && (*(opt+1) == '-') && (*(opt+2) != 'h')) + { + no_more_opts = 1; + if (i+1 >= argc) + { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "You added '--' but no filenames presented!\n"); + goto err_out; + } + continue; + } + + if ((no_more_opts == 0) && (*opt == '-') && (*(opt+1) != 0)) /* option */ + { + m_option_t* mp_opt = NULL; + /* remove trailing '-' */ + opt++; + mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = option: %s\n", opt); + mp_opt = m_config_get_option(config,opt); + if(!mp_opt) { + tmp = M_OPT_UNKNOW; + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "%s in not an MEncoder option\n",opt); + goto err_out; + } + // Hack for the -vcd ... options + if(strcasecmp(opt,"vcd") == 0) + add_file("VCD Track"); + if(strcasecmp(opt,"dvd") == 0) + add_file("DVD Title"); + if(strcasecmp(opt,"tv") == 0 && argv[i + 1]) { // TV is a bit more tricky + char* param = argv[i + 1]; + char* on = strstr(param,"on"); + for( ; on ; on = strstr(on + 1,"on")) { + if(on[2] != ':' && on[2] != '\0') continue; + if(on != param && *(on - 1) != ':') continue; + add_file("TV Channel"); + break; + } + } + if(!entry || (mp_opt->flags & M_OPT_GLOBAL)) + tmp = m_config_set_option(config, opt, argv[i + 1]); + else { + tmp = m_config_check_option(config, opt, argv[i + 1]); + if(tmp >= 0) { + entry->opts = realloc(entry->opts,(no+2)*2*sizeof(char*)); + entry->opts[2*no] = strdup(opt); + entry->opts[2*no+1] = argv[i + 1] ? strdup(argv[i + 1]) : NULL; + entry->opts[2*no+2] = entry->opts[2*no+3] = NULL; + no++; + } + } + if (tmp < 0) + goto err_out; + i += tmp; + } else /* filename */ + add_file(argv[i]); + } + + if(nf == 0) { + m_entry_list_free(lst); + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "No file given\n"); + return NULL; + } + return lst; + + err_out: + m_entry_list_free(lst); + return NULL; +} + +#endif diff -r 51e5033ee687 -r 487cfc28525d parser-mecmd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parser-mecmd.h Tue Nov 12 01:56:42 2002 +0000 @@ -0,0 +1,18 @@ + +/// A simple parser with per-entry settings. + +typedef struct m_entry_st { + char* name; // Filename, url or whatever + char** opts; // NULL terminated list of name,val pairs +} m_entry_t; + +// Free a list returned by m_config_parse_command_line +void +m_entry_list_free(m_entry_t* lst); +// Use this when you switch to another entry +int +m_entry_set_options(m_config_t *config, m_entry_t* entry); + +m_entry_t* +m_config_parse_me_command_line(m_config_t *config, int argc, char **argv); + diff -r 51e5033ee687 -r 487cfc28525d parser-mpcmd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parser-mpcmd.c Tue Nov 12 01:56:42 2002 +0000 @@ -0,0 +1,284 @@ + +#include "config.h" + +#ifdef NEW_CONFIG + +#include +#include +#include +#include + +#ifdef MP_DEBUG +#include +#endif + +#include "mp_msg.h" +#include "m_option.h" +#include "m_config.h" +#include "playtree.h" + +static int recursion_depth = 0; +static int mode = 0; + +#define GLOBAL 0 +#define LOCAL 1 +#define DROP_LOCAL 2 + +#define UNSET_GLOBAL (mode = LOCAL) +// Use this 1 if you want to have only global option (no per file option) +// #define UNSET_GLOBAL (mode = GLOBAL) + + +static int is_entry_option(char *opt, char *param, play_tree_t** ret) { + play_tree_t* entry = NULL; + + *ret = NULL; + + if(strcasecmp(opt,"playlist") == 0) { // We handle playlist here + if(!param) + return M_OPT_MISSING_PARAM; + entry = parse_playlist_file(param); + if(!entry) + return 1; + } else if(strcasecmp(opt,"vcd") == 0) { + char* s; + if(!param) + return M_OPT_MISSING_PARAM; + s = (char*)malloc((strlen(param) + 6 + 1)*sizeof(char)); + sprintf(s,"vcd://%s",param); + entry = play_tree_new(); + play_tree_add_file(entry,s); + free(s); + } else if(strcasecmp(opt,"dvd") == 0) { + char* s; + if(!param) + return M_OPT_MISSING_PARAM; + s = (char*)malloc((strlen(param) + 6 + 1)*sizeof(char)); + sprintf(s,"dvd://%s",param); + entry = play_tree_new(); + play_tree_add_file(entry,s); + free(s); + } else if(strcasecmp(opt,"tv") == 0) { + char *s,*pr,*prs; + char *ps,*pe,*channel=NULL; + char *as; + int on=0; + + if(!param) + return M_OPT_MISSING_PARAM; + ps = param; + pe = strchr(param,':'); + pr = prs = (char*)malloc((strlen(param)+1)*sizeof(char)); + pr[0] = '\0'; + while(ps) { + if(!pe) + pe = ps + strlen(ps); + + as = strchr(ps,'='); + if(as && as[1] != '\0' && pe-as > 0) + as++; + else + as = NULL; + if( !as && pe-ps == 2 && strncasecmp("on",ps,2) == 0 ) + on = 1; + else if(as && as-ps == 8 && strncasecmp("channel",ps,6) == 0 && pe-as > 0) { + channel = (char*)realloc(channel,(pe-as+1)*sizeof(char)); + strncpy(channel,as,pe-as); + channel[pe-as] = '\0'; + } else if(pe-ps > 0) { + if(prs != pr) { + prs[0] = ':'; + prs++; + } + strncpy(prs,ps,pe-ps); + prs += pe-ps; + prs[0] = '\0'; + } + + if(pe[0] != '\0') { + ps = pe+1; + pe = strchr(ps,':'); + } else + ps = NULL; + } + + if(on) { + int l=5; + + if(channel) + l += strlen(channel); + s = (char*) malloc((l+1)*sizeof(char)); + if(channel) + sprintf(s,"tv://%s",channel); + else + sprintf(s,"tv://"); + entry = play_tree_new(); + play_tree_add_file(entry,s); + if(strlen(pr) > 0) + play_tree_set_param(entry,"tv",pr); + free(s); + } + free(pr); + if(channel) + free(channel); + + } + + if(entry) { + *ret = entry; + return 1; + } else + return 0; +} + +play_tree_t* +m_config_parse_mp_command_line(m_config_t *config, int argc, char **argv) +{ + int i; + int tmp = 0; + char *opt; + int no_more_opts = 0; + play_tree_t *last_parent, *last_entry = NULL, *root; + void add_entry(play_tree_t *entry) { + if(last_entry == NULL) + play_tree_set_child(last_parent,entry); + else + play_tree_append_entry(last_entry,entry); + last_entry = entry; + } + +#ifdef MP_DEBUG + assert(config != NULL); + assert(argv != NULL); + assert(argc >= 1); +#endif + + config->mode = M_COMMAND_LINE; + mode = GLOBAL; + last_parent = root = play_tree_new(); + /* in order to work recursion detection properly in parse_config_file */ + ++recursion_depth; + + for (i = 1; i < argc; i++) { + //next: + opt = argv[i]; + /* check for -- (no more options id.) except --help! */ + if ((*opt == '-') && (*(opt+1) == '-') && (*(opt+2) != 'h')) + { + no_more_opts = 1; + if (i+1 >= argc) + { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "You added '--' but no filenames presented!\n"); + goto err_out; + } + continue; + } + if((opt[0] == '{') && (opt[1] == '\0')) + { + play_tree_t* entry = play_tree_new(); + UNSET_GLOBAL; + if(last_entry == NULL) { + play_tree_set_child(last_parent,entry); + } else { + play_tree_append_entry(last_entry,entry); + last_entry = NULL; + } + last_parent = entry; + continue; + } + + if((opt[0] == '}') && (opt[1] == '\0')) + { + if( ! last_parent || ! last_parent->parent) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "too much }-\n"); + goto err_out; + } + last_entry = last_parent; + last_parent = last_entry->parent; + continue; + } + + if ((no_more_opts == 0) && (*opt == '-') && (*(opt+1) != 0)) /* option */ + { + /* remove trailing '-' */ + opt++; + + mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = option: %s\n", opt); + // We handle here some specific option + if(strcasecmp(opt,"list-options") == 0) { + m_config_print_option_list(config); + exit(1); + // Loop option when it apply to a group + } else if(strcasecmp(opt,"loop") == 0 && + (! last_entry || last_entry->child) ) { + int l; + char* end; + l = strtol(argv[i+1],&end,0); + if(!end) + tmp = ERR_OUT_OF_RANGE; + else { + play_tree_t* pt = last_entry ? last_entry : last_parent; + l = l <= 0 ? -1 : l; + pt->loop = l; + tmp = 1; + } + } else { + m_option_t* mp_opt = NULL; + play_tree_t* entry = NULL; + + tmp = is_entry_option(opt,argv[i + 1],&entry); + if(tmp > 0) { // It's an entry + if(entry) { + add_entry(entry); + UNSET_GLOBAL; + } else if(mode == LOCAL) // Entry is empty we have to drop his params + mode = DROP_LOCAL; + } else if(tmp == 0) { // 'normal' options + mp_opt = m_config_get_option(config,opt); + if (mp_opt != NULL) { // Option exist + if(mode == GLOBAL || (mp_opt->flags & M_OPT_GLOBAL)) + tmp = m_config_set_option(config, opt, argv[i + 1]); + else { + tmp = m_config_check_option(config, opt, argv[i + 1]); + if(tmp >= 0 && mode != DROP_LOCAL) { + play_tree_t* pt = last_entry ? last_entry : last_parent; + play_tree_set_param(pt,opt, argv[i + 1]); + } + } + } else { + tmp = M_OPT_UNKNOW; + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Unknow option on the command line: %s\n",opt); + } + } + } + + if (tmp < 0) + goto err_out; + i += tmp; + } + else /* filename */ + { + play_tree_t* entry = play_tree_new(); + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Adding file %s\n",argv[i]); + play_tree_add_file(entry,argv[i]); + // Lock stdin if it will be used as input + if(strcasecmp(argv[i],"-") == 0) + m_config_set_option(config,"use-stdin",NULL); + add_entry(entry); + UNSET_GLOBAL; // We start entry specific options + + } + } + + --recursion_depth; + if(last_parent != root) + mp_msg(MSGT_CFGPARSER, MSGL_ERR,"Missing }- ?\n"); + return root; + + err_out: + --recursion_depth; + play_tree_free(root,1); + return NULL; +} + +#endif diff -r 51e5033ee687 -r 487cfc28525d playtree.c --- a/playtree.c Tue Nov 12 00:19:14 2002 +0000 +++ b/playtree.c Tue Nov 12 01:56:42 2002 +0000 @@ -8,6 +8,7 @@ #ifdef MP_DEBUG #include #endif +#include "cfgparser.h" #include "playtree.h" #include "mp_msg.h" diff -r 51e5033ee687 -r 487cfc28525d playtree.h --- a/playtree.h Tue Nov 12 00:19:14 2002 +0000 +++ b/playtree.h Tue Nov 12 01:56:42 2002 +0000 @@ -2,8 +2,8 @@ #ifndef __PLAYTREE_H #define __PLAYTREE_H -#include "libmpdemux/stream.h" - +struct stream_st; +struct m_config; #define PLAY_TREE_ITER_ERROR 0 #define PLAY_TREE_ITER_ENTRY 1 @@ -20,7 +20,6 @@ typedef struct play_tree_iter play_tree_iter_t; typedef struct play_tree_param play_tree_param_t; -#include "cfgparser.h" #if 0 typedef struct play_tree_info play_tree_info_t; @@ -56,7 +55,7 @@ struct play_tree_iter { play_tree_t* root; // Iter root tree play_tree_t* tree; // Current tree - m_config_t* config; + struct m_config* config; int loop; // Looping status int file; int num_files; @@ -124,7 +123,7 @@ /// Iterator play_tree_iter_t* -play_tree_iter_new(play_tree_t* pt, m_config_t* config); +play_tree_iter_new(play_tree_t* pt, struct m_config* config); play_tree_iter_t* play_tree_iter_new_copy(play_tree_iter_t* old); @@ -148,7 +147,7 @@ play_tree_iter_get_file(play_tree_iter_t* iter, int d); play_tree_t* -parse_playtree(stream_t *stream); +parse_playtree(struct stream_st *stream); play_tree_t* play_tree_cleanup(play_tree_t* pt); diff -r 51e5033ee687 -r 487cfc28525d playtreeparser.c --- a/playtreeparser.c Tue Nov 12 00:19:14 2002 +0000 +++ b/playtreeparser.c Tue Nov 12 01:56:42 2002 +0000 @@ -11,6 +11,7 @@ #include #include #include +#include "cfgparser.h" #include "playtree.h" #include "playtreeparser.h" #include "libmpdemux/stream.h" diff -r 51e5033ee687 -r 487cfc28525d playtreeparser.h --- a/playtreeparser.h Tue Nov 12 00:19:14 2002 +0000 +++ b/playtreeparser.h Tue Nov 12 01:56:42 2002 +0000 @@ -2,11 +2,10 @@ #ifndef __PLAYTREEPARSER_H #define __PLAYTREEPARSER_H -#include "playtree.h" -#include "libmpdemux/stream.h" +struct stream_st; typedef struct play_tree_parser { - stream_t* stream; + struct stream_st* stream; char *buffer,*iter,*line; int buffer_size , buffer_end; int deep,keep; @@ -14,7 +13,7 @@ play_tree_parser_t* -play_tree_parser_new(stream_t* stream,int deep); +play_tree_parser_new(struct stream_st* stream,int deep); void play_tree_parser_free(play_tree_parser_t* p);