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>
|
|
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) {
|
8168
|
318 return (val && VAL(val) && strlen(VAL(val)) > 0) ? strdup(VAL(val)) : NULL;
|
8164
|
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) {
|
8168
|
562 char **lst = NULL;
|
|
563 char *ret = NULL,*last = NULL;
|
|
564 int i;
|
|
565
|
|
566 if(!(src && VAL(src))) return NULL;
|
|
567 lst = VAL(src);
|
|
568
|
|
569 for(i = 0 ; lst[i] ; i++) {
|
|
570 if(last) {
|
|
571 ret = dup_printf("%s,%s",last,lst[i]);
|
|
572 free(last);
|
|
573 } else
|
|
574 ret = strdup(lst[i]);
|
|
575 last = ret;
|
|
576 }
|
|
577 if(last && last != ret) free(last);
|
|
578 return ret;
|
8164
|
579 }
|
|
580
|
|
581 m_option_type_t m_option_type_string_list = {
|
|
582 "String list",
|
|
583 "A list of string separated by ','\n"
|
|
584 "Option with name that finish by an * allow to use the following suffix : \n"
|
|
585 "\t-add : add the given parameters at the end of list\n"
|
|
586 "\t-pre : add the given parameters at the begining of list\n"
|
|
587 "\t-del : remove the entry at the given indexs\n"
|
|
588 "\t-clr : clear the list\n"
|
|
589 "e.g: -vop-add flip,mirror -vop-del 2,5\n",
|
|
590 sizeof(char**),
|
|
591 M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD,
|
|
592 parse_str_list,
|
|
593 print_str_list,
|
|
594 copy_str_list,
|
|
595 copy_str_list,
|
|
596 copy_str_list,
|
|
597 free_str_list
|
|
598 };
|
|
599
|
|
600
|
|
601 /////////////////// Func based options
|
|
602
|
|
603 // A chained list to save the various calls for func_param and func_full
|
|
604 typedef struct m_func_save m_func_save_t;
|
|
605 struct m_func_save {
|
|
606 m_func_save_t* next;
|
|
607 char* name;
|
|
608 char* param;
|
|
609 };
|
|
610
|
|
611 #undef VAL
|
|
612 #define VAL(x) (*(m_func_save_t**)(x))
|
|
613
|
|
614 static void free_func_pf(void* src) {
|
|
615 m_func_save_t *s,*n;
|
|
616
|
|
617 if(!src) return;
|
|
618
|
|
619 s = VAL(src);
|
|
620
|
|
621 while(s) {
|
|
622 n = s->next;
|
|
623 free(s->name);
|
|
624 if(s->param) free(s->param);
|
|
625 free(s);
|
|
626 s = n;
|
|
627 }
|
|
628 VAL(src) = NULL;
|
|
629 }
|
|
630
|
|
631 // Parser for func_param and func_full
|
|
632 static int parse_func_pf(m_option_t* opt,char *name, char *param, void* dst, int src) {
|
|
633 m_func_save_t *s,*p;
|
|
634
|
|
635 if(!dst)
|
|
636 return 1;
|
|
637
|
|
638 s = (m_func_save_t*)calloc(1,sizeof(m_func_save_t));
|
|
639 s->name = strdup(name);
|
|
640 s->param = param ? strdup(param) : NULL;
|
|
641
|
|
642 p = VAL(dst);
|
|
643 if(p) {
|
|
644 for( ; p->next != NULL ; p = p->next)
|
|
645 /**/;
|
|
646 p->next = s;
|
|
647 } else
|
|
648 VAL(dst) = s;
|
|
649
|
|
650 return 1;
|
|
651 }
|
|
652
|
|
653 static void copy_func_pf(m_option_t* opt,void* dst, void* src) {
|
|
654 m_func_save_t *d = NULL, *s,* last = NULL;
|
|
655
|
|
656 if(!(dst && src)) return;
|
|
657 s = VAL(src);
|
|
658
|
|
659 if(VAL(dst))
|
|
660 free_func_pf(dst);
|
|
661
|
|
662 while(s) {
|
|
663 d = (m_func_save_t*)malloc(sizeof(m_func_save_t));
|
|
664 d->name = strdup(s->name);
|
|
665 d->param = s->param ? strdup(s->param) : NULL;
|
|
666 if(last)
|
|
667 last->next = d;
|
|
668 else
|
|
669 VAL(dst) = d;
|
|
670 last = d;
|
|
671 s = s->next;
|
|
672 }
|
|
673
|
|
674
|
|
675 }
|
|
676
|
|
677 /////////////////// Func_param
|
|
678
|
|
679 static void set_func_param(m_option_t* opt, void* dst, void* src) {
|
|
680 m_func_save_t* s;
|
|
681
|
|
682 if(!src) return;
|
|
683 s = VAL(src);
|
|
684
|
|
685 if(!s) return;
|
|
686
|
|
687 // Revert if needed
|
|
688 if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,opt->name);
|
|
689 for( ; s != NULL ; s = s->next)
|
|
690 ((m_opt_func_param_t) opt->p)(opt,s->param);
|
|
691 }
|
|
692
|
|
693 m_option_type_t m_option_type_func_param = {
|
|
694 "Func param",
|
|
695 "",
|
|
696 sizeof(m_func_save_t*),
|
|
697 M_OPT_TYPE_INDIRECT,
|
|
698 parse_func_pf,
|
|
699 NULL,
|
|
700 NULL, // Nothing to do on save
|
|
701 set_func_param,
|
|
702 copy_func_pf,
|
|
703 free_func_pf
|
|
704 };
|
|
705
|
|
706 /////////////////// Func_full
|
|
707
|
|
708 static void set_func_full(m_option_t* opt, void* dst, void* src) {
|
|
709 m_func_save_t* s;
|
|
710
|
|
711 if(!src) return;
|
|
712
|
|
713 for(s = VAL(src) ; s ; s = s->next) {
|
|
714 // Revert if needed
|
|
715 if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,s->name);
|
|
716 ((m_opt_func_full_t) opt->p)(opt,s->name,s->param);
|
|
717 }
|
|
718 }
|
|
719
|
|
720 m_option_type_t m_option_type_func_full = {
|
|
721 "Func full",
|
|
722 "",
|
|
723 sizeof(m_func_save_t*),
|
|
724 M_OPT_TYPE_ALLOW_WILDCARD|M_OPT_TYPE_INDIRECT,
|
|
725 parse_func_pf,
|
|
726 NULL,
|
|
727 NULL, // Nothing to do on save
|
|
728 set_func_full,
|
|
729 copy_func_pf,
|
|
730 free_func_pf
|
|
731 };
|
|
732
|
|
733 /////////////// Func
|
|
734
|
|
735 #undef VAL
|
|
736 #define VAL(x) (*(int*)(x))
|
|
737
|
|
738 static int parse_func(m_option_t* opt,char *name, char *param, void* dst, int src) {
|
|
739 if(dst)
|
|
740 VAL(dst) += 1;
|
|
741 return 0;
|
|
742 }
|
|
743
|
|
744 static void set_func(m_option_t* opt,void* dst, void* src) {
|
|
745 int i;
|
|
746 if(opt->priv) ((m_opt_default_func_t)opt->priv)(opt,opt->name);
|
|
747 for(i = 0 ; i < VAL(src) ; i++)
|
|
748 ((m_opt_func_t) opt->p)(opt);
|
|
749 }
|
|
750
|
|
751 m_option_type_t m_option_type_func = {
|
|
752 "Func",
|
|
753 "",
|
|
754 sizeof(int),
|
|
755 M_OPT_TYPE_INDIRECT,
|
|
756 parse_func,
|
|
757 NULL,
|
|
758 NULL, // Nothing to do on save
|
|
759 set_func,
|
|
760 NULL,
|
|
761 NULL
|
|
762 };
|
|
763
|
|
764 /////////////////// Print
|
|
765
|
|
766 static int parse_print(m_option_t* opt,char *name, char *param, void* dst, int src) {
|
|
767 mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", (char *) opt->p);
|
|
768 if(opt->priv == NULL)
|
|
769 exit(1); // Call something else instead ??
|
|
770 return 1;
|
|
771 }
|
|
772
|
|
773 m_option_type_t m_option_type_print = {
|
|
774 "Print",
|
|
775 "",
|
|
776 0,
|
|
777 0,
|
|
778 parse_print,
|
|
779 NULL,
|
|
780 NULL,
|
|
781 NULL,
|
|
782 NULL,
|
|
783 NULL
|
|
784 };
|
|
785
|
|
786 /////////////////////// Subconfig
|
|
787 #undef VAL
|
|
788 #define VAL(x) (*(char***)(x))
|
|
789
|
|
790 static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int src) {
|
|
791 char *subparam;
|
|
792 char *subopt;
|
|
793 int nr = 0;
|
|
794 m_option_t *subopts;
|
|
795 char *token;
|
|
796 char *p;
|
|
797 char** lst = NULL;
|
|
798
|
|
799 if (param == NULL || strlen(param) == 0)
|
|
800 return M_OPT_MISSING_PARAM;
|
|
801
|
|
802 subparam = malloc(strlen(param)+1);
|
|
803 subopt = malloc(strlen(param)+1);
|
|
804 p = strdup(param); // In case that param is a static string (cf man strtok)
|
|
805
|
|
806 subopts = opt->p;
|
|
807
|
|
808 token = strtok(p, (char *)&(":"));
|
|
809 while(token)
|
|
810 {
|
|
811 int sscanf_ret;
|
|
812 /* clear out */
|
|
813 subopt[0] = subparam[0] = 0;
|
|
814
|
|
815 sscanf_ret = sscanf(token, "%[^=]=%[^:]", subopt, subparam);
|
|
816
|
|
817 mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "token: '%s', subopt='%s', subparam='%s' (ret: %d)\n", token, subopt, subparam, sscanf_ret);
|
|
818 switch(sscanf_ret)
|
|
819 {
|
|
820 case 1:
|
|
821 subparam[0] = 0;
|
|
822 case 2:
|
|
823 if(dst) {
|
|
824 lst = (char**)realloc(lst,2 * (nr+2) * sizeof(char*));
|
|
825 lst[2*nr] = strdup(subopt);
|
|
826 lst[2*nr+1] = subparam[0] == 0 ? NULL : strdup(subparam);
|
|
827 memset(&lst[2*(nr+1)],0,2*sizeof(char*));
|
|
828 nr++;
|
|
829 }
|
|
830 break;
|
|
831 default:
|
|
832 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid subconfig argument! ('%s')\n", token);
|
|
833 return M_OPT_INVALID;
|
|
834 }
|
|
835 token = strtok(NULL, (char *)&(":"));
|
|
836 }
|
|
837
|
|
838 free(subparam);
|
|
839 free(subopt);
|
|
840 free(p);
|
|
841 VAL(dst) = lst;
|
|
842
|
|
843 return 1;
|
|
844 }
|
|
845
|
|
846 m_option_type_t m_option_type_subconfig = {
|
|
847 "Subconfig",
|
|
848 "The syntax is -option opt1=foo:flag:opt2=blah",
|
|
849 sizeof(int),
|
|
850 M_OPT_TYPE_HAS_CHILD,
|
|
851 parse_subconf,
|
|
852 NULL,
|
|
853 NULL,
|
|
854 NULL,
|
|
855 NULL,
|
|
856 NULL
|
|
857 };
|
|
858
|
|
859 #include "libmpcodecs/img_format.h"
|
|
860 // TODO : use an array so we parse/print easily
|
|
861
|
|
862 static int parse_imgfmt(m_option_t* opt,char *name, char *param, void* dst, int src) {
|
|
863 uint32_t fmt = 0;
|
|
864
|
|
865 if (param == NULL || strlen(param) == 0)
|
|
866 return M_OPT_MISSING_PARAM;
|
|
867
|
|
868 // From vf_format
|
|
869 if(!strcasecmp(param,"444p")) fmt=IMGFMT_444P; else
|
|
870 if(!strcasecmp(param,"422p")) fmt=IMGFMT_422P; else
|
|
871 if(!strcasecmp(param,"411p")) fmt=IMGFMT_411P; else
|
|
872 if(!strcasecmp(param,"yuy2")) fmt=IMGFMT_YUY2; else
|
|
873 if(!strcasecmp(param,"yv12")) fmt=IMGFMT_YV12; else
|
|
874 if(!strcasecmp(param,"i420")) fmt=IMGFMT_I420; else
|
|
875 if(!strcasecmp(param,"yvu9")) fmt=IMGFMT_YVU9; else
|
|
876 if(!strcasecmp(param,"if09")) fmt=IMGFMT_IF09; else
|
|
877 if(!strcasecmp(param,"iyuv")) fmt=IMGFMT_IYUV; else
|
|
878 if(!strcasecmp(param,"uyvy")) fmt=IMGFMT_UYVY; else
|
|
879 if(!strcasecmp(param,"bgr24")) fmt=IMGFMT_BGR24; else
|
|
880 if(!strcasecmp(param,"bgr32")) fmt=IMGFMT_BGR32; else
|
|
881 if(!strcasecmp(param,"bgr16")) fmt=IMGFMT_BGR16; else
|
|
882 if(!strcasecmp(param,"bgr15")) fmt=IMGFMT_BGR15; else
|
|
883 if(!strcasecmp(param,"bgr8")) fmt=IMGFMT_BGR8; else
|
|
884 if(!strcasecmp(param,"bgr4")) fmt=IMGFMT_BGR4; else
|
|
885 if(!strcasecmp(param,"bgr1")) fmt=IMGFMT_BGR1; else
|
|
886 if(!strcasecmp(param,"rgb24")) fmt=IMGFMT_RGB24; else
|
|
887 if(!strcasecmp(param,"rgb32")) fmt=IMGFMT_RGB32; else
|
|
888 if(!strcasecmp(param,"rgb16")) fmt=IMGFMT_RGB16; else
|
|
889 if(!strcasecmp(param,"rgb15")) fmt=IMGFMT_RGB15; else
|
|
890 if(!strcasecmp(param,"rgb8")) fmt=IMGFMT_RGB8; else
|
|
891 if(!strcasecmp(param,"rgb4")) fmt=IMGFMT_RGB4; else
|
|
892 if(!strcasecmp(param,"rgb1")) fmt=IMGFMT_RGB1; else {
|
|
893 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: unknown format name: '%s'\n",param);
|
|
894 return M_OPT_INVALID;
|
|
895 }
|
|
896
|
|
897 if(dst)
|
|
898 *((uint32_t*)dst) = fmt;
|
|
899
|
|
900 return 1;
|
|
901 }
|
|
902
|
|
903 m_option_type_t m_option_type_imgfmt = {
|
|
904 "Image format (aka colorspace)",
|
|
905 "Pls report any missing colorspace",
|
|
906 sizeof(uint32_t),
|
|
907 0,
|
|
908 parse_imgfmt,
|
|
909 NULL,
|
|
910 copy_opt,
|
|
911 copy_opt,
|
|
912 NULL,
|
|
913 NULL
|
|
914 };
|
|
915
|
|
916 /// Span stuff : Not finished
|
|
917 static int parse_play_pos(m_play_pos_t* pos,char* opt, char *s) {
|
|
918 char *ep;
|
|
919 long tmp;
|
|
920 int i;
|
|
921
|
|
922 memset(pos,0,sizeof(m_play_pos_t));
|
|
923
|
|
924 if(!s || s[0] == '\0')
|
|
925 return M_OPT_MISSING_PARAM;
|
|
926
|
|
927 // Track index
|
|
928 tmp = strtol(s, &ep, 0);
|
|
929 if(ep != s) {
|
|
930 if(tmp < 1) {
|
|
931 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Track/Chapter index must be > 0\n", opt);
|
|
932 return M_OPT_OUT_OF_RANGE;
|
|
933 }
|
|
934 pos->idx = tmp;
|
|
935 if(ep[0] == '\0')
|
|
936 return 1;
|
|
937 s = ep;
|
|
938 }
|
|
939
|
|
940 // Span
|
|
941 tmp = strlen(s);
|
|
942 if(s[0] != '[' || s[tmp-1] != ']') {
|
|
943 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt);
|
|
944 return M_OPT_INVALID;
|
|
945 }
|
|
946 s[tmp-1] = '\0';
|
|
947 s++;
|
|
948
|
|
949 // hh:mm:ss
|
|
950 for( i = 2 ; i >= 0 && s[0] != 0 ; i--) {
|
|
951 if(s[0] == ':') {
|
|
952 tmp = 0;
|
|
953 s++;
|
|
954 } else {
|
|
955 tmp = strtol(s, &ep, 0);
|
|
956 if(tmp < 0 || (ep[0] != '\0' && ep[0] != (i > 0 ? ':' : '.') )) {
|
|
957 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt);
|
|
958 return M_OPT_INVALID;
|
|
959 }
|
|
960 pos->seconds += tmp * pow(60,i);
|
|
961 s = ep;
|
|
962 if(s[0] != '\0')
|
|
963 s++;
|
|
964
|
|
965 }
|
|
966 }
|
|
967
|
|
968 // sectors
|
|
969 if(s[0]) {
|
|
970 tmp = strtol(s, &ep, 0);
|
|
971 if(tmp < 0 || ep[0] != '\0') {
|
|
972 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt);
|
|
973 return M_OPT_INVALID;
|
|
974 }
|
|
975 pos->sectors = tmp;
|
|
976 }
|
|
977
|
|
978 return 1;
|
|
979 }
|
|
980
|
|
981
|
|
982 static int parse_span(m_option_t* opt,char *name, char *param, void* dst, int src) {
|
|
983 m_span_t* span = dst;
|
|
984 char *s = param,*e = NULL;
|
|
985 int r = M_OPT_INVALID;
|
|
986
|
|
987 if(param == NULL)
|
|
988 return M_OPT_MISSING_PARAM;
|
|
989
|
|
990 e = strchr(param,'-');
|
|
991 if(e) {
|
|
992 e[0] = '\0';
|
|
993 e++;
|
|
994 }
|
|
995
|
|
996 if(s[0] == '\0' && e[0] == '\0') {
|
|
997 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument\n");
|
|
998 return M_OPT_INVALID;
|
|
999 }
|
|
1000
|
|
1001 if(s[0]) {
|
|
1002 r = parse_play_pos(&span->start,name,s);
|
|
1003 if(r < 0) return r;
|
|
1004 }
|
|
1005 if(e && e[0] != '\0')
|
|
1006 r = parse_play_pos(&span->end,name,s);
|
|
1007
|
|
1008 return r;
|
|
1009 }
|
|
1010
|
|
1011 m_option_type_t m_option_type_span = {
|
|
1012 "Span",
|
|
1013 "The syntax is 1[hh:mm:ss.zz]-5[hh:mm:ss.zz]",
|
|
1014 sizeof(m_span_t),
|
|
1015 0,
|
|
1016 parse_span,
|
|
1017 NULL,
|
|
1018 copy_opt,
|
|
1019 copy_opt,
|
|
1020 NULL,
|
|
1021 NULL
|
|
1022 };
|
|
1023
|
|
1024 #endif
|