Mercurial > mplayer.hg
comparison m_option.c @ 8164:487cfc28525d
New config system + cleanup of header inter dependency
author | albeu |
---|---|
date | Tue, 12 Nov 2002 01:56:42 +0000 |
parents | |
children | ff6a98628e6c |
comparison
equal
deleted
inserted
replaced
8163:51e5033ee687 | 8164:487cfc28525d |
---|---|
1 | |
2 #include "config.h" | |
3 | |
4 #ifdef NEW_CONFIG | |
5 | |
6 #include <stdlib.h> | |
7 #include <string.h> | |
8 #include <math.h> | |
9 #include <stdio.h> | |
10 #include <stdarg.h> | |
11 #include <inttypes.h> | |
12 | |
13 #include "m_option.h" | |
14 //#include "m_config.h" | |
15 #include "mp_msg.h" | |
16 | |
17 // Default function that just do a memcpy | |
18 | |
19 static void copy_opt(m_option_t* opt,void* dst,void* src) { | |
20 if(dst && src) | |
21 memcpy(dst,src,opt->type->size); | |
22 } | |
23 | |
24 // Helper for the print funcs (from man printf) | |
25 static char* dup_printf(const char *fmt, ...) { | |
26 /* Guess we need no more than 50 bytes. */ | |
27 int n, size = 50; | |
28 char *p; | |
29 va_list ap; | |
30 if ((p = malloc (size)) == NULL) | |
31 return NULL; | |
32 while (1) { | |
33 /* Try to print in the allocated space. */ | |
34 va_start(ap, fmt); | |
35 n = vsnprintf (p, size, fmt, ap); | |
36 va_end(ap); | |
37 /* If that worked, return the string. */ | |
38 if (n > -1 && n < size) | |
39 return p; | |
40 /* Else try again with more space. */ | |
41 if (n > -1) /* glibc 2.1 */ | |
42 size = n+1; /* precisely what is needed */ | |
43 else /* glibc 2.0 */ | |
44 size *= 2; /* twice the old size */ | |
45 if ((p = realloc (p, size)) == NULL) | |
46 return NULL; | |
47 } | |
48 } | |
49 | |
50 | |
51 // Flag | |
52 | |
53 #define VAL(x) (*(int*)(x)) | |
54 | |
55 static int parse_flag(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
56 if (src == M_CONFIG_FILE) { | |
57 if (!strcasecmp(param, "yes") || /* any other language? */ | |
58 !strcasecmp(param, "ja") || | |
59 !strcasecmp(param, "si") || | |
60 !strcasecmp(param, "igen") || | |
61 !strcasecmp(param, "y") || | |
62 !strcasecmp(param, "j") || | |
63 !strcasecmp(param, "i") || | |
64 !strcmp(param, "1")) { | |
65 if(dst) VAL(dst) = opt->max; | |
66 } else if (!strcasecmp(param, "no") || | |
67 !strcasecmp(param, "nein") || | |
68 !strcasecmp(param, "nicht") || | |
69 !strcasecmp(param, "nem") || | |
70 !strcasecmp(param, "n") || | |
71 !strcmp(param, "0")) { | |
72 if(dst) VAL(dst) = opt->min; | |
73 } else { | |
74 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid parameter for %s flag: %s\n",name, param); | |
75 return M_OPT_INVALID; | |
76 } | |
77 return 1; | |
78 } else { | |
79 if(dst) VAL(dst) = opt->max; | |
80 return 0; | |
81 } | |
82 } | |
83 | |
84 static char* print_flag(m_option_t* opt, void* val) { | |
85 if(VAL(val) == opt->min) | |
86 return strdup("no"); | |
87 else | |
88 return strdup("yes"); | |
89 } | |
90 | |
91 m_option_type_t m_option_type_flag = { | |
92 "Flag", | |
93 "need yes or no in config files", | |
94 sizeof(int), | |
95 0, | |
96 parse_flag, | |
97 print_flag, | |
98 copy_opt, | |
99 copy_opt, | |
100 NULL, | |
101 NULL | |
102 }; | |
103 | |
104 // Integer | |
105 | |
106 static int parse_int(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
107 long tmp_int; | |
108 char *endptr; | |
109 src = 0; | |
110 | |
111 if (param == NULL) | |
112 return M_OPT_MISSING_PARAM; | |
113 | |
114 tmp_int = strtol(param, &endptr, 0); | |
115 if (*endptr) { | |
116 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be an integer: %s\n",name, param); | |
117 return M_OPT_INVALID; | |
118 } | |
119 | |
120 if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) { | |
121 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be >= %d: %s\n", name, (int) opt->min, param); | |
122 return M_OPT_OUT_OF_RANGE; | |
123 } | |
124 | |
125 if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) { | |
126 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be <= %d: %s\n",name, (int) opt->max, param); | |
127 return M_OPT_OUT_OF_RANGE; | |
128 } | |
129 | |
130 if(dst) VAL(dst) = tmp_int; | |
131 | |
132 return 1; | |
133 } | |
134 | |
135 static char* print_int(m_option_t* opt, void* val) { | |
136 opt = NULL; | |
137 return dup_printf("%d",VAL(val)); | |
138 } | |
139 | |
140 m_option_type_t m_option_type_int = { | |
141 "Integer", | |
142 "", | |
143 sizeof(int), | |
144 0, | |
145 parse_int, | |
146 print_int, | |
147 copy_opt, | |
148 copy_opt, | |
149 NULL, | |
150 NULL | |
151 }; | |
152 | |
153 // Float | |
154 | |
155 #undef VAL | |
156 #define VAL(x) (*(float*)(x)) | |
157 | |
158 static int parse_float(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
159 float tmp_float; | |
160 char* endptr; | |
161 src = 0; | |
162 | |
163 if (param == NULL) | |
164 return M_OPT_MISSING_PARAM; | |
165 | |
166 tmp_float = strtod(param, &endptr); | |
167 | |
168 switch(*endptr) { | |
169 case ':': | |
170 case '/': | |
171 tmp_float /= strtod(endptr+1, &endptr); | |
172 break; | |
173 case '.': | |
174 case ',': | |
175 /* we also handle floats specified with | |
176 * non-locale decimal point ::atmos | |
177 */ | |
178 if(tmp_float<0) | |
179 tmp_float -= 1.0/pow(10,strlen(endptr+1)) * strtod(endptr+1, &endptr); | |
180 else | |
181 tmp_float += 1.0/pow(10,strlen(endptr+1)) * strtod(endptr+1, &endptr); | |
182 break; | |
183 } | |
184 | |
185 if (*endptr) { | |
186 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be a floating point " | |
187 "number or a ratio (numerator[:/]denominator): %s\n",name, param); | |
188 return M_OPT_INVALID; | |
189 } | |
190 | |
191 if (opt->flags & M_OPT_MIN) | |
192 if (tmp_float < opt->min) { | |
193 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be >= %f: %s\n", name, opt->min, param); | |
194 return M_OPT_OUT_OF_RANGE; | |
195 } | |
196 | |
197 if (opt->flags & M_OPT_MAX) | |
198 if (tmp_float > opt->max) { | |
199 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be <= %f: %s\n", name, opt->max, param); | |
200 return M_OPT_OUT_OF_RANGE; | |
201 } | |
202 | |
203 if(dst) VAL(dst) = tmp_float; | |
204 return 1; | |
205 } | |
206 | |
207 static char* print_float(m_option_t* opt, void* val) { | |
208 opt = NULL; | |
209 return dup_printf("%f",VAL(val)); | |
210 } | |
211 | |
212 m_option_type_t m_option_type_float = { | |
213 "Float", | |
214 "floating point number or ratio (numerator[:/]denominator)", | |
215 sizeof(float), | |
216 0, | |
217 parse_float, | |
218 print_float, | |
219 copy_opt, | |
220 copy_opt, | |
221 NULL, | |
222 NULL | |
223 }; | |
224 | |
225 ///////////// Position | |
226 #undef VAL | |
227 #define VAL(x) (*(off_t*)(x)) | |
228 | |
229 static int parse_position(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
230 off_t tmp_off; | |
231 char dummy; | |
232 | |
233 if (param == NULL) | |
234 return M_OPT_MISSING_PARAM; | |
235 if (sscanf(param, sizeof(off_t) == sizeof(int) ? | |
236 "%d%c" : "%lld%c", &tmp_off, &dummy) != 1) { | |
237 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be an integer: %s\n",opt->name,param); | |
238 return M_OPT_INVALID; | |
239 } | |
240 | |
241 if (opt->flags & M_OPT_MIN) | |
242 if (tmp_off < opt->min) { | |
243 mp_msg(MSGT_CFGPARSER, MSGL_ERR, | |
244 (sizeof(off_t) == sizeof(int) ? | |
245 "The %s option must be >= %d: %s\n" : | |
246 "The %s option must be >= %lld: %s\n"), | |
247 (off_t) opt->min, param); | |
248 return M_OPT_OUT_OF_RANGE; | |
249 } | |
250 | |
251 if (opt->flags & M_OPT_MAX) | |
252 if (tmp_off > opt->max) { | |
253 mp_msg(MSGT_CFGPARSER, MSGL_ERR, | |
254 (sizeof(off_t) == sizeof(int) ? | |
255 "The %s option must be <= %d: %s\n" : | |
256 "The %s option must be <= %lld: %s\n"), | |
257 (off_t) opt->max, param); | |
258 return M_OPT_OUT_OF_RANGE; | |
259 } | |
260 | |
261 if(dst) | |
262 VAL(dst) = tmp_off; | |
263 return 1; | |
264 } | |
265 | |
266 static char* print_position(m_option_t* opt, void* val) { | |
267 return dup_printf(sizeof(off_t) == sizeof(int) ? "%d" : "%lld",VAL(val)); | |
268 } | |
269 | |
270 m_option_type_t m_option_type_position = { | |
271 "Position", | |
272 "Integer (off_t)", | |
273 sizeof(off_t), | |
274 0, | |
275 parse_position, | |
276 print_position, | |
277 copy_opt, | |
278 copy_opt, | |
279 NULL, | |
280 NULL | |
281 }; | |
282 | |
283 | |
284 ///////////// String | |
285 | |
286 #undef VAL | |
287 #define VAL(x) (*(char**)(x)) | |
288 | |
289 static int parse_str(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
290 | |
291 | |
292 if (param == NULL) | |
293 return M_OPT_MISSING_PARAM; | |
294 | |
295 if ((opt->flags & M_OPT_MIN) && (strlen(param) < opt->min)) { | |
296 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %d chars: %s\n", | |
297 (int) opt->min, param); | |
298 return M_OPT_OUT_OF_RANGE; | |
299 } | |
300 | |
301 if ((opt->flags & M_OPT_MAX) && (strlen(param) > opt->max)) { | |
302 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %d chars: %s\n", | |
303 (int) opt->max, param); | |
304 return M_OPT_OUT_OF_RANGE; | |
305 } | |
306 | |
307 if(dst) { | |
308 if(VAL(dst)) | |
309 free(VAL(dst)); | |
310 VAL(dst) = strdup(param); | |
311 } | |
312 | |
313 return 1; | |
314 | |
315 } | |
316 | |
317 static char* print_str(m_option_t* opt, void* val) { | |
318 return (val && VAL(val) && strlen(VAL(val)) > 0) ? strdup(VAL(val)) : strdup("(empty)"); | |
319 } | |
320 | |
321 static void copy_str(m_option_t* opt,void* dst, void* src) { | |
322 if(dst && src) { | |
323 if(VAL(dst)) free(VAL(dst)); | |
324 VAL(dst) = VAL(src) ? strdup(VAL(src)) : NULL; | |
325 } | |
326 } | |
327 | |
328 static void free_str(void* src) { | |
329 if(src && VAL(src)){ | |
330 free(VAL(src)); | |
331 VAL(src) = NULL; | |
332 } | |
333 } | |
334 | |
335 m_option_type_t m_option_type_string = { | |
336 "String", | |
337 "", | |
338 sizeof(char*), | |
339 M_OPT_TYPE_DYNAMIC, | |
340 parse_str, | |
341 print_str, | |
342 copy_str, | |
343 copy_str, | |
344 copy_str, | |
345 free_str | |
346 }; | |
347 | |
348 //////////// String list | |
349 | |
350 #define LIST_SEPARATOR ',' | |
351 #undef VAL | |
352 #define VAL(x) (*(char***)(x)) | |
353 | |
354 #define OP_NONE 0 | |
355 #define OP_ADD 1 | |
356 #define OP_PRE 2 | |
357 #define OP_DEL 3 | |
358 #define OP_CLR 4 | |
359 | |
360 static void free_str_list(void* dst) { | |
361 char** d; | |
362 int i; | |
363 | |
364 if(!dst || !VAL(dst)) return; | |
365 d = VAL(dst); | |
366 | |
367 | |
368 for(i = 0 ; d[i] != NULL ; i++) | |
369 free(d[i]); | |
370 free(d); | |
371 VAL(dst) = NULL; | |
372 } | |
373 | |
374 static int str_list_add(char** add, int n,void* dst,int pre) { | |
375 char** lst = VAL(dst); | |
376 int ln; | |
377 | |
378 if(!dst) return M_OPT_PARSER_ERR; | |
379 lst = VAL(dst); | |
380 | |
381 for(ln = 0 ; lst && lst[ln] ; ln++) | |
382 /**/; | |
383 | |
384 lst = realloc(lst,(n+ln+1)*sizeof(char*)); | |
385 | |
386 if(pre) { | |
387 memmove(&lst[n],lst,(ln+1)*sizeof(char*)); | |
388 memcpy(lst,add,n*sizeof(char*)); | |
389 } else | |
390 memcpy(&lst[ln],add,(n+1)*sizeof(char*)); | |
391 | |
392 free(add); | |
393 | |
394 VAL(dst) = lst; | |
395 | |
396 return 1; | |
397 } | |
398 | |
399 static int str_list_del(char** del, int n,void* dst) { | |
400 char **lst,*ep,**d; | |
401 int i,ln,s; | |
402 long idx; | |
403 | |
404 if(!dst) return M_OPT_PARSER_ERR; | |
405 lst = VAL(dst); | |
406 | |
407 for(ln = 0 ; lst && lst[ln] ; ln++) | |
408 /**/; | |
409 s = ln; | |
410 | |
411 for(i = 0 ; del[i] != NULL ; i++) { | |
412 idx = strtol(del[i], &ep, 0); | |
413 if(*ep) { | |
414 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid index: %s\n",del[i]); | |
415 free(del[i]); | |
416 continue; | |
417 } | |
418 free(del[i]); | |
419 if(idx < 0 || idx >= ln) { | |
420 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Index %d is out of range\n",idx); | |
421 continue; | |
422 } else if(!lst[idx]) | |
423 continue; | |
424 free(lst[idx]); | |
425 lst[idx] = NULL; | |
426 s--; | |
427 } | |
428 free(del); | |
429 | |
430 if(s == 0) { | |
431 if(lst) free(lst); | |
432 VAL(dst) = NULL; | |
433 return 1; | |
434 } | |
435 | |
436 d = calloc(s+1,sizeof(char*)); | |
437 for(i = 0, n = 0 ; i < ln ; i++) { | |
438 if(!lst[i]) continue; | |
439 d[n] = lst[i]; | |
440 n++; | |
441 } | |
442 d[s] = NULL; | |
443 | |
444 if(lst) free(lst); | |
445 VAL(dst) = d; | |
446 | |
447 return 1; | |
448 } | |
449 | |
450 | |
451 static int parse_str_list(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
452 int n = 0,len = strlen(opt->name); | |
453 char *ptr = param, *last_ptr, **res; | |
454 int op = OP_NONE; | |
455 | |
456 if(opt->name[len-1] == '*' && ((int)strlen(name) > len - 1)) { | |
457 char* n = &name[len-1]; | |
458 if(strcasecmp(n,"-add") == 0) | |
459 op = OP_ADD; | |
460 else if(strcasecmp(n,"-pre") == 0) | |
461 op = OP_PRE; | |
462 else if(strcasecmp(n,"-del") == 0) | |
463 op = OP_DEL; | |
464 else if(strcasecmp(n,"-clr") == 0) | |
465 op = OP_CLR; | |
466 else | |
467 return M_OPT_UNKNOW; | |
468 } | |
469 | |
470 // Clear the list ?? | |
471 if(op == OP_CLR) { | |
472 if(dst) | |
473 free_str_list(dst); | |
474 return 0; | |
475 } | |
476 | |
477 // All other op need a param | |
478 if (param == NULL || strlen(param) == 0) | |
479 return M_OPT_MISSING_PARAM; | |
480 | |
481 | |
482 while(ptr[0] != '\0') { | |
483 last_ptr = ptr; | |
484 ptr = strchr(ptr,LIST_SEPARATOR); | |
485 if(!ptr) { | |
486 n++; | |
487 break; | |
488 } | |
489 ptr++; | |
490 n++; | |
491 } | |
492 if(n == 0) | |
493 return M_OPT_INVALID; | |
494 if( ((opt->flags & M_OPT_MIN) && (n < opt->min)) || | |
495 ((opt->flags & M_OPT_MAX) && (n > opt->max)) ) | |
496 return M_OPT_OUT_OF_RANGE; | |
497 | |
498 if(!dst) return 1; | |
499 | |
500 res = malloc((n+1)*sizeof(char*)); | |
501 ptr = param; | |
502 n = 0; | |
503 | |
504 while(1) { | |
505 last_ptr = ptr; | |
506 ptr = strchr(ptr,LIST_SEPARATOR); | |
507 if(!ptr) { | |
508 res[n] = strdup(last_ptr); | |
509 n++; | |
510 break; | |
511 } | |
512 len = ptr - last_ptr; | |
513 res[n] = (char*)malloc(len + 1); | |
514 if(len) strncpy(res[n],last_ptr,len); | |
515 res[n][len] = '\0'; | |
516 ptr++; | |
517 n++; | |
518 } | |
519 res[n] = NULL; | |
520 | |
521 switch(op) { | |
522 case OP_ADD: | |
523 return str_list_add(res,n,dst,0); | |
524 case OP_PRE: | |
525 return str_list_add(res,n,dst,1); | |
526 case OP_DEL: | |
527 return str_list_del(res,n,dst); | |
528 } | |
529 | |
530 if(VAL(dst)) | |
531 free_str_list(dst); | |
532 VAL(dst) = res; | |
533 | |
534 return 1; | |
535 } | |
536 | |
537 static void copy_str_list(m_option_t* opt,void* dst, void* src) { | |
538 int n; | |
539 char **d,**s; | |
540 | |
541 if(!(dst && src)) return; | |
542 s = VAL(src); | |
543 | |
544 if(VAL(dst)) | |
545 free_str_list(dst); | |
546 | |
547 if(!s) { | |
548 VAL(dst) = NULL; | |
549 return; | |
550 } | |
551 | |
552 for(n = 0 ; s[n] != NULL ; n++) | |
553 /* NOTHING */; | |
554 d = (char**)malloc((n+1)*sizeof(char*)); | |
555 for( ; n >= 0 ; n--) | |
556 d[n] = s[n] ? strdup(s[n]) : NULL; | |
557 | |
558 VAL(dst) = d; | |
559 } | |
560 | |
561 static char* print_str_list(m_option_t* opt, void* src) { | |
562 return strdup("TODO ;)"); | |
563 } | |
564 | |
565 m_option_type_t m_option_type_string_list = { | |
566 "String list", | |
567 "A list of string separated by ','\n" | |
568 "Option with name that finish by an * allow to use the following suffix : \n" | |
569 "\t-add : add the given parameters at the end of list\n" | |
570 "\t-pre : add the given parameters at the begining of list\n" | |
571 "\t-del : remove the entry at the given indexs\n" | |
572 "\t-clr : clear the list\n" | |
573 "e.g: -vop-add flip,mirror -vop-del 2,5\n", | |
574 sizeof(char**), | |
575 M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD, | |
576 parse_str_list, | |
577 print_str_list, | |
578 copy_str_list, | |
579 copy_str_list, | |
580 copy_str_list, | |
581 free_str_list | |
582 }; | |
583 | |
584 | |
585 /////////////////// Func based options | |
586 | |
587 // A chained list to save the various calls for func_param and func_full | |
588 typedef struct m_func_save m_func_save_t; | |
589 struct m_func_save { | |
590 m_func_save_t* next; | |
591 char* name; | |
592 char* param; | |
593 }; | |
594 | |
595 #undef VAL | |
596 #define VAL(x) (*(m_func_save_t**)(x)) | |
597 | |
598 static void free_func_pf(void* src) { | |
599 m_func_save_t *s,*n; | |
600 | |
601 if(!src) return; | |
602 | |
603 s = VAL(src); | |
604 | |
605 while(s) { | |
606 n = s->next; | |
607 free(s->name); | |
608 if(s->param) free(s->param); | |
609 free(s); | |
610 s = n; | |
611 } | |
612 VAL(src) = NULL; | |
613 } | |
614 | |
615 // Parser for func_param and func_full | |
616 static int parse_func_pf(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
617 m_func_save_t *s,*p; | |
618 | |
619 if(!dst) | |
620 return 1; | |
621 | |
622 s = (m_func_save_t*)calloc(1,sizeof(m_func_save_t)); | |
623 s->name = strdup(name); | |
624 s->param = param ? strdup(param) : NULL; | |
625 | |
626 p = VAL(dst); | |
627 if(p) { | |
628 for( ; p->next != NULL ; p = p->next) | |
629 /**/; | |
630 p->next = s; | |
631 } else | |
632 VAL(dst) = s; | |
633 | |
634 return 1; | |
635 } | |
636 | |
637 static void copy_func_pf(m_option_t* opt,void* dst, void* src) { | |
638 m_func_save_t *d = NULL, *s,* last = NULL; | |
639 | |
640 if(!(dst && src)) return; | |
641 s = VAL(src); | |
642 | |
643 if(VAL(dst)) | |
644 free_func_pf(dst); | |
645 | |
646 while(s) { | |
647 d = (m_func_save_t*)malloc(sizeof(m_func_save_t)); | |
648 d->name = strdup(s->name); | |
649 d->param = s->param ? strdup(s->param) : NULL; | |
650 if(last) | |
651 last->next = d; | |
652 else | |
653 VAL(dst) = d; | |
654 last = d; | |
655 s = s->next; | |
656 } | |
657 | |
658 | |
659 } | |
660 | |
661 /////////////////// Func_param | |
662 | |
663 static void set_func_param(m_option_t* opt, void* dst, void* src) { | |
664 m_func_save_t* s; | |
665 | |
666 if(!src) return; | |
667 s = VAL(src); | |
668 | |
669 if(!s) return; | |
670 | |
671 // Revert if needed | |
672 if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,opt->name); | |
673 for( ; s != NULL ; s = s->next) | |
674 ((m_opt_func_param_t) opt->p)(opt,s->param); | |
675 } | |
676 | |
677 m_option_type_t m_option_type_func_param = { | |
678 "Func param", | |
679 "", | |
680 sizeof(m_func_save_t*), | |
681 M_OPT_TYPE_INDIRECT, | |
682 parse_func_pf, | |
683 NULL, | |
684 NULL, // Nothing to do on save | |
685 set_func_param, | |
686 copy_func_pf, | |
687 free_func_pf | |
688 }; | |
689 | |
690 /////////////////// Func_full | |
691 | |
692 static void set_func_full(m_option_t* opt, void* dst, void* src) { | |
693 m_func_save_t* s; | |
694 | |
695 if(!src) return; | |
696 | |
697 for(s = VAL(src) ; s ; s = s->next) { | |
698 // Revert if needed | |
699 if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,s->name); | |
700 ((m_opt_func_full_t) opt->p)(opt,s->name,s->param); | |
701 } | |
702 } | |
703 | |
704 m_option_type_t m_option_type_func_full = { | |
705 "Func full", | |
706 "", | |
707 sizeof(m_func_save_t*), | |
708 M_OPT_TYPE_ALLOW_WILDCARD|M_OPT_TYPE_INDIRECT, | |
709 parse_func_pf, | |
710 NULL, | |
711 NULL, // Nothing to do on save | |
712 set_func_full, | |
713 copy_func_pf, | |
714 free_func_pf | |
715 }; | |
716 | |
717 /////////////// Func | |
718 | |
719 #undef VAL | |
720 #define VAL(x) (*(int*)(x)) | |
721 | |
722 static int parse_func(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
723 if(dst) | |
724 VAL(dst) += 1; | |
725 return 0; | |
726 } | |
727 | |
728 static void set_func(m_option_t* opt,void* dst, void* src) { | |
729 int i; | |
730 if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,opt->name); | |
731 for(i = 0 ; i < VAL(src) ; i++) | |
732 ((m_opt_func_t) opt->p)(opt); | |
733 } | |
734 | |
735 m_option_type_t m_option_type_func = { | |
736 "Func", | |
737 "", | |
738 sizeof(int), | |
739 M_OPT_TYPE_INDIRECT, | |
740 parse_func, | |
741 NULL, | |
742 NULL, // Nothing to do on save | |
743 set_func, | |
744 NULL, | |
745 NULL | |
746 }; | |
747 | |
748 /////////////////// Print | |
749 | |
750 static int parse_print(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
751 mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", (char *) opt->p); | |
752 if(opt->priv == NULL) | |
753 exit(1); // Call something else instead ?? | |
754 return 1; | |
755 } | |
756 | |
757 m_option_type_t m_option_type_print = { | |
758 "Print", | |
759 "", | |
760 0, | |
761 0, | |
762 parse_print, | |
763 NULL, | |
764 NULL, | |
765 NULL, | |
766 NULL, | |
767 NULL | |
768 }; | |
769 | |
770 /////////////////////// Subconfig | |
771 #undef VAL | |
772 #define VAL(x) (*(char***)(x)) | |
773 | |
774 static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
775 char *subparam; | |
776 char *subopt; | |
777 int nr = 0; | |
778 m_option_t *subopts; | |
779 char *token; | |
780 char *p; | |
781 char** lst = NULL; | |
782 | |
783 if (param == NULL || strlen(param) == 0) | |
784 return M_OPT_MISSING_PARAM; | |
785 | |
786 subparam = malloc(strlen(param)+1); | |
787 subopt = malloc(strlen(param)+1); | |
788 p = strdup(param); // In case that param is a static string (cf man strtok) | |
789 | |
790 subopts = opt->p; | |
791 | |
792 token = strtok(p, (char *)&(":")); | |
793 while(token) | |
794 { | |
795 int sscanf_ret; | |
796 /* clear out */ | |
797 subopt[0] = subparam[0] = 0; | |
798 | |
799 sscanf_ret = sscanf(token, "%[^=]=%[^:]", subopt, subparam); | |
800 | |
801 mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "token: '%s', subopt='%s', subparam='%s' (ret: %d)\n", token, subopt, subparam, sscanf_ret); | |
802 switch(sscanf_ret) | |
803 { | |
804 case 1: | |
805 subparam[0] = 0; | |
806 case 2: | |
807 if(dst) { | |
808 lst = (char**)realloc(lst,2 * (nr+2) * sizeof(char*)); | |
809 lst[2*nr] = strdup(subopt); | |
810 lst[2*nr+1] = subparam[0] == 0 ? NULL : strdup(subparam); | |
811 memset(&lst[2*(nr+1)],0,2*sizeof(char*)); | |
812 nr++; | |
813 } | |
814 break; | |
815 default: | |
816 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid subconfig argument! ('%s')\n", token); | |
817 return M_OPT_INVALID; | |
818 } | |
819 token = strtok(NULL, (char *)&(":")); | |
820 } | |
821 | |
822 free(subparam); | |
823 free(subopt); | |
824 free(p); | |
825 VAL(dst) = lst; | |
826 | |
827 return 1; | |
828 } | |
829 | |
830 m_option_type_t m_option_type_subconfig = { | |
831 "Subconfig", | |
832 "The syntax is -option opt1=foo:flag:opt2=blah", | |
833 sizeof(int), | |
834 M_OPT_TYPE_HAS_CHILD, | |
835 parse_subconf, | |
836 NULL, | |
837 NULL, | |
838 NULL, | |
839 NULL, | |
840 NULL | |
841 }; | |
842 | |
843 #include "libmpcodecs/img_format.h" | |
844 // TODO : use an array so we parse/print easily | |
845 | |
846 static int parse_imgfmt(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
847 uint32_t fmt = 0; | |
848 | |
849 if (param == NULL || strlen(param) == 0) | |
850 return M_OPT_MISSING_PARAM; | |
851 | |
852 // From vf_format | |
853 if(!strcasecmp(param,"444p")) fmt=IMGFMT_444P; else | |
854 if(!strcasecmp(param,"422p")) fmt=IMGFMT_422P; else | |
855 if(!strcasecmp(param,"411p")) fmt=IMGFMT_411P; else | |
856 if(!strcasecmp(param,"yuy2")) fmt=IMGFMT_YUY2; else | |
857 if(!strcasecmp(param,"yv12")) fmt=IMGFMT_YV12; else | |
858 if(!strcasecmp(param,"i420")) fmt=IMGFMT_I420; else | |
859 if(!strcasecmp(param,"yvu9")) fmt=IMGFMT_YVU9; else | |
860 if(!strcasecmp(param,"if09")) fmt=IMGFMT_IF09; else | |
861 if(!strcasecmp(param,"iyuv")) fmt=IMGFMT_IYUV; else | |
862 if(!strcasecmp(param,"uyvy")) fmt=IMGFMT_UYVY; else | |
863 if(!strcasecmp(param,"bgr24")) fmt=IMGFMT_BGR24; else | |
864 if(!strcasecmp(param,"bgr32")) fmt=IMGFMT_BGR32; else | |
865 if(!strcasecmp(param,"bgr16")) fmt=IMGFMT_BGR16; else | |
866 if(!strcasecmp(param,"bgr15")) fmt=IMGFMT_BGR15; else | |
867 if(!strcasecmp(param,"bgr8")) fmt=IMGFMT_BGR8; else | |
868 if(!strcasecmp(param,"bgr4")) fmt=IMGFMT_BGR4; else | |
869 if(!strcasecmp(param,"bgr1")) fmt=IMGFMT_BGR1; else | |
870 if(!strcasecmp(param,"rgb24")) fmt=IMGFMT_RGB24; else | |
871 if(!strcasecmp(param,"rgb32")) fmt=IMGFMT_RGB32; else | |
872 if(!strcasecmp(param,"rgb16")) fmt=IMGFMT_RGB16; else | |
873 if(!strcasecmp(param,"rgb15")) fmt=IMGFMT_RGB15; else | |
874 if(!strcasecmp(param,"rgb8")) fmt=IMGFMT_RGB8; else | |
875 if(!strcasecmp(param,"rgb4")) fmt=IMGFMT_RGB4; else | |
876 if(!strcasecmp(param,"rgb1")) fmt=IMGFMT_RGB1; else { | |
877 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: unknown format name: '%s'\n",param); | |
878 return M_OPT_INVALID; | |
879 } | |
880 | |
881 if(dst) | |
882 *((uint32_t*)dst) = fmt; | |
883 | |
884 return 1; | |
885 } | |
886 | |
887 m_option_type_t m_option_type_imgfmt = { | |
888 "Image format (aka colorspace)", | |
889 "Pls report any missing colorspace", | |
890 sizeof(uint32_t), | |
891 0, | |
892 parse_imgfmt, | |
893 NULL, | |
894 copy_opt, | |
895 copy_opt, | |
896 NULL, | |
897 NULL | |
898 }; | |
899 | |
900 /// Span stuff : Not finished | |
901 static int parse_play_pos(m_play_pos_t* pos,char* opt, char *s) { | |
902 char *ep; | |
903 long tmp; | |
904 int i; | |
905 | |
906 memset(pos,0,sizeof(m_play_pos_t)); | |
907 | |
908 if(!s || s[0] == '\0') | |
909 return M_OPT_MISSING_PARAM; | |
910 | |
911 // Track index | |
912 tmp = strtol(s, &ep, 0); | |
913 if(ep != s) { | |
914 if(tmp < 1) { | |
915 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Track/Chapter index must be > 0\n", opt); | |
916 return M_OPT_OUT_OF_RANGE; | |
917 } | |
918 pos->idx = tmp; | |
919 if(ep[0] == '\0') | |
920 return 1; | |
921 s = ep; | |
922 } | |
923 | |
924 // Span | |
925 tmp = strlen(s); | |
926 if(s[0] != '[' || s[tmp-1] != ']') { | |
927 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt); | |
928 return M_OPT_INVALID; | |
929 } | |
930 s[tmp-1] = '\0'; | |
931 s++; | |
932 | |
933 // hh:mm:ss | |
934 for( i = 2 ; i >= 0 && s[0] != 0 ; i--) { | |
935 if(s[0] == ':') { | |
936 tmp = 0; | |
937 s++; | |
938 } else { | |
939 tmp = strtol(s, &ep, 0); | |
940 if(tmp < 0 || (ep[0] != '\0' && ep[0] != (i > 0 ? ':' : '.') )) { | |
941 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt); | |
942 return M_OPT_INVALID; | |
943 } | |
944 pos->seconds += tmp * pow(60,i); | |
945 s = ep; | |
946 if(s[0] != '\0') | |
947 s++; | |
948 | |
949 } | |
950 } | |
951 | |
952 // sectors | |
953 if(s[0]) { | |
954 tmp = strtol(s, &ep, 0); | |
955 if(tmp < 0 || ep[0] != '\0') { | |
956 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt); | |
957 return M_OPT_INVALID; | |
958 } | |
959 pos->sectors = tmp; | |
960 } | |
961 | |
962 return 1; | |
963 } | |
964 | |
965 | |
966 static int parse_span(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
967 m_span_t* span = dst; | |
968 char *s = param,*e = NULL; | |
969 int r = M_OPT_INVALID; | |
970 | |
971 if(param == NULL) | |
972 return M_OPT_MISSING_PARAM; | |
973 | |
974 e = strchr(param,'-'); | |
975 if(e) { | |
976 e[0] = '\0'; | |
977 e++; | |
978 } | |
979 | |
980 if(s[0] == '\0' && e[0] == '\0') { | |
981 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument\n"); | |
982 return M_OPT_INVALID; | |
983 } | |
984 | |
985 if(s[0]) { | |
986 r = parse_play_pos(&span->start,name,s); | |
987 if(r < 0) return r; | |
988 } | |
989 if(e && e[0] != '\0') | |
990 r = parse_play_pos(&span->end,name,s); | |
991 | |
992 return r; | |
993 } | |
994 | |
995 m_option_type_t m_option_type_span = { | |
996 "Span", | |
997 "The syntax is 1[hh:mm:ss.zz]-5[hh:mm:ss.zz]", | |
998 sizeof(m_span_t), | |
999 0, | |
1000 parse_span, | |
1001 NULL, | |
1002 copy_opt, | |
1003 copy_opt, | |
1004 NULL, | |
1005 NULL | |
1006 }; | |
1007 | |
1008 #endif |