From 5fafd19ee28c13e90f1af33db15480ed2a42324f Mon Sep 17 00:00:00 2001 From: albeu Date: Mon, 21 Jan 2002 10:45:53 +0000 Subject: [PATCH] Bug fix for subconfig option. A -tv option containing the on parameter is now take as an entry. New functions to set/get options and know if an option is alredy set. A few comments. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@4293 b3059339-0415-0410-9bf9-f77b7e298cf2 --- cfgparser.c | 323 +++++++++++++++++++++++++++++++++++++++++++++++----- cfgparser.h | 104 ++++++++++++++--- playtree.c | 5 +- 3 files changed, 386 insertions(+), 46 deletions(-) diff --git a/cfgparser.c b/cfgparser.c index 624a2bef79..f4d3bf02c5 100644 --- a/cfgparser.c +++ b/cfgparser.c @@ -67,22 +67,21 @@ m_config_save_option(m_config_t* config, config_t* conf,char* opt, char *param) if(save) { for(sl = 0; save[sl].opt != NULL; sl++){ - // Check to not allocate the same arg two times + // Check to not save 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)); + if(save[sl].opt) return; - } - memset(&save[sl],0,2*sizeof(config_save_t)); - save[sl].opt = conf; } + 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 : @@ -323,6 +322,69 @@ static int config_is_entry_option(m_config_t *config, char *opt, char *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 ERR_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); + } } @@ -394,7 +456,8 @@ static int config_read_option(m_config_t *config,config_t** conf_list, char *opt return ret; else ret = -1; - if(! IS_RUNNING(config) && ! IS_GLOBAL(config) && ! (conf[i].flags & CONF_GLOBAL) ) + if(! IS_RUNNING(config) && ! IS_GLOBAL(config) && + ! (conf[i].flags & CONF_GLOBAL) && conf[i].type != CONF_TYPE_SUBCONFIG ) m_config_push(config); if( !(conf[i].flags & CONF_NOSAVE) && ! (conf[i].flags & CONF_GLOBAL) ) m_config_save_option(config,&conf[i],opt,param); @@ -560,7 +623,7 @@ static int config_read_option(m_config_t *config,config_t** conf_list, char *opt sublist[0] = subconf; for (subconf_optnr = 0; subconf[subconf_optnr].name != NULL; subconf_optnr++) /* NOTHING */; - + config->sub_conf = opt; token = strtok(p, (char *)&(":")); while(token) { @@ -590,7 +653,7 @@ static int config_read_option(m_config_t *config,config_t** conf_list, char *opt } token = strtok(NULL, (char *)&(":")); } - + config->sub_conf = NULL; free(subparam); free(subopt); free(p); @@ -605,15 +668,23 @@ static int config_read_option(m_config_t *config,config_t** conf_list, char *opt break; } out: - if(ret >= 0 && ! IS_RUNNING(config) && ! IS_GLOBAL(config) && ! (conf[i].flags & CONF_GLOBAL)) { + if(ret >= 0 && ! IS_RUNNING(config) && ! IS_GLOBAL(config) && ! (conf[i].flags & CONF_GLOBAL) && conf[i].type != CONF_TYPE_SUBCONFIG ) { play_tree_t* dest = config->last_entry ? config->last_entry : config->last_parent; + char* o; #ifdef MP_DEBUG assert(dest != NULL); #endif + if(config->sub_conf) { + o = (char*)malloc((strlen(config->sub_conf) + 1 + strlen(opt) + 1)*sizeof(char)); + sprintf(o,"%s:%s",config->sub_conf,opt); + } else + o =strdup(opt); + if(ret == 0) - play_tree_set_param(dest,opt,NULL); + play_tree_set_param(dest,o,NULL); else if(ret > 0) - play_tree_set_param(dest,opt,param); + play_tree_set_param(dest,o,param); + free(o); m_config_pop(config); } return ret; @@ -624,13 +695,34 @@ err_missing_param: } int m_config_set_option(m_config_t *config,char *opt, char *param) { - + char *e; #ifdef MP_DEBUG assert(config != NULL); assert(config->opt_list != NULL); assert(opt != NULL); #endif mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Setting option %s=%s\n",opt,param); + e = strchr(opt,':'); + if(e && e[1] != '\0') { + int ret; + config_t* opt_list[] = { NULL, NULL }; + char* s = (char*)malloc((e-opt+1)*sizeof(char)); + strncpy(s,opt,e-opt); + s[e-opt] = '\0'; + opt_list[0] = m_config_get_option_ptr(config,s); + if(!opt_list[0]) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR,"m_config_set_option %s=%s : no %s subconfig\n",opt,param,s); + free(s); + return ERR_NOT_AN_OPTION; + } + e++; + s = (char*)realloc(s,strlen(e) + 1); + strcpy(s,e); + ret = config_read_option(config,opt_list,s,param); + free(s); + return ret; + } + return config_read_option(config,config->opt_list,opt,param); } @@ -942,7 +1034,7 @@ err_out: return -1; } -void +int m_config_register_options(m_config_t *config,config_t *args) { int list_len = 0; config_t** conf_list = config->opt_list; @@ -960,26 +1052,42 @@ m_config_register_options(m_config_t *config,config_t *args) { 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; + return 0; } conf_list[list_len] = args; conf_list[list_len+1] = NULL; config->opt_list = conf_list; + + return 1; } config_t* m_config_get_option(m_config_t *config, char* arg) { int i,j; + char *e; config_t *conf; config_t **conf_list; + config_t* cl[] = { NULL, NULL }; #ifdef MP_DEBUG assert(config != NULL); assert(arg != NULL); #endif - conf_list = config->opt_list; + e = strchr(arg,':'); + + if(e) { + char *s; + s = (char*)malloc((e-arg+1)*sizeof(char)); + strncpy(s,arg,e-arg); + s[e-arg] = '\0'; + cl[0] = m_config_get_option(config,s); + conf_list = cl; + free(s); + } else + conf_list = config->opt_list; + if(conf_list) { for(j = 0 ; conf_list[j] != NULL ; j++) { conf = conf_list[j]; @@ -994,20 +1102,122 @@ m_config_get_option(m_config_t *config, char* arg) { void* m_config_get_option_ptr(m_config_t *config, char* arg) { - config_t* conf = m_config_get_option(config,arg); + config_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; } +int +m_config_get_int (m_config_t *config, char* arg,int* err_ret) { + int *ret; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(arg != NULL); +#endif + + ret = m_config_get_option_ptr(config,arg); + if(err_ret) + *err_ret = 0; + if(!ret) { + if(err_ret) + *err_ret = 1; + return -1; + } else + return (*ret); +} + +float +m_config_get_float (m_config_t *config, char* arg,int* err_ret) { + float *ret; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(arg != NULL); +#endif + + ret = m_config_get_option_ptr(config,arg); + if(err_ret) + *err_ret = 0; + if(!ret) { + if(err_ret) + *err_ret = 1; + return -1; + } else + return (*ret); +} + #define AS_INT(c) (*((int*)c->p)) +int +m_config_set_int(m_config_t *config, char* arg,int val) { + config_t* opt; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(arg != NULL); +#endif + + opt = m_config_get_option(config,arg); + + if(!opt || opt->type != CONF_TYPE_INT) + return ERR_NOT_AN_OPTION; + + if(opt->flags & CONF_MIN && val < opt->min) + return ERR_OUT_OF_RANGE; + if(opt->flags & CONF_MAX && val > opt->max) + return ERR_OUT_OF_RANGE; + + m_config_save_option(config,opt,arg,NULL); + AS_INT(opt) = val; + + return 1; +} + +int +m_config_set_float(m_config_t *config, char* arg,float val) { + config_t* opt; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(arg != NULL); +#endif + + opt = m_config_get_option(config,arg); + + if(!opt || opt->type != CONF_TYPE_FLOAT) + return ERR_NOT_AN_OPTION; + + if(opt->flags & CONF_MIN && val < opt->min) + return ERR_OUT_OF_RANGE; + if(opt->flags & CONF_MAX && val > opt->max) + return ERR_OUT_OF_RANGE; + + m_config_save_option(config,opt,arg,NULL); + *((float*)opt->p) = val; + + return 1; +} + + int m_config_switch_flag(m_config_t *config, char* opt) { config_t *conf; - + +#ifdef MP_DEBUG + assert(config != NULL); + assert(opt != NULL); +#endif + conf = m_config_get_option(config,opt); - if(!conf) return 0; - if(conf->type != CONF_TYPE_FLAG) return 0; + if(!conf || conf->type != CONF_TYPE_FLAG) return 0; if( AS_INT(conf) == conf->min) AS_INT(conf) = conf->max; else if(AS_INT(conf) == conf->max) AS_INT(conf) = conf->min; else return 0; @@ -1015,12 +1225,67 @@ m_config_switch_flag(m_config_t *config, char* opt) { return 1; } -void -m_config_set_flag(m_config_t *config, char* opt, int max) { +int +m_config_set_flag(m_config_t *config, char* opt, int state) { config_t *conf; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(opt != NULL); +#endif + conf = m_config_get_option(config,opt); - if(!conf) return; - if(conf->type != CONF_TYPE_FLAG) return; - if(max) AS_INT(conf) = conf->max; + if(!conf || conf->type != CONF_TYPE_FLAG) return 0; + if(state) AS_INT(conf) = conf->max; else AS_INT(conf) = conf->min; + return 1; } + +int +m_config_get_flag(m_config_t *config, char* opt) { + config_t *conf; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(opt != NULL); +#endif + + conf = m_config_get_option(config,opt); + if(!conf || conf->type != CONF_TYPE_FLAG) return -1; + if(AS_INT(conf) == conf->max) + return 1; + else if(AS_INT(conf) == conf->min) + return 0; + else + return -1; +} + +int m_config_is_option_set(m_config_t *config, char* arg) { + config_t* opt; + config_save_t* save; + int l,i; + +#ifdef MP_DEBUG + assert(config != NULL); + assert(arg != NULL); +#endif + + opt = m_config_get_option(config,arg); + + if(!opt) + return -1; + + for(l = config->cs_level ; l >= 0 ; l--) { + save = config->config_stack[l]; + if(!save) + continue; + for(i = 0 ; save[i].opt != NULL ; i++) { + if(save[i].opt == opt) + return 1; + } + } + + return 0; +} + +#undef AS_INT diff --git a/cfgparser.h b/cfgparser.h index f340141a4b..bb36a32f05 100644 --- a/cfgparser.h +++ b/cfgparser.h @@ -46,6 +46,8 @@ struct config { unsigned int type; unsigned int flags; float min,max; + /* Use this field when your need to do something before a new value is + assigned to your option */ cfg_default_func_t default_func; }; @@ -57,6 +59,7 @@ struct m_config { int cs_level; 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 @@ -87,29 +90,100 @@ 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 otherwise */ 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); - -int m_config_switch_flag(m_config_t *config, char* opt); - -void m_config_set_flag(m_config_t *config, char* opt, int max); - -void* m_config_get_option_ptr(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); +/* + * Return 0 on error 1 on success + */ int m_config_pop(m_config_t* config); + +/* + * Return 0 on error 1 on success + */ +int m_config_register_options(m_config_t *config,config_t *args); + +/* + * For all the following function when it's a subconfig option + * you must give an option name like 'tv:channel' and not just + * 'channel' + */ + +/* + * Return 1 on sucess 0 on failure + */ +int m_config_set_option(m_config_t *config,char *opt, char *param); + +/* + * Get the config struct defining an option + * Return NULL on error + */ +config_t* m_config_get_option(m_config_t *config, char* arg); + +/* + * Get the p field of the struct defining an option + * Return NULL on error + */ +void* m_config_get_option_ptr(m_config_t *config, char* arg); + +/* + * Tell is an option is alredy set or not + * Return -1 one error (requested option arg exist) + * Otherwise 0 or 1 + */ +int m_config_is_option_set(m_config_t *config, char* arg); + +/* + * Return 0 on error 1 on success + */ +int m_config_switch_flag(m_config_t *config, char* opt); + +/* + * Return 0 on error 1 on success + */ +int m_config_set_flag(m_config_t *config, char* opt, int max); + +/* + * Return the value of a flag (O or 1) and -1 on error + */ +int m_config_get_flag(m_config_t *config, char* opt); + +/* + * Set the value of an int option + * Return 0 on error 1 on success + */ +int +m_config_set_int(m_config_t *config, char* arg,int val); + +/* + * Get the value of an int option + * Return the option value or -1 on error + * If err_ret is not NULL it's set to 1 on error + */ +int +m_config_get_int (m_config_t *config, char* arg,int* err_ret); + +/* + * Set the value of a float option + * Return 0 on error 1 on success + */ +int +m_config_set_float(m_config_t *config, char* arg,float val); + + +/* + * Get the value of a float option + * Return the option value or -1 on error + * If err_ret is not NULL it's set to 1 on error + */ +float +m_config_get_float (m_config_t *config, char* arg,int* err_ret); + #endif /* __CONFIG_H */ diff --git a/playtree.c b/playtree.c index b42333faf5..ff2e6e72cc 100644 --- a/playtree.c +++ b/playtree.c @@ -403,8 +403,9 @@ play_tree_iter_push_params(play_tree_iter_t* iter) { for(n = 0; pt->params[n].name != NULL ; n++) { - if(m_config_set_option(iter->config,pt->params[n].name,pt->params[n].value) < 0) { - mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Error while setting option '%s' with value '%s'\n", + int e; + if((e = m_config_set_option(iter->config,pt->params[n].name,pt->params[n].value)) < 0) { + mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Error %d while setting option '%s' with value '%s'\n",e, pt->params[n].name,pt->params[n].value); } }