1
0
mirror of https://github.com/mpv-player/mpv synced 2025-02-16 20:27:23 +00:00

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
This commit is contained in:
arpi 2002-01-14 23:38:49 +00:00
parent ef93c93380
commit ef4a38a54e
9 changed files with 741 additions and 209 deletions

View File

@ -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)

View File

@ -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
/* calculate the number of options in 'conf' */
for (nr_options = 0; conf[nr_options].name != NULL; nr_options++)
/* NOTHING */;
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
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;
}

View File

@ -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;
};
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 *);
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)(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 */

View File

@ -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);

View File

@ -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){

132
mplayer.c
View File

@ -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
playtree = play_tree_new();
{
play_tree_t* list = NULL;
int i;
play_tree_t *entry = NULL, *tree = play_tree_new();
for(i= 0; i < num_filenames ; i++) {
entry = entry != NULL ? play_tree_new() : tree;
play_tree_add_file(entry,filenames[i]);
play_tree_append_entry(tree,entry);
}
entry = play_tree_new();
play_tree_set_child(entry,tree);
list = entry;
if(playlist_file!=NULL) {
entry = parse_playlist_file(playlist_file);
if(entry != NULL){
if(list) play_tree_append_entry(list,entry);
else list = entry;
}
}
if(list) play_tree_set_child(playtree,list);
}
mconfig = m_config_new(playtree);
m_config_register_options(mconfig,mplayer_opts);
// TODO : add something to let modules register their options
parse_cfgfiles(mconfig);
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);
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);
@ -606,7 +604,6 @@ if(!parse_codec_cfg(get_path("codecs.conf"))){
printf("CommandLine:");
for(i=1;i<argc;i++)printf(" '%s'",argv[i]);
printf("\n");
printf("num_filenames: %d\n",num_filenames);
}
mp_msg_init(verbose+MSGL_STATUS);
@ -1172,7 +1169,7 @@ mp_msg(MSGT_CPLAYER,MSGL_INFO,"%s video codec: [%s] drv:%d prio:%d (%s)\n",video
for(i=0;i<CODECS_MAX_OUTFMT;i++){
// int ret;
out_fmt=sh_video->codec->outfmt[i];
if(out_fmt==0xFFFFFFFF) continue;
if(out_fmt==(signed int)0xFFFFFFFF) continue;
#ifdef USE_LIBVO2
vo_flags=vo2_query_format(video_out);
#else
@ -1223,10 +1220,12 @@ current_module="init_libvo";
if(!screen_size_xy) screen_size_xy=vo_screenwidth; // scale with asp.ratio
}
#endif
// Set default VGA 1:1 aspect as fallback ::atmos
if(movie_aspect>-1.0) sh_video->aspect = movie_aspect; // cmdline overrides autodetect
// if(!sh_video->aspect) sh_video->aspect=1.0;
screen_size_x = opt_screen_size_x;
screen_size_y = opt_screen_size_y;
if(screen_size_xy||screen_size_x||screen_size_y){
if(screen_size_xy>0){
if(screen_size_xy<=8){
@ -1829,7 +1828,9 @@ if(auto_quality>0){
#endif
if(osd_function==OSD_PAUSE){
#ifdef HAVE_NEW_GUI
int gui_pause_flag=0; // gany!
#endif
mp_msg(MSGT_CPLAYER,MSGL_STATUS,"\n------ PAUSED -------\r");fflush(stdout);
#ifdef HAVE_NEW_GUI
if(use_gui) mplShMem->Playing=2;
@ -1963,18 +1964,10 @@ if(step_sec>0) {
break;
// quit
case KEY_ESC: // ESC
case 'q': exit_player(MSGTR_Exit_quit);
case '>':
if(curr_filename>=num_filenames-1)
break;
case 'q':
exit_player(MSGTR_Exit_quit);
case KEY_ENTER: // ESC
eof=2; // jump to next file
break;
case '<':
if(curr_filename < 1)
break;
curr_filename-=2;
eof=2;
eof=1; // force jump to next file : quit if no next file
break;
case 'g': grab_frames=2;break;
// pause
@ -1985,26 +1978,42 @@ if(step_sec>0) {
case KEY_HOME:
{
play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter);
if(play_tree_iter_step(i,1,0) == PLAY_TREE_ITER_ENTRY)
eof = 1;
if(play_tree_iter_up_step(i,1,0) == PLAY_TREE_ITER_ENTRY)
eof = PT_UP_NEXT;
play_tree_iter_free(i);
}
break;
case KEY_END:
{
play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter);
if(play_tree_iter_up_step(i,-1,0) == PLAY_TREE_ITER_ENTRY)
eof = PT_UP_PREV;
play_tree_iter_free(i);
}
break;
case '>':
{
play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter);
if(play_tree_iter_step(i,1,0) == PLAY_TREE_ITER_ENTRY)
eof = PT_NEXT_ENTRY;
play_tree_iter_free(i);
}
break;
case '<':
{
play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter);
if(play_tree_iter_step(i,-1,0) == PLAY_TREE_ITER_ENTRY)
eof = -1;
eof = PT_PREV_ENTRY;
play_tree_iter_free(i);
}
break;
case KEY_INS:
if(playtree_iter->num_files > 1 && playtree_iter->file < playtree_iter->num_files)
eof = 2;
eof = PT_NEXT_SRC;
break;
case KEY_DEL:
if(playtree_iter->num_files > 1 && playtree_iter->file > 1)
eof = -2;
eof = PT_PREV_SRC;
break;
case 'o': // toggle OSD
osd_level=(osd_level+1)%3;
@ -2345,7 +2354,7 @@ mp_msg(MSGT_GLOBAL,MSGL_V,"EOF code: %d \n",eof);
goto_next_file: // don't jump here after ao/vo/getch initialization!
if(eof == 1 || eof == -1) {
if(eof == PT_NEXT_ENTRY || eof == PT_PREV_ENTRY) {
if(play_tree_iter_step(playtree_iter,eof,0) == PLAY_TREE_ITER_ENTRY) {
uninit_player(INITED_ALL-(INITED_GUI+INITED_LIRC));
eof = 1;
@ -2353,9 +2362,18 @@ if(eof == 1 || eof == -1) {
play_tree_iter_free(playtree_iter);
playtree_iter = NULL;
}
} else {
} else if (eof == PT_UP_NEXT || eof == PT_UP_PREV) {
eof = eof == PT_UP_NEXT ? 1 : -1;
if(play_tree_iter_up_step(playtree_iter,eof,0) == PLAY_TREE_ITER_ENTRY) {
uninit_player(INITED_ALL-(INITED_GUI+INITED_LIRC));
eof = 1;
} else {
play_tree_iter_free(playtree_iter);
playtree_iter = NULL;
}
}else { // NEXT PREV SRC
uninit_player(INITED_ALL-(INITED_GUI+INITED_LIRC));
eof = eof == -2 ? -1 : 1;
eof = eof == PT_PREV_SRC ? -1 : 1;
}
goto_next_file_src: // When we have multiple src for file

View File

@ -1,9 +1,12 @@
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#ifdef MP_DEBUG
#include <assert.h>
#endif
#include "playtree.h"
#include "mp_msg.h"
@ -22,7 +25,7 @@ void
play_tree_free(play_tree_t* pt, int childs) {
play_tree_t* iter;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
@ -52,7 +55,7 @@ void
play_tree_free_list(play_tree_t* pt, int childs) {
play_tree_t* iter;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
@ -69,7 +72,7 @@ void
play_tree_append_entry(play_tree_t* pt, play_tree_t* entry) {
play_tree_t* iter;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
assert(entry != NULL);
#endif
@ -90,7 +93,7 @@ void
play_tree_prepend_entry(play_tree_t* pt, play_tree_t* entry) {
play_tree_t* iter;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
assert(entry != NULL);
#endif
@ -104,7 +107,7 @@ play_tree_prepend_entry(play_tree_t* pt, play_tree_t* entry) {
iter->prev = entry;
if(entry->parent) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(entry->parent->child == iter);
#endif
entry->parent->child = entry;
@ -114,7 +117,7 @@ play_tree_prepend_entry(play_tree_t* pt, play_tree_t* entry) {
void
play_tree_insert_entry(play_tree_t* pt, play_tree_t* entry) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
assert(entry != NULL);
#endif
@ -122,7 +125,7 @@ play_tree_insert_entry(play_tree_t* pt, play_tree_t* entry) {
entry->parent = pt->parent;
entry->prev = pt;
if(pt->next) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt->next->prev == pt);
#endif
entry->next = pt->next;
@ -136,13 +139,13 @@ play_tree_insert_entry(play_tree_t* pt, play_tree_t* entry) {
void
play_tree_remove(play_tree_t* pt, int free_it,int with_childs) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
// Middle of list
if(pt->prev && pt->next) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt->prev->next == pt);
assert(pt->next->prev == pt);
#endif
@ -150,25 +153,25 @@ play_tree_remove(play_tree_t* pt, int free_it,int with_childs) {
pt->next->prev = pt->prev;
} // End of list
else if(pt->prev) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt->prev->next == pt);
#endif
pt->prev->next = NULL;
} // Begining of list
else if(pt->next) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt->next->prev == pt);
#endif
pt->next->prev = NULL;
if(pt->parent) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt->parent->child == pt);
#endif
pt->parent->child = pt->next;
}
} // The only one
else if(pt->parent) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt->parent->child == pt);
#endif
pt->parent->child = NULL;
@ -184,7 +187,7 @@ void
play_tree_set_child(play_tree_t* pt, play_tree_t* child) {
play_tree_t* iter;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
assert(pt->files == NULL);
#endif
@ -207,7 +210,7 @@ void
play_tree_set_parent(play_tree_t* pt, play_tree_t* parent) {
play_tree_t* iter;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
@ -232,7 +235,7 @@ void
play_tree_add_file(play_tree_t* pt,char* file) {
int n = 0;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
assert(pt->child == NULL);
assert(file != NULL);
@ -257,7 +260,7 @@ int
play_tree_remove_file(play_tree_t* pt,char* file) {
int n,f = -1;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
assert(file != NULL);
assert(pt->files != NULL);
@ -271,7 +274,7 @@ play_tree_remove_file(play_tree_t* pt,char* file) {
if(f < 0) // Not found
return 0;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(n > f);
#endif
@ -292,12 +295,11 @@ play_tree_remove_file(play_tree_t* pt,char* file) {
return 1;
}
#if 0
void
play_tree_set_param(play_tree_t* pt, char* name, char* val) {
int n = 0,ni = -1;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
assert(name != NULL);
#endif
@ -325,9 +327,9 @@ play_tree_set_param(play_tree_t* pt, char* name, char* val) {
int
play_tree_unset_param(play_tree_t* pt, char* name) {
int n,ni = 0;
int n,ni = -1;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
assert(name != NULL);
assert(pt->params != NULL);
@ -341,10 +343,16 @@ play_tree_unset_param(play_tree_t* pt, char* name) {
if(ni < 0)
return 0;
if(pt->params[ni].name) free(pt->params[ni].name);
if(pt->params[ni].value) free(pt->params[ni].value);
if(n > 1) {
memmove(&pt->params[ni],&pt->params[ni+1],(n-ni)*sizeof(play_tree_param_t));
pt->params = (play_tree_param_t*)realloc(pt->params,n*sizeof(play_tree_param_t));
assert(pt->params != NULL);
if(pt->params == NULL) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",n*sizeof(play_tree_param_t));
return -1;
}
} else {
free(pt->params);
pt->params = NULL;
@ -353,14 +361,53 @@ play_tree_unset_param(play_tree_t* pt, char* name) {
return 1;
}
static int
play_tree_iter_push_params(play_tree_iter_t* iter) {
int n;
play_tree_t* pt;
#ifdef MP_DEBUG
assert(iter != NULL);
assert(iter->config != NULL);
assert(iter->tree != NULL);
#endif
pt = iter->tree;
if(pt->params == NULL)
return 0;
m_config_push(iter->config);
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",
pt->params[n].name,pt->params[n].value);
}
}
//printf("Param pushed\n");
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;
//printf("Poping params\n");
m_config_pop(iter->config);
}
play_tree_iter_t*
play_tree_iter_new(play_tree_t* pt) {
play_tree_iter_new(play_tree_t* pt,m_config_t* config) {
play_tree_iter_t* iter;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
assert(config != NULL);
#endif
if( ! play_tree_is_valid(pt))
@ -370,6 +417,7 @@ play_tree_iter_new(play_tree_t* pt) {
if(! iter) return NULL;
iter->root = pt;
iter->tree = NULL;
iter->config = config;
if(pt->parent)
iter->loop = pt->parent->loop;
@ -380,12 +428,12 @@ play_tree_iter_new(play_tree_t* pt) {
void
play_tree_iter_free(play_tree_iter_t* iter) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(iter != NULL);
#endif
if(iter->status_stack) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(iter->stack_size > 0);
#endif
free(iter->status_stack);
@ -398,9 +446,10 @@ int
play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) {
play_tree_t* pt;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(iter != NULL);
assert(iter->root != NULL);
//printf("PT : Stepping = %d\n",d);
#endif
if(iter->tree == NULL) {
@ -408,6 +457,11 @@ 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);
iter->entry_pushed = 0;
}
iter->file = 0;
if( d > 0 )
pt = iter->tree->next;
@ -454,14 +508,17 @@ play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) {
return play_tree_iter_step(iter,d,with_nodes);
}
#ifdef DEBUG
assert(iter->tree->files != NULL);
#ifdef MP_DEBUG
assert(pt->files != NULL);
#endif
iter->tree = pt;
for(d = 0 ; iter->tree->files[d] != NULL ; d++)
/* NOTHING */;
iter->num_files = d;
if(iter->config)
iter->entry_pushed = play_tree_iter_push_params(iter);
return PLAY_TREE_ITER_ENTRY;
@ -471,7 +528,7 @@ static int
play_tree_is_valid(play_tree_t* pt) {
play_tree_t* iter;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
@ -489,22 +546,22 @@ play_tree_is_valid(play_tree_t* pt) {
int
play_tree_iter_up_step(play_tree_iter_t* iter, int d,int with_nodes) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(iter != NULL);
assert(iter->tree != NULL);
//printf("PT : Go UP\n");
#endif
iter->file = 0;
if(iter->tree->parent == iter->root->parent)
return PLAY_TREE_ITER_END;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(iter->tree->parent != NULL);
assert(iter->stack_size > 0);
assert(iter->status_stack != NULL);
#endif
// Pop status
iter->stack_size--;
iter->loop = iter->status_stack[iter->stack_size];
iter->status_stack = (int*)realloc(iter->status_stack,iter->stack_size*sizeof(int));
@ -513,20 +570,30 @@ play_tree_iter_up_step(play_tree_iter_t* iter, int d,int with_nodes) {
return PLAY_TREE_ITER_ERROR;
}
iter->tree = iter->tree->parent;
// Pop subtree params
if(iter->config)
play_tree_iter_pop_params(iter);
return play_tree_iter_step(iter,d,with_nodes);
}
int
play_tree_iter_down_step(play_tree_iter_t* iter, int d,int with_nodes) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(iter->tree->files == NULL);
assert(iter->tree->child != NULL);
assert(iter->tree->child->parent == iter->tree);
//printf("PT : Go DOWN\n");
#endif
iter->file = 0;
// Push status
// Push subtree params
if(iter->config)
play_tree_iter_push_params(iter);
iter->stack_size++;
iter->status_stack = (int*)realloc(iter->status_stack,iter->stack_size*sizeof(int));
if(iter->status_stack == NULL) {
@ -544,13 +611,14 @@ play_tree_iter_down_step(play_tree_iter_t* iter, int d,int with_nodes) {
/*NOTING*/;
iter->tree = pt;
}
return play_tree_iter_step(iter,0,with_nodes);
}
char*
play_tree_iter_get_file(play_tree_iter_t* iter, int d) {
#ifdef DEBUG
#ifdef MP_DEBUG
assert(iter != NULL);
assert(iter->tree->child == NULL);
#endif
@ -574,7 +642,7 @@ play_tree_t*
play_tree_cleanup(play_tree_t* pt) {
play_tree_t* iter, *tmp, *first;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
@ -608,7 +676,7 @@ play_tree_iter_t*
play_tree_iter_new_copy(play_tree_iter_t* old) {
play_tree_iter_t* iter;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(old != NULL);
#endif
@ -628,5 +696,7 @@ play_tree_iter_new_copy(play_tree_iter_t* old) {
}
memcpy(iter->status_stack,old->status_stack,iter->stack_size*sizeof(int));
}
iter->config = NULL;
return iter;
}

View File

@ -1,6 +1,10 @@
#ifndef __PLAYTREE_H
#define __PLAYTREE_H
#include "libmpdemux/stream.h"
#define PLAY_TREE_ITER_ERROR 0
#define PLAY_TREE_ITER_ENTRY 1
#define PLAY_TREE_ITER_NODE 2
@ -8,11 +12,12 @@
typedef struct play_tree play_tree_t;
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;
typedef struct play_tree_param play_tree_param_t;
// TODO : a attrib,val pair system and not something hardcoded
struct play_tree_info {
char* title;
@ -21,12 +26,13 @@ struct play_tree_info {
char* abstract;
// Some more ??
}
#endif
struct play_tree_param {
char* name;
char* value;
}
#endif
};
struct play_tree {
play_tree_t* parent;
@ -35,8 +41,7 @@ struct play_tree {
play_tree_t* prev;
//play_tree_info_t info;
//int n_param;
//play_tree_param_t* params;
play_tree_param_t* params;
int loop;
char** files;
};
@ -44,10 +49,11 @@ struct play_tree {
struct play_tree_iter {
play_tree_t* root; // Iter root tree
play_tree_t* tree; // Current tree
// struct m_config* config;
m_config_t* config;
int loop; // Looping status
int file;
int num_files;
int entry_pushed;
int* status_stack; // loop/valid stack to save/revert status when we go up/down
int stack_size; // status stack size
@ -97,7 +103,6 @@ int
play_tree_remove_file(play_tree_t* pt,char* file);
#if 0
// Val can be NULL
void
play_tree_set_param(play_tree_t* pt, char* name, char* val);
@ -105,13 +110,11 @@ play_tree_set_param(play_tree_t* pt, char* name, char* val);
int
play_tree_unset_param(play_tree_t* pt, char* name);
#endif
/// Iterator
play_tree_iter_t*
play_tree_iter_new(play_tree_t* pt);
play_tree_iter_new(play_tree_t* pt, m_config_t* config);
play_tree_iter_t*
play_tree_iter_new_copy(play_tree_iter_t* old);
@ -142,3 +145,5 @@ play_tree_cleanup(play_tree_t* pt);
play_tree_t*
parse_playlist_file(char* file);
#endif

View File

@ -1,8 +1,11 @@
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef MP_DEBUG
#include <assert.h>
#endif
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
@ -240,7 +243,7 @@ play_tree_t*
parse_playtree(stream_t *stream) {
play_tree_t* tree = NULL;
#ifdef DEBUG
#ifdef MP_DEBUG
assert(stream != NULL);
assert(stream->type == STREAMTYPE_PLAYLIST);
#endif