Mercurial > mplayer.hg
annotate m_option.c @ 9503:f47d484d8f28
cbAlign=1 fix for proper Windows support (noticed by Sascha Sommer)
author | alex |
---|---|
date | Tue, 25 Feb 2003 16:17:23 +0000 |
parents | 01a713dcaf23 |
children | e9a2af584986 |
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) { | |
9177
01a713dcaf23
disable free() in string and string_list parsers. yes, it's a hack
arpi
parents:
8736
diff
changeset
|
324 // if(VAL(dst)) free(VAL(dst)); //FIXME!!! |
8164 | 325 VAL(dst) = VAL(src) ? strdup(VAL(src)) : NULL; |
326 } | |
327 } | |
328 | |
329 static void free_str(void* src) { | |
330 if(src && VAL(src)){ | |
9177
01a713dcaf23
disable free() in string and string_list parsers. yes, it's a hack
arpi
parents:
8736
diff
changeset
|
331 // free(VAL(src)); //FIXME!!! |
8164 | 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 | |
9177
01a713dcaf23
disable free() in string and string_list parsers. yes, it's a hack
arpi
parents:
8736
diff
changeset
|
368 // FIXME!!! |
01a713dcaf23
disable free() in string and string_list parsers. yes, it's a hack
arpi
parents:
8736
diff
changeset
|
369 // for(i = 0 ; d[i] != NULL ; i++) |
01a713dcaf23
disable free() in string and string_list parsers. yes, it's a hack
arpi
parents:
8736
diff
changeset
|
370 // free(d[i]); |
01a713dcaf23
disable free() in string and string_list parsers. yes, it's a hack
arpi
parents:
8736
diff
changeset
|
371 // free(d); |
8164 | 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 |