summaryrefslogtreecommitdiffstats
path: root/m_option.c
diff options
context:
space:
mode:
authoralbeu <albeu@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-11-12 01:56:42 +0000
committeralbeu <albeu@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-11-12 01:56:42 +0000
commit126725660d4bebbab8570221c5681dc01d98fe86 (patch)
tree3ebdca9acf6fae38bfdba5b4159fbd16177da828 /m_option.c
parent0f622e2d6fe735d727b9d8fd12cea22e03fd954b (diff)
downloadmpv-126725660d4bebbab8570221c5681dc01d98fe86.tar.bz2
mpv-126725660d4bebbab8570221c5681dc01d98fe86.tar.xz
New config system + cleanup of header inter dependency
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8165 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'm_option.c')
-rw-r--r--m_option.c1008
1 files changed, 1008 insertions, 0 deletions
diff --git a/m_option.c b/m_option.c
new file mode 100644
index 0000000000..a5824895ee
--- /dev/null
+++ b/m_option.c
@@ -0,0 +1,1008 @@
+
+#include "config.h"
+
+#ifdef NEW_CONFIG
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <inttypes.h>
+
+#include "m_option.h"
+//#include "m_config.h"
+#include "mp_msg.h"
+
+// Default function that just do a memcpy
+
+static void copy_opt(m_option_t* opt,void* dst,void* src) {
+ if(dst && src)
+ memcpy(dst,src,opt->type->size);
+}
+
+// Helper for the print funcs (from man printf)
+static char* dup_printf(const char *fmt, ...) {
+ /* Guess we need no more than 50 bytes. */
+ int n, size = 50;
+ char *p;
+ va_list ap;
+ if ((p = malloc (size)) == NULL)
+ return NULL;
+ while (1) {
+ /* Try to print in the allocated space. */
+ va_start(ap, fmt);
+ n = vsnprintf (p, size, fmt, ap);
+ va_end(ap);
+ /* If that worked, return the string. */
+ if (n > -1 && n < size)
+ return p;
+ /* Else try again with more space. */
+ if (n > -1) /* glibc 2.1 */
+ size = n+1; /* precisely what is needed */
+ else /* glibc 2.0 */
+ size *= 2; /* twice the old size */
+ if ((p = realloc (p, size)) == NULL)
+ return NULL;
+ }
+}
+
+
+// Flag
+
+#define VAL(x) (*(int*)(x))
+
+static int parse_flag(m_option_t* opt,char *name, char *param, void* dst, int src) {
+ if (src == M_CONFIG_FILE) {
+ if (!strcasecmp(param, "yes") || /* any other language? */
+ !strcasecmp(param, "ja") ||
+ !strcasecmp(param, "si") ||
+ !strcasecmp(param, "igen") ||
+ !strcasecmp(param, "y") ||
+ !strcasecmp(param, "j") ||
+ !strcasecmp(param, "i") ||
+ !strcmp(param, "1")) {
+ if(dst) VAL(dst) = opt->max;
+ } else if (!strcasecmp(param, "no") ||
+ !strcasecmp(param, "nein") ||
+ !strcasecmp(param, "nicht") ||
+ !strcasecmp(param, "nem") ||
+ !strcasecmp(param, "n") ||
+ !strcmp(param, "0")) {
+ if(dst) VAL(dst) = opt->min;
+ } else {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid parameter for %s flag: %s\n",name, param);
+ return M_OPT_INVALID;
+ }
+ return 1;
+ } else {
+ if(dst) VAL(dst) = opt->max;
+ return 0;
+ }
+}
+
+static char* print_flag(m_option_t* opt, void* val) {
+ if(VAL(val) == opt->min)
+ return strdup("no");
+ else
+ return strdup("yes");
+}
+
+m_option_type_t m_option_type_flag = {
+ "Flag",
+ "need yes or no in config files",
+ sizeof(int),
+ 0,
+ parse_flag,
+ print_flag,
+ copy_opt,
+ copy_opt,
+ NULL,
+ NULL
+};
+
+// Integer
+
+static int parse_int(m_option_t* opt,char *name, char *param, void* dst, int src) {
+ long tmp_int;
+ char *endptr;
+ src = 0;
+
+ if (param == NULL)
+ return M_OPT_MISSING_PARAM;
+
+ tmp_int = strtol(param, &endptr, 0);
+ if (*endptr) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be an integer: %s\n",name, param);
+ return M_OPT_INVALID;
+ }
+
+ if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be >= %d: %s\n", name, (int) opt->min, param);
+ return M_OPT_OUT_OF_RANGE;
+ }
+
+ if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be <= %d: %s\n",name, (int) opt->max, param);
+ return M_OPT_OUT_OF_RANGE;
+ }
+
+ if(dst) VAL(dst) = tmp_int;
+
+ return 1;
+}
+
+static char* print_int(m_option_t* opt, void* val) {
+ opt = NULL;
+ return dup_printf("%d",VAL(val));
+}
+
+m_option_type_t m_option_type_int = {
+ "Integer",
+ "",
+ sizeof(int),
+ 0,
+ parse_int,
+ print_int,
+ copy_opt,
+ copy_opt,
+ NULL,
+ NULL
+};
+
+// Float
+
+#undef VAL
+#define VAL(x) (*(float*)(x))
+
+static int parse_float(m_option_t* opt,char *name, char *param, void* dst, int src) {
+ float tmp_float;
+ char* endptr;
+ src = 0;
+
+ if (param == NULL)
+ return M_OPT_MISSING_PARAM;
+
+ tmp_float = strtod(param, &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, "The %s option must be a floating point "
+ "number or a ratio (numerator[:/]denominator): %s\n",name, param);
+ return M_OPT_INVALID;
+ }
+
+ if (opt->flags & M_OPT_MIN)
+ if (tmp_float < opt->min) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be >= %f: %s\n", name, opt->min, param);
+ return M_OPT_OUT_OF_RANGE;
+ }
+
+ if (opt->flags & M_OPT_MAX)
+ if (tmp_float > opt->max) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be <= %f: %s\n", name, opt->max, param);
+ return M_OPT_OUT_OF_RANGE;
+ }
+
+ if(dst) VAL(dst) = tmp_float;
+ return 1;
+}
+
+static char* print_float(m_option_t* opt, void* val) {
+ opt = NULL;
+ return dup_printf("%f",VAL(val));
+}
+
+m_option_type_t m_option_type_float = {
+ "Float",
+ "floating point number or ratio (numerator[:/]denominator)",
+ sizeof(float),
+ 0,
+ parse_float,
+ print_float,
+ copy_opt,
+ copy_opt,
+ NULL,
+ NULL
+};
+
+///////////// Position
+#undef VAL
+#define VAL(x) (*(off_t*)(x))
+
+static int parse_position(m_option_t* opt,char *name, char *param, void* dst, int src) {
+ off_t tmp_off;
+ char dummy;
+
+ if (param == NULL)
+ return M_OPT_MISSING_PARAM;
+ if (sscanf(param, sizeof(off_t) == sizeof(int) ?
+ "%d%c" : "%lld%c", &tmp_off, &dummy) != 1) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be an integer: %s\n",opt->name,param);
+ return M_OPT_INVALID;
+ }
+
+ if (opt->flags & M_OPT_MIN)
+ if (tmp_off < opt->min) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR,
+ (sizeof(off_t) == sizeof(int) ?
+ "The %s option must be >= %d: %s\n" :
+ "The %s option must be >= %lld: %s\n"),
+ (off_t) opt->min, param);
+ return M_OPT_OUT_OF_RANGE;
+ }
+
+ if (opt->flags & M_OPT_MAX)
+ if (tmp_off > opt->max) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR,
+ (sizeof(off_t) == sizeof(int) ?
+ "The %s option must be <= %d: %s\n" :
+ "The %s option must be <= %lld: %s\n"),
+ (off_t) opt->max, param);
+ return M_OPT_OUT_OF_RANGE;
+ }
+
+ if(dst)
+ VAL(dst) = tmp_off;
+ return 1;
+}
+
+static char* print_position(m_option_t* opt, void* val) {
+ return dup_printf(sizeof(off_t) == sizeof(int) ? "%d" : "%lld",VAL(val));
+}
+
+m_option_type_t m_option_type_position = {
+ "Position",
+ "Integer (off_t)",
+ sizeof(off_t),
+ 0,
+ parse_position,
+ print_position,
+ copy_opt,
+ copy_opt,
+ NULL,
+ NULL
+};
+
+
+///////////// String
+
+#undef VAL
+#define VAL(x) (*(char**)(x))
+
+static int parse_str(m_option_t* opt,char *name, char *param, void* dst, int src) {
+
+
+ if (param == NULL)
+ return M_OPT_MISSING_PARAM;
+
+ if ((opt->flags & M_OPT_MIN) && (strlen(param) < opt->min)) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %d chars: %s\n",
+ (int) opt->min, param);
+ return M_OPT_OUT_OF_RANGE;
+ }
+
+ if ((opt->flags & M_OPT_MAX) && (strlen(param) > opt->max)) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %d chars: %s\n",
+ (int) opt->max, param);
+ return M_OPT_OUT_OF_RANGE;
+ }
+
+ if(dst) {
+ if(VAL(dst))
+ free(VAL(dst));
+ VAL(dst) = strdup(param);
+ }
+
+ return 1;
+
+}
+
+static char* print_str(m_option_t* opt, void* val) {
+ return (val && VAL(val) && strlen(VAL(val)) > 0) ? strdup(VAL(val)) : strdup("(empty)");
+}
+
+static void copy_str(m_option_t* opt,void* dst, void* src) {
+ if(dst && src) {
+ if(VAL(dst)) free(VAL(dst));
+ VAL(dst) = VAL(src) ? strdup(VAL(src)) : NULL;
+ }
+}
+
+static void free_str(void* src) {
+ if(src && VAL(src)){
+ free(VAL(src));
+ VAL(src) = NULL;
+ }
+}
+
+m_option_type_t m_option_type_string = {
+ "String",
+ "",
+ sizeof(char*),
+ M_OPT_TYPE_DYNAMIC,
+ parse_str,
+ print_str,
+ copy_str,
+ copy_str,
+ copy_str,
+ free_str
+};
+
+//////////// String list
+
+#define LIST_SEPARATOR ','
+#undef VAL
+#define VAL(x) (*(char***)(x))
+
+#define OP_NONE 0
+#define OP_ADD 1
+#define OP_PRE 2
+#define OP_DEL 3
+#define OP_CLR 4
+
+static void free_str_list(void* dst) {
+ char** d;
+ int i;
+
+ if(!dst || !VAL(dst)) return;
+ d = VAL(dst);
+
+
+ for(i = 0 ; d[i] != NULL ; i++)
+ free(d[i]);
+ free(d);
+ VAL(dst) = NULL;
+}
+
+static int str_list_add(char** add, int n,void* dst,int pre) {
+ char** lst = VAL(dst);
+ int ln;
+
+ if(!dst) return M_OPT_PARSER_ERR;
+ lst = VAL(dst);
+
+ for(ln = 0 ; lst && lst[ln] ; ln++)
+ /**/;
+
+ lst = realloc(lst,(n+ln+1)*sizeof(char*));
+
+ if(pre) {
+ memmove(&lst[n],lst,(ln+1)*sizeof(char*));
+ memcpy(lst,add,n*sizeof(char*));
+ } else
+ memcpy(&lst[ln],add,(n+1)*sizeof(char*));
+
+ free(add);
+
+ VAL(dst) = lst;
+
+ return 1;
+}
+
+static int str_list_del(char** del, int n,void* dst) {
+ char **lst,*ep,**d;
+ int i,ln,s;
+ long idx;
+
+ if(!dst) return M_OPT_PARSER_ERR;
+ lst = VAL(dst);
+
+ for(ln = 0 ; lst && lst[ln] ; ln++)
+ /**/;
+ s = ln;
+
+ for(i = 0 ; del[i] != NULL ; i++) {
+ idx = strtol(del[i], &ep, 0);
+ if(*ep) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid index: %s\n",del[i]);
+ free(del[i]);
+ continue;
+ }
+ free(del[i]);
+ if(idx < 0 || idx >= ln) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Index %d is out of range\n",idx);
+ continue;
+ } else if(!lst[idx])
+ continue;
+ free(lst[idx]);
+ lst[idx] = NULL;
+ s--;
+ }
+ free(del);
+
+ if(s == 0) {
+ if(lst) free(lst);
+ VAL(dst) = NULL;
+ return 1;
+ }
+
+ d = calloc(s+1,sizeof(char*));
+ for(i = 0, n = 0 ; i < ln ; i++) {
+ if(!lst[i]) continue;
+ d[n] = lst[i];
+ n++;
+ }
+ d[s] = NULL;
+
+ if(lst) free(lst);
+ VAL(dst) = d;
+
+ return 1;
+}
+
+
+static int parse_str_list(m_option_t* opt,char *name, char *param, void* dst, int src) {
+ int n = 0,len = strlen(opt->name);
+ char *ptr = param, *last_ptr, **res;
+ int op = OP_NONE;
+
+ if(opt->name[len-1] == '*' && ((int)strlen(name) > len - 1)) {
+ char* n = &name[len-1];
+ if(strcasecmp(n,"-add") == 0)
+ op = OP_ADD;
+ else if(strcasecmp(n,"-pre") == 0)
+ op = OP_PRE;
+ else if(strcasecmp(n,"-del") == 0)
+ op = OP_DEL;
+ else if(strcasecmp(n,"-clr") == 0)
+ op = OP_CLR;
+ else
+ return M_OPT_UNKNOW;
+ }
+
+ // Clear the list ??
+ if(op == OP_CLR) {
+ if(dst)
+ free_str_list(dst);
+ return 0;
+ }
+
+ // All other op need a param
+ if (param == NULL || strlen(param) == 0)
+ return M_OPT_MISSING_PARAM;
+
+
+ while(ptr[0] != '\0') {
+ last_ptr = ptr;
+ ptr = strchr(ptr,LIST_SEPARATOR);
+ if(!ptr) {
+ n++;
+ break;
+ }
+ ptr++;
+ n++;
+ }
+ if(n == 0)
+ return M_OPT_INVALID;
+ if( ((opt->flags & M_OPT_MIN) && (n < opt->min)) ||
+ ((opt->flags & M_OPT_MAX) && (n > opt->max)) )
+ return M_OPT_OUT_OF_RANGE;
+
+ if(!dst) return 1;
+
+ res = malloc((n+1)*sizeof(char*));
+ ptr = param;
+ n = 0;
+
+ while(1) {
+ last_ptr = ptr;
+ ptr = strchr(ptr,LIST_SEPARATOR);
+ if(!ptr) {
+ res[n] = strdup(last_ptr);
+ n++;
+ break;
+ }
+ len = ptr - last_ptr;
+ res[n] = (char*)malloc(len + 1);
+ if(len) strncpy(res[n],last_ptr,len);
+ res[n][len] = '\0';
+ ptr++;
+ n++;
+ }
+ res[n] = NULL;
+
+ switch(op) {
+ case OP_ADD:
+ return str_list_add(res,n,dst,0);
+ case OP_PRE:
+ return str_list_add(res,n,dst,1);
+ case OP_DEL:
+ return str_list_del(res,n,dst);
+ }
+
+ if(VAL(dst))
+ free_str_list(dst);
+ VAL(dst) = res;
+
+ return 1;
+}
+
+static void copy_str_list(m_option_t* opt,void* dst, void* src) {
+ int n;
+ char **d,**s;
+
+ if(!(dst && src)) return;
+ s = VAL(src);
+
+ if(VAL(dst))
+ free_str_list(dst);
+
+ if(!s) {
+ VAL(dst) = NULL;
+ return;
+ }
+
+ for(n = 0 ; s[n] != NULL ; n++)
+ /* NOTHING */;
+ d = (char**)malloc((n+1)*sizeof(char*));
+ for( ; n >= 0 ; n--)
+ d[n] = s[n] ? strdup(s[n]) : NULL;
+
+ VAL(dst) = d;
+}
+
+static char* print_str_list(m_option_t* opt, void* src) {
+ return strdup("TODO ;)");
+}
+
+m_option_type_t m_option_type_string_list = {
+ "String list",
+ "A list of string separated by ','\n"
+ "Option with name that finish by an * allow to use the following suffix : \n"
+ "\t-add : add the given parameters at the end of list\n"
+ "\t-pre : add the given parameters at the begining of list\n"
+ "\t-del : remove the entry at the given indexs\n"
+ "\t-clr : clear the list\n"
+ "e.g: -vop-add flip,mirror -vop-del 2,5\n",
+ sizeof(char**),
+ M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD,
+ parse_str_list,
+ print_str_list,
+ copy_str_list,
+ copy_str_list,
+ copy_str_list,
+ free_str_list
+};
+
+
+/////////////////// Func based options
+
+// A chained list to save the various calls for func_param and func_full
+typedef struct m_func_save m_func_save_t;
+struct m_func_save {
+ m_func_save_t* next;
+ char* name;
+ char* param;
+};
+
+#undef VAL
+#define VAL(x) (*(m_func_save_t**)(x))
+
+static void free_func_pf(void* src) {
+ m_func_save_t *s,*n;
+
+ if(!src) return;
+
+ s = VAL(src);
+
+ while(s) {
+ n = s->next;
+ free(s->name);
+ if(s->param) free(s->param);
+ free(s);
+ s = n;
+ }
+ VAL(src) = NULL;
+}
+
+// Parser for func_param and func_full
+static int parse_func_pf(m_option_t* opt,char *name, char *param, void* dst, int src) {
+ m_func_save_t *s,*p;
+
+ if(!dst)
+ return 1;
+
+ s = (m_func_save_t*)calloc(1,sizeof(m_func_save_t));
+ s->name = strdup(name);
+ s->param = param ? strdup(param) : NULL;
+
+ p = VAL(dst);
+ if(p) {
+ for( ; p->next != NULL ; p = p->next)
+ /**/;
+ p->next = s;
+ } else
+ VAL(dst) = s;
+
+ return 1;
+}
+
+static void copy_func_pf(m_option_t* opt,void* dst, void* src) {
+ m_func_save_t *d = NULL, *s,* last = NULL;
+
+ if(!(dst && src)) return;
+ s = VAL(src);
+
+ if(VAL(dst))
+ free_func_pf(dst);
+
+ while(s) {
+ d = (m_func_save_t*)malloc(sizeof(m_func_save_t));
+ d->name = strdup(s->name);
+ d->param = s->param ? strdup(s->param) : NULL;
+ if(last)
+ last->next = d;
+ else
+ VAL(dst) = d;
+ last = d;
+ s = s->next;
+ }
+
+
+}
+
+/////////////////// Func_param
+
+static void set_func_param(m_option_t* opt, void* dst, void* src) {
+ m_func_save_t* s;
+
+ if(!src) return;
+ s = VAL(src);
+
+ if(!s) return;
+
+ // Revert if needed
+ if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,opt->name);
+ for( ; s != NULL ; s = s->next)
+ ((m_opt_func_param_t) opt->p)(opt,s->param);
+}
+
+m_option_type_t m_option_type_func_param = {
+ "Func param",
+ "",
+ sizeof(m_func_save_t*),
+ M_OPT_TYPE_INDIRECT,
+ parse_func_pf,
+ NULL,
+ NULL, // Nothing to do on save
+ set_func_param,
+ copy_func_pf,
+ free_func_pf
+};
+
+/////////////////// Func_full
+
+static void set_func_full(m_option_t* opt, void* dst, void* src) {
+ m_func_save_t* s;
+
+ if(!src) return;
+
+ for(s = VAL(src) ; s ; s = s->next) {
+ // Revert if needed
+ if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,s->name);
+ ((m_opt_func_full_t) opt->p)(opt,s->name,s->param);
+ }
+}
+
+m_option_type_t m_option_type_func_full = {
+ "Func full",
+ "",
+ sizeof(m_func_save_t*),
+ M_OPT_TYPE_ALLOW_WILDCARD|M_OPT_TYPE_INDIRECT,
+ parse_func_pf,
+ NULL,
+ NULL, // Nothing to do on save
+ set_func_full,
+ copy_func_pf,
+ free_func_pf
+};
+
+/////////////// Func
+
+#undef VAL
+#define VAL(x) (*(int*)(x))
+
+static int parse_func(m_option_t* opt,char *name, char *param, void* dst, int src) {
+ if(dst)
+ VAL(dst) += 1;
+ return 0;
+}
+
+static void set_func(m_option_t* opt,void* dst, void* src) {
+ int i;
+ if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,opt->name);
+ for(i = 0 ; i < VAL(src) ; i++)
+ ((m_opt_func_t) opt->p)(opt);
+}
+
+m_option_type_t m_option_type_func = {
+ "Func",
+ "",
+ sizeof(int),
+ M_OPT_TYPE_INDIRECT,
+ parse_func,
+ NULL,
+ NULL, // Nothing to do on save
+ set_func,
+ NULL,
+ NULL
+};
+
+/////////////////// Print
+
+static int parse_print(m_option_t* opt,char *name, char *param, void* dst, int src) {
+ mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", (char *) opt->p);
+ if(opt->priv == NULL)
+ exit(1); // Call something else instead ??
+ return 1;
+}
+
+m_option_type_t m_option_type_print = {
+ "Print",
+ "",
+ 0,
+ 0,
+ parse_print,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/////////////////////// Subconfig
+#undef VAL
+#define VAL(x) (*(char***)(x))
+
+static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int src) {
+ char *subparam;
+ char *subopt;
+ int nr = 0;
+ m_option_t *subopts;
+ char *token;
+ char *p;
+ char** lst = NULL;
+
+ if (param == NULL || strlen(param) == 0)
+ return M_OPT_MISSING_PARAM;
+
+ subparam = malloc(strlen(param)+1);
+ subopt = malloc(strlen(param)+1);
+ p = strdup(param); // In case that param is a static string (cf man strtok)
+
+ subopts = opt->p;
+
+ token = strtok(p, (char *)&(":"));
+ while(token)
+ {
+ int sscanf_ret;
+ /* clear out */
+ subopt[0] = subparam[0] = 0;
+
+ sscanf_ret = sscanf(token, "%[^=]=%[^:]", subopt, subparam);
+
+ 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(dst) {
+ lst = (char**)realloc(lst,2 * (nr+2) * sizeof(char*));
+ lst[2*nr] = strdup(subopt);
+ lst[2*nr+1] = subparam[0] == 0 ? NULL : strdup(subparam);
+ memset(&lst[2*(nr+1)],0,2*sizeof(char*));
+ nr++;
+ }
+ break;
+ default:
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid subconfig argument! ('%s')\n", token);
+ return M_OPT_INVALID;
+ }
+ token = strtok(NULL, (char *)&(":"));
+ }
+
+ free(subparam);
+ free(subopt);
+ free(p);
+ VAL(dst) = lst;
+
+ return 1;
+}
+
+m_option_type_t m_option_type_subconfig = {
+ "Subconfig",
+ "The syntax is -option opt1=foo:flag:opt2=blah",
+ sizeof(int),
+ M_OPT_TYPE_HAS_CHILD,
+ parse_subconf,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+#include "libmpcodecs/img_format.h"
+// TODO : use an array so we parse/print easily
+
+static int parse_imgfmt(m_option_t* opt,char *name, char *param, void* dst, int src) {
+ uint32_t fmt = 0;
+
+ if (param == NULL || strlen(param) == 0)
+ return M_OPT_MISSING_PARAM;
+
+ // From vf_format
+ if(!strcasecmp(param,"444p")) fmt=IMGFMT_444P; else
+ if(!strcasecmp(param,"422p")) fmt=IMGFMT_422P; else
+ if(!strcasecmp(param,"411p")) fmt=IMGFMT_411P; else
+ if(!strcasecmp(param,"yuy2")) fmt=IMGFMT_YUY2; else
+ if(!strcasecmp(param,"yv12")) fmt=IMGFMT_YV12; else
+ if(!strcasecmp(param,"i420")) fmt=IMGFMT_I420; else
+ if(!strcasecmp(param,"yvu9")) fmt=IMGFMT_YVU9; else
+ if(!strcasecmp(param,"if09")) fmt=IMGFMT_IF09; else
+ if(!strcasecmp(param,"iyuv")) fmt=IMGFMT_IYUV; else
+ if(!strcasecmp(param,"uyvy")) fmt=IMGFMT_UYVY; else
+ if(!strcasecmp(param,"bgr24")) fmt=IMGFMT_BGR24; else
+ if(!strcasecmp(param,"bgr32")) fmt=IMGFMT_BGR32; else
+ if(!strcasecmp(param,"bgr16")) fmt=IMGFMT_BGR16; else
+ if(!strcasecmp(param,"bgr15")) fmt=IMGFMT_BGR15; else
+ if(!strcasecmp(param,"bgr8")) fmt=IMGFMT_BGR8; else
+ if(!strcasecmp(param,"bgr4")) fmt=IMGFMT_BGR4; else
+ if(!strcasecmp(param,"bgr1")) fmt=IMGFMT_BGR1; else
+ if(!strcasecmp(param,"rgb24")) fmt=IMGFMT_RGB24; else
+ if(!strcasecmp(param,"rgb32")) fmt=IMGFMT_RGB32; else
+ if(!strcasecmp(param,"rgb16")) fmt=IMGFMT_RGB16; else
+ if(!strcasecmp(param,"rgb15")) fmt=IMGFMT_RGB15; else
+ if(!strcasecmp(param,"rgb8")) fmt=IMGFMT_RGB8; else
+ if(!strcasecmp(param,"rgb4")) fmt=IMGFMT_RGB4; else
+ if(!strcasecmp(param,"rgb1")) fmt=IMGFMT_RGB1; else {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: unknown format name: '%s'\n",param);
+ return M_OPT_INVALID;
+ }
+
+ if(dst)
+ *((uint32_t*)dst) = fmt;
+
+ return 1;
+}
+
+m_option_type_t m_option_type_imgfmt = {
+ "Image format (aka colorspace)",
+ "Pls report any missing colorspace",
+ sizeof(uint32_t),
+ 0,
+ parse_imgfmt,
+ NULL,
+ copy_opt,
+ copy_opt,
+ NULL,
+ NULL
+};
+
+/// Span stuff : Not finished
+static int parse_play_pos(m_play_pos_t* pos,char* opt, char *s) {
+ char *ep;
+ long tmp;
+ int i;
+
+ memset(pos,0,sizeof(m_play_pos_t));
+
+ if(!s || s[0] == '\0')
+ return M_OPT_MISSING_PARAM;
+
+ // Track index
+ tmp = strtol(s, &ep, 0);
+ if(ep != s) {
+ if(tmp < 1) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Track/Chapter index must be > 0\n", opt);
+ return M_OPT_OUT_OF_RANGE;
+ }
+ pos->idx = tmp;
+ if(ep[0] == '\0')
+ return 1;
+ s = ep;
+ }
+
+ // Span
+ tmp = strlen(s);
+ if(s[0] != '[' || s[tmp-1] != ']') {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt);
+ return M_OPT_INVALID;
+ }
+ s[tmp-1] = '\0';
+ s++;
+
+ // hh:mm:ss
+ for( i = 2 ; i >= 0 && s[0] != 0 ; i--) {
+ if(s[0] == ':') {
+ tmp = 0;
+ s++;
+ } else {
+ tmp = strtol(s, &ep, 0);
+ if(tmp < 0 || (ep[0] != '\0' && ep[0] != (i > 0 ? ':' : '.') )) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt);
+ return M_OPT_INVALID;
+ }
+ pos->seconds += tmp * pow(60,i);
+ s = ep;
+ if(s[0] != '\0')
+ s++;
+
+ }
+ }
+
+ // sectors
+ if(s[0]) {
+ tmp = strtol(s, &ep, 0);
+ if(tmp < 0 || ep[0] != '\0') {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt);
+ return M_OPT_INVALID;
+ }
+ pos->sectors = tmp;
+ }
+
+ return 1;
+}
+
+
+static int parse_span(m_option_t* opt,char *name, char *param, void* dst, int src) {
+ m_span_t* span = dst;
+ char *s = param,*e = NULL;
+ int r = M_OPT_INVALID;
+
+ if(param == NULL)
+ return M_OPT_MISSING_PARAM;
+
+ e = strchr(param,'-');
+ if(e) {
+ e[0] = '\0';
+ e++;
+ }
+
+ if(s[0] == '\0' && e[0] == '\0') {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument\n");
+ return M_OPT_INVALID;
+ }
+
+ if(s[0]) {
+ r = parse_play_pos(&span->start,name,s);
+ if(r < 0) return r;
+ }
+ if(e && e[0] != '\0')
+ r = parse_play_pos(&span->end,name,s);
+
+ return r;
+}
+
+m_option_type_t m_option_type_span = {
+ "Span",
+ "The syntax is 1[hh:mm:ss.zz]-5[hh:mm:ss.zz]",
+ sizeof(m_span_t),
+ 0,
+ parse_span,
+ NULL,
+ copy_opt,
+ copy_opt,
+ NULL,
+ NULL
+};
+
+#endif