diff options
Diffstat (limited to 'm_option.c')
-rw-r--r-- | m_option.c | 444 |
1 files changed, 436 insertions, 8 deletions
diff --git a/m_option.c b/m_option.c index 418214a989..f623047621 100644 --- a/m_option.c +++ b/m_option.c @@ -15,6 +15,26 @@ //#include "m_config.h" #include "mp_msg.h" +// Don't free for 'production' atm +#ifndef MP_DEBUG +#define NO_FREE +#endif + +m_option_t* m_option_list_find(m_option_t* list,char* name) { + int i; + + for(i = 0 ; list[i].name ; i++) { + int l = strlen(list[i].name) - 1; + if((list[i].type->flags & M_OPT_TYPE_ALLOW_WILDCARD) && + (l > 0) && (list[i].name[l] == '*')) { + if(strncasecmp(list[i].name,name,l) == 0) + return &list[i]; + } else if(strcasecmp(list[i].name,name) == 0) + return &list[i]; + } + return NULL; +} + // Default function that just do a memcpy static void copy_opt(m_option_t* opt,void* dst,void* src) { @@ -321,14 +341,18 @@ static char* print_str(m_option_t* opt, void* val) { static void copy_str(m_option_t* opt,void* dst, void* src) { if(dst && src) { -// if(VAL(dst)) free(VAL(dst)); //FIXME!!! +#ifndef NO_FREE + if(VAL(dst)) free(VAL(dst)); //FIXME!!! +#endif VAL(dst) = VAL(src) ? strdup(VAL(src)) : NULL; } } static void free_str(void* src) { - if(src && VAL(src)){ -// free(VAL(src)); //FIXME!!! + if(src && VAL(src)){ +#ifndef NO_FREE + free(VAL(src)); //FIXME!!! +#endif VAL(src) = NULL; } } @@ -366,9 +390,11 @@ static void free_str_list(void* dst) { d = VAL(dst); // FIXME!!! -// for(i = 0 ; d[i] != NULL ; i++) -// free(d[i]); -// free(d); +#ifndef NO_FREE + for(i = 0 ; d[i] != NULL ; i++) + free(d[i]); + free(d); +#endif VAL(dst) = NULL; } @@ -809,7 +835,7 @@ m_option_type_t m_option_type_print_indirect = { static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int src) { char *subparam; char *subopt; - int nr = 0; + int nr = 0,i,r; m_option_t *subopts; char *token; char *p; @@ -839,6 +865,16 @@ static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int case 1: subparam[0] = 0; case 2: + for(i = 0 ; subopts[i].name ; i++) { + if(!strcmp(subopts[i].name,subopt)) break; + } + if(!subopts[i].name) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Unknow suboption %s\n",name,subopt); + return M_OPT_UNKNOW; + } + r = m_option_parse(&subopts[i],subopt, + subparam[0] == 0 ? NULL : subparam,NULL,src); + if(r < 0) return r; if(dst) { lst = (char**)realloc(lst,2 * (nr+2) * sizeof(char*)); lst[2*nr] = strdup(subopt); @@ -857,7 +893,8 @@ static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int free(subparam); free(subopt); free(p); - VAL(dst) = lst; + if(dst) + VAL(dst) = lst; return 1; } @@ -1040,4 +1077,395 @@ m_option_type_t m_option_type_span = { NULL }; + +//// Objects (ie filters, etc) settings + +#include "m_struct.h" + +#undef VAL +#define VAL(x) (*(m_obj_settings_t**)(x)) + +static int find_obj_desc(char* name,m_obj_list_t* l,m_struct_t** ret) { + int i; + char* n; + + for(i = 0 ; l->list[i] ; i++) { + n = M_ST_MB(char*,l->list[i],l->name_off); + if(!strcmp(n,name)) { + *ret = M_ST_MB(m_struct_t*,l->list[i],l->desc_off); + return 1; + } + } + return 0; +} + +static int get_obj_param(char* opt_name,char* obj_name, m_struct_t* desc, + char* str,int* nold,int oldmax,char** dst) { + char* eq,param; + m_option_t* opt; + int r; + + eq = strchr(str,'='); + if(eq && eq == str) + eq = NULL; + + if(eq) { + char* p = eq + 1; + if(p[0] == '\0') p = NULL; + eq[0] = '\0'; + opt = m_option_list_find(desc->fields,str); + if(!opt) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: %s doesn't have a %s parameter\n",opt_name,obj_name,str); + return M_OPT_UNKNOW; + } + r = m_option_parse(opt,str,p,NULL,M_CONFIG_FILE); + if(r < 0) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: error while parsing %s parameter %s (%s)\n",opt_name,obj_name,str,p); + eq[0] = '='; + return r; + } + if(dst) { + dst[0] = strdup(str); + dst[1] = p ? strdup(p) : NULL; + } + eq[0] = '='; + } else { + if((*nold) >= oldmax) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: %s have only %d params, so yon can't give more than that unnamed params\n", + opt_name,obj_name,oldmax); + return M_OPT_OUT_OF_RANGE; + } + opt = &desc->fields[(*nold)]; + r = m_option_parse(opt,opt->name,str,NULL,M_CONFIG_FILE); + if(r < 0) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: error while parsing %s parameter %s (%s)\n",opt_name,obj_name,opt->name,str); + return r; + } + if(dst) { + dst[0] = strdup(opt->name); + dst[1] = strdup(str); + } + (*nold)++; + } + return 1; +} + +static int get_obj_params(char* opt_name, char* name,char* params, + m_struct_t* desc,char*** _ret) { + int n = 0,nold = 0, nopts,r; + char* ptr,*last_ptr = params,*eq; + char** ret; + + if(!strcmp(params,"help")) { // Help + char min[50],max[50]; + if(!desc->fields) { + printf("%s doesn't have any options\n\n",name); + //exit_player(); + exit(0); + } + printf("\n Name Type Min Max\n\n"); + for(n = 0 ; desc->fields[n].name ; n++) { + m_option_t* opt = &desc->fields[n]; + if(opt->type->flags & M_OPT_TYPE_HAS_CHILD) continue; + if(opt->flags & M_OPT_MIN) + sprintf(min,"%-8.0f",opt->min); + else + strcpy(min,"No"); + if(opt->flags & M_OPT_MAX) + sprintf(max,"%-8.0f",opt->max); + else + strcpy(max,"No"); + printf(" %-20.20s %-15.15s %-10.10s %-10.10s\n", + opt->name, + opt->type->name, + min, + max); + } + printf("\n"); + //exit_player() isn't avaible in mencoder + exit(0); + } + + for(nopts = 0 ; desc->fields[nopts].name ; nopts++) + /* NOP */; + + // TODO : Check that each opt can be parsed + r = 1; + while(last_ptr && last_ptr[0] != '\0') { + ptr = strchr(last_ptr,':'); + if(!ptr) { + r = get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,NULL); + n++; + break; + } + ptr[0] = '\0'; + r = get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,NULL); + ptr[0] = ':'; + if(r < 0) break; + n++; + last_ptr = ptr+1; + } + if(r < 0) return r; + if(!_ret) // Just test + return 1; + + ret = malloc((n+2)*2*sizeof(char*)); + n = nold = 0; + last_ptr = params; + + while(last_ptr && last_ptr[0] != '\0') { + ptr = strchr(last_ptr,':'); + if(!ptr) { + get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,&ret[n*2]); + n++; + break; + } + ptr[0] = '\0'; + get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,&ret[n*2]); + n++; + last_ptr = ptr+1; + } + ret[n*2] = ret[n*2+1] = NULL; + *_ret = ret; + + return 1; +} + + +static int parse_obj_settings(char* opt,char* str,m_obj_list_t* list, + m_obj_settings_t **_ret, int ret_n) { + int r; + char *param,**plist = NULL; + m_struct_t* desc; + m_obj_settings_t *ret = _ret ? *_ret : NULL; + + + // Now check that the object exist + param = strchr(str,'='); + if(param) { + param[0] = '\0'; + param++; + if(strlen(param) <= 0) + param = NULL; + } + + + if(!find_obj_desc(str,list,&desc)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: %s doesn't exist\n",opt,str); + return M_OPT_INVALID; + } + + if(param) { + if(!desc && _ret) { + plist = calloc(4,sizeof(char*)); + plist[0] = strdup("_oldargs_"); + plist[1] = strdup(param); + } else if(desc) { + r = get_obj_params(opt,str,param,desc,_ret ? &plist : NULL); + if(r < 0) + return r; + } + } + if(!_ret) + return 1; + + ret = realloc(ret,(ret_n+2)*sizeof(m_obj_settings_t)); + memset(&ret[ret_n],0,2*sizeof(m_obj_settings_t)); + ret[ret_n].name = strdup(str); + ret[ret_n].attribs = plist; + + *_ret = ret; + return 1; +} + + +static int parse_obj_settings_list(m_option_t* opt,char *name, + char *param, void* dst, int src) { + int n = 0,r; + char *str; + char *ptr, *last_ptr; + m_obj_settings_t *res = NULL; + + // We need the objects list + if(!opt->priv) + return M_OPT_INVALID; + + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; + + if(!strcmp(param,"help")) { + m_obj_list_t* ol = opt->priv; + for(n = 0 ; ol->list[n] ; n++) + mp_msg(MSGT_VFILTER,MSGL_INFO," %-15s: %s\n", + M_ST_MB(char*,ol->list[n],ol->name_off), + M_ST_MB(char*,ol->list[n],ol->info_off)); + exit(0); + } + ptr = str = strdup(param); + + while(ptr[0] != '\0') { + last_ptr = ptr; + ptr = strchr(ptr,LIST_SEPARATOR); + if(!ptr) { + r = parse_obj_settings(name,last_ptr,opt->priv,dst ? &res : NULL,n); + if(r < 0) { + free(str); + return r; + } + n++; + break; + } + ptr[0] = '\0'; + r = parse_obj_settings(name,last_ptr,opt->priv,dst ? &res : NULL,n); + if(r < 0) { + free(str); + return r; + } + ptr++; + n++; + } + free(str); + 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) + VAL(dst) = res; + + return 1; +} + +static void free_obj_settings_list(void* dst) { + int n; + m_obj_settings_t *d; + + if(!dst || !VAL(dst)) return; + + d = VAL(dst); +#ifndef NO_FREE + for(n = 0 ; d[n].name ; n++) { + free(d[n].name); + free_str_list(&(d[n].attribs)); + } + free(d); +#endif + VAL(dst) = NULL; +} + +static void copy_obj_settings_list(m_option_t* opt,void* dst, void* src) { + m_obj_settings_t *d,*s; + int n; + + if(!(dst && src)) + return; + + s = VAL(src); + + if(VAL(dst)) + free_obj_settings_list(dst); + if(!s) return; + + + + for(n = 0 ; s[n].name ; n++) + /* NOP */; + d = malloc((n+1)*sizeof(m_obj_settings_t)); + for(n = 0 ; s[n].name ; n++) { + d[n].name = strdup(s[n].name); + d[n].attribs = NULL; + copy_str_list(NULL,&(d[n].attribs),&(s[n].attribs)); + } + d[n].name = d[n].attribs = NULL; + VAL(dst) = d; +} + +m_option_type_t m_option_type_obj_settings_list = { + "Object settings list", + "", + sizeof(m_obj_settings_t*), + M_OPT_TYPE_DYNAMIC, + parse_obj_settings_list, + NULL, + copy_obj_settings_list, + copy_obj_settings_list, + copy_obj_settings_list, + free_obj_settings_list, +}; + + + +static int parse_obj_presets(m_option_t* opt,char *name, + char *param, void* dst, int src) { + m_obj_presets_t* obj_p = (m_obj_presets_t*)opt->priv; + m_struct_t *in_desc,*out_desc; + int s,i; + unsigned char* pre = obj_p->presets; + char* pre_name = NULL; + + if(!obj_p) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: presets need a pointer to a m_obj_presets_t in the priv field\n",name); + return M_OPT_PARSER_ERR; + } + + if(!param) + return M_OPT_MISSING_PARAM; + + in_desc = obj_p->in_desc; + out_desc = obj_p->out_desc ? obj_p->out_desc : obj_p->in_desc; + s = in_desc->size; + + if(!strcmp(param,"help")) { + mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Avaible presets for %s->%s :",out_desc->name,name); + for(pre = obj_p->presets;(pre_name = M_ST_MB(char*,pre,obj_p->name_off)) ; + pre += s) + mp_msg(MSGT_CFGPARSER, MSGL_ERR, " %s",pre_name); + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "\n"); + exit(0); + } + + for(pre_name = M_ST_MB(char*,pre,obj_p->name_off) ; pre_name ; + pre += s, pre_name = M_ST_MB(char*,pre,obj_p->name_off)) { + if(!strcmp(pre_name,param)) break; + } + if(!pre_name) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: there no preset named %s\n" + "Avaible presets are :",name,param); + for(pre = obj_p->presets;(pre_name = M_ST_MB(char*,pre,obj_p->name_off)) ; + pre += s) + mp_msg(MSGT_CFGPARSER, MSGL_ERR, " %s",pre_name); + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "\n"); + return M_OPT_INVALID; + } + + if(!dst) return 1; + + for(i = 0 ; in_desc->fields[i].name ; i++) { + m_option_t* out_opt = m_option_list_find(out_desc->fields, + in_desc->fields[i].name); + if(!out_opt) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: unable to find the target option for field %s.\nYou should report that to the developpers\n",name,in_desc->fields[i].name); + return M_OPT_PARSER_ERR; + } + m_option_copy(out_opt,M_ST_MB_P(dst,out_opt->p),M_ST_MB_P(pre,in_desc->fields[i].p)); + } + return 1; +} + + +m_option_type_t m_option_type_obj_presets = { + "Object presets", + "", + 0, + 0, + parse_obj_presets, + NULL, + NULL, + NULL, + NULL, + NULL +}; + #endif |