2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include "stream/url.h"
36 #include "libavutil/avstring.h"
38 // Don't free for 'production' atm
43 const m_option_t
*m_option_list_find(const m_option_t
*list
, const char *name
)
47 for (i
= 0; list
[i
].name
; i
++) {
48 int l
= strlen(list
[i
].name
) - 1;
49 if ((list
[i
].type
->flags
& M_OPT_TYPE_ALLOW_WILDCARD
)
50 && (l
> 0) && (list
[i
].name
[l
] == '*')) {
51 if (strncasecmp(list
[i
].name
, name
, l
) == 0)
53 } else if (strcasecmp(list
[i
].name
, name
) == 0)
59 // Default function that just does a memcpy
61 static void copy_opt(const m_option_t
*opt
, void *dst
, const void *src
)
64 memcpy(dst
, src
, opt
->type
->size
);
69 #define VAL(x) (*(int *)(x))
71 static int parse_flag(const m_option_t
*opt
, const char *name
,
72 const char *param
, void *dst
, int src
)
74 if (src
== M_CONFIG_FILE
) {
76 return M_OPT_MISSING_PARAM
;
77 if (!strcasecmp(param
, "yes") || /* any other language? */
78 !strcasecmp(param
, "on") ||
79 !strcasecmp(param
, "ja") ||
80 !strcasecmp(param
, "si") ||
81 !strcasecmp(param
, "igen") ||
82 !strcasecmp(param
, "y") ||
83 !strcasecmp(param
, "j") ||
84 !strcasecmp(param
, "i") ||
85 !strcasecmp(param
, "tak") ||
86 !strcasecmp(param
, "ja") ||
87 !strcasecmp(param
, "true") ||
88 !strcmp(param
, "1")) {
91 } else if (!strcasecmp(param
, "no") ||
92 !strcasecmp(param
, "off") ||
93 !strcasecmp(param
, "nein") ||
94 !strcasecmp(param
, "nicht") ||
95 !strcasecmp(param
, "nem") ||
96 !strcasecmp(param
, "n") ||
97 !strcasecmp(param
, "nie") ||
98 !strcasecmp(param
, "nej") ||
99 !strcasecmp(param
, "false") ||
100 !strcmp(param
, "0")) {
104 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
105 "Invalid parameter for %s flag: %s\n", name
, param
);
106 return M_OPT_INVALID
;
116 static char *print_flag(const m_option_t
*opt
, const void *val
)
118 if (VAL(val
) == opt
->min
)
119 return talloc_strdup(NULL
, "no");
121 return talloc_strdup(NULL
, "yes");
124 const m_option_type_t m_option_type_flag
= {
126 "need yes or no in config files",
139 static int parse_int(const m_option_t
*opt
, const char *name
,
140 const char *param
, void *dst
, int src
)
147 return M_OPT_MISSING_PARAM
;
149 tmp_int
= strtoll(param
, &endptr
, 10);
151 tmp_int
= strtoll(param
, &endptr
, 0);
153 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
154 "The %s option must be an integer: %s\n", name
, param
);
155 return M_OPT_INVALID
;
158 if ((opt
->flags
& M_OPT_MIN
) && (tmp_int
< opt
->min
)) {
159 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
160 "The %s option must be >= %d: %s\n",
161 name
, (int) opt
->min
, param
);
162 return M_OPT_OUT_OF_RANGE
;
165 if ((opt
->flags
& M_OPT_MAX
) && (tmp_int
> opt
->max
)) {
166 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
167 "The %s option must be <= %d: %s\n",
168 name
, (int) opt
->max
, param
);
169 return M_OPT_OUT_OF_RANGE
;
173 if (opt
->type
->size
== sizeof(int64_t))
174 *(int64_t *)dst
= tmp_int
;
182 static char *print_int(const m_option_t
*opt
, const void *val
)
184 if (opt
->type
->size
== sizeof(int64_t))
185 return talloc_asprintf(NULL
, "%"PRId64
, *(const int64_t *)val
);
186 return talloc_asprintf(NULL
, "%d", VAL(val
));
189 const m_option_type_t m_option_type_int
= {
202 const m_option_type_t m_option_type_int64
= {
215 static int parse_intpair(const struct m_option
*opt
, const char *name
,
216 const char *param
, void *dst
, int src
)
219 return M_OPT_MISSING_PARAM
;
221 char *s
= (char *)param
;
225 start
= strtol(s
, &s
, 10);
235 end
= strtol(s
, &s
, 10);
248 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Invalid integer range "
249 "specification for option %s: %s\n", name
, param
);
250 return M_OPT_INVALID
;
253 const struct m_option_type m_option_type_intpair
= {
255 .size
= sizeof(int[2]),
256 .parse
= parse_intpair
,
261 static int parse_choice(const struct m_option
*opt
, const char *name
,
262 const char *param
, void *dst
, int src
)
265 return M_OPT_MISSING_PARAM
;
267 struct m_opt_choice_alternatives
*alt
;
268 for (alt
= opt
->priv
; alt
->name
; alt
++)
269 if (!strcmp(param
, alt
->name
))
272 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Invalid value for option %s: %s\n",
274 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Valid values are:");
275 for (alt
= opt
->priv
; alt
->name
; alt
++)
276 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, " %s", alt
->name
);
277 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "\n");
278 return M_OPT_INVALID
;
281 *(int *)dst
= alt
->value
;
286 static char *print_choice(const m_option_t
*opt
, const void *val
)
289 struct m_opt_choice_alternatives
*alt
;
290 for (alt
= opt
->priv
; alt
->name
; alt
++)
292 return talloc_strdup(NULL
, alt
->name
);
296 const struct m_option_type m_option_type_choice
= {
297 .name
= "String", // same as arbitrary strings in option list for now
299 .parse
= parse_choice
,
300 .print
= print_choice
,
308 #define VAL(x) (*(double *)(x))
310 static int parse_double(const m_option_t
*opt
, const char *name
,
311 const char *param
, void *dst
, int src
)
318 return M_OPT_MISSING_PARAM
;
320 tmp_float
= strtod(param
, &endptr
);
325 tmp_float
/= strtod(endptr
+ 1, &endptr
);
329 /* we also handle floats specified with
330 * non-locale decimal point ::atmos
333 tmp_float
-= 1.0 / pow(10, strlen(endptr
+ 1)) *
334 strtod(endptr
+ 1, &endptr
);
336 tmp_float
+= 1.0 / pow(10, strlen(endptr
+ 1)) *
337 strtod(endptr
+ 1, &endptr
);
342 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
343 "The %s option must be a floating point number or a "
344 "ratio (numerator[:/]denominator): %s\n", name
, param
);
345 return M_OPT_INVALID
;
348 if (opt
->flags
& M_OPT_MIN
)
349 if (tmp_float
< opt
->min
) {
350 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
351 "The %s option must be >= %f: %s\n", name
, opt
->min
, param
);
352 return M_OPT_OUT_OF_RANGE
;
355 if (opt
->flags
& M_OPT_MAX
)
356 if (tmp_float
> opt
->max
) {
357 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
358 "The %s option must be <= %f: %s\n", name
, opt
->max
, param
);
359 return M_OPT_OUT_OF_RANGE
;
363 VAL(dst
) = tmp_float
;
367 static char *print_double(const m_option_t
*opt
, const void *val
)
370 return talloc_asprintf(NULL
, "%f", VAL(val
));
373 const m_option_type_t m_option_type_double
= {
375 "double precision floating point number or ratio (numerator[:/]denominator)",
387 #define VAL(x) (*(float *)(x))
389 static int parse_float(const m_option_t
*opt
, const char *name
,
390 const char *param
, void *dst
, int src
)
393 int r
= parse_double(opt
, name
, param
, &tmp
, src
);
399 static char *print_float(const m_option_t
*opt
, const void *val
)
402 return talloc_asprintf(NULL
, "%f", VAL(val
));
405 const m_option_type_t m_option_type_float
= {
407 "floating point number or ratio (numerator[:/]denominator)",
418 ///////////// Position
420 #define VAL(x) (*(off_t *)(x))
422 static int parse_position(const m_option_t
*opt
, const char *name
,
423 const char *param
, void *dst
, int src
)
429 return M_OPT_MISSING_PARAM
;
430 if (sscanf(param
, sizeof(off_t
) == sizeof(int) ?
431 "%d%c" : "%"PRId64
"%c", &tmp_off
, &dummy
) != 1) {
432 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
433 "The %s option must be an integer: %s\n", opt
->name
, param
);
434 return M_OPT_INVALID
;
437 if (opt
->flags
& M_OPT_MIN
)
438 if (tmp_off
< opt
->min
) {
439 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
440 "The %s option must be >= %"PRId64
": %s\n",
441 name
, (int64_t) opt
->min
, param
);
442 return M_OPT_OUT_OF_RANGE
;
445 if (opt
->flags
& M_OPT_MAX
)
446 if (tmp_off
> opt
->max
) {
447 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
448 "The %s option must be <= %"PRId64
": %s\n",
449 name
, (int64_t) opt
->max
, param
);
450 return M_OPT_OUT_OF_RANGE
;
458 static char *print_position(const m_option_t
*opt
, const void *val
)
460 return talloc_asprintf(NULL
, "%"PRId64
, (int64_t)VAL(val
));
463 const m_option_type_t m_option_type_position
= {
480 #define VAL(x) (*(char **)(x))
482 static int parse_str(const m_option_t
*opt
, const char *name
,
483 const char *param
, void *dst
, int src
)
488 return M_OPT_MISSING_PARAM
;
490 if ((opt
->flags
& M_OPT_MIN
) && (strlen(param
) < opt
->min
)) {
491 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Parameter must be >= %d chars: %s\n",
492 (int) opt
->min
, param
);
493 return M_OPT_OUT_OF_RANGE
;
496 if ((opt
->flags
& M_OPT_MAX
) && (strlen(param
) > opt
->max
)) {
497 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Parameter must be <= %d chars: %s\n",
498 (int) opt
->max
, param
);
499 return M_OPT_OUT_OF_RANGE
;
504 VAL(dst
) = strdup(param
);
511 static char *print_str(const m_option_t
*opt
, const void *val
)
513 return (val
&& VAL(val
)) ? talloc_strdup(NULL
, VAL(val
)) : NULL
;
516 static void copy_str(const m_option_t
*opt
, void *dst
, const void *src
)
520 free(VAL(dst
)); //FIXME!!!
522 VAL(dst
) = VAL(src
) ? strdup(VAL(src
)) : NULL
;
526 static void free_str(void *src
)
528 if (src
&& VAL(src
)) {
530 free(VAL(src
)); //FIXME!!!
536 const m_option_type_t m_option_type_string
= {
549 //////////// String list
552 #define VAL(x) (*(char ***)(x))
560 static void free_str_list(void *dst
)
565 if (!dst
|| !VAL(dst
))
571 for (i
= 0; d
[i
] != NULL
; i
++)
578 static int str_list_add(char **add
, int n
, void *dst
, int pre
)
580 char **lst
= VAL(dst
);
584 return M_OPT_PARSER_ERR
;
587 for (ln
= 0; lst
&& lst
[ln
]; ln
++)
590 lst
= realloc(lst
, (n
+ ln
+ 1) * sizeof(char *));
593 memmove(&lst
[n
], lst
, ln
* sizeof(char *));
594 memcpy(lst
, add
, n
* sizeof(char *));
596 memcpy(&lst
[ln
], add
, n
* sizeof(char *));
597 // (re-)add NULL-termination
607 static int str_list_del(char **del
, int n
, void *dst
)
609 char **lst
, *ep
, **d
;
614 return M_OPT_PARSER_ERR
;
617 for (ln
= 0; lst
&& lst
[ln
]; ln
++)
621 for (i
= 0; del
[i
] != NULL
; i
++) {
622 idx
= strtol(del
[i
], &ep
, 0);
624 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Invalid index: %s\n", del
[i
]);
629 if (idx
< 0 || idx
>= ln
) {
630 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
631 "Index %ld is out of range.\n", idx
);
633 } else if (!lst
[idx
])
647 d
= calloc(s
+ 1, sizeof(char *));
648 for (i
= 0, n
= 0; i
< ln
; i
++) {
662 static char *get_nextsep(char *ptr
, char sep
, int modify
)
664 char *last_ptr
= ptr
;
666 ptr
= strchr(ptr
, sep
);
667 if (ptr
&& ptr
> last_ptr
&& ptr
[-1] == '\\') {
669 memmove(ptr
- 1, ptr
, strlen(ptr
) + 1);
678 static int parse_str_list(const m_option_t
*opt
, const char *name
,
679 const char *param
, void *dst
, int src
)
681 int n
= 0, len
= strlen(opt
->name
);
683 char *ptr
= (char *)param
, *last_ptr
, **res
;
686 if (opt
->name
[len
- 1] == '*' && ((int)strlen(name
) > len
- 1)) {
687 const char *n
= &name
[len
- 1];
688 if (strcasecmp(n
, "-add") == 0)
690 else if (strcasecmp(n
, "-pre") == 0)
692 else if (strcasecmp(n
, "-del") == 0)
694 else if (strcasecmp(n
, "-clr") == 0)
697 return M_OPT_UNKNOWN
;
707 // All other ops need a param
708 if (param
== NULL
|| strlen(param
) == 0)
709 return M_OPT_MISSING_PARAM
;
711 // custom type for "profile" calls this but uses ->priv for something else
712 char separator
= opt
->type
== &m_option_type_string_list
&& opt
->priv
?
713 *(char *)opt
->priv
: OPTION_LIST_SEPARATOR
;
714 while (ptr
[0] != '\0') {
715 ptr
= get_nextsep(ptr
, separator
, 0);
724 return M_OPT_INVALID
;
725 if (((opt
->flags
& M_OPT_MIN
) && (n
< opt
->min
)) ||
726 ((opt
->flags
& M_OPT_MAX
) && (n
> opt
->max
)))
727 return M_OPT_OUT_OF_RANGE
;
732 res
= malloc((n
+ 2) * sizeof(char *));
733 ptr
= str
= strdup(param
);
738 ptr
= get_nextsep(ptr
, separator
, 1);
740 res
[n
] = strdup(last_ptr
);
744 len
= ptr
- last_ptr
;
745 res
[n
] = malloc(len
+ 1);
747 strncpy(res
[n
], last_ptr
, len
);
757 return str_list_add(res
, n
, dst
, 0);
759 return str_list_add(res
, n
, dst
, 1);
761 return str_list_del(res
, n
, dst
);
771 static void copy_str_list(const m_option_t
*opt
, void *dst
, const void *src
)
788 for (n
= 0; s
[n
] != NULL
; n
++)
790 d
= malloc((n
+ 1) * sizeof(char *));
792 d
[n
] = s
[n
] ? strdup(s
[n
]) : NULL
;
797 static char *print_str_list(const m_option_t
*opt
, const void *src
)
802 if (!(src
&& VAL(src
)))
806 for (int i
= 0; lst
[i
]; i
++) {
808 ret
= talloc_strdup_append_buffer(ret
, ",");
809 ret
= talloc_strdup_append_buffer(ret
, lst
[i
]);
814 const m_option_type_t m_option_type_string_list
= {
816 "A list of strings separated by ','\n"
817 "Option with a name ending in an * permits using the following suffix: \n"
818 "\t-add: Add the given parameters at the end of the list.\n"
819 "\t-pre: Add the given parameters at the beginning of the list.\n"
820 "\t-del: Remove the entry at the given indices.\n"
821 "\t-clr: Clear the list.\n"
822 "e.g: -vf-add flip,mirror -vf-del 2,5\n",
824 M_OPT_TYPE_DYNAMIC
| M_OPT_TYPE_ALLOW_WILDCARD
,
834 /////////////////// Func based options
836 // A chained list to save the various calls for func_param
837 typedef struct m_func_save m_func_save_t
;
845 #define VAL(x) (*(m_func_save_t **)(x))
847 static void free_func_pf(void *src
)
849 m_func_save_t
*s
, *n
;
866 // Parser for func_param
867 static int parse_func_pf(const m_option_t
*opt
, const char *name
,
868 const char *param
, void *dst
, int src
)
870 m_func_save_t
*s
, *p
;
875 s
= calloc(1, sizeof(m_func_save_t
));
876 s
->name
= strdup(name
);
877 s
->param
= param
? strdup(param
) : NULL
;
881 for (; p
->next
!= NULL
; p
= p
->next
)
890 static void copy_func_pf(const m_option_t
*opt
, void *dst
, const void *src
)
892 m_func_save_t
*d
= NULL
, *s
, *last
= NULL
;
902 d
= calloc(1, sizeof(m_func_save_t
));
903 d
->name
= strdup(s
->name
);
904 d
->param
= s
->param
? strdup(s
->param
) : NULL
;
916 /////////////////// Func_param
918 static void set_func_param(const m_option_t
*opt
, void *dst
, const void *src
)
929 for (; s
!= NULL
; s
= s
->next
)
930 ((m_opt_func_param_t
) opt
->p
)(opt
, s
->param
);
933 const m_option_type_t m_option_type_func_param
= {
936 sizeof(m_func_save_t
*),
940 NULL
, // Nothing to do on save
950 static int parse_func(const m_option_t
*opt
, const char *name
,
951 const char *param
, void *dst
, int src
)
956 static void set_func(const m_option_t
*opt
, void *dst
, const void *src
)
958 ((m_opt_func_t
) opt
->p
)(opt
);
961 const m_option_type_t m_option_type_func
= {
968 NULL
, // Nothing to do on save
974 /////////////////// Print
976 static int parse_print(const m_option_t
*opt
, const char *name
,
977 const char *param
, void *dst
, int src
)
979 if (opt
->type
== CONF_TYPE_PRINT_INDIRECT
)
980 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "%s", *(char **) opt
->p
);
981 else if (opt
->type
== CONF_TYPE_PRINT_FUNC
)
982 return ((m_opt_func_full_t
) opt
->p
)(opt
, name
, param
);
984 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "%s", mp_gtext(opt
->p
));
986 if (opt
->priv
== NULL
)
991 const m_option_type_t m_option_type_print
= {
1004 const m_option_type_t m_option_type_print_indirect
= {
1017 const m_option_type_t m_option_type_print_func
= {
1021 M_OPT_TYPE_ALLOW_WILDCARD
,
1031 /////////////////////// Subconfig
1033 #define VAL(x) (*(char ***)(x))
1035 static int parse_subconf(const m_option_t
*opt
, const char *name
,
1036 const char *param
, void *dst
, int src
)
1041 const m_option_t
*subopts
;
1045 if (param
== NULL
|| strlen(param
) == 0)
1046 return M_OPT_MISSING_PARAM
;
1048 subparam
= malloc(strlen(param
) + 1);
1049 subopt
= malloc(strlen(param
) + 1);
1056 int optlen
= strcspn(p
, ":=");
1058 subopt
[0] = subparam
[0] = 0;
1059 av_strlcpy(subopt
, p
, optlen
+ 1);
1066 optlen
= strcspn(p
, "\"");
1067 av_strlcpy(subparam
, p
, optlen
+ 1);
1070 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1071 "Terminating '\"' missing for '%s'\n", subopt
);
1072 return M_OPT_INVALID
;
1075 } else if (p
[0] == '%') {
1077 optlen
= (int)strtol(p
, (char **)&p
, 0);
1078 if (!p
|| p
[0] != '%' || (optlen
> strlen(p
) - 1)) {
1079 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1080 "Invalid length %i for '%s'\n", optlen
, subopt
);
1081 return M_OPT_INVALID
;
1084 av_strlcpy(subparam
, p
, optlen
+ 1);
1087 optlen
= strcspn(p
, ":");
1088 av_strlcpy(subparam
, p
, optlen
+ 1);
1095 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1096 "Incorrect termination for '%s'\n", subopt
);
1097 return M_OPT_INVALID
;
1100 switch (sscanf_ret
) {
1104 for (i
= 0; subopts
[i
].name
; i
++)
1105 if (!strcmp(subopts
[i
].name
, subopt
))
1107 if (!subopts
[i
].name
) {
1108 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1109 "Option %s: Unknown suboption %s\n", name
, subopt
);
1110 return M_OPT_UNKNOWN
;
1112 r
= m_option_parse(&subopts
[i
], subopt
,
1113 subparam
[0] == 0 ? NULL
: subparam
, NULL
, src
);
1117 lst
= realloc(lst
, 2 * (nr
+ 2) * sizeof(char *));
1118 lst
[2 * nr
] = strdup(subopt
);
1119 lst
[2 * nr
+ 1] = subparam
[0] == 0 ? NULL
: strdup(subparam
);
1120 memset(&lst
[2 * (nr
+ 1)], 0, 2 * sizeof(char *));
1135 const m_option_type_t m_option_type_subconfig
= {
1137 "The syntax is -option opt1=foo:flag:opt2=blah",
1139 M_OPT_TYPE_HAS_CHILD
,
1148 #include "libmpcodecs/img_format.h"
1150 /* FIXME: snyc with img_format.h */
1154 } mp_imgfmt_list
[] = {
1155 {"444p16le", IMGFMT_444P16_LE
},
1156 {"444p16be", IMGFMT_444P16_BE
},
1157 {"444p10le", IMGFMT_444P10_LE
},
1158 {"444p10be", IMGFMT_444P10_BE
},
1159 {"444p9le", IMGFMT_444P9_LE
},
1160 {"444p9be", IMGFMT_444P9_BE
},
1161 {"422p16le", IMGFMT_422P16_LE
},
1162 {"422p16be", IMGFMT_422P16_BE
},
1163 {"422p10le", IMGFMT_422P10_LE
},
1164 {"422p10be", IMGFMT_422P10_BE
},
1165 {"420p16le", IMGFMT_420P16_LE
},
1166 {"420p16be", IMGFMT_420P16_BE
},
1167 {"420p10le", IMGFMT_420P10_LE
},
1168 {"420p10be", IMGFMT_420P10_BE
},
1169 {"420p9le", IMGFMT_420P9_LE
},
1170 {"420p9be", IMGFMT_420P9_BE
},
1171 {"444p16", IMGFMT_444P16
},
1172 {"444p10", IMGFMT_444P10
},
1173 {"444p9", IMGFMT_444P9
},
1174 {"422p16", IMGFMT_422P16
},
1175 {"422p10", IMGFMT_422P10
},
1176 {"420p10", IMGFMT_420P10
},
1177 {"420p9", IMGFMT_420P9
},
1178 {"420p16", IMGFMT_420P16
},
1179 {"420a", IMGFMT_420A
},
1180 {"444p", IMGFMT_444P
},
1181 {"422p", IMGFMT_422P
},
1182 {"411p", IMGFMT_411P
},
1183 {"440p", IMGFMT_440P
},
1184 {"yuy2", IMGFMT_YUY2
},
1185 {"uyvy", IMGFMT_UYVY
},
1186 {"yvu9", IMGFMT_YVU9
},
1187 {"if09", IMGFMT_IF09
},
1188 {"yv12", IMGFMT_YV12
},
1189 {"i420", IMGFMT_I420
},
1190 {"iyuv", IMGFMT_IYUV
},
1191 {"clpl", IMGFMT_CLPL
},
1192 {"hm12", IMGFMT_HM12
},
1193 {"y800", IMGFMT_Y800
},
1195 {"nv12", IMGFMT_NV12
},
1196 {"nv21", IMGFMT_NV21
},
1197 {"bgr24", IMGFMT_BGR24
},
1198 {"bgr32", IMGFMT_BGR32
},
1199 {"bgr16", IMGFMT_BGR16
},
1200 {"bgr15", IMGFMT_BGR15
},
1201 {"bgr12", IMGFMT_BGR12
},
1202 {"bgr8", IMGFMT_BGR8
},
1203 {"bgr4", IMGFMT_BGR4
},
1204 {"bg4b", IMGFMT_BG4B
},
1205 {"bgr1", IMGFMT_BGR1
},
1206 {"rgb48be", IMGFMT_RGB48BE
},
1207 {"rgb48le", IMGFMT_RGB48LE
},
1208 {"rgb48ne", IMGFMT_RGB48NE
},
1209 {"rgb24", IMGFMT_RGB24
},
1210 {"rgb32", IMGFMT_RGB32
},
1211 {"rgb16", IMGFMT_RGB16
},
1212 {"rgb15", IMGFMT_RGB15
},
1213 {"rgb12", IMGFMT_RGB12
},
1214 {"rgb8", IMGFMT_RGB8
},
1215 {"rgb4", IMGFMT_RGB4
},
1216 {"rg4b", IMGFMT_RG4B
},
1217 {"rgb1", IMGFMT_RGB1
},
1218 {"rgba", IMGFMT_RGBA
},
1219 {"argb", IMGFMT_ARGB
},
1220 {"bgra", IMGFMT_BGRA
},
1221 {"abgr", IMGFMT_ABGR
},
1222 {"mjpeg", IMGFMT_MJPEG
},
1223 {"mjpg", IMGFMT_MJPEG
},
1227 static int parse_imgfmt(const m_option_t
*opt
, const char *name
,
1228 const char *param
, void *dst
, int src
)
1233 if (param
== NULL
|| strlen(param
) == 0)
1234 return M_OPT_MISSING_PARAM
;
1236 if (!strcmp(param
, "help")) {
1237 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "Available formats:");
1238 for (i
= 0; mp_imgfmt_list
[i
].name
; i
++)
1239 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, " %s", mp_imgfmt_list
[i
].name
);
1240 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "\n");
1241 return M_OPT_EXIT
- 1;
1244 if (sscanf(param
, "0x%x", &fmt
) != 1) {
1245 for (i
= 0; mp_imgfmt_list
[i
].name
; i
++) {
1246 if (!strcasecmp(param
, mp_imgfmt_list
[i
].name
)) {
1247 fmt
= mp_imgfmt_list
[i
].fmt
;
1251 if (!mp_imgfmt_list
[i
].name
) {
1252 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1253 "Option %s: unknown format name: '%s'\n", name
, param
);
1254 return M_OPT_INVALID
;
1259 *((uint32_t *)dst
) = fmt
;
1264 const m_option_type_t m_option_type_imgfmt
= {
1266 "Please report any missing colorspaces.",
1277 #include "libaf/af_format.h"
1279 /* FIXME: snyc with af_format.h */
1283 } mp_afmt_list
[] = {
1285 {"mulaw", AF_FORMAT_MU_LAW
},
1286 {"alaw", AF_FORMAT_A_LAW
},
1287 {"mpeg2", AF_FORMAT_MPEG2
},
1288 {"ac3le", AF_FORMAT_AC3_LE
},
1289 {"ac3be", AF_FORMAT_AC3_BE
},
1290 {"ac3ne", AF_FORMAT_AC3_NE
},
1291 {"imaadpcm", AF_FORMAT_IMA_ADPCM
},
1293 {"u8", AF_FORMAT_U8
},
1294 {"s8", AF_FORMAT_S8
},
1295 {"u16le", AF_FORMAT_U16_LE
},
1296 {"u16be", AF_FORMAT_U16_BE
},
1297 {"u16ne", AF_FORMAT_U16_NE
},
1298 {"s16le", AF_FORMAT_S16_LE
},
1299 {"s16be", AF_FORMAT_S16_BE
},
1300 {"s16ne", AF_FORMAT_S16_NE
},
1301 {"u24le", AF_FORMAT_U24_LE
},
1302 {"u24be", AF_FORMAT_U24_BE
},
1303 {"u24ne", AF_FORMAT_U24_NE
},
1304 {"s24le", AF_FORMAT_S24_LE
},
1305 {"s24be", AF_FORMAT_S24_BE
},
1306 {"s24ne", AF_FORMAT_S24_NE
},
1307 {"u32le", AF_FORMAT_U32_LE
},
1308 {"u32be", AF_FORMAT_U32_BE
},
1309 {"u32ne", AF_FORMAT_U32_NE
},
1310 {"s32le", AF_FORMAT_S32_LE
},
1311 {"s32be", AF_FORMAT_S32_BE
},
1312 {"s32ne", AF_FORMAT_S32_NE
},
1313 {"floatle", AF_FORMAT_FLOAT_LE
},
1314 {"floatbe", AF_FORMAT_FLOAT_BE
},
1315 {"floatne", AF_FORMAT_FLOAT_NE
},
1319 static int parse_afmt(const m_option_t
*opt
, const char *name
,
1320 const char *param
, void *dst
, int src
)
1325 if (param
== NULL
|| strlen(param
) == 0)
1326 return M_OPT_MISSING_PARAM
;
1328 if (!strcmp(param
, "help")) {
1329 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "Available formats:");
1330 for (i
= 0; mp_afmt_list
[i
].name
; i
++)
1331 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, " %s", mp_afmt_list
[i
].name
);
1332 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "\n");
1333 return M_OPT_EXIT
- 1;
1336 if (sscanf(param
, "0x%x", &fmt
) != 1) {
1337 for (i
= 0; mp_afmt_list
[i
].name
; i
++) {
1338 if (!strcasecmp(param
, mp_afmt_list
[i
].name
)) {
1339 fmt
= mp_afmt_list
[i
].fmt
;
1343 if (!mp_afmt_list
[i
].name
) {
1344 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1345 "Option %s: unknown format name: '%s'\n", name
, param
);
1346 return M_OPT_INVALID
;
1351 *((uint32_t *)dst
) = fmt
;
1356 const m_option_type_t m_option_type_afmt
= {
1358 "Please report any missing formats.",
1370 int parse_timestring(const char *str
, double *time
, char endchar
)
1374 *time
= 0; /* ensure initialization for error cases */
1375 if (sscanf(str
, "%d:%d:%lf%n", &a
, &b
, &d
, &len
) >= 3)
1376 *time
= 3600 * a
+ 60 * b
+ d
;
1377 else if (sscanf(str
, "%d:%lf%n", &a
, &d
, &len
) >= 2)
1379 else if (sscanf(str
, "%lf%n", &d
, &len
) >= 1)
1382 return 0; /* unsupported time format */
1383 if (str
[len
] && str
[len
] != endchar
)
1384 return 0; /* invalid extra characters at the end */
1389 static int parse_time(const m_option_t
*opt
, const char *name
,
1390 const char *param
, void *dst
, int src
)
1394 if (param
== NULL
|| strlen(param
) == 0)
1395 return M_OPT_MISSING_PARAM
;
1397 if (!parse_timestring(param
, &time
, 0)) {
1398 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option %s: invalid time: '%s'\n",
1400 return M_OPT_INVALID
;
1404 *(double *)dst
= time
;
1408 const m_option_type_t m_option_type_time
= {
1422 // Time or size (-endpos)
1424 static int parse_time_size(const m_option_t
*opt
, const char *name
,
1425 const char *param
, void *dst
, int src
)
1431 if (param
== NULL
|| strlen(param
) == 0)
1432 return M_OPT_MISSING_PARAM
;
1435 /* End at size parsing */
1436 if (sscanf(param
, "%lf%3s", &end_at
, unit
) == 2) {
1437 ts
.type
= END_AT_SIZE
;
1438 if (!strcasecmp(unit
, "b"))
1440 else if (!strcasecmp(unit
, "kb"))
1442 else if (!strcasecmp(unit
, "mb"))
1443 end_at
*= 1024 * 1024;
1444 else if (!strcasecmp(unit
, "gb"))
1445 end_at
*= 1024 * 1024 * 1024;
1447 ts
.type
= END_AT_NONE
;
1449 if (ts
.type
== END_AT_SIZE
) {
1455 /* End at time parsing. This has to be last because the parsing accepts
1456 * even a number followed by garbage */
1457 if (!parse_timestring(param
, &end_at
, 0)) {
1458 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1459 "Option %s: invalid time or size: '%s'\n",
1461 return M_OPT_INVALID
;
1464 ts
.type
= END_AT_TIME
;
1468 *(m_time_size_t
*)dst
= ts
;
1472 const m_option_type_t m_option_type_time_size
= {
1475 sizeof(m_time_size_t
),
1486 //// Objects (i.e. filters, etc) settings
1488 #include "m_struct.h"
1491 #define VAL(x) (*(m_obj_settings_t **)(x))
1493 static int find_obj_desc(const char *name
, const m_obj_list_t
*l
,
1494 const m_struct_t
**ret
)
1499 for (i
= 0; l
->list
[i
]; i
++) {
1500 n
= M_ST_MB(char *, l
->list
[i
], l
->name_off
);
1501 if (!strcmp(n
, name
)) {
1502 *ret
= M_ST_MB(m_struct_t
*, l
->list
[i
], l
->desc_off
);
1509 static int get_obj_param(const char *opt_name
, const char *obj_name
,
1510 const m_struct_t
*desc
, char *str
, int *nold
,
1511 int oldmax
, char **dst
)
1514 const m_option_t
*opt
;
1517 eq
= strchr(str
, '=');
1518 if (eq
&& eq
== str
)
1526 opt
= m_option_list_find(desc
->fields
, str
);
1528 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1529 "Option %s: %s doesn't have a %s parameter.\n",
1530 opt_name
, obj_name
, str
);
1531 return M_OPT_UNKNOWN
;
1533 r
= m_option_parse(opt
, str
, p
, NULL
, M_CONFIG_FILE
);
1536 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1537 "Option %s: Error while parsing %s parameter %s (%s)\n",
1538 opt_name
, obj_name
, str
, p
);
1543 dst
[0] = strdup(str
);
1544 dst
[1] = p
? strdup(p
) : NULL
;
1548 if ((*nold
) >= oldmax
) {
1549 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option %s: %s has only %d params, so you can't give more than %d unnamed params.\n",
1550 opt_name
, obj_name
, oldmax
, oldmax
);
1551 return M_OPT_OUT_OF_RANGE
;
1553 opt
= &desc
->fields
[(*nold
)];
1554 r
= m_option_parse(opt
, opt
->name
, str
, NULL
, M_CONFIG_FILE
);
1557 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1558 "Option %s: Error while parsing %s parameter %s (%s)\n",
1559 opt_name
, obj_name
, opt
->name
, str
);
1563 dst
[0] = strdup(opt
->name
);
1564 dst
[1] = strdup(str
);
1571 static int get_obj_params(const char *opt_name
, const char *name
, char *params
,
1572 const m_struct_t
*desc
, char separator
, char ***_ret
)
1574 int n
= 0, nold
= 0, nopts
, r
;
1575 char *ptr
, *last_ptr
= params
;
1578 if (!strcmp(params
, "help")) { // Help
1579 char min
[50], max
[50];
1580 if (!desc
->fields
) {
1581 printf("%s doesn't have any options.\n\n", name
);
1582 return M_OPT_EXIT
- 1;
1584 printf("\n Name Type Min Max\n\n");
1585 for (n
= 0; desc
->fields
[n
].name
; n
++) {
1586 const m_option_t
*opt
= &desc
->fields
[n
];
1587 if (opt
->type
->flags
& M_OPT_TYPE_HAS_CHILD
)
1589 if (opt
->flags
& M_OPT_MIN
)
1590 sprintf(min
, "%-8.0f", opt
->min
);
1593 if (opt
->flags
& M_OPT_MAX
)
1594 sprintf(max
, "%-8.0f", opt
->max
);
1597 printf(" %-20.20s %-15.15s %-10.10s %-10.10s\n",
1604 return M_OPT_EXIT
- 1;
1607 for (nopts
= 0; desc
->fields
[nopts
].name
; nopts
++)
1610 // TODO : Check that each opt can be parsed
1612 while (last_ptr
&& last_ptr
[0] != '\0') {
1613 ptr
= strchr(last_ptr
, separator
);
1615 r
= get_obj_param(opt_name
, name
, desc
, last_ptr
, &nold
, nopts
,
1620 if (ptr
== last_ptr
) { // Empty field, count it and go on
1626 r
= get_obj_param(opt_name
, name
, desc
, last_ptr
, &nold
, nopts
, NULL
);
1635 if (!last_ptr
[0]) // count an empty field at the end, too
1638 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Too many options for %s\n", name
);
1639 return M_OPT_OUT_OF_RANGE
;
1641 if (!_ret
) // Just test
1643 if (n
== 0) // No options or only empty options
1646 ret
= malloc((n
+ 2) * 2 * sizeof(char *));
1650 while (last_ptr
&& last_ptr
[0] != '\0') {
1651 ptr
= strchr(last_ptr
, separator
);
1653 get_obj_param(opt_name
, name
, desc
, last_ptr
, &nold
, nopts
,
1658 if (ptr
== last_ptr
) { // Empty field, count it and go on
1664 get_obj_param(opt_name
, name
, desc
, last_ptr
, &nold
, nopts
,
1669 ret
[n
* 2] = ret
[n
* 2 + 1] = NULL
;
1675 static int parse_obj_params(const m_option_t
*opt
, const char *name
,
1676 const char *param
, void *dst
, int src
)
1680 m_obj_params_t
*p
= opt
->priv
;
1681 const m_struct_t
*desc
;
1684 // We need the object desc
1686 return M_OPT_INVALID
;
1689 cpy
= strdup(param
);
1690 r
= get_obj_params(name
, desc
->name
, cpy
, desc
, p
->separator
,
1691 dst
? &opts
: NULL
);
1697 if (!opts
) // no arguments given
1700 for (r
= 0; opts
[r
]; r
+= 2)
1701 m_struct_set(desc
, dst
, opts
[r
], opts
[r
+ 1]);
1707 const m_option_type_t m_option_type_obj_params
= {
1720 /// Some predefined types as a definition would be quite lengthy
1723 static const m_span_t m_span_params_dflts
= {
1726 static const m_option_t m_span_params_fields
[] = {
1727 {"start", M_ST_OFF(m_span_t
, start
), CONF_TYPE_INT
, M_OPT_MIN
, 1, 0, NULL
},
1728 {"end", M_ST_OFF(m_span_t
, end
), CONF_TYPE_INT
, M_OPT_MIN
, 1, 0, NULL
},
1729 { NULL
, NULL
, 0, 0, 0, 0, NULL
}
1731 static const struct m_struct_st m_span_opts
= {
1734 &m_span_params_dflts
,
1735 m_span_params_fields
1737 const m_obj_params_t m_span_params_def
= {
1742 static int parse_obj_settings(const char *opt
, char *str
,
1743 const m_obj_list_t
*list
,
1744 m_obj_settings_t
**_ret
, int ret_n
)
1747 char *param
, **plist
= NULL
;
1748 const m_struct_t
*desc
;
1749 m_obj_settings_t
*ret
= _ret
? *_ret
: NULL
;
1752 // Now check that the object exists
1753 param
= strchr(str
, '=');
1757 if (strlen(param
) <= 0)
1762 if (!find_obj_desc(str
, list
, &desc
)) {
1763 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option %s: %s doesn't exist.\n",
1765 return M_OPT_INVALID
;
1769 if (!desc
&& _ret
) {
1770 if (!strcmp(param
, "help")) {
1771 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
,
1772 "Option %s: %s have no option description.\n", opt
, str
);
1773 return M_OPT_EXIT
- 1;
1775 plist
= calloc(4, sizeof(char *));
1776 plist
[0] = strdup("_oldargs_");
1777 plist
[1] = strdup(param
);
1779 r
= get_obj_params(opt
, str
, param
, desc
, ':',
1780 _ret
? &plist
: NULL
);
1788 ret
= realloc(ret
, (ret_n
+ 2) * sizeof(m_obj_settings_t
));
1789 memset(&ret
[ret_n
], 0, 2 * sizeof(m_obj_settings_t
));
1790 ret
[ret_n
].name
= strdup(str
);
1791 ret
[ret_n
].attribs
= plist
;
1797 static int obj_settings_list_del(const char *opt_name
, const char *param
,
1800 char **str_list
= NULL
;
1801 int r
, i
, idx_max
= 0;
1802 char *rem_id
= "_removed_marker_";
1803 const m_option_t list_opt
= {
1804 opt_name
, NULL
, CONF_TYPE_STRING_LIST
,
1807 m_obj_settings_t
*obj_list
= dst
? VAL(dst
) : NULL
;
1809 if (dst
&& !obj_list
) {
1810 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
, "Option %s: the list is empty.\n",
1813 } else if (obj_list
) {
1814 for (idx_max
= 0; obj_list
[idx_max
].name
!= NULL
; idx_max
++)
1818 r
= m_option_parse(&list_opt
, opt_name
, param
, &str_list
, src
);
1819 if (r
< 0 || !str_list
)
1822 for (r
= 0; str_list
[r
]; r
++) {
1825 id
= strtol(str_list
[r
], &endptr
, 0);
1826 if (endptr
== str_list
[r
]) {
1827 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option %s: invalid parameter. We need a list of integers which are the indices of the elements to remove.\n", opt_name
);
1828 m_option_free(&list_opt
, &str_list
);
1829 return M_OPT_INVALID
;
1833 if (id
>= idx_max
|| id
< -idx_max
) {
1834 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
1835 "Option %s: Index %d is out of range.\n", opt_name
, id
);
1840 free(obj_list
[id
].name
);
1841 free_str_list(&(obj_list
[id
].attribs
));
1842 obj_list
[id
].name
= rem_id
;
1846 m_option_free(&list_opt
, &str_list
);
1850 for (i
= 0; obj_list
[i
].name
; i
++) {
1851 while (obj_list
[i
].name
== rem_id
) {
1852 memmove(&obj_list
[i
], &obj_list
[i
+ 1],
1853 sizeof(m_obj_settings_t
) * (idx_max
- i
));
1857 obj_list
= realloc(obj_list
, sizeof(m_obj_settings_t
) * (idx_max
+ 1));
1858 VAL(dst
) = obj_list
;
1863 static void free_obj_settings_list(void *dst
)
1866 m_obj_settings_t
*d
;
1868 if (!dst
|| !VAL(dst
))
1873 for (n
= 0; d
[n
].name
; n
++) {
1875 free_str_list(&(d
[n
].attribs
));
1882 static int parse_obj_settings_list(const m_option_t
*opt
, const char *name
,
1883 const char *param
, void *dst
, int src
)
1885 int n
= 0, r
, len
= strlen(opt
->name
);
1887 char *ptr
, *last_ptr
;
1888 m_obj_settings_t
*res
= NULL
, *queue
= NULL
, *head
= NULL
;
1891 // We need the objects list
1893 return M_OPT_INVALID
;
1895 if (opt
->name
[len
- 1] == '*' && ((int)strlen(name
) > len
- 1)) {
1896 const char *n
= &name
[len
- 1];
1897 if (strcasecmp(n
, "-add") == 0)
1899 else if (strcasecmp(n
, "-pre") == 0)
1901 else if (strcasecmp(n
, "-del") == 0)
1903 else if (strcasecmp(n
, "-clr") == 0)
1907 strncpy(prefix
, opt
->name
, len
- 1);
1908 prefix
[len
- 1] = '\0';
1909 mp_msg(MSGT_VFILTER
, MSGL_ERR
, "Option %s: unknown postfix %s\n"
1910 "Supported postfixes are:\n"
1912 " Append the given list to the current list\n\n"
1914 " Prepend the given list to the current list\n\n"
1916 " Remove the given elements. Take the list element index (starting from 0).\n"
1917 " Negative index can be used (i.e. -1 is the last element)\n\n"
1919 " Clear the current list.\n",
1920 name
, n
, prefix
, prefix
, prefix
, prefix
);
1922 return M_OPT_UNKNOWN
;
1926 // Clear the list ??
1929 free_obj_settings_list(dst
);
1933 if (param
== NULL
|| strlen(param
) == 0)
1934 return M_OPT_MISSING_PARAM
;
1946 return obj_settings_list_del(name
, param
, dst
, src
);
1948 if (dst
&& VAL(dst
))
1949 free_obj_settings_list(dst
);
1952 mp_msg(MSGT_VFILTER
, MSGL_ERR
, "Option %s: FIXME\n", name
);
1953 return M_OPT_UNKNOWN
;
1956 if (!strcmp(param
, "help")) {
1957 m_obj_list_t
*ol
= opt
->priv
;
1958 mp_msg(MSGT_VFILTER
, MSGL_INFO
, "Available video filters:\n");
1959 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VIDEO_FILTERS\n");
1960 for (n
= 0; ol
->list
[n
]; n
++)
1961 mp_msg(MSGT_VFILTER
, MSGL_INFO
, " %-15s: %s\n",
1962 M_ST_MB(char *, ol
->list
[n
], ol
->name_off
),
1963 M_ST_MB(char *, ol
->list
[n
], ol
->info_off
));
1964 mp_msg(MSGT_VFILTER
, MSGL_INFO
, "\n");
1965 return M_OPT_EXIT
- 1;
1967 ptr
= str
= strdup(param
);
1969 while (ptr
[0] != '\0') {
1971 ptr
= get_nextsep(ptr
, OPTION_LIST_SEPARATOR
, 1);
1974 r
= parse_obj_settings(name
, last_ptr
, opt
->priv
,
1975 dst
? &res
: NULL
, n
);
1984 r
= parse_obj_settings(name
, last_ptr
, opt
->priv
, dst
? &res
: NULL
, n
);
1994 return M_OPT_INVALID
;
1996 if (((opt
->flags
& M_OPT_MIN
) && (n
< opt
->min
)) ||
1997 ((opt
->flags
& M_OPT_MAX
) && (n
> opt
->max
)))
1998 return M_OPT_OUT_OF_RANGE
;
2003 for (qsize
= 0; queue
[qsize
].name
; qsize
++)
2005 res
= realloc(res
, (qsize
+ n
+ 1) * sizeof(m_obj_settings_t
));
2006 memcpy(&res
[n
], queue
, (qsize
+ 1) * sizeof(m_obj_settings_t
));
2012 for (hsize
= 0; head
[hsize
].name
; hsize
++)
2014 head
= realloc(head
, (hsize
+ n
+ 1) * sizeof(m_obj_settings_t
));
2015 memcpy(&head
[hsize
], res
, (n
+ 1) * sizeof(m_obj_settings_t
));
2024 static void copy_obj_settings_list(const m_option_t
*opt
, void *dst
,
2027 m_obj_settings_t
*d
, *s
;
2036 free_obj_settings_list(dst
);
2042 for (n
= 0; s
[n
].name
; n
++)
2044 d
= malloc((n
+ 1) * sizeof(m_obj_settings_t
));
2045 for (n
= 0; s
[n
].name
; n
++) {
2046 d
[n
].name
= strdup(s
[n
].name
);
2047 d
[n
].attribs
= NULL
;
2048 copy_str_list(NULL
, &(d
[n
].attribs
), &(s
[n
].attribs
));
2051 d
[n
].attribs
= NULL
;
2055 const m_option_type_t m_option_type_obj_settings_list
= {
2056 "Object settings list",
2058 sizeof(m_obj_settings_t
*),
2059 M_OPT_TYPE_DYNAMIC
| M_OPT_TYPE_ALLOW_WILDCARD
,
2060 parse_obj_settings_list
,
2062 copy_obj_settings_list
,
2063 copy_obj_settings_list
,
2064 copy_obj_settings_list
,
2065 free_obj_settings_list
,
2070 static int parse_obj_presets(const m_option_t
*opt
, const char *name
,
2071 const char *param
, void *dst
, int src
)
2073 m_obj_presets_t
*obj_p
= (m_obj_presets_t
*)opt
->priv
;
2074 const m_struct_t
*in_desc
;
2075 const m_struct_t
*out_desc
;
2077 const unsigned char *pre
;
2078 char *pre_name
= NULL
;
2081 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option %s: Presets need a "
2082 "pointer to a m_obj_presets_t in the priv field.\n", name
);
2083 return M_OPT_PARSER_ERR
;
2087 return M_OPT_MISSING_PARAM
;
2089 pre
= obj_p
->presets
;
2090 in_desc
= obj_p
->in_desc
;
2091 out_desc
= obj_p
->out_desc
? obj_p
->out_desc
: obj_p
->in_desc
;
2094 if (!strcmp(param
, "help")) {
2095 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "Available presets for %s->%s:",
2096 out_desc
->name
, name
);
2097 for (pre
= obj_p
->presets
;
2098 (pre_name
= M_ST_MB(char *, pre
, obj_p
->name_off
)); pre
+= s
)
2099 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, " %s", pre_name
);
2100 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "\n");
2101 return M_OPT_EXIT
- 1;
2104 for (pre_name
= M_ST_MB(char *, pre
, obj_p
->name_off
); pre_name
;
2105 pre
+= s
, pre_name
= M_ST_MB(char *, pre
, obj_p
->name_off
))
2106 if (!strcmp(pre_name
, param
))
2109 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2110 "Option %s: There is no preset named %s\n"
2111 "Available presets are:", name
, param
);
2112 for (pre
= obj_p
->presets
;
2113 (pre_name
= M_ST_MB(char *, pre
, obj_p
->name_off
)); pre
+= s
)
2114 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, " %s", pre_name
);
2115 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "\n");
2116 return M_OPT_INVALID
;
2122 for (i
= 0; in_desc
->fields
[i
].name
; i
++) {
2123 const m_option_t
*out_opt
= m_option_list_find(out_desc
->fields
,
2124 in_desc
->fields
[i
].name
);
2126 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2127 "Option %s: Unable to find the target option for field %s.\n"
2128 "Please report this to the developers.\n",
2129 name
, in_desc
->fields
[i
].name
);
2130 return M_OPT_PARSER_ERR
;
2132 m_option_copy(out_opt
, M_ST_MB_P(dst
, out_opt
->p
),
2133 M_ST_MB_P(pre
, in_desc
->fields
[i
].p
));
2139 const m_option_type_t m_option_type_obj_presets
= {
2152 static int parse_custom_url(const m_option_t
*opt
, const char *name
,
2153 const char *url
, void *dst
, int src
)
2155 int pos1
, pos2
, r
, v6addr
= 0;
2156 char *ptr1
= NULL
, *ptr2
= NULL
, *ptr3
= NULL
, *ptr4
= NULL
;
2157 m_struct_t
*desc
= opt
->priv
;
2160 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option %s: Custom URL needs "
2161 "a pointer to a m_struct_t in the priv field.\n", name
);
2162 return M_OPT_PARSER_ERR
;
2165 // extract the protocol
2166 ptr1
= strstr(url
, "://");
2169 if (m_option_list_find(desc
->fields
, "filename")) {
2170 m_struct_set(desc
, dst
, "filename", url
);
2173 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2174 "Option %s: URL doesn't have a valid protocol!\n", name
);
2175 return M_OPT_INVALID
;
2177 if (m_option_list_find(desc
->fields
, "string")) {
2178 if (strlen(ptr1
) > 3) {
2179 m_struct_set(desc
, dst
, "string", ptr1
+ 3);
2184 if (dst
&& m_option_list_find(desc
->fields
, "protocol")) {
2186 r
= m_struct_set(desc
, dst
, "protocol", url
);
2189 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2190 "Option %s: Error while setting protocol.\n", name
);
2199 // check if a username:password is given
2200 ptr2
= strstr(ptr1
, "@");
2201 ptr3
= strstr(ptr1
, "/");
2202 if (ptr3
!= NULL
&& ptr3
< ptr2
) {
2203 // it isn't really a username but rather a part of the path
2208 // We got something, at least a username...
2209 if (!m_option_list_find(desc
->fields
, "username")) {
2210 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
2211 "Option %s: This URL doesn't have a username part.\n", name
);
2214 ptr3
= strstr(ptr1
, ":");
2215 if (ptr3
!= NULL
&& ptr3
< ptr2
) {
2216 // We also have a password
2217 if (!m_option_list_find(desc
->fields
, "password")) {
2218 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
2219 "Option %s: This URL doesn't have a password part.\n",
2222 } else { // Username and password
2225 r
= m_struct_set(desc
, dst
, "username", ptr1
);
2228 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2229 "Option %s: Error while setting username.\n",
2234 r
= m_struct_set(desc
, dst
, "password", ptr3
+ 1);
2237 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2238 "Option %s: Error while setting password.\n",
2244 } else { // User name only
2246 r
= m_struct_set(desc
, dst
, "username", ptr1
);
2249 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2250 "Option %s: Error while setting username.\n", name
);
2259 // Before looking for a port number check if we have an IPv6 type
2261 // In an IPv6 URL the numeric address should be inside square braces.
2262 ptr2
= strstr(ptr1
, "[");
2263 ptr3
= strstr(ptr1
, "]");
2264 // If the [] is after the first it isn't the hostname
2265 ptr4
= strstr(ptr1
, "/");
2266 if (ptr2
!= NULL
&& ptr3
!= NULL
&& (ptr2
< ptr3
)
2267 && (!ptr4
|| ptr4
> ptr3
)) {
2268 // we have an IPv6 numeric address
2276 // look if the port is given
2277 ptr2
= strstr(ptr2
, ":");
2278 // If the : is after the first / it isn't the port
2279 ptr3
= strstr(ptr1
, "/");
2280 if (ptr3
&& ptr3
- ptr2
< 0)
2284 // Look if a path is given
2287 // So we have an URL like http://www.hostname.com
2290 // We have an URL like http://www.hostname.com/file.txt
2294 // We have an URL beginning like http://www.hostname.com:1212
2295 // Get the port number
2296 if (!m_option_list_find(desc
->fields
, "port")) {
2297 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
2298 "Option %s: This URL doesn't have a port part.\n", name
);
2302 int p
= atoi(ptr2
+ 1);
2304 snprintf(tmp
, 99, "%d", p
);
2305 r
= m_struct_set(desc
, dst
, "port", tmp
);
2307 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2308 "Option %s: Error while setting port.\n", name
);
2318 if (pos2
- pos1
> 0) {
2319 if (!m_option_list_find(desc
->fields
, "hostname")) {
2320 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
2321 "Option %s: This URL doesn't have a hostname part.\n", name
);
2324 char tmp
[pos2
- pos1
+ 1];
2325 strncpy(tmp
, ptr1
, pos2
- pos1
);
2326 tmp
[pos2
- pos1
] = '\0';
2327 r
= m_struct_set(desc
, dst
, "hostname", tmp
);
2329 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2330 "Option %s: Error while setting hostname.\n", name
);
2335 // Look if a path is given
2336 ptr2
= strstr(ptr1
, "/");
2338 // A path/filename is given
2339 // check if it's not a trailing '/'
2340 if (strlen(ptr2
) > 1) {
2341 // copy the path/filename in the URL container
2342 if (!m_option_list_find(desc
->fields
, "filename")) {
2343 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
2344 "Option %s: This URL doesn't have a hostname part.\n",
2349 int l
= strlen(ptr2
+ 1) + 1;
2350 char *fname
= ptr2
+ 1;
2353 url_unescape_string(fname
, ptr2
+ 1);
2355 r
= m_struct_set(desc
, dst
, "filename", fname
);
2356 if (fname
!= ptr2
+ 1)
2359 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2360 "Option %s: Error while setting filename.\n",
2371 /// TODO : Write the other needed funcs for 'normal' options
2372 const m_option_type_t m_option_type_custom_url
= {