diff options
author | arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-01-14 23:38:49 +0000 |
---|---|---|
committer | arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-01-14 23:38:49 +0000 |
commit | ef4a38a54e18b59df94dccfd9f819281b88ce579 (patch) | |
tree | ebbea287364120a0965869b0061bd2a51665c4f3 | |
parent | ef93c933803c01fa778bb1c6397044d9c592f66d (diff) | |
download | mpv-ef4a38a54e18b59df94dccfd9f819281b88ce579.tar.bz2 mpv-ef4a38a54e18b59df94dccfd9f819281b88ce579.tar.xz |
playtree-based config patch by Alban Bedel <albeu@free.fr>
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@4157 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | cfgparser.c | 534 | ||||
-rw-r--r-- | cfgparser.h | 63 | ||||
-rw-r--r-- | dec_video.c | 4 | ||||
-rw-r--r-- | mencoder.c | 31 | ||||
-rw-r--r-- | mplayer.c | 132 | ||||
-rw-r--r-- | playtree.c | 150 | ||||
-rw-r--r-- | playtree.h | 27 | ||||
-rw-r--r-- | playtreeparser.c | 5 |
9 files changed, 741 insertions, 209 deletions
@@ -27,9 +27,9 @@ MANDIR = ${prefix}/man # a BSD compatible 'install' program INSTALL = install -SRCS_COMMON = cyuv.c adpcm.c xacodec.c cpudetect.c mp_msg.c ac3-iec958.c dec_audio.c dec_video.c msvidc.c cinepak.c fli.c qtrle.c codec-cfg.c cfgparser.c my_profile.c RTjpegN.c minilzo.c nuppelvideo.c spudec.c +SRCS_COMMON = cyuv.c adpcm.c xacodec.c cpudetect.c mp_msg.c ac3-iec958.c dec_audio.c dec_video.c msvidc.c cinepak.c fli.c qtrle.c codec-cfg.c cfgparser.c my_profile.c RTjpegN.c minilzo.c nuppelvideo.c spudec.c playtree.c playtreeparser.c asxparser.c SRCS_MENCODER = mencoder.c $(SRCS_COMMON) libao2/afmt.c divx4_vbr.c libvo/aclib.c libvo/img_format.c libvo/osd.c -SRCS_MPLAYER = mplayer.c $(SRCS_COMMON) find_sub.c subreader.c lirc_mp.c mixer.c playtree.c playtreeparser.c asxparser.c vobsub.c +SRCS_MPLAYER = mplayer.c $(SRCS_COMMON) find_sub.c subreader.c lirc_mp.c mixer.c vobsub.c OBJS_MENCODER = $(SRCS_MENCODER:.c=.o) OBJS_MPLAYER = $(SRCS_MPLAYER:.c=.o) diff --git a/cfgparser.c b/cfgparser.c index efa42ad367..69b87b777e 100644 --- a/cfgparser.c +++ b/cfgparser.c @@ -15,6 +15,7 @@ #include <fcntl.h> #include <string.h> #include <errno.h> +#include "config.h" #include "mp_msg.h" @@ -23,84 +24,345 @@ #define MAX_RECURSION_DEPTH 8 -#ifdef DEBUG +#ifdef MP_DEBUG #include <assert.h> #endif #include "cfgparser.h" -static struct config *config; -static int nr_options; /* number of options in 'conf' */ -static int parser_mode; /* COMMAND_LINE or CONFIG_FILE */ -static int recursion_depth = 0; -static int init_conf(struct config *conf, int mode) -{ -#ifdef DEBUG - assert(conf != NULL); + +static void +m_config_save_option(m_config_t* config, config_t* conf,char* opt, char *param) { + config_save_t* save; + int sl=0; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->cs_level >= 0); + assert(conf != NULL); + assert(opt != NULL); + assert( ! (conf->flags & CONF_NOSAVE)); +#endif + + switch(conf->type) { + case CONF_TYPE_PRINT : + case CONF_TYPE_SUBCONFIG : + return; + default : + } + + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Saving option %s\n",opt); + + save = config->config_stack[config->cs_level]; + + if(save) { + for(sl = 0; save[sl].opt != NULL; sl++){ + // Check to not allocate the same arg two times + if(save[sl].opt == conf && (save[sl].opt_name == NULL || strcasecmp(save[sl].opt_name,opt) == 0)) + break; + } + + } + if(save == NULL || save[sl].opt == NULL) { + save = (config_save_t*)realloc(save,(sl+2)*sizeof(config_save_t)); + if(save == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",(sl+2)*sizeof(config_save_t),strerror(errno)); + return; + } + memset(&save[sl],0,2*sizeof(config_save_t)); + save[sl].opt = conf; + } + + + switch(conf->type) { + case CONF_TYPE_FLAG : + case CONF_TYPE_INT : + save[sl].param.as_int = *((int*)conf->p); + break; + case CONF_TYPE_FLOAT : + save[sl].param.as_float = *((float*)conf->p); + break; + case CONF_TYPE_STRING : + save[sl].param.as_pointer = *((char**)conf->p); + break; + case CONF_TYPE_FUNC_FULL : + if(strcasecmp(conf->name,opt) != 0) save->opt_name = strdup(opt); + case CONF_TYPE_FUNC_PARAM : + save->param.as_pointer = strdup(param); + case CONF_TYPE_FUNC : + break; + default : + printf("Should never append in m_config_save_option : conf->type=%d\n",conf->type); + } + + config->config_stack[config->cs_level] = save; +} + +static int +m_config_revert_option(m_config_t* config, config_save_t* save) { + char* arg = NULL; + config_save_t* iter=NULL; + int i=-1; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->cs_level >= 0); + assert(save != NULL); +#endif + + + arg = save->opt_name ? save->opt_name : save->opt->name; + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Reverting option %s\n",arg); + + if(save->opt->default_func) + save->opt->default_func(save->opt,arg); + + switch(save->opt->type) { + case CONF_TYPE_FLAG : + case CONF_TYPE_INT : + *((int*)save->opt->p) = save->param.as_int; + break; + case CONF_TYPE_FLOAT : + *((float*)save->opt->p) = save->param.as_float; + break; + case CONF_TYPE_STRING : + *((char**)save->opt->p) = save->param.as_pointer; + break; + case CONF_TYPE_FUNC_PARAM : + case CONF_TYPE_FUNC_FULL : + case CONF_TYPE_FUNC : + if(config->cs_level > 0) { + for(i = config->cs_level - 1 ; i >= 0 ; i--){ + if(config->config_stack[i] == NULL) continue; + for(iter = config->config_stack[i]; iter != NULL && iter->opt != NULL ; iter++) { + if(iter->opt == save->opt && + strcasecmp(save->param.as_pointer,iter->param.as_pointer) == 0 && + (save->opt_name == NULL || + (iter->opt_name && strcasecmp(save->opt_name,iter->opt_name)))) break; + } + } + } + free(save->param.as_pointer); + if(save->opt_name) free(save->opt_name); + save->opt_name = save->param.as_pointer = NULL; + if(i < 0) break; + arg = iter->opt_name ? iter->opt_name : iter->opt->name; + switch(iter->opt->type) { + case CONF_TYPE_FUNC : + if ((((cfg_func_t) iter->opt->p)(iter->opt)) < 0) + return -1; + break; + case CONF_TYPE_FUNC_PARAM : + if (iter->param.as_pointer == NULL) { + printf("We lost param for option %s?\n",iter->opt->name); + return -1; + } + if ((((cfg_func_param_t) iter->opt->p)(iter->opt, (char*)iter->param.as_pointer)) < 0) + return -1; + break; + case CONF_TYPE_FUNC_FULL : + if (iter->param.as_pointer != NULL && ((char*)iter->param.as_pointer)[0]=='-'){ + if( ((cfg_func_arg_param_t) iter->opt->p)(iter->opt, arg, NULL) < 0) + return -1; + }else { + if (((cfg_func_arg_param_t) save->opt->p)(iter->opt, arg, (char*)iter->param.as_pointer) < 0) + return -1; + + } + break; + } + break; + default : + printf("Why do we reverse this : name=%s type=%d ?\n",save->opt->name,save->opt->type); + } + + return 1; +} + +void +m_config_push(m_config_t* config) { + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->cs_level >= 0); #endif - /* calculate the number of options in 'conf' */ - for (nr_options = 0; conf[nr_options].name != NULL; nr_options++) - /* NOTHING */; + config->cs_level++; + config->config_stack = (config_save_t**)realloc(config->config_stack ,sizeof(config_save_t*)*(config->cs_level+1)); + if(config->config_stack == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",sizeof(config_save_t*)*(config->cs_level+1),strerror(errno)); + config->cs_level = -1; + return; + } + config->config_stack[config->cs_level] = NULL; + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config pushed level=%d\n",config->cs_level); +} + +int +m_config_pop(m_config_t* config) { + int i,ret= 1; + config_save_t* cs; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->cs_level > 0); +#endif + + if(config->config_stack[config->cs_level] != NULL) { + cs = config->config_stack[config->cs_level]; + for(i=0; cs[i].opt != NULL ; i++ ) { + if (m_config_revert_option(config,&cs[i]) < 0) + ret = -1; + } + free(config->config_stack[config->cs_level]); + } + config->config_stack = (config_save_t**)realloc(config->config_stack ,sizeof(config_save_t*)*config->cs_level); + config->cs_level--; + if(config->cs_level > 0 && config->config_stack == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",sizeof(config_save_t*)*config->cs_level,strerror(errno)); + config->cs_level = -1; + return -1; + } + mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config poped level=%d\n",config->cs_level); + return ret; +} + +m_config_t* +m_config_new(play_tree_t* pt) { + m_config_t* config; + +#ifdef MP_DEBUG + assert(pt != NULL); +#endif + + config = (m_config_t*)calloc(1,sizeof(m_config_t)); + if(config == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",sizeof(m_config_t),strerror(errno)); + return NULL; + } + config->config_stack = (config_save_t**)calloc(1,sizeof(config_save_t*)); + if(config->config_stack == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",sizeof(config_save_t*),strerror(errno)); + free(config); + return NULL; + } + config->global = 1; // We always start with global options + config->pt = pt; + return config; +} + +void +m_config_free(m_config_t* config) { + +#ifdef MP_DEBUG + assert(config != NULL); +#endif + + free(config->opt_list); + free(config->config_stack); + free(config); +} + + +static int init_conf(m_config_t *config, int mode) +{ +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->pt != NULL); + assert(config->last_entry == NULL || config->last_entry->parent == config->pt); - config = conf; -#ifdef DEBUG if (mode != COMMAND_LINE && mode != CONFIG_FILE) { mp_msg(MSGT_CFGPARSER, MSGL_ERR, "init_conf: wrong mode!\n"); return -1; } #endif - parser_mode = mode; + config->parser_mode = mode; + config->global = 1; return 1; } -static int read_option(struct config *conf, int conf_optnr, char *opt, char *param) + +static int config_read_option(m_config_t *config,config_t** conf_list, char *opt, char *param) { - int i; + int i=0,nconf = 0; long tmp_int; double tmp_float; int ret = -1; char *endptr; + config_t* conf=NULL; - mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "read_option: conf=%p optnr=%d opt='%s' param='%s'\n", - conf, conf_optnr, opt, param); - for (i = 0; i < conf_optnr; i++) { - int namelength; - /* allow 'aa*' in config.name */ - namelength=strlen(conf[i].name); - if ( (conf[i].name[namelength-1]=='*') && - !memcmp(opt, conf[i].name, namelength-1)) - break; - - - if (!strcasecmp(opt, conf[i].name)) +#ifdef MP_DEBUG + assert(config != NULL); + assert(conf_list != NULL); + assert(opt != NULL); +#endif + + mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "read_option: conf=%p opt='%s' param='%s'\n", + conf, opt, param); + for(nconf = 0 ; conf_list&& conf_list[nconf] != NULL; nconf++) { + conf = conf_list[nconf]; + for (i = 0; conf[i].name != NULL; i++) { + int namelength; + /* allow 'aa*' in config.name */ + namelength=strlen(conf[i].name); + if ( (conf[i].name[namelength-1]=='*') && + !memcmp(opt, conf[i].name, namelength-1)) + break; + if (!strcasecmp(opt, conf[i].name)) break; + } } - if (i == conf_optnr) { - if (parser_mode == CONFIG_FILE) - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid option: %s\n", opt); + if (conf[i].name == NULL) { + if (config->parser_mode == CONFIG_FILE) + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid option:\n"); ret = ERR_NOT_AN_OPTION; goto out; } mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "read_option: name='%s' p=%p type=%d\n", conf[i].name, conf[i].p, conf[i].type); - if (conf[i].flags & CONF_NOCFG && parser_mode == CONFIG_FILE) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used on command line: %s\n", opt); + if (conf[i].flags & CONF_NOCFG && config->parser_mode == CONFIG_FILE) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used on command line:\n", opt); ret = ERR_NOT_AN_OPTION; goto out; } - if (conf[i].flags & CONF_NOCMD && parser_mode == COMMAND_LINE) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used in config file: %s\n", opt); + if (conf[i].flags & CONF_NOCMD && config->parser_mode == COMMAND_LINE) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used in config file:\n", opt); ret = ERR_NOT_AN_OPTION; goto out; } - + if(strcasecmp(opt,"playlist") == 0) { // We handle playlist here + play_tree_t* list; +#ifdef MP_DEBUG + assert(config->pt != NULL); +#endif + if(!param) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "playlist option need a filename\n"); + ret = ERR_MISSING_PARAM; + goto out; + } + list = parse_playlist_file(param); + if(list) { + if(config->last_entry) { + play_tree_append_entry(config->last_entry,list); + } + else + play_tree_set_child(config->pt,list); + config->last_entry = list; + } + if(config->parser_mode == COMMAND_LINE) + config->global = 0; + return 1; + } + if(config->global == 0 && ! (conf[i].flags & CONF_GLOBAL) ) + m_config_push(config); + if( !(conf[i].flags & CONF_NOSAVE) && ! (conf[i].flags & CONF_GLOBAL) ) + m_config_save_option(config,&conf[i],opt,param); switch (conf[i].type) { case CONF_TYPE_FLAG: /* flags need a parameter in config file */ - if (parser_mode == CONFIG_FILE) { + if (config->parser_mode == CONFIG_FILE) { if (!strcasecmp(param, "yes") || /* any other language? */ !strcasecmp(param, "ja") || !strcasecmp(param, "si") || @@ -214,7 +476,7 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par case CONF_TYPE_FUNC_PARAM: if (param == NULL) goto err_missing_param; - if ((((cfg_func_param_t) conf[i].p)(config + i, param)) < 0) { + if ((((cfg_func_param_t) conf[i].p)(conf + i, param)) < 0) { ret = ERR_FUNC_ERR; goto out; } @@ -222,17 +484,17 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par break; case CONF_TYPE_FUNC_FULL: if (param!=NULL && param[0]=='-'){ - ret=((cfg_func_arg_param_t) conf[i].p)(config + i, opt, NULL); + ret=((cfg_func_arg_param_t) conf[i].p)(conf + i, opt, NULL); if (ret>=0) ret=0; /* if we return >=0: param is processed again (if there is any) */ }else{ - ret=((cfg_func_arg_param_t) conf[i].p)(config + i, opt, param); + ret=((cfg_func_arg_param_t) conf[i].p)(conf + i, opt, param); /* if we return 0: need no param, precess it again */ /* if we return 1: accepted param */ } break; case CONF_TYPE_FUNC: - if ((((cfg_func_t) conf[i].p)(config + i)) < 0) { + if ((((cfg_func_t) conf[i].p)(conf + i)) < 0) { ret = ERR_FUNC_ERR; goto out; } @@ -243,9 +505,9 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par char *subparam; char *subopt; int subconf_optnr; - struct config *subconf; + config_t *subconf; + config_t *sublist[] = { NULL , NULL }; char *token; - int sscanf_ret; if (param == NULL) goto err_missing_param; @@ -254,16 +516,17 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par subopt = malloc(strlen(param)+1); subconf = conf[i].p; + sublist[0] = subconf; for (subconf_optnr = 0; subconf[subconf_optnr].name != NULL; subconf_optnr++) /* NOTHING */; token = strtok(param, (char *)&(":")); while(token) { + int sscanf_ret; /* clear out */ subopt[0] = subparam[0] = 0; -// sscanf_ret = sscanf(token, "%[^=]=%[^\n\0]", subopt, subparam); sscanf_ret = sscanf(token, "%[^=]=%s", subopt, subparam); mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "token: '%s', i=%d, subopt='%s', subparam='%s' (ret: %d)\n", token, i, subopt, subparam, sscanf_ret); @@ -272,7 +535,7 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par case 1: subparam[0] = 0; case 2: - if ((ret = read_option((struct config *)subconf, subconf_optnr, subopt, subparam)) < 0) + if ((ret = config_read_option(config,sublist, subopt, subparam)) < 0) { mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Subconfig parsing returned error: %d in token: %s\n", ret, token); @@ -300,6 +563,17 @@ static int read_option(struct config *conf, int conf_optnr, char *opt, char *par break; } out: + if(config->global == 0 && ! (conf[i].flags & CONF_GLOBAL)) { + play_tree_t* dest = config->last_entry ? config->last_entry : config->last_parent; +#ifdef MP_DEBUG + assert(dest != NULL); +#endif + if(ret == 0) + play_tree_set_param(dest,opt,NULL); + else if(ret > 0) + play_tree_set_param(dest,opt,param); + m_config_pop(config); + } return ret; err_missing_param: mp_msg(MSGT_CFGPARSER, MSGL_ERR, "missing parameter for option: %s\n", opt); @@ -307,7 +581,17 @@ err_missing_param: goto out; } -int parse_config_file(struct config *conf, char *conffile) +int m_config_set_option(m_config_t *config,char *opt, char *param) { + +#ifdef MP_DEBUG + assert(config != NULL); + assert(opt != NULL); +#endif + mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Setting option %s=%s\n",opt,param); + return config_read_option(config,config->opt_list,opt,param); +} + +int m_config_parse_config_file(m_config_t *config, char *conffile) { #define PRINT_LINENUM printf("%s(%d): ", conffile, line_num) #define MAX_LINE_LEN 1000 @@ -326,19 +610,20 @@ int parse_config_file(struct config *conf, char *conffile) int ret = 1; int errors = 0; -#ifdef DEBUG - assert(conffile != NULL); +#ifdef MP_DEBUG + assert(config != NULL); + // assert(conf_list != NULL); #endif - if (++recursion_depth > 1) + if (++config->recursion_depth > 1) printf("Reading config file: %s", conffile); - if (recursion_depth > MAX_RECURSION_DEPTH) { + if (config->recursion_depth > MAX_RECURSION_DEPTH) { printf(": too deep 'include'. check your configfiles\n"); ret = -1; goto out; } - if (init_conf(conf, CONFIG_FILE) == -1) { + if (init_conf(config, CONFIG_FILE) == -1) { ret = -1; goto out; } @@ -350,13 +635,13 @@ int parse_config_file(struct config *conf, char *conffile) } if ((fp = fopen(conffile, "r")) == NULL) { - if (recursion_depth > 1) + if (config->recursion_depth > 1) printf(": %s\n", strerror(errno)); free(line); ret = 0; goto out; } - if (recursion_depth > 1) + if (config->recursion_depth > 1) printf("\n"); while (fgets(line, MAX_LINE_LEN, fp)) { @@ -399,7 +684,7 @@ int parse_config_file(struct config *conf, char *conffile) } opt[opt_pos] = '\0'; -#ifdef DEBUG +#ifdef MP_DEBUG PRINT_LINENUM; printf("option: %s\n", opt); #endif @@ -460,7 +745,7 @@ int parse_config_file(struct config *conf, char *conffile) continue; } -#ifdef DEBUG +#ifdef MP_DEBUG PRINT_LINENUM; printf("parameter: %s\n", param); #endif @@ -477,7 +762,7 @@ int parse_config_file(struct config *conf, char *conffile) ret = -1; } - tmp = read_option(config, nr_options, opt, param); + tmp = m_config_set_option(config, opt, param); switch (tmp) { case ERR_NOT_AN_OPTION: case ERR_MISSING_PARAM: @@ -497,33 +782,34 @@ nextline: free(line); fclose(fp); out: - --recursion_depth; + --config->recursion_depth; return ret; } -int parse_command_line(struct config *conf, int argc, char **argv, char **envp, char ***filenames) +int m_config_parse_command_line(m_config_t *config, int argc, char **argv, char **envp) { int i; - char **f = NULL; - int f_nr = 0; int tmp; char *opt; int no_more_opts = 0; -#ifdef DEBUG +#ifdef MP_DEBUG + assert(config != NULL); + assert(config->pt != NULL); assert(argv != NULL); assert(envp != NULL); assert(argc >= 1); #endif - - if (init_conf(conf, COMMAND_LINE) == -1) - return -1; - + + if (init_conf(config, COMMAND_LINE) == -1) + return -1; + if(config->last_parent == NULL) + config->last_parent = config->pt; /* in order to work recursion detection properly in parse_config_file */ - ++recursion_depth; + ++config->recursion_depth; for (i = 1; i < argc; i++) { -next: + //next: opt = argv[i]; /* check for -- (no more options id.) except --help! */ if ((*opt == '-') && (*(opt+1) == '-') && (*(opt+2) != 'h')) @@ -534,9 +820,32 @@ next: mp_msg(MSGT_CFGPARSER, MSGL_ERR, "You added '--' but no filenames presented!\n"); goto err_out; } - i++; - goto next; + continue; } + if((opt[0] == '{') && (opt[1] == '\0')) + { + play_tree_t* entry = play_tree_new(); + config->global = 0; + if(config->last_entry == NULL) { + play_tree_set_child(config->last_parent,entry); + } else { + play_tree_append_entry(config->last_entry,entry); + config->last_entry = NULL; + } + config->last_parent = entry; + continue; + } + + if((opt[0] == '}') && (opt[1] == '\0')) + { + if( ! config->last_parent || ! config->last_parent->parent) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "too much }-\n"); + goto err_out; + } + config->last_entry = config->last_parent; + config->last_parent = config->last_entry->parent; + continue; + } if ((no_more_opts == 0) && (*opt == '-') && (*(opt+1) != 0)) /* option */ { @@ -544,8 +853,7 @@ next: opt++; mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = option: %s\n", opt); - - tmp = read_option(config, nr_options, opt, argv[i + 1]); + tmp = m_config_set_option(config, opt, argv[i + 1]); switch (tmp) { case ERR_NOT_AN_OPTION: @@ -562,26 +870,82 @@ next: } else /* filename */ { - mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = filename: %s\n", opt); - + 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]); /* opt is not an option -> treat it as a filename */ - if (!(f = (char **) realloc(f, sizeof(*f) * (f_nr + 2)))) - goto err_out_mem; - - f[f_nr++] = argv[i]; + config->global = 0; // We start entry specific options + if(config->last_entry == NULL) + play_tree_set_child(config->last_parent,entry); + else + play_tree_append_entry(config->last_entry,entry); + config->last_entry = entry; } } - if (f) - f[f_nr] = NULL; - if (filenames) - *filenames = f; - --recursion_depth; - return f_nr; //filenames_nr; + --config->recursion_depth; + if(config->last_parent != config->pt) + mp_msg(MSGT_CFGPARSER, MSGL_ERR,"Missing }- ?\n"); + config->global = 1; + return 1; +#if 0 err_out_mem: mp_msg(MSGT_CFGPARSER, MSGL_ERR, "can't allocate memory for filenames (%s)\n", strerror(errno)); +#endif err_out: - --recursion_depth; + --config->recursion_depth; + config->global = 1; mp_msg(MSGT_CFGPARSER, MSGL_ERR, "command line: %s\n", argv[i]); return -1; } + +void +m_config_register_options(m_config_t *config,config_t *args) { + int list_len = 0; + config_t** conf_list = config->opt_list; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(args != NULL); +#endif + + if(conf_list) { + for ( ; conf_list[list_len] != NULL; list_len++) + /* NOTHING */; + } + + conf_list = (config_t**)realloc(conf_list,sizeof(struct conf*)*(list_len+2)); + if(conf_list == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Can't allocate %d bytes of memory : %s\n",sizeof(struct conf*)*(list_len+2),strerror(errno)); + return; + } + conf_list[list_len] = args; + conf_list[list_len+1] = NULL; + + config->opt_list = conf_list; +} + +config_t* +m_config_get_option(m_config_t *config, char* arg) { + int i; + config_t *conf; + config_t **conf_list; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(arg != NULL); +#endif + + conf_list = config->opt_list; + if(conf_list) { + for(conf = conf_list[0]; conf != NULL ; conf ++) { + for(i=0; conf[i].name != NULL; i++) { + if(strcasecmp(conf[i].name,arg) == 0) + return &conf[i]; + } + } + } + return NULL; +} + + diff --git a/cfgparser.h b/cfgparser.h index 54c924da32..bf4ccb6870 100644 --- a/cfgparser.h +++ b/cfgparser.h @@ -28,6 +28,17 @@ #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) + + +typedef struct config config_t; +typedef struct m_config m_config_t; +typedef struct config_save config_save_t; + +#include "playtree.h" + +typedef void (*cfg_default_func_t)(config_t *, char*); struct config { char *name; @@ -35,24 +46,64 @@ struct config { unsigned int type; unsigned int flags; float min,max; + cfg_default_func_t default_func; +}; + + + +struct m_config { + config_t** opt_list; + config_save_t** config_stack; + int cs_level; + int parser_mode; /* COMMAND_LINE or CONFIG_FILE */ + int global; // Are we parsing global option + 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 + int recursion_depth; +}; + +struct config_save { + config_t* opt; + union { + int as_int; + float as_float; + void* as_pointer; + } param; + char* opt_name; }; -typedef int (*cfg_func_arg_param_t)(struct config *, char *, char *); -typedef int (*cfg_func_param_t)(struct config *, char *); -typedef int (*cfg_func_t)(struct config *); + +typedef int (*cfg_func_arg_param_t)(config_t *, char *, char *); +typedef int (*cfg_func_param_t)(config_t *, char *); +typedef int (*cfg_func_t)(config_t *); /* parse_config_file returns: * -1 on error (can't malloc, invalid option...) * 0 if can't open configfile * 1 on success */ -int parse_config_file(struct config *conf, char *conffile); +int m_config_parse_config_file(m_config_t *config, char *conffile); /* parse_command_line returns: * -1 on error (invalid option...) * 0 if there was no filename on command line - * >=1 if there were filenames + * 1 if there were filenames */ -int parse_command_line(struct config *conf, int argc, char **argv, char **envp, char ***filenames); +int m_config_parse_command_line(m_config_t* config, int argc, char **argv, char **envp); + + +void m_config_register_options(m_config_t *config,config_t *args); + +int m_config_set_option(m_config_t *config,char *opt, char *param); + +config_t* m_config_get_option(m_config_t *config, char* arg); + +m_config_t* m_config_new(play_tree_t* pt); + +void m_config_free(m_config_t* config); + +void m_config_push(m_config_t* config); +int m_config_pop(m_config_t* config); #endif /* __CONFIG_H */ diff --git a/dec_video.c b/dec_video.c index 0f500a313c..7a5ac2f0dc 100644 --- a/dec_video.c +++ b/dec_video.c @@ -331,6 +331,10 @@ void uninit_video(sh_video_t *sh_video){ xacodec_exit(); break; #endif + case VFM_DIVX4: + case VFM_ODIVX: + decore(0x123,DEC_OPT_RELEASE,NULL,NULL); + break; } if(sh_video->our_out_buffer){ free(sh_video->our_out_buffer); diff --git a/mencoder.c b/mencoder.c index b6d2522623..d01af2f442 100644 --- a/mencoder.c +++ b/mencoder.c @@ -31,6 +31,7 @@ static char* banner_text= #include "stream.h" #include "demuxer.h" #include "stheader.h" +#include "playtree.h" #include "aviwrite.h" @@ -171,10 +172,12 @@ static int vo_w=0, vo_h=0; #include "cfgparser.h" +m_config_t* mconfig; + static int cfg_inc_verbose(struct config *conf){ ++verbose; return 0;} static int cfg_include(struct config *conf, char *filename){ - return parse_config_file(conf, filename); + return m_config_parse_config_file(mconfig, filename); } #include "get_path.c" @@ -340,9 +343,9 @@ float audio_preload=0.5; double v_pts_corr=0; double v_timer_corr=0; -char** filenames=NULL; +play_tree_t* playtree; +play_tree_iter_t* playtree_iter; char* filename=NULL; -int num_filenames; int decoded_frameno=0; @@ -378,16 +381,30 @@ divx4_param.rc_reaction_period = 10; divx4_param.rc_reaction_ratio = 20; #endif - num_filenames=parse_command_line(conf, argc, argv, envp, &filenames); - if(num_filenames<0) exit(1); // error parsing cmdline - if(!num_filenames && !vcd_track && !dvd_title && !tv_param_on){ + playtree = play_tree_new(); + mconfig = m_config_new(playtree); + m_config_register_options(mconfig,mencoder_opts); + + if(m_config_parse_command_line(mconfig, argc, argv, envp) < 0) exit(1); // error parsing cmdline + playtree = play_tree_cleanup(playtree); + if(playtree) { + playtree_iter = play_tree_iter_new(playtree,mconfig); + if(playtree_iter) { + if(play_tree_iter_step(playtree_iter,0,0) != PLAY_TREE_ITER_ENTRY) { + play_tree_iter_free(playtree_iter); + playtree_iter = NULL; + } + filename = play_tree_iter_get_file(playtree_iter,1); + } + } + + if(!filename && !vcd_track && !dvd_title && !tv_param_on){ printf("\nMissing filename!\n\n"); exit(1); } mp_msg_init(verbose+MSGL_STATUS); - filename=(num_filenames>0)?filenames[0]:NULL; stream=open_stream(filename,vcd_track,&file_format); if(!stream){ @@ -97,6 +97,19 @@ extern tvi_handle_t *tv_handler; play_tree_t* playtree; +#define PT_NEXT_ENTRY 1 +#define PT_PREV_ENTRY -1 +#define PT_NEXT_SRC 2 +#define PT_PREV_SRC -2 +#define PT_UP_NEXT 3 +#define PT_UP_PREV -3 + +//**************************************************************************// +// Config +//**************************************************************************// + +m_config_t* mconfig; + //**************************************************************************// // Config file //**************************************************************************// @@ -104,7 +117,7 @@ play_tree_t* playtree; static int cfg_inc_verbose(struct config *conf){ ++verbose; return 0;} static int cfg_include(struct config *conf, char *filename){ - return parse_config_file(conf, filename); + return m_config_parse_config_file(mconfig, filename); } #include "get_path.c" @@ -234,6 +247,10 @@ static int fullscreen=0; static int vidmode=0; static int softzoom=0; static int flip=-1; +// We need this opt_* because the values are then calculated so the options use the opt_* +// and before each file we reset the calculated value using this opt_* values +static int opt_screen_size_x=0;//SCREEN_SIZE_X; +static int opt_screen_size_y=0;//SCREEN_SIZE_Y; static int screen_size_x=0;//SCREEN_SIZE_X; static int screen_size_y=0;//SCREEN_SIZE_Y; static int screen_size_xy=0; @@ -373,11 +390,11 @@ void exit_sighandler(int x){ #include "mixer.h" #include "cfg-mplayer.h" -void parse_cfgfiles( void ) +void parse_cfgfiles( m_config_t* conf ) |