[MPlayer-G2-dev] Re: G2 CLI/GUI

Andriy N. Gritsenko andrej at lucky.net
Mon May 12 16:55:41 CEST 2003


    Hi, community!

    It's ready now! I mean new config API. Main goals:
1) independency from all other API;
2) independency from any parsers/UI impementation;
3) no global static vars (since all may have many instances);
and I strict on keeping these goals forever. :)
    The proposed API consist of two parts: plugins API (loadable plugin
support isn't implemented yet but it's only question of time, I think)
and config API.
    Plugins API consists of 3 structs and 3 functions. Config API consist
of 3 structs, 3 functions, and number of constants. And I want to don't
extend that API any more, it's big enough. ;)

    Plugins API (all prefixed pl_ ):
struct pl_info_t      - info for plugin (it's only structure in loadable
                        module that is visible for link); contains all
                        module information, pointer to open() function
                        and to module type specific functions array (it
                        may replace all *_info_t in the future, may be)
struct pl_func_s      - module type specific functions
struct pl_instance_t  - plugin instance specification; is dinamically
                        created
pl_register_plugin()  - to register plugin in internal list
pl_get_plugin()       - to get new plugin instance by name and type and
                        add it to chain
pl_open_plugin()      - wrapper to module specific open() function

    Config API (all prefixed cfg_ ):
struct cfg_t          - former struct config (cfg_t is simplest prefixed
                        with cfg_ name) - the most common structure for
                        modules configuration;
struct pl_func_s      - config specific functions list
struct cfg_tree_t     - module independent tree of options
cfg_register()        - to register options in tree
cfg_unregister()      - to unregister options in tree
cfg_find()            - to find the option's subtree in tree by name

    So tree may be extandable at any time (you can add and remove options
and suboptions on the fly on any branch), trees may be different, each
context may have its own if you need, any UI may be attached just by
opening module, no parser-specific calls are allowed.
    cfg-new.tar.gz contains new API files. g2-diff is patch, it applies
new API to cfgparser.c (it's config/commandline parser module now),
cfgparser.h (it's for backward compatibility of config parser module only
now) and test-cfg.h. Also cfg_register() is added to test-codecs.c and
test-play.c. I hope I commented it all well in cfg.h.

    Try it, please, and send any remarks, demands, changes, etc. I want
to have it independent and flexible. Let's do it together! :)

    With the best wishes.
    Andriy.

P.S. By next step I want to apply new API to -vf option (and to -ovc of
 mencoder-g2, of course) to get it fully configurable. :)
P.P.S. CONF_TYPE_POSITION CONF_TYPE_CHOOSE CONF_TYPE_LIST CONF_TYPE_CHAIN
 types and save_config() function are not implemented in cfgparser.c yet.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cfg-new.tar.gz
Type: application/x-tar-gz
Size: 4172 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/mplayer-g2-dev/attachments/20030512/fa95b08b/attachment.bin>
-------------- next part --------------
diff -udpr g2/Makefile g2.new/Makefile
--- g2/Makefile	Mon May 12 02:52:44 2003
+++ g2.new/Makefile	Mon May 12 16:17:13 2003
@@ -1,7 +1,7 @@
 
 include config.mak
 
-SRCS = mp_msg.c get_path.c codec-cfg.c cfgparser.c # test-stream.c test-codecs.c 
+SRCS = mp_msg.c get_path.c codec-cfg.c cfgparser.c cfg.c cfg-plugin.c # test-stream.c test-codecs.c 
 
 OBJS	= $(SRCS:.c=.o)
 INCLUDE = -I. $(EXTRA_INC) $(X11_INC)
diff -udpr g2/cfgparser.c g2.new/cfgparser.c
--- g2/cfgparser.c	Sat Apr 19 02:14:16 2003
+++ g2.new/cfgparser.c	Mon May 12 16:17:13 2003
@@ -4,6 +4,8 @@
  * (C) 2001
  *
  * subconfig support by alex
+ *
+ * new way of modularized config by Andriy Gritsenko (C) 2003
  */
 
 //#define DEBUG
@@ -31,78 +33,147 @@
 
 #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 */
+struct pl_priv_s {
+  int num; // number of unparsed parameters
+  char **name; // unparsed options list
+  char **param; // unparsed parameters list
+  pl_instance_t *cfgparser; // used for CLI plugin management
+};
+
 static int recursion_depth = 0;
 
-static int init_conf(struct config *conf, int mode)
+static char *print_option_help(cfg_t *opt, char *c, size_t s)
 {
-#ifdef DEBUG
-	assert(conf != NULL);
-#endif
+    switch(opt->type){
+	case CONF_TYPE_INT:
+	    if (opt->flags & CONF_MIN){
+		if (opt->flags & CONF_MAX)
+		    snprintf(c, s, "%s <%d .. %d>", opt->desc, (int)opt->min, (int)opt->max);
+		else snprintf(c, s, "%s <%d .. >", opt->desc, (int)opt->min);
+	    } else if (opt->flags & CONF_MAX) {
+		snprintf(c, s, "%s < .. %d>", opt->desc, (int)opt->max);
+	    } else
+		goto help_simple;
+	    break;
+	case CONF_TYPE_FLOAT:
+	    if (opt->flags & CONF_MIN){
+		if (opt->flags & CONF_MAX)
+		    snprintf(c, s, "%s <%3.1f .. %3.1f>", opt->desc, opt->min, opt->max);
+		else snprintf(c, s, "%s <%3.1f .. >", opt->desc, opt->min);
+	    } else if (opt->flags & CONF_MAX) {
+		snprintf(c, s, "%s < .. %3.1f>", opt->desc, opt->max);
+	    } else
+		snprintf(c, s, "%s <float>", opt->desc);
+	    break;
+	case CONF_TYPE_STRING:
+	    if (opt->flags & CONF_MIN){
+		if (opt->flags & CONF_MAX)
+		    snprintf(c, s, "%s <%d...%d chars>", opt->desc, (int)opt->min, (int)opt->max);
+		else snprintf(c, s, "%s <%d chars min>", opt->desc, (int)opt->min);
+	    } else if (opt->flags & CONF_MAX) {
+		snprintf(c, s, "%s <%d chars max>", opt->desc, (int)opt->max);
+	    } else
+		goto help_simple;
+	    break;
+	case CONF_TYPE_STRING_LIST:
+	    snprintf(c, s, "%s <string[,string2,...]>", opt->desc);
+	    break;
+	case CONF_TYPE_FUNC_PARAM:
+	    snprintf(c, s, "%s <?>", opt->desc);
+	    break;
+	case CONF_TYPE_FUNC_FULL:
+	    snprintf(c, s, "%s [<?>]", opt->desc);
+	    break;
+	case CONF_TYPE_SUBCONFIG:
+	    snprintf(c, s, "%s <opt1=param1[:opt2=param2:...]>", opt->desc);
+	    break;
+	case CONF_TYPE_FLAG:
+	case CONF_TYPE_FUNC:
+	default:
+help_simple:
+	    snprintf(c, s, "%s", opt->desc);
+    }
+    return c;
+}
 
