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
|
|
501 res = malloc((n+1)*sizeof(char*));
|
|
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) {
|
|
768 mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", (char *) opt->p);
|
|
769 if(opt->priv == NULL)
|
|
770 exit(1); // Call something else instead ??
|
|
771 return 1;
|
|
772 }
|
|
773
|
|
774 m_option_type_t m_option_type_print = {
|
|
775 "Print",
|
|
776 "",
|
|
777 0,
|
|
778 0,
|
|
779 parse_print,
|
|
780 NULL,
|
|
781 NULL,
|
|
782 NULL,
|
|
783 NULL,
|
|
784 NULL
|
|
785 };
|
|
786
|
|
787 /////////////////////// Subconfig
|
|
788 #undef VAL
|
|
789 #define VAL(x) (*(char***)(x))
|
|
790
|
|
791 static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int src) {
|
|
792 char *subparam;
|
|
793 char *subopt;
|
|
794 int nr = 0;
|
|
795 m_option_t *subopts;
|
|
796 char *token;
|
|
797 char *p;
|
|
798 char** lst = NULL;
|
|
799
|
|
800 if (param == NULL || strlen(param) == 0)
|
|
801 return M_OPT_MISSING_PARAM;
|
|
802
|
|
803 subparam = malloc(strlen(param)+1);
|
|
804 subopt = malloc(strlen(param)+1);
|
|
805 p = strdup(param); // In case that param is a static string (cf man strtok)
|
|
806
|
|
807 subopts = opt->p;
|
|
808
|
|
809 token = strtok(p, (char *)&(":"));
|
|
810 while(token)
|
|
811 {
|
|
812 int sscanf_ret;
|
|
813 /* clear out */
|
|
814 subopt[0] = subparam[0] = 0;
|
|
815
|
|
816 sscanf_ret = sscanf(token, "%[^=]=%[^:]", subopt, subparam);
|
|
817
|
|
818 mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "token: '%s', subopt='%s', subparam='%s' (ret: %d)\n", token, subopt, subparam, sscanf_ret);
|
|
819 switch(sscanf_ret)
|
|
820 {
|
|
821 case 1:
|
|
822 subparam[0] = 0;
|
|
823 case 2:
|
|
824 if(dst) {
|
|
825 lst = (char**)realloc(lst,2 * (nr+2) * sizeof(char*));
|
|
826 lst[2*nr] = strdup(subopt);
|
|
827 lst[2*nr+1] = subparam[0] == 0 ? NULL : strdup(subparam);
|
|
828 memset(&lst[2*(nr+1)],0,2*sizeof(char*));
|
|
829 nr++;
|
|
830 }
|
|
831 break;
|
|
832 default:
|
|
833 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid subconfig argument! ('%s')\n", token);
|
|
834 return M_OPT_INVALID;
|
|
835 }
|
|
836 token = strtok(NULL, (char *)&(":"));
|
|
837 }
|
|
838
|
|
839 free(subparam);
|
|
840 free(subopt);
|
|
841 free(p);
|
|
842 VAL(dst) = lst;
|
|
843
|
|
844 return 1;
|
|
845 }
|
|
846
|
|
847 m_option_type_t m_option_type_subconfig = {
|
|
848 "Subconfig",
|
|
849 "The syntax is -option opt1=foo:flag:opt2=blah",
|
|
850 sizeof(int),
|
|
851 M_OPT_TYPE_HAS_CHILD,
|
|
852 parse_subconf,
|
|
853 NULL,
|
|
854 NULL,
|
|
855 NULL,
|
|
856 NULL,
|
|
857 NULL
|
|
858 };
|
|
859
|
|
860 #include "libmpcodecs/img_format.h"
|
|
861 // TODO : use an array so we parse/print easily
|
|
862
|
|
863 static int parse_imgfmt(m_option_t* opt,char *name, char *param, void* dst, int src) {
|
|
864 uint32_t fmt = 0;
|
|
865
|
|
866 if (param == NULL || strlen(param) == 0)
|
|
867 return M_OPT_MISSING_PARAM;
|
|
868
|
|
869 // From vf_format
|
|
870 if(!strcasecmp(param,"444p")) fmt=IMGFMT_444P; else
|
|
871 if(!strcasecmp(param,"422p")) fmt=IMGFMT_422P; else
|
|
872 if(!strcasecmp(param,"411p")) fmt=IMGFMT_411P; else
|
|
873 if(!strcasecmp(param,"yuy2")) fmt=IMGFMT_YUY2; else
|
|
874 if(!strcasecmp(param,"yv12")) fmt=IMGFMT_YV12; else
|
|
875 if(!strcasecmp(param,"i420")) fmt=IMGFMT_I420; else
|
|
876 if(!strcasecmp(param,"yvu9")) fmt=IMGFMT_YVU9; else
|
|
877 if(!strcasecmp(param,"if09")) fmt=IMGFMT_IF09; else
|
|
878 if(!strcasecmp(param,"iyuv")) fmt=IMGFMT_IYUV; else
|
|
879 if(!strcasecmp(param,"uyvy")) fmt=IMGFMT_UYVY; else
|
|
880 if(!strcasecmp(param,"bgr24")) fmt=IMGFMT_BGR24; else
|
|
881 if(!strcasecmp(param,"bgr32")) fmt=IMGFMT_BGR32; else
|
|
882 if(!strcasecmp(param,"bgr16")) fmt=IMGFMT_BGR16; else
|
|
883 if(!strcasecmp(param,"bgr15")) fmt=IMGFMT_BGR15; else
|
|
884 if(!strcasecmp(param,"bgr8")) fmt=IMGFMT_BGR8; else
|
|
885 if(!strcasecmp(param,"bgr4")) fmt=IMGFMT_BGR4; else
|
|
886 if(!strcasecmp(param,"bgr1")) fmt=IMGFMT_BGR1; else
|
|
887 if(!strcasecmp(param,"rgb24")) fmt=IMGFMT_RGB24; else
|
|
888 if(!strcasecmp(param,"rgb32")) fmt=IMGFMT_RGB32; else
|
|
889 if(!strcasecmp(param,"rgb16")) fmt=IMGFMT_RGB16; else
|
|
890 if(!strcasecmp(param,"rgb15")) fmt=IMGFMT_RGB15; else
|
|
891 if(!strcasecmp(param,"rgb8")) fmt=IMGFMT_RGB8; else
|
|
892 if(!strcasecmp(param,"rgb4")) fmt=IMGFMT_RGB4; else
|
|
893 if(!strcasecmp(param,"rgb1")) fmt=IMGFMT_RGB1; else {
|
|
894 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: unknown format name: '%s'\n",param);
|
|
895 return M_OPT_INVALID;
|
|
896 }
|
|
897
|
|
898 if(dst)
|
|
899 *((uint32_t*)dst) = fmt;
|
|
900
|
|
901 return 1;
|
|
902 }
|
|
903
|
|
904 m_option_type_t m_option_type_imgfmt = {
|
|
905 "Image format (aka colorspace)",
|
|
906 "Pls report any missing colorspace",
|
|
907 sizeof(uint32_t),
|
|
908 0,
|
|
909 parse_imgfmt,
|
|
910 NULL,
|
|
911 copy_opt,
|
|
912 copy_opt,
|
|
913 NULL,
|
|
914 NULL
|
|
915 };
|
|
916
|
|
917 /// Span stuff : Not finished
|
|
918 static int parse_play_pos(m_play_pos_t* pos,char* opt, char *s) {
|
|
919 char *ep;
|
|
920 long tmp;
|
|
921 int i;
|
|
922
|
|
923 memset(pos,0,sizeof(m_play_pos_t));
|
|
924
|
|
925 if(!s || s[0] == '\0')
|
|
926 return M_OPT_MISSING_PARAM;
|
|
927
|
|
928 // Track index
|
|
929 tmp = strtol(s, &ep, 0);
|
|
930 if(ep != s) {
|
|
931 if(tmp < 1) {
|
|
932 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Track/Chapter index must be > 0\n", opt);
|
|
933 return M_OPT_OUT_OF_RANGE;
|
|
934 }
|
|
935 pos->idx = tmp;
|
|
936 if(ep[0] == '\0')
|
|
937 return 1;
|
|
938 s = ep;
|
|
939 }
|
|
940
|
|
941 // Span
|
|
942 tmp = strlen(s);
|
|
943 if(s[0] != '[' || s[tmp-1] != ']') {
|
|
944 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt);
|
|
945 return M_OPT_INVALID;
|
|
946 }
|
|
947 s[tmp-1] = '\0';
|
|
948 s++;
|
|
949
|
|
950 // hh:mm:ss
|
|
951 for( i = 2 ; i >= 0 && s[0] != 0 ; i--) {
|
|
952 if(s[0] == ':') {
|
|
953 tmp = 0;
|
|
954 s++;
|
|
955 } else {
|
|
956 tmp = strtol(s, &ep, 0);
|
|
957 if(tmp < 0 || (ep[0] != '\0' && ep[0] != (i > 0 ? ':' : '.') )) {
|
|
958 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt);
|
|
959 return M_OPT_INVALID;
|
|
960 }
|
|
961 pos->seconds += tmp * pow(60,i);
|
|
962 s = ep;
|
|
963 if(s[0] != '\0')
|
|
964 s++;
|
|
965
|
|
966 }
|
|
967 }
|
|
968
|
|
969 // sectors
|
|
970 if(s[0]) {
|
|
971 tmp = strtol(s, &ep, 0);
|
|
972 if(tmp < 0 || ep[0] != '\0') {
|
|
973 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument ?\n", opt);
|
|
974 return M_OPT_INVALID;
|
|
975 }
|
|
976 pos->sectors = tmp;
|
|
977 }
|
|
978
|
|
979 return 1;
|
|
980 }
|
|
981
|
|
982
|
|
983 static int parse_span(m_option_t* opt,char *name, char *param, void* dst, int src) {
|
|
984 m_span_t* span = dst;
|
|
985 char *s = param,*e = NULL;
|
|
986 int r = M_OPT_INVALID;
|
|
987
|
|
988 if(param == NULL)
|
|
989 return M_OPT_MISSING_PARAM;
|
|
990
|
|
991 e = strchr(param,'-');
|
|
992 if(e) {
|
|
993 e[0] = '\0';
|
|
994 e++;
|
|
995 }
|
|
996
|
|
997 if(s[0] == '\0' && e[0] == '\0') {
|
|
998 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid argument\n");
|
|
999 return M_OPT_INVALID;
|
|
1000 }
|
|
1001
|
|
1002 if(s[0]) {
|
|
1003 r = parse_play_pos(&span->start,name,s);
|
|
1004 if(r < 0) return r;
|
|
1005 }
|
|
1006 if(e && e[0] != '\0')
|
|
1007 r = parse_play_pos(&span->end,name,s);
|
|
1008
|
|
1009 return r;
|
|
1010 }
|
|
1011
|
|
1012 m_option_type_t m_option_type_span = {
|
|
1013 "Span",
|
|
1014 "The syntax is 1[hh:mm:ss.zz]-5[hh:mm:ss.zz]",
|
|
1015 sizeof(m_span_t),
|
|
1016 0,
|
|
1017 parse_span,
|
|
1018 NULL,
|
|
1019 copy_opt,
|
|
1020 copy_opt,
|
|
1021 NULL,
|
|
1022 NULL
|
|
1023 };
|
|
1024
|
|
1025 #endif
|