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