-	/* calculate the number of options in 'conf' */
-	for (nr_options = 0; conf[nr_options].name != NULL; nr_options++)
-		/* NOTHING */;
+static char *reparse_postponed(pl_instance_t *pli, cfg_tree_t *conf, char *name)
+{
+  int i;
+  char *param;
+  (void) conf;
 
-	config = conf;
-#ifdef DEBUG
-	if (mode != COMMAND_LINE && mode != CONFIG_FILE) {
-		mp_msg(MSGT_CFGPARSER, MSGL_ERR, "init_conf: wrong mode!\n");
-		return -1;
+  for (i = 0; i < pli->priv->num; i++) {
+    if (strcmp(pli->priv->name[i], name) == 0) {
+      pli->priv->num--;
+      free(pli->priv->name[i]);
+      param = pli->priv->param[i];
+      if (pli->priv->num != i) {
+	if (i) {
+	  memmove(&pli->priv->name[i], &pli->priv->name[i+1],
+		  (pli->priv->num - i) * sizeof(*pli->priv->name));
+	  memmove(&pli->priv->param[i], &pli->priv->param[i+1],
+		  (pli->priv->num - i) * sizeof(*pli->priv->param));
+	} else {
+	  free(pli->priv->param);
+	  free(pli->priv->name);
 	}
-#endif
-	parser_mode = mode;
-	return 1;
+      }
+      return param;
+    }
+  }
+  return NULL;
 }
 
-static int read_option(struct config *conf, int conf_optnr, char *opt, char *param)
+static int read_option(cfg_tree_t *conf, char *name, char *param, int mode)
 {
-	int i;
 	long tmp_int;
 	double tmp_float;
 	int ret = -1;
 	char *endptr;
+	cfg_t *opt = conf->opt;
 
-	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))
-			break;
-	}
-	if (i == conf_optnr) {
-		if (parser_mode == CONFIG_FILE)
-			mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid option: %s\n", opt);
+	mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "read_option: name='%s' p=%p type=%d\n",
+	    name, opt->p, opt->type);
+
+	if ((opt->flags & CONF_NOCFG) && mode == CONFIG_FILE) {
+		mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used on command line: %s\n", name);
 		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 ((opt->flags & CONF_NOCMD) && mode == COMMAND_LINE) {
+		mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used in config file: %s\n", name);
 		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);
+
+	// Special treat for option listing
+	if (param && !strcasecmp (param, "help")) {
+	    char c[256];
+
+	    if (mode != COMMAND_LINE) {
 		ret = ERR_NOT_AN_OPTION;
 		goto out;
+	    }
+	    if (CONF_TYPE_HAS_CHILD(opt->type)) {
+		if (opt->type != CONF_TYPE_DUMMY)
+		    mp_msg(MSGT_CFGPARSER,MSGL_INFO,"\nAvailable suboptions for %s:\n",print_option_help(opt,c,sizeof(c)));
+		for (conf = conf->subtree; conf; conf = conf->next) {
+		    if (conf->opt->type == CONF_TYPE_DUMMY) // recurse
+			read_option(conf, name, param, mode);
+		    else if (!(conf->opt->flags & CONF_NOCMD) && opt->desc)
+			mp_msg(MSGT_CFGPARSER,MSGL_INFO,"  %-15s - %s\n",conf->opt->name,print_option_help(conf->opt,c,sizeof(c)));
+		}
+	    } else if (opt->desc)
+		mp_msg(MSGT_CFGPARSER,MSGL_INFO,"\n  %-15s - %s\n",name,print_option_help(opt,c,sizeof(c)));
+	    exit(1); /* terminate all */
 	}
 
-	switch (conf[i].type) {
+	switch (opt->type) {
 		case CONF_TYPE_FLAG:
 			/* flags need a parameter in config file */
-			if (parser_mode == CONFIG_FILE) {
+			if (mode == CONFIG_FILE && param == NULL)
+				goto err_missing_param;
+			else if (param) {
 				if (!strcasecmp(param, "yes") ||	/* any other language? */
 				    !strcasecmp(param, "ja") ||
 				    !strcasecmp(param, "si") ||
@@ -111,22 +182,22 @@ static int read_option(struct config *co
 				    !strcasecmp(param, "j") ||
 				    !strcasecmp(param, "i") ||
 				    !strcmp(param, "1"))
-					*((int *) conf[i].p) = conf[i].max;
+					*((int *) opt->p) = opt->max;
 				else if (!strcasecmp(param, "no") ||
 				    !strcasecmp(param, "nein") ||
 				    !strcasecmp(param, "nicht") ||
 				    !strcasecmp(param, "nem") ||
 				    !strcasecmp(param, "n") ||
 				    !strcmp(param, "0"))
-					*((int *) conf[i].p) = conf[i].min;
+					*((int *) opt->p) = opt->min;
 				else {
 					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid parameter for flag: %s\n", param);
 					ret = ERR_OUT_OF_RANGE;
 					goto out;
 				}
 				ret = 1;
-			} else {	/* parser_mode == COMMAND_LINE */
-				*((int *) conf[i].p) = conf[i].max;
+			} else {	/* mode == COMMAND_LINE */
+				*((int *) opt->p) = opt->max;
 				ret = 0;
 			}
 			break;
@@ -141,21 +212,19 @@ static int read_option(struct config *co
 				goto out;
 			}
 
-			if (conf[i].flags & CONF_MIN)
-				if (tmp_int < conf[i].min) {
-					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %d: %s\n", (int) conf[i].min, param);
+			if ((opt->flags & CONF_MIN) && tmp_int < opt->min) {
+					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %d: %s\n", (int) opt->min, param);
 					ret = ERR_OUT_OF_RANGE;
 					goto out;
 				}
 
-			if (conf[i].flags & CONF_MAX)
-				if (tmp_int > conf[i].max) {
-					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %d: %s\n", (int) conf[i].max, param);
+			if ((opt->flags & CONF_MAX) && tmp_int > opt->max) {
+					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %d: %s\n", (int) opt->max, param);
 					ret = ERR_OUT_OF_RANGE;
 					goto out;
 				}
 
-			*((int *) conf[i].p) = tmp_int;
+			*((int *) opt->p) = tmp_int;
 			ret = 1;
 			break;
 		case CONF_TYPE_FLOAT:
@@ -164,8 +233,22 @@ static int read_option(struct config *co
 
 			tmp_float = strtod(param, &endptr);
 
-			if ((*endptr == ':') || (*endptr == '/'))
+			switch (*endptr) {
+			    case ':':
+			    case '/':
 				tmp_float /= strtod(endptr+1, &endptr);
+				break;
+			    case '.':
+			    case ',':
+				/* we also handle floats specified with
+				 * non-locale decimal point ::atmos
+				 */
+				if(tmp_float<0)
+				    tmp_float -= 1.0/pow(10,strlen(endptr+1)) * strtod(endptr+1, &endptr);
+				else
+				    tmp_float += 1.0/pow(10,strlen(endptr+1)) * strtod(endptr+1, &endptr);
+				break;
+			}
 
 			if (*endptr) {
 				mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be a floating point number"
@@ -174,43 +257,39 @@ static int read_option(struct config *co
 				goto out;
 			}
 
-			if (conf[i].flags & CONF_MIN)
-				if (tmp_float < conf[i].min) {
-					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %f: %s\n", conf[i].min, param);
+			if ((opt->flags & CONF_MIN) && tmp_float < opt->min) {
+					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %f: %s\n", opt->min, param);
 					ret = ERR_OUT_OF_RANGE;
 					goto out;
 				}
 
-			if (conf[i].flags & CONF_MAX)
-				if (tmp_float > conf[i].max) {
-					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %f: %s\n", conf[i].max, param);
+			if ((opt->flags & CONF_MAX) && tmp_float > opt->max) {
+					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %f: %s\n", opt->max, param);
 					ret = ERR_OUT_OF_RANGE;
 					goto out;
 				}
 
-			*((float *) conf[i].p) = tmp_float;
+			*((float *) opt->p) = tmp_float;
 			ret = 1;
 			break;
 		case CONF_TYPE_STRING:
 			if (param == NULL)
 				goto err_missing_param;
 
-			if (conf[i].flags & CONF_MIN)
-				if (strlen(param) < conf[i].min) {
+			if ((opt->flags & CONF_MIN) && strlen(param) < opt->min) {
 					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %d chars: %s\n",
-							(int) conf[i].min, param);
+							(int) opt->min, param);
 					ret = ERR_OUT_OF_RANGE;
 					goto out;
 				}
 
-			if (conf[i].flags & CONF_MAX)
-				if (strlen(param) > conf[i].max) {
+			if ((opt->flags & CONF_MAX) && strlen(param) > opt->max) {
 					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %d chars: %s\n",
-							(int) conf[i].max, param);
+							(int) opt->max, param);
 					ret = ERR_OUT_OF_RANGE;
 					goto out;
 				}
-			*((char **) conf[i].p) = strdup(param);
+			*((char **) opt->p) = strdup(param);
 			ret = 1;
 			break;
 		case CONF_TYPE_STRING_LIST:
@@ -233,8 +312,8 @@ static int read_option(struct config *co
 			  }
 			  if(n == 0)
 			    goto err_missing_param;
-			  else if( (conf[i].flags & CONF_MIN && n < conf[i].min) || 
-				   (conf[i].flags & CONF_MAX && n > conf[i].max) ) {
+			  else if( ((opt->flags & CONF_MIN) && n < opt->min) ||
+				   ((opt->flags & CONF_MAX) && n > opt->max) ) {
 			    ret = ERR_OUT_OF_RANGE;
 			    goto out;
 			  }
@@ -262,13 +341,13 @@ static int read_option(struct config *co
 			     n++;
 			  }
 			  res[n] = NULL;
-			  *((char ***) conf[i].p) = res;
+			  *((char ***) opt->p) = res;
 			}
 			break;
 		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) opt->p)(conf, param)) < 0) {
 				ret = ERR_FUNC_ERR;
 				goto out;
 			}
@@ -276,17 +355,17 @@ static int read_option(struct config *co
 			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) opt->p)(conf, name, 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) opt->p)(conf, name, param);
 			    /* if we return 0: need no param, precess it again */
 			    /* if we return 1: accepted param */
 			}
 			break;
 		case CONF_TYPE_FUNC:
-			ret = (((cfg_func_t) conf[i].p)(config + i));
+			ret = (((cfg_func_t) opt->p)(conf));
 			if(ret<0){
 				ret = ERR_FUNC_ERR;
 				goto out;
@@ -298,95 +377,115 @@ static int read_option(struct config *co
 		    {
 			char *subparam;
 			char *subopt;
-			int subconf_optnr;
-			struct config *subconf;
+			char *p, *subopt_p;
+			char *c;
+			cfg_tree_t *subconf;
 			char *token;
 			int sscanf_ret;
+			int subparam_n = 0;
 
 			if (param == NULL)
 				goto err_missing_param;
 
 			subparam = malloc(strlen(param)+1);
-			subopt = malloc(strlen(param)+1);
+			subopt = subopt_p = malloc(strlen(param)+1);
 
-			subconf = conf[i].p;
-			for (subconf_optnr = 0; subconf[subconf_optnr].name != NULL; subconf_optnr++)
-			    /* NOTHING */;
+			subconf = conf->subtree;
+			p = strdup(param); // In case that param is a static string (cf man strtok)
 
+			ret = 1;
 			token = strtok(param, (char *)&(":"));
-			while(token)
+			while(token && ret > 0)
 			{
 			    /* clear out */
-			    subopt[0] = subparam[0] = 0;
+			    subopt_p[0] = subparam[0] = 0;
 			    
 //			    sscanf_ret = sscanf(token, "%[^=]=%[^\n\0]", subopt, subparam);
-			    sscanf_ret = sscanf(token, "%[^=]=%s", subopt, subparam);
+			    /* special care for unnamed */
+			    if (opt->flags & CONF_SEQUENT) {
+				if (++subparam_n > 9) { // SEQUENT cannot have above of 10 options
+				    sscanf_ret = 0;
+				    c = NULL;
+				} else {
+				    // form the name for read_option()
+				    c = malloc(strlen(name)+4);
+				    sprintf(c, "%s[%d]", name, subparam_n);
+				    sscanf_ret = 1;
+				    subopt = token;
+				}
+			    } else {
+				// form the name for read_option()
+				c = malloc(strlen(name)+1+strlen(subopt)+1);
+				sprintf(c, "%s:%s", name, subopt);
+				sscanf_ret = sscanf(token, "%[^=]=%s", subopt_p, subparam);
+			    }
 
-			    mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "token: '%s', i=%d, subopt='%s', subparam='%s' (ret: %d)\n", token, i, subopt, subparam, sscanf_ret);
+			    mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "token: '%s', subopt='%s', subparam='%s' (ret: %d)\n", token, subopt, subparam, sscanf_ret);
 			    switch(sscanf_ret)
 			    {
 				case 1:
 				    subparam[0] = 0;
 				case 2:
-				    if ((ret = read_option((struct config *)subconf, subconf_optnr, subopt, subparam)) < 0)
+				    if ((subconf = cfg_find(conf->subtree, subopt)) == NULL ||
+					(ret = read_option(subconf, c, *subparam ? subparam : NULL, mode)) < 0)
 				    {
-					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Subconfig parsing returned error: %d in token: %s\n",
-					    ret, token);
-					goto out;
+					mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Subconfig parsing returned error: %d in token: %s\n", ret, token);
+					ret = ERR_NOT_AN_OPTION;
 				    }
+				    if (c) free(c);
 				    break;
 				default:
 				    mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid subconfig argument! ('%s')\n", token);
 				    ret = ERR_NOT_AN_OPTION;
-				    goto out;
 			    }
 			    token = strtok(NULL, (char *)&(":"));
 			}
 
 			free(subparam);
-			free(subopt);
-			ret = 1;
+			free(subopt_p);
+			free(p);
 			break;
 		    }
 		case CONF_TYPE_PRINT:
-			printf("%s", (char *) conf[i].p);
+			mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", (char *) opt->p);
 			exit(1);
 		default:
 			mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Unknown config type specified in conf-mplayer.h!\n");
-			break;
+			goto out;
 	}
