summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--cfgparser.c534
-rw-r--r--cfgparser.h63
-rw-r--r--dec_video.c4
-rw-r--r--mencoder.c31
-rw-r--r--mplayer.c132
-rw-r--r--playtree.c150
-rw-r--r--playtree.h27
-rw-r--r--playtreeparser.c5
9 files changed, 741 insertions, 209 deletions
diff --git a/Makefile b/Makefile
index 7e074981e6..c718fee605 100644
--- a/Makefile
+++ b/Makefile
@@ -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){
diff --git a/mplayer.c b/mplayer.c
index 0597adea84..2f99326255 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -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 )
{
char *conffile;
int conffile_fd;
-if (parse_config_file(conf, "/etc/mplayer.conf") < 0)
+if (m_config_parse_config_file(conf, "/etc/mplayer.conf") < 0)
exit(1);
if ((conffile = get_path("")) == NULL) {
mp_msg(MSGT_CPLAYER,MSGL_WARN,MSGTR_NoHomeDir);
@@ -392,7 +409,7 @@ if ((conffile = get_path("")) == NULL) {
write(conffile_fd, default_config, strlen(default_config));
close(conffile_fd);
}
- if (parse_config_file(conf, conffile) < 0)
+ if (m_config_parse_config_file(conf, conffile) < 0)
exit(1);
free(conffile);
}
@@ -417,13 +434,10 @@ static sh_video_t *sh_video=NULL;
// for multifile support:
play_tree_iter_t* playtree_iter = NULL;
-char **filenames=NULL;
-int num_filenames=0;
-int curr_filename=0;
char* filename=NULL; //"MI2-Trailer.avi";
int file_format=DEMUXER_TYPE_UNKNOWN;
-//
+
int delay_corrected=1;
char* title="MPlayer";
@@ -493,36 +507,20 @@ int gui_no_filename=0;
(strrchr(argv[0],'/') && !strcmp(strrchr(argv[0],'/'),"/gmplayer") ) )
use_gui=1;
- parse_cfgfiles();
- num_filenames=parse_command_line(conf, argc, argv, envp, &filenames);
- if(num_filenames<0) exit(1); // error parsing cmdline