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) {
|
|
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
|