+	conf->flags = 1; // mark it as set
 out:
 	return ret;
 err_missing_param:
-	mp_msg(MSGT_CFGPARSER, MSGL_ERR, "missing parameter for option: %s\n", opt);
+	mp_msg(MSGT_CFGPARSER, MSGL_ERR, "missing parameter for option: %s\n", name);
 	ret = ERR_MISSING_PARAM;
 	goto out;
 }
 
-int parse_config_file(struct config *conf, char *conffile)
+static int parse_config(pl_instance_t *pli, cfg_tree_t *conf, int argc, char **argv)
 {
-#define PRINT_LINENUM	printf("%s(%d): ", conffile, line_num)
-#define MAX_LINE_LEN	1000
+#define PRINT_LINENUM	printf("%s(%d): ", argv[ret], line_num)
+#define MAX_LINE_LEN	2000
 #define MAX_OPT_LEN	100
-#define MAX_PARAM_LEN	100
+#define MAX_PARAM_LEN	1000
 	FILE *fp;
 	char *line;
 	char opt[MAX_OPT_LEN + 1];
 	char param[MAX_PARAM_LEN + 1];
 	char c;		/* for the "" and '' check */
+	cfg_tree_t *co;
 	int tmp;
 	int line_num = 0;
 	int line_pos;	/* line pos */
 	int opt_pos;	/* opt pos */
 	int param_pos;	/* param pos */
-	int ret = 1;
+	int ret;
 	int errors = 0;
 
 #ifdef DEBUG
-	assert(conffile != NULL);
+	assert(argv != NULL);
+	assert(argc >= 1);
 #endif
-	if (++recursion_depth > 1)
-		printf("Reading config file: %s", conffile);
 
 	if (recursion_depth > MAX_RECURSION_DEPTH) {
 		printf(": too deep 'include'. check your configfiles\n");
@@ -394,30 +493,32 @@ int parse_config_file(struct config *con
 		goto out;
 	}
 
-	if (init_conf(conf, CONFIG_FILE) == -1) {
-		ret = -1;
-		goto out;
-	}
-
 	if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) {
 		printf("\ncan't get memory for 'line': %s", strerror(errno));
 		ret = -1;
 		goto out;
 	}
 
-	if ((fp = fopen(conffile, "r")) == NULL) {
+	for (ret = 0; ret < argc; ret++) {
+	    if (++recursion_depth > 1)
+		printf("Reading config file: %s", argv[ret]);
+
+	    fp = fopen(argv[ret], "r");
+	    if (fp == NULL) {
 		if (recursion_depth > 1)
 			printf(": %s\n", strerror(errno));
 		free(line);
 		ret = 0;
 		goto out;
-	}
-	if (recursion_depth > 1)
+	    }
+	    if (recursion_depth > 1)
 		printf("\n");
 
-	while (fgets(line, MAX_LINE_LEN, fp)) {
+	    while (fgets(line, MAX_LINE_LEN, fp)) {
 		if (errors >= 16) {
 			printf("too many errors\n");
+			free(line);
+			fclose(fp);
 			goto out;
 		}
 
@@ -442,14 +543,12 @@ int parse_config_file(struct config *con
 				PRINT_LINENUM;
 				printf("too long option\n");
 				errors++;
-				ret = -1;
 				goto nextline;
 			}
 		}
 		if (opt_pos == 0) {
 			PRINT_LINENUM;
 			printf("parse error\n");
-			ret = -1;
 			errors++;
 			continue;
 		}
@@ -468,7 +567,6 @@ int parse_config_file(struct config *con
 		if (line[line_pos++] != '=') {
 			PRINT_LINENUM;
 			printf("option without parameter\n");
-			ret = -1;
 			errors++;
 			continue;
 		}
@@ -486,7 +584,6 @@ int parse_config_file(struct config *con
 				if (param_pos >= MAX_PARAM_LEN) {
 					PRINT_LINENUM;
 					printf("too long parameter\n");
-					ret = -1;
 					errors++;
 					goto nextline;
 				}
@@ -499,7 +596,6 @@ int parse_config_file(struct config *con
 				if (param_pos >= MAX_PARAM_LEN) {
 					PRINT_LINENUM;
 					printf("too long parameter\n");
-					ret = -1;
 					errors++;
 					goto nextline;
 				}
@@ -511,7 +607,6 @@ int parse_config_file(struct config *con
 		if (param_pos == 0) {
 			PRINT_LINENUM;
 			printf("option without parameter\n");
-			ret = -1;
 			errors++;
 			continue;
 		}
@@ -530,51 +625,65 @@ int parse_config_file(struct config *con
 		if (line[line_pos] != '\0' && line[line_pos] != '#') {
 			PRINT_LINENUM;
 			printf("extra characters on line: %s\n", line+line_pos);
-			ret = -1;
+			errors++;
 		}
 
-		tmp = read_option(config, nr_options, opt, param);
+		co = cfg_find(conf, opt);
+		if (co)
+			tmp = read_option(co, opt, param, CONFIG_FILE);
+		else
+			tmp = ERR_NOT_AN_OPTION;
+//	mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "read_option: conf=%p optnr=%d opt='%s' param='%s'\n",
+//	    ??conf??, ??conf_optnr??, opt, param);
 		switch (tmp) {
 		case ERR_NOT_AN_OPTION:
+			if (co) { // option exist but isn't filled yet (plugin)
+			    pli->priv->num++;
+			    //TODO: check for realloc errors?
+			    pli->priv->name = realloc(pli->priv->name, pli->priv->num * sizeof(char*));
+			    pli->priv->param = realloc(pli->priv->param, pli->priv->num * sizeof(char*));
+			    pli->priv->name[pli->priv->num-1] = strdup(opt);
+			    pli->priv->param[pli->priv->num-1] = strdup(param);
+#ifdef DEBUG
+			    PRINT_LINENUM;
+			    printf("%s postponed\n", opt);
+#endif
+			    continue;
+			}
 		case ERR_MISSING_PARAM:
 		case ERR_OUT_OF_RANGE:
 		case ERR_FUNC_ERR:
 			PRINT_LINENUM;
 			printf("%s\n", opt);
-			ret = -1;
 			errors++;
 			continue;
 			/* break */
 		}	
 nextline:
 		;
+	    }
+	    free(line);
+	    fclose(fp);
 	}
 
-	free(line);
-	fclose(fp);
 out:
 	--recursion_depth;
+	if (errors) return -1;
 	return ret;
 }
 
-int parse_command_line(struct config *conf, int argc, char **argv, char **envp, char ***filenames)
+static int parse_cl(pl_instance_t *pli, cfg_tree_t *conf, int argc, char **argv)
 {
 	int i;
-	char **f = NULL;
-	int f_nr = 0;
 	int tmp;
 	char *opt;
 	int no_more_opts = 0;
 
 #ifdef DEBUG
 	assert(argv != NULL);
-	assert(envp != NULL);
 	assert(argc >= 1);
 #endif
 
-	if (init_conf(conf, COMMAND_LINE) == -1)
-		return -1;
-
 	/* in order to work recursion detection properly in parse_config_file */
 	++recursion_depth;
 
@@ -596,12 +705,20 @@ next:
 			
 		if ((no_more_opts == 0) && (*opt == '-') && (*(opt+1) != 0)) /* option */
 		{
+		    cfg_tree_t *co;
+
 		    /* remove trailing '-' */
 		    opt++;
 
 		    mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = option: %s\n", opt);
 
-		    tmp = read_option(config, nr_options, opt, argv[i + 1]);
+		    co = cfg_find(conf, opt);
+		    if (co)
+			tmp = read_option(co, opt, argv[i + 1], COMMAND_LINE);
+		    else
+			tmp = ERR_NOT_AN_OPTION;
+//	mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "read_option: conf=%p optnr=%d opt='%s' param='%s'\n",
+//	    ??conf??, ??conf_optnr??, opt, param);
 
 		    switch (tmp) {
 		    case ERR_NOT_AN_OPTION:
@@ -621,19 +738,18 @@ next:
 		    mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = filename: %s\n", opt);
 
 		    /* opt is not an option -> treat it as a filename */
-		    if (!(f = (char **) realloc(f, sizeof(*f) * (f_nr + 2))))
+		    if (!(pli->priv->param = (char **) realloc(pli->priv->param,
+			    sizeof(*pli->priv->param) * (pli->priv->num + 2))))
 			goto err_out_mem;
 
-		    f[f_nr++] = argv[i];
+		    pli->priv->param[pli->priv->num++] = argv[i];
 		}
 	}
 
-	if (f)
-		f[f_nr] = NULL;
-	if (filenames)
-		*filenames = f;
+	if (pli->priv->param)
+		pli->priv->param[pli->priv->num] = NULL;
 	--recursion_depth;
-	return f_nr; //filenames_nr;
+	return pli->priv->num; //filenames_nr;
 err_out_mem:
 	mp_msg(MSGT_CFGPARSER, MSGL_ERR, "can't allocate memory for filenames (%s)\n", strerror(errno));
 err_out:
@@ -642,49 +758,140 @@ err_out:
 	return -1;
 }
 
-int list_cfg_options(struct config *conf){
-    while(conf->name){
-	printf("  -%s",conf->name);
-	switch(conf->type){
-	case CONF_TYPE_FUNC:
-	case CONF_TYPE_FLAG:
-	default:
-	    break;
-	case CONF_TYPE_INT:
-	    if(conf->flags&CONF_RANGE){
-		if(conf->flags&CONF_MIN) printf(" <%d",(int)conf->min); else printf("<");
-		printf(" .. ");
-		if(conf->flags&CONF_MAX) printf("%d>",(int)conf->max); else printf(">");
-	    } else
-		printf(" <int>");
-	    break;
-	case CONF_TYPE_FLOAT:
-	    if(conf->flags&CONF_RANGE){
-		if(conf->flags&CONF_MIN) printf(" <%3.1f",conf->min); else printf("<");
-		printf(" .. ");
-		if(conf->flags&CONF_MAX) printf("%3.1f>",conf->max); else printf(">");
-	    } else
-		printf(" <float>");
-	    break;
-	case CONF_TYPE_STRING:
-	    printf(" <string>");
-	    break;
-	case CONF_TYPE_STRING_LIST:
-	    printf(" <string[,string2,...]>");
-	    break;
-	case CONF_TYPE_FUNC_PARAM:
-	    printf(" <?>");
-	    break;
-	case CONF_TYPE_FUNC_FULL:
-	    printf("* [<?>]");
-	    break;
-	case CONF_TYPE_SUBCONFIG:
-	    printf(" opt1=param1[:opt2=param2:...]");
-	    break;
-	}
-	printf("\n");
-	++conf;
+static char *get_next_file(pl_instance_t *pli, cfg_tree_t *conf, char *name)
+{
+  (void) conf;
+
+  if (pli->priv->num == 0) return NULL;
+  pli->priv->num--;
+  name = pli->priv->param[0];
+  if (pli->priv->num)
+    memmove(pli->priv->param, &pli->priv->param[1], pli->priv->num * sizeof(char *));
+  else
+    free(pli->priv->param);
+  return name;
+}
+
+static int save_config(cfg_tree_t *conf, FILE *f){
+  return -1; // not ready yet
+}
+
+/* plugin information */
+static int open_cli(pl_instance_t *pli);
+
+static struct pl_func_s funcs_CLI={
+  &parse_cl,
+  NULL,
+  &get_next_file,
+  NULL
+};
+
+static pl_info_t info_cli={
+  { PLUGIN_VERSION_MAJOR, PLUGIN_VERSION_MINOR },
+  PLUGIN_TYPE_CTL,
+  "CLI",
+  "commandline parser",
+  "",
+  "",
+  "",
+  &open_cli,
+  &funcs_CLI,
+  NULL
+};
+
+static struct pl_func_s funcs_cfgparser={
+  &parse_config,
+  NULL, // may be do revert??
+  &reparse_postponed,
+  &save_config
+};
+
+static pl_info_t info_cfgparser={
+  { PLUGIN_VERSION_MAJOR, PLUGIN_VERSION_MINOR },
+  PLUGIN_TYPE_CTL,
+  "cfgparser",
+  "config file parser",
+  "",
+  "",
+  "",
+  &open_cli,
+  &funcs_cfgparser,
+  NULL
+};
+
+static int open_cli(pl_instance_t *pli)
+{
+  if (!pli->priv) { // trying to keep all configs together
+    if (pli->prev && pli->prev->priv->cfgparser && pli->info == &info_cfgparser)
+      pli->priv = pli->prev->priv->cfgparser->priv;
+    else {
+      pli->priv = calloc(1, sizeof(struct pl_priv_s));
+      if (pli->prev && pli->prev->priv->cfgparser)
+	pli->priv->cfgparser = pli->prev->priv->cfgparser;
+      else if (pli->info == &info_cfgparser)
+	pli->priv->cfgparser = pli;
     }
-    return 1;
+  }
+  return 0;
+}
+
+/*void register_CLI(cfg_tree_t *conf)
+{
+  pl_register_plugin(info_cli, conf, &cli_preopen);
+  pl_register_plugin(info_cfgparser, conf, &cli_preopen);
+}*/
+
+/* backward compatibility stuff :) */
+static pl_instance_t *pl_cfgparser = NULL;
+
+int parse_config_file(cfg_tree_t *conf, char *conffile)
+{
+#ifdef DEBUG
+	assert(conffile != NULL);
+	assert(conf != NULL);
+#endif
+
+  if (pl_cfgparser == NULL) {
+    pl_register_plugin(&info_cfgparser, conf, NULL);
+    pl_cfgparser = pl_get_plugin(NULL, PLUGIN_TYPE_CTL, "cfgparser");
+    pl_open_plugin(pl_cfgparser);
+  }
+  return parse_config(pl_cfgparser, conf, 1, &conffile);
 }
 
+static pl_instance_t *pl_cli = NULL;
+
+int parse_command_line(cfg_tree_t *conf, int argc, char **argv, char **envp, char ***filenames)
+{
+  int res;
+  (void) envp;
+
+#ifdef DEBUG
+  assert(conf != NULL);
+#endif
+
+  if (pl_cli == NULL) {
+    pl_register_plugin(&info_cli, conf, NULL);
+    pl_cli = pl_get_plugin(pl_cfgparser, PLUGIN_TYPE_CTL, "CLI");
+    pl_open_plugin(pl_cli);
+  }
+  res = parse_cl(pl_cli, conf, argc, argv);
+  if (res >= 0 && filenames) {
+    *filenames = pl_cli->priv->param;
+    pl_cli->priv->num = 0; // returned so must be empty
+  }
+  return res;
+}
+
+int list_cfg_options(cfg_tree_t *config)
+{
+  char c[256];
+
+  for ( ; config; config = config->next) {
+    if (config->opt->type == CONF_TYPE_DUMMY)
+      list_cfg_options(config->subtree);
+    else if (config->opt->desc)
+      printf("  -%-15s - %s\n",config->opt->name,print_option_help(config->opt,c,sizeof(c)));
+  }
+  return 1;
+}
diff -udpr g2/cfgparser.h g2.new/cfgparser.h
--- g2/cfgparser.h	Sat Apr 19 02:09:52 2003
+++ g2.new/cfgparser.h	Mon May 12 16:17:13 2003
@@ -2,60 +2,27 @@
  * command line and config file parser
  */
 
-#ifndef __CONFIG_H
-#define __CONFIG_H
-
-#define CONF_TYPE_FLAG		0
-#define CONF_TYPE_INT		1
-#define CONF_TYPE_FLOAT		2
-#define CONF_TYPE_STRING	3
-#define CONF_TYPE_FUNC		4
-#define CONF_TYPE_FUNC_PARAM	5
-#define CONF_TYPE_PRINT		6
-#define CONF_TYPE_FUNC_FULL	7
-#define CONF_TYPE_SUBCONFIG	8
-#define CONF_TYPE_STRING_LIST   9
-
-
-#define ERR_NOT_AN_OPTION	-1
-#define ERR_MISSING_PARAM	-2
-#define ERR_OUT_OF_RANGE	-3
-#define ERR_FUNC_ERR		-4
-
-
-
-#define CONF_MIN		(1<<0)
-#define CONF_MAX		(1<<1)
-#define CONF_RANGE		(CONF_MIN|CONF_MAX)
-#define CONF_NOCFG		(1<<2)
-#define CONF_NOCMD		(1<<3)
-
-struct config {
-	char *name;
-	void *p;
-	unsigned int type;
-	unsigned int flags;
-	float min,max;
-};
-
-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 *);
+#include "cfg.h"
 
+// --------- Backward compatibility stuff ---------
 /* 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 parse_config_file(cfg_tree_t *conf, 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
  */
-int parse_command_line(struct config *conf, int argc, char **argv, char **envp, char ***filenames);
+int parse_command_line(cfg_tree_t *conf, int argc, char **argv, char **envp, char ***filenames);
 
-int list_cfg_options(struct config *conf);
+int list_cfg_options(cfg_tree_t *conf);
 
-#endif /* __CONFIG_H */
+/* register internal parsers - config and commandline
+ * called internally if you use only two functions above
+ * parse_config_file(main config) must be called before parse_command_line()
+ */
+//void register_CLI(cfg_tree_t *conf);
diff -udpr g2/test-cfg.h g2.new/test-cfg.h
--- g2/test-cfg.h	Sat Apr 19 02:10:15 2003
+++ g2.new/test-cfg.h	Mon May 12 16:17:13 2003
@@ -2,18 +2,18 @@
  * config for cfgparser
  */
 
-static int cfg_inc_verbose(struct config *conf){ ++verbose; return 0;}
+static int cfg_inc_verbose(cfg_tree_t *conf){ ++verbose; return 0;}
 
-static int cfg_include(struct config *conf, char *filename){
+static int cfg_include(cfg_tree_t *conf, char *filename){
 	return parse_config_file(conf, filename);
 }
 
-struct config conf[]={
+static cfg_t conf[]={
 	/* name, pointer, type, flags, min, max */
-	{"include", cfg_include, CONF_TYPE_FUNC_PARAM, 0, 0, 0}, /* this must be the first!!! */
-	{"-help", list_cfg_options, CONF_TYPE_FUNC, CONF_NOCFG, 0, 0},
-	{"help", list_cfg_options, CONF_TYPE_FUNC, CONF_NOCFG, 0, 0},
-	{"h", list_cfg_options, CONF_TYPE_FUNC, CONF_NOCFG, 0, 0},
+	{"-help", list_cfg_options, CONF_TYPE_FUNC, CONF_NOCFG, 0, 0, NULL, NULL},
+	{"help", list_cfg_options, CONF_TYPE_FUNC, CONF_NOCFG, 0, 0, NULL, NULL},
+	{"h", list_cfg_options, CONF_TYPE_FUNC, CONF_NOCFG, 0, 0, NULL, NULL},
+	{"include", cfg_include, CONF_TYPE_FUNC_PARAM, CONF_NOSAVE, 0, 0, NULL, "include config file"}, /* this must be the first!!! */
 
 //---------------------- libao/libvo/mplayer options ------------------------
 //	{"o", "Option -o has been renamed to -vo (video-out), use -vo !\n",
@@ -22,24 +22,24 @@ struct config conf[]={
 //	{"aop", ao_plugin_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0},
 //	{"osdlevel", &osd_level, CONF_TYPE_INT, CONF_RANGE, 0, 2 },
 
-	{"dumpstream", &dumpstream, CONF_TYPE_FLAG, 0, 0, 1},
-	{"id", &stream_id, CONF_TYPE_INT, CONF_RANGE, 0, MAX_STREAMS-1},
+	{"dumpstream", &dumpstream, CONF_TYPE_FLAG, 0, 0, 1, NULL, NULL},
+	{"id", &stream_id, CONF_TYPE_INT, CONF_RANGE, 0, MAX_STREAMS-1, NULL, NULL},
 
-	{"extbased", &demuxer_use_file_ext, CONF_TYPE_FLAG, 0, 0, 1},
-	{"noextbased", &demuxer_use_file_ext, CONF_TYPE_FLAG, 0, 1, 0},
+	{"extbased", &demuxer_use_file_ext, CONF_TYPE_FLAG, 0, 0, 1, NULL, NULL},
+	{"noextbased", &demuxer_use_file_ext, CONF_TYPE_FLAG, 0, 1, 0, NULL, NULL},
 
-	{"demuxer", &demuxer_name, CONF_TYPE_STRING, 0, 0, 0},
+	{"demuxer", &demuxer_name, CONF_TYPE_STRING, 0, 0, 0, NULL, "demuxer name"},
 
 #ifdef TEST_CODECS
-	{"c", &codec_name_list, CONF_TYPE_STRING_LIST, 0, 0, 0},
-	{"fm", &codec_fm_list, CONF_TYPE_STRING_LIST, 0, 0, 0},
+	{"c", &codec_name_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL, "codec name"},
+	{"fm", &codec_fm_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL, "codec family"},
 
-	{"vo", &video_driver_list, CONF_TYPE_STRING_LIST, 0, 0, 0},
-	{"ao", &audio_driver_list, CONF_TYPE_STRING_LIST, 0, 0, 0},
-	{"vop", &video_filter_list, CONF_TYPE_STRING_LIST, 0, 0, 0},
+	{"vo", &video_driver_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL, "video out driver"},
+	{"ao", &audio_driver_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL, "audio out driver"},
+	{"vop", &video_filter_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL, "video filter list"},
 #endif
 
-	{"verbose", &verbose, CONF_TYPE_INT, CONF_RANGE, 0, 100},
-	{"v", cfg_inc_verbose, CONF_TYPE_FUNC, 0, 0, 0},
-	{NULL, NULL, 0, 0, 0, 0}
+	{"verbose", &verbose, CONF_TYPE_INT, CONF_RANGE|CONF_GLOBAL, 0, 100, NULL, "verbosity level"},
+	{"v", cfg_inc_verbose, CONF_TYPE_FUNC, CONF_GLOBAL, 0, 0, NULL, "increase verbosity"},
+	{NULL, NULL, 0, 0, 0, 0, NULL, NULL}
 };
diff -udpr g2/test-play.c g2.new/test-play.c
--- g2/test-play.c	Sun May 11 15:12:06 2003
+++ g2.new/test-play.c	Mon May 12 16:17:13 2003
@@ -83,6 +83,7 @@ int main(int argc,char* argv[], char *en
   ao_functions_t* audio_out=NULL;
   vo_instance_t* video_out=NULL;
   vf_instance_t* vf_vo2;
+  cfg_tree_t* mconfig=NULL;
   int i,ret;
 
 //INIT mp_msg
@@ -92,8 +93,9 @@ int main(int argc,char* argv[], char *en
   GetCpuCaps(&gCpuCaps);
 
 //INIT config/cmdline
-  if (parse_config_file(conf, "test.conf") < 0) exit(1);
-  num_filenames=parse_command_line(conf, argc, argv, envp, &filenames);
+  cfg_register(&mconfig, conf, 0);
+  if (parse_config_file(mconfig, "test.conf") < 0) exit(1);
+  num_filenames=parse_command_line(mconfig, argc, argv, envp, &filenames);
 
   mp_msg_set_level(verbose+MSGL_STATUS);
 
diff -udpr g2/test-stream.c g2.new/test-stream.c
--- g2/test-stream.c	Mon May 12 02:05:01 2003
+++ g2.new/test-stream.c	Mon May 12 16:17:13 2003
@@ -29,6 +29,7 @@ int main(int argc,char* argv[], char *en
   demuxer_t* demuxer;
   FILE* f;
   int i;
+  cfg_tree_t* mconfig=NULL;
   off_t start_pos;
 
 //INIT mp_msg
@@ -36,8 +37,9 @@ int main(int argc,char* argv[], char *en
   mp_msg_set_level(MSGL_STATUS);
 
 //INIT config/cmdline
-  if (parse_config_file(conf, "test.conf") < 0) exit(1);
-  num_filenames=parse_command_line(conf, argc, argv, envp, &filenames);
+  cfg_register(&mconfig, conf, 0);
+  if (parse_config_file(mconfig, "test.conf") < 0) exit(1);
+  num_filenames=parse_command_line(mconfig, argc, argv, envp, &filenames);
 
   mp_msg_set_level(verbose+MSGL_STATUS);
 
diff -udpr g2/video/vf.h g2.new/video/vf.h
--- g2/video/vf.h	Fri May  2 23:02:21 2003
+++ g2.new/video/vf.h	Mon May 12 16:17:13 2003
@@ -2,6 +2,8 @@
 struct vf_instance_s;
 struct vf_priv_s;
 
+#include "../cfg.h"
+
 typedef struct vf_info_s {
     const char *info;
     const char *name;
@@ -9,7 +11,7 @@ typedef struct vf_info_s {
     const char *comment;
     int (*open)(struct vf_instance_s* vf,char* args);
     // Ptr to a struct dscribing the options
-    void* opts;
+    cfg_t* opts;
 } vf_info_t;
 
 typedef struct vf_image_context_s {


More information about the MPlayer-G2-dev mailing list