diff --git a/cfgparser.c b/cfgparser.c index c44f5a2910..624a2bef79 100644 --- a/cfgparser.c +++ b/cfgparser.c @@ -22,6 +22,15 @@ #define COMMAND_LINE 0 #define CONFIG_FILE 1 +#define CONFIG_GLOBAL (1<<0) +#define CONFIG_RUNNING (1<<1) + +#define SET_GLOBAL(c) (c->flags |= CONFIG_GLOBAL) +#define UNSET_GLOBAL(c) (c->flags &= (!CONFIG_GLOBAL)) +#define IS_GLOBAL(c) (c->flags & CONFIG_GLOBAL) +#define SET_RUNNING(c) (c->flags |= CONFIG_RUNNING) +#define IS_RUNNING(c) (c->flags & CONFIG_RUNNING) + #define MAX_RECURSION_DEPTH 8 #ifdef MP_DEBUG @@ -248,7 +257,7 @@ m_config_new(play_tree_t* pt) { free(config); return NULL; } - config->global = 1; // We always start with global options + SET_GLOBAL(config); // We always start with global options config->pt = pt; return config; } @@ -279,10 +288,58 @@ static int init_conf(m_config_t *config, int mode) } #endif config->parser_mode = mode; - config->global = 1; return 1; } +static int config_is_entry_option(m_config_t *config, char *opt, char *param) { + play_tree_t* entry = NULL; + +#ifdef MP_DEBUG + assert(config->pt != NULL); +#endif + + if(strcasecmp(opt,"playlist") == 0) { // We handle playlist here + if(!param) + return ERR_MISSING_PARAM; + entry = parse_playlist_file(param); + } + + if(! IS_RUNNING(config)) { + if(strcasecmp(opt,"vcd") == 0) { + char* s; + if(!param) + return ERR_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 ERR_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); + } + } + + if(entry) { + if(config->last_entry) + play_tree_append_entry(config->last_entry,entry); + else + play_tree_set_child(config->pt,entry); + config->last_entry = entry; + if(config->parser_mode == COMMAND_LINE) + UNSET_GLOBAL(config); + return 1; + } else + return 0; +} + + static int config_read_option(m_config_t *config,config_t** conf_list, char *opt, char *param) { @@ -315,7 +372,7 @@ static int config_read_option(m_config_t *config,config_t** conf_list, char *opt } } if (config->parser_mode == CONFIG_FILE) - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid option:\n"); + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid option: %s\n",opt); ret = ERR_NOT_AN_OPTION; goto out; option_found : @@ -332,30 +389,12 @@ static int config_read_option(m_config_t *config,config_t** conf_list, char *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) ) + ret = config_is_entry_option(config,opt,param); + if(ret != 0) + return ret; + else + ret = -1; + if(! IS_RUNNING(config) && ! IS_GLOBAL(config) && ! (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); @@ -508,19 +547,21 @@ static int config_read_option(m_config_t *config,config_t** conf_list, char *opt config_t *subconf; config_t *sublist[] = { NULL , NULL }; char *token; + char *p; if (param == NULL) goto err_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) subconf = conf[i].p; sublist[0] = subconf; for (subconf_optnr = 0; subconf[subconf_optnr].name != NULL; subconf_optnr++) /* NOTHING */; - token = strtok(param, (char *)&(":")); + token = strtok(p, (char *)&(":")); while(token) { int sscanf_ret; @@ -552,6 +593,7 @@ static int config_read_option(m_config_t *config,config_t** conf_list, char *opt free(subparam); free(subopt); + free(p); ret = 1; break; } @@ -563,7 +605,7 @@ static int config_read_option(m_config_t *config,config_t** conf_list, char *opt break; } out: - if(ret >= 0 && config->global == 0 && ! (conf[i].flags & CONF_GLOBAL)) { + if(ret >= 0 && ! IS_RUNNING(config) && ! IS_GLOBAL(config) && ! (conf[i].flags & CONF_GLOBAL)) { play_tree_t* dest = config->last_entry ? config->last_entry : config->last_parent; #ifdef MP_DEBUG assert(dest != NULL); @@ -585,6 +627,7 @@ int m_config_set_option(m_config_t *config,char *opt, char *param) { #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); @@ -825,7 +868,7 @@ int m_config_parse_command_line(m_config_t *config, int argc, char **argv, char if((opt[0] == '{') && (opt[1] == '\0')) { play_tree_t* entry = play_tree_new(); - config->global = 0; + UNSET_GLOBAL(config); if(config->last_entry == NULL) { play_tree_set_child(config->last_parent,entry); } else { @@ -874,7 +917,7 @@ int m_config_parse_command_line(m_config_t *config, int argc, char **argv, char 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 */ - config->global = 0; // We start entry specific options + UNSET_GLOBAL(config); // We start entry specific options if(config->last_entry == NULL) play_tree_set_child(config->last_parent,entry); else @@ -886,7 +929,8 @@ int m_config_parse_command_line(m_config_t *config, int argc, char **argv, char --config->recursion_depth; if(config->last_parent != config->pt) mp_msg(MSGT_CFGPARSER, MSGL_ERR,"Missing }- ?\n"); - config->global = 1; + UNSET_GLOBAL(config); + SET_RUNNING(config); return 1; #if 0 err_out_mem: @@ -894,7 +938,6 @@ err_out_mem: #endif err_out: --config->recursion_depth; - config->global = 1; mp_msg(MSGT_CFGPARSER, MSGL_ERR, "command line: %s\n", argv[i]); return -1; } @@ -977,7 +1020,7 @@ m_config_set_flag(m_config_t *config, char* opt, int max) { config_t *conf; conf = m_config_get_option(config,opt); if(!conf) return; - if(conf->type != CONF_TYPE_FLAG) return 0; + if(conf->type != CONF_TYPE_FLAG) return; if(max) AS_INT(conf) = conf->max; else AS_INT(conf) = conf->min; } diff --git a/cfgparser.h b/cfgparser.h index a9c4e95885..f340141a4b 100644 --- a/cfgparser.h +++ b/cfgparser.h @@ -56,7 +56,7 @@ struct m_config { config_save_t** config_stack; int cs_level; int parser_mode; /* COMMAND_LINE or CONFIG_FILE */ - int global; // Are we parsing global option + int flags; 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 diff --git a/playtree.c b/playtree.c index 61b00518fe..b42333faf5 100644 --- a/playtree.c +++ b/playtree.c @@ -14,9 +14,6 @@ static int play_tree_is_valid(play_tree_t* pt); -static void -play_tree_iter_set_param(play_tree_iter_t* iter,char* opt,char* val); - play_tree_t* play_tree_new(void) { play_tree_t* r = (play_tree_t*)calloc(1,sizeof(play_tree_t)); @@ -264,13 +261,13 @@ play_tree_add_file(play_tree_t* pt,char* file) { e = pt->files[n] = strdup(file); pt->files[n+1] = NULL; - if(strncasecmp(e,"vcd://",6) == 0 && strlen(&e[6]) > 0) { + if(strncasecmp(e,"vcd://",6) == 0) { pt->entry_type = PLAY_TREE_ENTRY_VCD; memmove(e,e + 6,strlen(&e[6])+1); - } else if(strncasecmp(e,"dvd://",6) == 0 && strlen(&e[6]) > 0) { + } else if(strncasecmp(e,"dvd://",6) == 0) { pt->entry_type = PLAY_TREE_ENTRY_DVD; memmove(e,&e[6],strlen(&e[6])+1); - } else if(strncasecmp(e,"tv://",5) == 0 && strlen(&e[5]) > 0) { + } else if(strncasecmp(e,"tv://",5) == 0) { pt->entry_type = PLAY_TREE_ENTRY_TV; memmove(e,&e[5],strlen(&e[5])+1); } else @@ -385,7 +382,7 @@ play_tree_unset_param(play_tree_t* pt, char* name) { return 1; } -static int +static void play_tree_iter_push_params(play_tree_iter_t* iter) { int n; play_tree_t* pt; @@ -397,10 +394,14 @@ play_tree_iter_push_params(play_tree_iter_t* iter) { pt = iter->tree; - if(pt->params == NULL) - return 0; - + // We always push a config because we can set some option + // while playing m_config_push(iter->config); + + if(pt->params == NULL) + return; + + 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", @@ -410,21 +411,7 @@ play_tree_iter_push_params(play_tree_iter_t* iter) { if(!pt->child) iter->entry_pushed = 1; - return 1; -} - -static void -play_tree_iter_pop_params(play_tree_iter_t* iter) { - -#ifdef MP_DEBUG - assert(iter != NULL); - assert(iter->config != NULL); -#endif - - if(iter->tree->params == NULL) - return; - iter->entry_pushed = 0; - m_config_pop(iter->config); + return; } play_tree_iter_t* @@ -483,8 +470,10 @@ play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) { return play_tree_iter_step(iter,0,with_nodes); } - if(iter->config && iter->entry_pushed) - play_tree_iter_pop_params(iter); + if(iter->config && iter->entry_pushed > 0) { + iter->entry_pushed--; + m_config_pop(iter->config); + } iter->file = -1; if( d > 0 ) @@ -542,8 +531,10 @@ play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) { /* NOTHING */; iter->num_files = d; - if(iter->config) + if(iter->config) { play_tree_iter_push_params(iter); + iter->entry_pushed++; + } return PLAY_TREE_ITER_ENTRY; @@ -602,7 +593,7 @@ play_tree_iter_up_step(play_tree_iter_t* iter, int d,int with_nodes) { // Pop subtree params if(iter->config) - play_tree_iter_pop_params(iter); + m_config_pop(iter->config); return play_tree_iter_step(iter,d,with_nodes); } @@ -644,6 +635,9 @@ play_tree_iter_down_step(play_tree_iter_t* iter, int d,int with_nodes) { return play_tree_iter_step(iter,0,with_nodes); } +// This is used as a file name for vcd/tv/dvd +char playtree_ret_filename[256]; + char* play_tree_iter_get_file(play_tree_iter_t* iter, int d) { char* entry; @@ -677,17 +671,38 @@ play_tree_iter_get_file(play_tree_iter_t* iter, int d) { switch(iter->tree->entry_type) { case PLAY_TREE_ENTRY_DVD : - play_tree_iter_set_param(iter,"dvd",entry); - break; + if(strlen(entry) == 0) entry = "1"; + if(iter->config) + m_config_set_option(iter->config,"dvd",entry); + snprintf(playtree_ret_filename,255,"DVD title %s",entry); + return playtree_ret_filename; case PLAY_TREE_ENTRY_VCD : - play_tree_iter_set_param(iter,"vcd",entry); - break; + if(strlen(entry) == 0) entry = "1"; + if(iter->config) + m_config_set_option(iter->config,"vcd",entry); + snprintf(playtree_ret_filename,255,"VCD track %s",entry); + return playtree_ret_filename; case PLAY_TREE_ENTRY_TV : { - char* val = (char*)malloc(strlen(entry) + 11 + 1); - sprintf(val,"on:channel=%s",entry); - play_tree_iter_set_param(iter,"tv",val); - break; + if(strlen(entry) != 0) { + char *s,*e, *val = (char*)malloc(strlen(entry) + 11 + 1); + sprintf(val,"on:channel=%s",entry); + if(iter->config) + m_config_set_option(iter->config,"tv",val); + s = playtree_ret_filename + sprintf(playtree_ret_filename,"TV channel "); + e = strchr(entry,':'); + if(!e) strncpy(s,entry,255-11); + else { + if(entry-e > 255) e = entry+255; + strncpy(s,entry,val-e); + s[val-e] = '\0'; + } + return playtree_ret_filename; + } else { + if(iter->config) + m_config_set_option(iter->config,"tv","on"); + return "TV"; + } } } @@ -757,26 +772,4 @@ play_tree_iter_new_copy(play_tree_iter_t* old) { return iter; } -static void -play_tree_iter_set_param(play_tree_iter_t* iter,char* opt,char* val) { - int push = 0; - play_tree_t* pt; -#ifdef MP_DEBUG - assert(iter != NULL); - assert(iter->tree != NULL); -#endif - - pt = iter->tree; - - if(iter->tree->params == NULL) - push = 1; - - play_tree_set_param(iter->tree,opt,val); - - if(push) - play_tree_iter_push_params(iter); - else if(iter->config) - m_config_set_option(iter->config,opt,val); - -}