From 126725660d4bebbab8570221c5681dc01d98fe86 Mon Sep 17 00:00:00 2001 From: albeu Date: Tue, 12 Nov 2002 01:56:42 +0000 Subject: New config system + cleanup of header inter dependency git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8165 b3059339-0415-0410-9bf9-f77b7e298cf2 --- m_option.c | 1008 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1008 insertions(+) create mode 100644 m_option.c (limited to 'm_option.c') 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 +#include +#include +#include +#include +#include + +#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 -- cgit v1.2.3