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 const m_option_t
*m_option_list_find(const m_option_t
*list
, const char *name
)
42 for (i
= 0; list
[i
].name
; i
++) {
43 int l
= strlen(list
[i
].name
) - 1;
44 if ((list
[i
].type
->flags
& M_OPT_TYPE_ALLOW_WILDCARD
)
45 && (l
> 0) && (list
[i
].name
[l
] == '*')) {
46 if (strncasecmp(list
[i
].name
, name
, l
) == 0)
48 } else if (strcasecmp(list
[i
].name
, name
) == 0)
54 // Default function that just does a memcpy
56 static void copy_opt(const m_option_t
*opt
, void *dst
, const void *src
)
59 memcpy(dst
, src
, opt
->type
->size
);
64 #define VAL(x) (*(int *)(x))
66 static int parse_flag(const m_option_t
*opt
, const char *name
,
67 const char *param
, void *dst
, int src
)
69 if (src
== M_CONFIG_FILE
) {
71 return M_OPT_MISSING_PARAM
;
72 if (!strcasecmp(param
, "yes") || /* any other language? */
73 !strcasecmp(param
, "on") ||
74 !strcasecmp(param
, "ja") ||
75 !strcasecmp(param
, "si") ||
76 !strcasecmp(param
, "igen") ||
77 !strcasecmp(param
, "y") ||
78 !strcasecmp(param
, "j") ||
79 !strcasecmp(param
, "i") ||
80 !strcasecmp(param
, "tak") ||
81 !strcasecmp(param
, "ja") ||
82 !strcasecmp(param
, "true") ||
83 !strcmp(param
, "1")) {
86 } else if (!strcasecmp(param
, "no") ||
87 !strcasecmp(param
, "off") ||
88 !strcasecmp(param
, "nein") ||
89 !strcasecmp(param
, "nicht") ||
90 !strcasecmp(param
, "nem") ||
91 !strcasecmp(param
, "n") ||
92 !strcasecmp(param
, "nie") ||
93 !strcasecmp(param
, "nej") ||
94 !strcasecmp(param
, "false") ||
95 !strcmp(param
, "0")) {
99 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
100 "Invalid parameter for %s flag: %s\n", name
, param
);
101 return M_OPT_INVALID
;
111 static char *print_flag(const m_option_t
*opt
, const void *val
)
113 if (VAL(val
) == opt
->min
)
114 return talloc_strdup(NULL
, "no");
116 return talloc_strdup(NULL
, "yes");
119 const m_option_type_t m_option_type_flag
= {
121 "need yes or no in config files",
134 static int parse_int(const m_option_t
*opt
, const char *name
,
135 const char *param
, void *dst
, int src
)
142 return M_OPT_MISSING_PARAM
;
144 tmp_int
= strtoll(param
, &endptr
, 10);
146 tmp_int
= strtoll(param
, &endptr
, 0);
148 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
149 "The %s option must be an integer: %s\n", name
, param
);
150 return M_OPT_INVALID
;
153 if ((opt
->flags
& M_OPT_MIN
) && (tmp_int
< opt
->min
)) {
154 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
155 "The %s option must be >= %d: %s\n",
156 name
, (int) opt
->min
, param
);
157 return M_OPT_OUT_OF_RANGE
;
160 if ((opt
->flags
& M_OPT_MAX
) && (tmp_int
> opt
->max
)) {
161 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
162 "The %s option must be <= %d: %s\n",
163 name
, (int) opt
->max
, param
);
164 return M_OPT_OUT_OF_RANGE
;
168 if (opt
->type
->size
== sizeof(int64_t))
169 *(int64_t *)dst
= tmp_int
;
177 static char *print_int(const m_option_t
*opt
, const void *val
)
179 if (opt
->type
->size
== sizeof(int64_t))
180 return talloc_asprintf(NULL
, "%"PRId64
, *(const int64_t *)val
);
181 return talloc_asprintf(NULL
, "%d", VAL(val
));
184 const m_option_type_t m_option_type_int
= {
197 const m_option_type_t m_option_type_int64
= {
210 static int parse_intpair(const struct m_option
*opt
, const char *name
,
211 const char *param
, void *dst
, int src
)
214 return M_OPT_MISSING_PARAM
;
216 char *s
= (char *)param
;
220 start
= strtol(s
, &s
, 10);
230 end
= strtol(s
, &s
, 10);
243 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Invalid integer range "
244 "specification for option %s: %s\n", name
, param
);
245 return M_OPT_INVALID
;
248 const struct m_option_type m_option_type_intpair
= {
250 .size
= sizeof(int[2]),
251 .parse
= parse_intpair
,
256 static int parse_choice(const struct m_option
*opt
, const char *name
,
257 const char *param
, void *dst
, int src
)
260 return M_OPT_MISSING_PARAM
;
262 struct m_opt_choice_alternatives
*alt
;
263 for (alt
= opt
->priv
; alt
->name
; alt
++)
264 if (!strcmp(param
, alt
->name
))
267 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Invalid value for option %s: %s\n",
269 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Valid values are:");
270 for (alt
= opt
->priv
; alt
->name
; alt
++)
271 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, " %s", alt
->name
);
272 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "\n");
273 return M_OPT_INVALID
;
276 *(int *)dst
= alt
->value
;
281 static char *print_choice(const m_option_t
*opt
, const void *val
)
284 struct m_opt_choice_alternatives
*alt
;
285 for (alt
= opt
->priv
; alt
->name
; alt
++)
287 return talloc_strdup(NULL
, alt
->name
);
291 const struct m_option_type m_option_type_choice
= {
292 .name
= "String", // same as arbitrary strings in option list for now
294 .parse
= parse_choice
,
295 .print
= print_choice
,
303 #define VAL(x) (*(double *)(x))
305 static int parse_double(const m_option_t
*opt
, const char *name
,
306 const char *param
, void *dst
, int src
)
313 return M_OPT_MISSING_PARAM
;
315 tmp_float
= strtod(param
, &endptr
);
320 tmp_float
/= strtod(endptr
+ 1, &endptr
);
324 /* we also handle floats specified with
325 * non-locale decimal point ::atmos
328 tmp_float
-= 1.0 / pow(10, strlen(endptr
+ 1)) *
329 strtod(endptr
+ 1, &endptr
);
331 tmp_float
+= 1.0 / pow(10, strlen(endptr
+ 1)) *
332 strtod(endptr
+ 1, &endptr
);
337 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
338 "The %s option must be a floating point number or a "
339 "ratio (numerator[:/]denominator): %s\n", name
, param
);
340 return M_OPT_INVALID
;
343 if (opt
->flags
& M_OPT_MIN
)
344 if (tmp_float
< opt
->min
) {
345 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
346 "The %s option must be >= %f: %s\n", name
, opt
->min
, param
);
347 return M_OPT_OUT_OF_RANGE
;
350 if (opt
->flags
& M_OPT_MAX
)
351 if (tmp_float
> opt
->max
) {
352 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
353 "The %s option must be <= %f: %s\n", name
, opt
->max
, param
);
354 return M_OPT_OUT_OF_RANGE
;
358 VAL(dst
) = tmp_float
;
362 static char *print_double(const m_option_t
*opt
, const void *val
)
365 return talloc_asprintf(NULL
, "%f", VAL(val
));
368 const m_option_type_t m_option_type_double
= {
370 "double precision floating point number or ratio (numerator[:/]denominator)",
382 #define VAL(x) (*(float *)(x))
384 static int parse_float(const m_option_t
*opt
, const char *name
,
385 const char *param
, void *dst
, int src
)
388 int r
= parse_double(opt
, name
, param
, &tmp
, src
);
394 static char *print_float(const m_option_t
*opt
, const void *val
)
397 return talloc_asprintf(NULL
, "%f", VAL(val
));
400 const m_option_type_t m_option_type_float
= {
402 "floating point number or ratio (numerator[:/]denominator)",
413 ///////////// Position
415 #define VAL(x) (*(off_t *)(x))
417 static int parse_position(const m_option_t
*opt
, const char *name
,
418 const char *param
, void *dst
, int src
)
424 return M_OPT_MISSING_PARAM
;
425 if (sscanf(param
, sizeof(off_t
) == sizeof(int) ?
426 "%d%c" : "%"PRId64
"%c", &tmp_off
, &dummy
) != 1) {
427 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
428 "The %s option must be an integer: %s\n", opt
->name
, param
);
429 return M_OPT_INVALID
;
432 if (opt
->flags
& M_OPT_MIN
)
433 if (tmp_off
< opt
->min
) {
434 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
435 "The %s option must be >= %"PRId64
": %s\n",
436 name
, (int64_t) opt
->min
, param
);
437 return M_OPT_OUT_OF_RANGE
;
440 if (opt
->flags
& M_OPT_MAX
)
441 if (tmp_off
> opt
->max
) {
442 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
443 "The %s option must be <= %"PRId64
": %s\n",
444 name
, (int64_t) opt
->max
, param
);
445 return M_OPT_OUT_OF_RANGE
;
453 static char *print_position(const m_option_t
*opt
, const void *val
)
455 return talloc_asprintf(NULL
, "%"PRId64
, (int64_t)VAL(val
));
458 const m_option_type_t m_option_type_position
= {
475 #define VAL(x) (*(char **)(x))
477 static int parse_str(const m_option_t
*opt
, const char *name
,
478 const char *param
, void *dst
, int src
)
483 return M_OPT_MISSING_PARAM
;
485 if ((opt
->flags
& M_OPT_MIN
) && (strlen(param
) < opt
->min
)) {
486 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Parameter must be >= %d chars: %s\n",
487 (int) opt
->min
, param
);
488 return M_OPT_OUT_OF_RANGE
;
491 if ((opt
->flags
& M_OPT_MAX
) && (strlen(param
) > opt
->max
)) {
492 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Parameter must be <= %d chars: %s\n",
493 (int) opt
->max
, param
);
494 return M_OPT_OUT_OF_RANGE
;
498 talloc_free(VAL(dst
));
499 VAL(dst
) = talloc_strdup(NULL
, param
);
506 static char *print_str(const m_option_t
*opt
, const void *val
)
508 return (val
&& VAL(val
)) ? talloc_strdup(NULL
, VAL(val
)) : NULL
;
511 static void copy_str(const m_option_t
*opt
, void *dst
, const void *src
)
514 talloc_free(VAL(dst
));
515 VAL(dst
) = talloc_strdup(NULL
, VAL(src
));
519 static void free_str(void *src
)
521 if (src
&& VAL(src
)) {
522 talloc_free(VAL(src
));
527 const m_option_type_t m_option_type_string
= {
540 //////////// String list
543 #define VAL(x) (*(char ***)(x))
551 static void free_str_list(void *dst
)
556 if (!dst
|| !VAL(dst
))
560 for (i
= 0; d
[i
] != NULL
; i
++)
566 static int str_list_add(char **add
, int n
, void *dst
, int pre
)
568 char **lst
= VAL(dst
);
572 return M_OPT_PARSER_ERR
;
575 for (ln
= 0; lst
&& lst
[ln
]; ln
++)
578 lst
= talloc_realloc(NULL
, lst
, char *, n
+ ln
+ 1);
581 memmove(&lst
[n
], lst
, ln
* sizeof(char *));
582 memcpy(lst
, add
, n
* sizeof(char *));
584 memcpy(&lst
[ln
], add
, n
* sizeof(char *));
585 // (re-)add NULL-termination
595 static int str_list_del(char **del
, int n
, void *dst
)
602 return M_OPT_PARSER_ERR
;
605 for (ln
= 0; lst
&& lst
[ln
]; ln
++)
609 for (i
= 0; del
[i
] != NULL
; i
++) {
610 idx
= strtol(del
[i
], &ep
, 0);
612 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Invalid index: %s\n", del
[i
]);
617 if (idx
< 0 || idx
>= ln
) {
618 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
619 "Index %ld is out of range.\n", idx
);
621 } else if (!lst
[idx
])
623 talloc_free(lst
[idx
]);
635 // Don't bother shrinking the list allocation
636 for (i
= 0, n
= 0; i
< ln
; i
++) {
647 static char *get_nextsep(char *ptr
, char sep
, int modify
)
649 char *last_ptr
= ptr
;
651 ptr
= strchr(ptr
, sep
);
652 if (ptr
&& ptr
> last_ptr
&& ptr
[-1] == '\\') {
654 memmove(ptr
- 1, ptr
, strlen(ptr
) + 1);
663 static int parse_str_list(const m_option_t
*opt
, const char *name
,
664 const char *param
, void *dst
, int src
)
666 int n
= 0, len
= strlen(opt
->name
);
668 char *ptr
= (char *)param
, *last_ptr
, **res
;
671 if (opt
->name
[len
- 1] == '*' && ((int)strlen(name
) > len
- 1)) {
672 const char *n
= &name
[len
- 1];
673 if (strcasecmp(n
, "-add") == 0)
675 else if (strcasecmp(n
, "-pre") == 0)
677 else if (strcasecmp(n
, "-del") == 0)
679 else if (strcasecmp(n
, "-clr") == 0)
682 return M_OPT_UNKNOWN
;
692 // All other ops need a param
693 if (param
== NULL
|| strlen(param
) == 0)
694 return M_OPT_MISSING_PARAM
;
696 // custom type for "profile" calls this but uses ->priv for something else
697 char separator
= opt
->type
== &m_option_type_string_list
&& opt
->priv
?
698 *(char *)opt
->priv
: OPTION_LIST_SEPARATOR
;
699 while (ptr
[0] != '\0') {
700 ptr
= get_nextsep(ptr
, separator
, 0);
709 return M_OPT_INVALID
;
710 if (((opt
->flags
& M_OPT_MIN
) && (n
< opt
->min
)) ||
711 ((opt
->flags
& M_OPT_MAX
) && (n
> opt
->max
)))
712 return M_OPT_OUT_OF_RANGE
;
717 res
= talloc_array(NULL
, char *, n
+ 2);
718 ptr
= str
= talloc_strdup(NULL
, param
);
723 ptr
= get_nextsep(ptr
, separator
, 1);
725 res
[n
] = talloc_strdup(NULL
, last_ptr
);
729 len
= ptr
- last_ptr
;
730 res
[n
] = talloc_strndup(NULL
, last_ptr
, len
);
739 return str_list_add(res
, n
, dst
, 0);
741 return str_list_add(res
, n
, dst
, 1);
743 return str_list_del(res
, n
, dst
);
753 static void copy_str_list(const m_option_t
*opt
, void *dst
, const void *src
)
770 for (n
= 0; s
[n
] != NULL
; n
++)
772 d
= talloc_array(NULL
, char *, n
+ 1);
774 d
[n
] = talloc_strdup(NULL
, s
[n
]);
779 static char *print_str_list(const m_option_t
*opt
, const void *src
)
784 if (!(src
&& VAL(src
)))
788 for (int i
= 0; lst
[i
]; i
++) {
790 ret
= talloc_strdup_append_buffer(ret
, ",");
791 ret
= talloc_strdup_append_buffer(ret
, lst
[i
]);
796 const m_option_type_t m_option_type_string_list
= {
798 "A list of strings separated by ','\n"
799 "Option with a name ending in an * permits using the following suffix: \n"
800 "\t-add: Add the given parameters at the end of the list.\n"
801 "\t-pre: Add the given parameters at the beginning of the list.\n"
802 "\t-del: Remove the entry at the given indices.\n"
803 "\t-clr: Clear the list.\n"
804 "e.g: -vf-add flip,mirror -vf-del 2,5\n",
806 M_OPT_TYPE_DYNAMIC
| M_OPT_TYPE_ALLOW_WILDCARD
,
816 /////////////////// Func based options
818 // A chained list to save the various calls for func_param
820 struct m_func_save
*next
;
826 #define VAL(x) (*(struct m_func_save **)(x))
828 static void free_func_pf(void *src
)
830 struct m_func_save
*s
, *n
;
839 talloc_free(s
->name
);
840 talloc_free(s
->param
);
847 // Parser for func_param
848 static int parse_func_pf(const m_option_t
*opt
, const char *name
,
849 const char *param
, void *dst
, int src
)
851 struct m_func_save
*s
, *p
;
856 s
= talloc_zero(NULL
, struct m_func_save
);
857 s
->name
= talloc_strdup(NULL
, name
);
858 s
->param
= talloc_strdup(NULL
, param
);
862 for (; p
->next
!= NULL
; p
= p
->next
)
871 static void copy_func_pf(const m_option_t
*opt
, void *dst
, const void *src
)
873 struct m_func_save
*d
= NULL
, *s
, *last
= NULL
;
883 d
= talloc_zero(NULL
, struct m_func_save
);
884 d
->name
= talloc_strdup(NULL
, s
->name
);
885 d
->param
= talloc_strdup(NULL
, s
->param
);
897 /////////////////// Func_param
899 static void set_func_param(const m_option_t
*opt
, void *dst
, const void *src
)
901 struct m_func_save
*s
;
910 for (; s
!= NULL
; s
= s
->next
)
911 ((m_opt_func_param_t
) opt
->p
)(opt
, s
->param
);
914 const m_option_type_t m_option_type_func_param
= {
917 sizeof(struct m_func_save
*),
921 NULL
, // Nothing to do on save
931 static int parse_func(const m_option_t
*opt
, const char *name
,
932 const char *param
, void *dst
, int src
)
937 static void set_func(const m_option_t
*opt
, void *dst
, const void *src
)
939 ((m_opt_func_t
) opt
->p
)(opt
);
942 const m_option_type_t m_option_type_func
= {
949 NULL
, // Nothing to do on save
955 /////////////////// Print
957 static int parse_print(const m_option_t
*opt
, const char *name
,
958 const char *param
, void *dst
, int src
)
960 if (opt
->type
== CONF_TYPE_PRINT_INDIRECT
)
961 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "%s", *(char **) opt
->p
);
962 else if (opt
->type
== CONF_TYPE_PRINT_FUNC
)
963 return ((m_opt_func_full_t
) opt
->p
)(opt
, name
, param
);
965 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "%s", mp_gtext(opt
->p
));
967 if (opt
->priv
== NULL
)
972 const m_option_type_t m_option_type_print
= {
985 const m_option_type_t m_option_type_print_indirect
= {
998 const m_option_type_t m_option_type_print_func
= {
1002 M_OPT_TYPE_ALLOW_WILDCARD
,
1012 /////////////////////// Subconfig
1014 #define VAL(x) (*(char ***)(x))
1016 static int parse_subconf(const m_option_t
*opt
, const char *name
,
1017 const char *param
, void *dst
, int src
)
1022 const m_option_t
*subopts
;
1026 if (param
== NULL
|| strlen(param
) == 0)
1027 return M_OPT_MISSING_PARAM
;
1029 subparam
= talloc_size(NULL
, strlen(param
) + 1);
1030 subopt
= talloc_size(NULL
, strlen(param
) + 1);
1037 int optlen
= strcspn(p
, ":=");
1039 subopt
[0] = subparam
[0] = 0;
1040 av_strlcpy(subopt
, p
, optlen
+ 1);
1047 optlen
= strcspn(p
, "\"");
1048 av_strlcpy(subparam
, p
, optlen
+ 1);
1051 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1052 "Terminating '\"' missing for '%s'\n", subopt
);
1053 return M_OPT_INVALID
;
1056 } else if (p
[0] == '%') {
1058 optlen
= (int)strtol(p
, (char **)&p
, 0);
1059 if (!p
|| p
[0] != '%' || (optlen
> strlen(p
) - 1)) {
1060 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1061 "Invalid length %i for '%s'\n", optlen
, subopt
);
1062 return M_OPT_INVALID
;
1065 av_strlcpy(subparam
, p
, optlen
+ 1);
1068 optlen
= strcspn(p
, ":");
1069 av_strlcpy(subparam
, p
, optlen
+ 1);
1076 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1077 "Incorrect termination for '%s'\n", subopt
);
1078 return M_OPT_INVALID
;
1081 switch (sscanf_ret
) {
1085 for (i
= 0; subopts
[i
].name
; i
++)
1086 if (!strcmp(subopts
[i
].name
, subopt
))
1088 if (!subopts
[i
].name
) {
1089 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1090 "Option %s: Unknown suboption %s\n", name
, subopt
);
1091 return M_OPT_UNKNOWN
;
1093 r
= m_option_parse(&subopts
[i
], subopt
,
1094 subparam
[0] == 0 ? NULL
: subparam
, NULL
, src
);
1098 lst
= talloc_realloc(NULL
, lst
, char *, 2 * (nr
+ 2));
1099 lst
[2 * nr
] = talloc_strdup(NULL
, subopt
);
1100 lst
[2 * nr
+ 1] = subparam
[0] == 0 ? NULL
:
1101 talloc_strdup(NULL
, subparam
);
1102 memset(&lst
[2 * (nr
+ 1)], 0, 2 * sizeof(char *));
1109 talloc_free(subparam
);
1110 talloc_free(subopt
);
1117 const m_option_type_t m_option_type_subconfig
= {
1119 "The syntax is -option opt1=foo:flag:opt2=blah",
1121 M_OPT_TYPE_HAS_CHILD
,
1130 #include "libmpcodecs/img_format.h"
1132 /* FIXME: snyc with img_format.h */
1136 } mp_imgfmt_list
[] = {
1137 {"444p16le", IMGFMT_444P16_LE
},
1138 {"444p16be", IMGFMT_444P16_BE
},
1139 {"444p10le", IMGFMT_444P10_LE
},
1140 {"444p10be", IMGFMT_444P10_BE
},
1141 {"444p9le", IMGFMT_444P9_LE
},
1142 {"444p9be", IMGFMT_444P9_BE
},
1143 {"422p16le", IMGFMT_422P16_LE
},
1144 {"422p16be", IMGFMT_422P16_BE
},
1145 {"422p10le", IMGFMT_422P10_LE
},
1146 {"422p10be", IMGFMT_422P10_BE
},
1147 {"420p16le", IMGFMT_420P16_LE
},
1148 {"420p16be", IMGFMT_420P16_BE
},
1149 {"420p10le", IMGFMT_420P10_LE
},
1150 {"420p10be", IMGFMT_420P10_BE
},
1151 {"420p9le", IMGFMT_420P9_LE
},
1152 {"420p9be", IMGFMT_420P9_BE
},
1153 {"444p16", IMGFMT_444P16
},
1154 {"444p10", IMGFMT_444P10
},
1155 {"444p9", IMGFMT_444P9
},
1156 {"422p16", IMGFMT_422P16
},
1157 {"422p10", IMGFMT_422P10
},
1158 {"420p10", IMGFMT_420P10
},
1159 {"420p9", IMGFMT_420P9
},
1160 {"420p16", IMGFMT_420P16
},
1161 {"420a", IMGFMT_420A
},
1162 {"444p", IMGFMT_444P
},
1163 {"422p", IMGFMT_422P
},
1164 {"411p", IMGFMT_411P
},
1165 {"440p", IMGFMT_440P
},
1166 {"yuy2", IMGFMT_YUY2
},
1167 {"yvyu", IMGFMT_YVYU
},
1168 {"uyvy", IMGFMT_UYVY
},
1169 {"yvu9", IMGFMT_YVU9
},
1170 {"if09", IMGFMT_IF09
},
1171 {"yv12", IMGFMT_YV12
},
1172 {"i420", IMGFMT_I420
},
1173 {"iyuv", IMGFMT_IYUV
},
1174 {"clpl", IMGFMT_CLPL
},
1175 {"hm12", IMGFMT_HM12
},
1176 {"y800", IMGFMT_Y800
},
1178 {"nv12", IMGFMT_NV12
},
1179 {"nv21", IMGFMT_NV21
},
1180 {"bgr24", IMGFMT_BGR24
},
1181 {"bgr32", IMGFMT_BGR32
},
1182 {"bgr16", IMGFMT_BGR16
},
1183 {"bgr15", IMGFMT_BGR15
},
1184 {"bgr12", IMGFMT_BGR12
},
1185 {"bgr8", IMGFMT_BGR8
},
1186 {"bgr4", IMGFMT_BGR4
},
1187 {"bg4b", IMGFMT_BG4B
},
1188 {"bgr1", IMGFMT_BGR1
},
1189 {"rgb48be", IMGFMT_RGB48BE
},
1190 {"rgb48le", IMGFMT_RGB48LE
},
1191 {"rgb48ne", IMGFMT_RGB48NE
},
1192 {"rgb24", IMGFMT_RGB24
},
1193 {"rgb32", IMGFMT_RGB32
},
1194 {"rgb16", IMGFMT_RGB16
},
1195 {"rgb15", IMGFMT_RGB15
},
1196 {"rgb12", IMGFMT_RGB12
},
1197 {"rgb8", IMGFMT_RGB8
},
1198 {"rgb4", IMGFMT_RGB4
},
1199 {"rg4b", IMGFMT_RG4B
},
1200 {"rgb1", IMGFMT_RGB1
},
1201 {"rgba", IMGFMT_RGBA
},
1202 {"argb", IMGFMT_ARGB
},
1203 {"bgra", IMGFMT_BGRA
},
1204 {"abgr", IMGFMT_ABGR
},
1205 {"mjpeg", IMGFMT_MJPEG
},
1206 {"mjpg", IMGFMT_MJPEG
},
1210 static int parse_imgfmt(const m_option_t
*opt
, const char *name
,
1211 const char *param
, void *dst
, int src
)
1216 if (param
== NULL
|| strlen(param
) == 0)
1217 return M_OPT_MISSING_PARAM
;
1219 if (!strcmp(param
, "help")) {
1220 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "Available formats:");
1221 for (i
= 0; mp_imgfmt_list
[i
].name
; i
++)
1222 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, " %s", mp_imgfmt_list
[i
].name
);
1223 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "\n");
1224 return M_OPT_EXIT
- 1;
1227 if (sscanf(param
, "0x%x", &fmt
) != 1) {
1228 for (i
= 0; mp_imgfmt_list
[i
].name
; i
++) {
1229 if (!strcasecmp(param
, mp_imgfmt_list
[i
].name
)) {
1230 fmt
= mp_imgfmt_list
[i
].fmt
;
1234 if (!mp_imgfmt_list
[i
].name
) {
1235 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1236 "Option %s: unknown format name: '%s'\n", name
, param
);
1237 return M_OPT_INVALID
;
1242 *((uint32_t *)dst
) = fmt
;
1247 const m_option_type_t m_option_type_imgfmt
= {
1249 "Please report any missing colorspaces.",
1260 #include "libaf/af_format.h"
1262 /* FIXME: snyc with af_format.h */
1266 } mp_afmt_list
[] = {
1268 {"mulaw", AF_FORMAT_MU_LAW
},
1269 {"alaw", AF_FORMAT_A_LAW
},
1270 {"mpeg2", AF_FORMAT_MPEG2
},
1271 {"ac3le", AF_FORMAT_AC3_LE
},
1272 {"ac3be", AF_FORMAT_AC3_BE
},
1273 {"ac3ne", AF_FORMAT_AC3_NE
},
1274 {"imaadpcm", AF_FORMAT_IMA_ADPCM
},
1276 {"u8", AF_FORMAT_U8
},
1277 {"s8", AF_FORMAT_S8
},
1278 {"u16le", AF_FORMAT_U16_LE
},
1279 {"u16be", AF_FORMAT_U16_BE
},
1280 {"u16ne", AF_FORMAT_U16_NE
},
1281 {"s16le", AF_FORMAT_S16_LE
},
1282 {"s16be", AF_FORMAT_S16_BE
},
1283 {"s16ne", AF_FORMAT_S16_NE
},
1284 {"u24le", AF_FORMAT_U24_LE
},
1285 {"u24be", AF_FORMAT_U24_BE
},
1286 {"u24ne", AF_FORMAT_U24_NE
},
1287 {"s24le", AF_FORMAT_S24_LE
},
1288 {"s24be", AF_FORMAT_S24_BE
},
1289 {"s24ne", AF_FORMAT_S24_NE
},
1290 {"u32le", AF_FORMAT_U32_LE
},
1291 {"u32be", AF_FORMAT_U32_BE
},
1292 {"u32ne", AF_FORMAT_U32_NE
},
1293 {"s32le", AF_FORMAT_S32_LE
},
1294 {"s32be", AF_FORMAT_S32_BE
},
1295 {"s32ne", AF_FORMAT_S32_NE
},
1296 {"floatle", AF_FORMAT_FLOAT_LE
},
1297 {"floatbe", AF_FORMAT_FLOAT_BE
},
1298 {"floatne", AF_FORMAT_FLOAT_NE
},
1302 static int parse_afmt(const m_option_t
*opt
, const char *name
,
1303 const char *param
, void *dst
, int src
)
1308 if (param
== NULL
|| strlen(param
) == 0)
1309 return M_OPT_MISSING_PARAM
;
1311 if (!strcmp(param
, "help")) {
1312 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "Available formats:");
1313 for (i
= 0; mp_afmt_list
[i
].name
; i
++)
1314 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, " %s", mp_afmt_list
[i
].name
);
1315 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "\n");
1316 return M_OPT_EXIT
- 1;
1319 if (sscanf(param
, "0x%x", &fmt
) != 1) {
1320 for (i
= 0; mp_afmt_list
[i
].name
; i
++) {
1321 if (!strcasecmp(param
, mp_afmt_list
[i
].name
)) {
1322 fmt
= mp_afmt_list
[i
].fmt
;
1326 if (!mp_afmt_list
[i
].name
) {
1327 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1328 "Option %s: unknown format name: '%s'\n", name
, param
);
1329 return M_OPT_INVALID
;
1334 *((uint32_t *)dst
) = fmt
;
1339 const m_option_type_t m_option_type_afmt
= {
1341 "Please report any missing formats.",
1353 int parse_timestring(const char *str
, double *time
, char endchar
)
1357 *time
= 0; /* ensure initialization for error cases */
1358 if (sscanf(str
, "%d:%d:%lf%n", &a
, &b
, &d
, &len
) >= 3)
1359 *time
= 3600 * a
+ 60 * b
+ d
;
1360 else if (sscanf(str
, "%d:%lf%n", &a
, &d
, &len
) >= 2)
1362 else if (sscanf(str
, "%lf%n", &d
, &len
) >= 1)
1365 return 0; /* unsupported time format */
1366 if (str
[len
] && str
[len
] != endchar
)
1367 return 0; /* invalid extra characters at the end */
1372 static int parse_time(const m_option_t
*opt
, const char *name
,
1373 const char *param
, void *dst
, int src
)
1377 if (param
== NULL
|| strlen(param
) == 0)
1378 return M_OPT_MISSING_PARAM
;
1380 if (!parse_timestring(param
, &time
, 0)) {
1381 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option %s: invalid time: '%s'\n",
1383 return M_OPT_INVALID
;
1387 *(double *)dst
= time
;
1391 const m_option_type_t m_option_type_time
= {
1405 // Time or size (-endpos)
1407 static int parse_time_size(const m_option_t
*opt
, const char *name
,
1408 const char *param
, void *dst
, int src
)
1414 if (param
== NULL
|| strlen(param
) == 0)
1415 return M_OPT_MISSING_PARAM
;
1418 /* End at size parsing */
1419 if (sscanf(param
, "%lf%3s", &end_at
, unit
) == 2) {
1420 ts
.type
= END_AT_SIZE
;
1421 if (!strcasecmp(unit
, "b"))
1423 else if (!strcasecmp(unit
, "kb"))
1425 else if (!strcasecmp(unit
, "mb"))
1426 end_at
*= 1024 * 1024;
1427 else if (!strcasecmp(unit
, "gb"))
1428 end_at
*= 1024 * 1024 * 1024;
1430 ts
.type
= END_AT_NONE
;
1432 if (ts
.type
== END_AT_SIZE
) {
1438 /* End at time parsing. This has to be last because the parsing accepts
1439 * even a number followed by garbage */
1440 if (!parse_timestring(param
, &end_at
, 0)) {
1441 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1442 "Option %s: invalid time or size: '%s'\n",
1444 return M_OPT_INVALID
;
1447 ts
.type
= END_AT_TIME
;
1451 *(m_time_size_t
*)dst
= ts
;
1455 const m_option_type_t m_option_type_time_size
= {
1458 sizeof(m_time_size_t
),
1469 //// Objects (i.e. filters, etc) settings
1471 #include "m_struct.h"
1474 #define VAL(x) (*(m_obj_settings_t **)(x))
1476 static int find_obj_desc(const char *name
, const m_obj_list_t
*l
,
1477 const m_struct_t
**ret
)
1482 for (i
= 0; l
->list
[i
]; i
++) {
1483 n
= M_ST_MB(char *, l
->list
[i
], l
->name_off
);
1484 if (!strcmp(n
, name
)) {
1485 *ret
= M_ST_MB(m_struct_t
*, l
->list
[i
], l
->desc_off
);
1492 static int get_obj_param(const char *opt_name
, const char *obj_name
,
1493 const m_struct_t
*desc
, char *str
, int *nold
,
1494 int oldmax
, char **dst
)
1497 const m_option_t
*opt
;
1500 eq
= strchr(str
, '=');
1501 if (eq
&& eq
== str
)
1509 opt
= m_option_list_find(desc
->fields
, str
);
1511 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1512 "Option %s: %s doesn't have a %s parameter.\n",
1513 opt_name
, obj_name
, str
);
1514 return M_OPT_UNKNOWN
;
1516 r
= m_option_parse(opt
, str
, p
, NULL
, M_CONFIG_FILE
);
1519 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1520 "Option %s: Error while parsing %s parameter %s (%s)\n",
1521 opt_name
, obj_name
, str
, p
);
1526 dst
[0] = talloc_strdup(NULL
, str
);
1527 dst
[1] = talloc_strdup(NULL
, p
);
1531 if ((*nold
) >= oldmax
) {
1532 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option %s: %s has only %d params, so you can't give more than %d unnamed params.\n",
1533 opt_name
, obj_name
, oldmax
, oldmax
);
1534 return M_OPT_OUT_OF_RANGE
;
1536 opt
= &desc
->fields
[(*nold
)];
1537 r
= m_option_parse(opt
, opt
->name
, str
, NULL
, M_CONFIG_FILE
);
1540 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
1541 "Option %s: Error while parsing %s parameter %s (%s)\n",
1542 opt_name
, obj_name
, opt
->name
, str
);
1546 dst
[0] = talloc_strdup(NULL
, opt
->name
);
1547 dst
[1] = talloc_strdup(NULL
, str
);
1554 static int get_obj_params(const char *opt_name
, const char *name
, char *params
,
1555 const m_struct_t
*desc
, char separator
, char ***_ret
)
1557 int n
= 0, nold
= 0, nopts
, r
;
1558 char *ptr
, *last_ptr
= params
;
1561 if (!strcmp(params
, "help")) { // Help
1562 char min
[50], max
[50];
1563 if (!desc
->fields
) {
1564 printf("%s doesn't have any options.\n\n", name
);
1565 return M_OPT_EXIT
- 1;
1567 printf("\n Name Type Min Max\n\n");
1568 for (n
= 0; desc
->fields
[n
].name
; n
++) {
1569 const m_option_t
*opt
= &desc
->fields
[n
];
1570 if (opt
->type
->flags
& M_OPT_TYPE_HAS_CHILD
)
1572 if (opt
->flags
& M_OPT_MIN
)
1573 sprintf(min
, "%-8.0f", opt
->min
);
1576 if (opt
->flags
& M_OPT_MAX
)
1577 sprintf(max
, "%-8.0f", opt
->max
);
1580 printf(" %-20.20s %-15.15s %-10.10s %-10.10s\n",
1587 return M_OPT_EXIT
- 1;
1590 for (nopts
= 0; desc
->fields
[nopts
].name
; nopts
++)
1593 // TODO : Check that each opt can be parsed
1595 while (last_ptr
&& last_ptr
[0] != '\0') {
1596 ptr
= strchr(last_ptr
, separator
);
1598 r
= get_obj_param(opt_name
, name
, desc
, last_ptr
, &nold
, nopts
,
1603 if (ptr
== last_ptr
) { // Empty field, count it and go on
1609 r
= get_obj_param(opt_name
, name
, desc
, last_ptr
, &nold
, nopts
, NULL
);
1618 if (!last_ptr
[0]) // count an empty field at the end, too
1621 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Too many options for %s\n", name
);
1622 return M_OPT_OUT_OF_RANGE
;
1624 if (!_ret
) // Just test
1626 if (n
== 0) // No options or only empty options
1629 ret
= talloc_array(NULL
, char *, (n
+ 2) * 2);
1633 while (last_ptr
&& last_ptr
[0] != '\0') {
1634 ptr
= strchr(last_ptr
, separator
);
1636 get_obj_param(opt_name
, name
, desc
, last_ptr
, &nold
, nopts
,
1641 if (ptr
== last_ptr
) { // Empty field, count it and go on
1647 get_obj_param(opt_name
, name
, desc
, last_ptr
, &nold
, nopts
,
1652 ret
[n
* 2] = ret
[n
* 2 + 1] = NULL
;
1658 static int parse_obj_params(const m_option_t
*opt
, const char *name
,
1659 const char *param
, void *dst
, int src
)
1663 m_obj_params_t
*p
= opt
->priv
;
1664 const m_struct_t
*desc
;
1667 // We need the object desc
1669 return M_OPT_INVALID
;
1672 cpy
= talloc_strdup(NULL
, param
);
1673 r
= get_obj_params(name
, desc
->name
, cpy
, desc
, p
->separator
,
1674 dst
? &opts
: NULL
);
1680 if (!opts
) // no arguments given
1683 for (r
= 0; opts
[r
]; r
+= 2)
1684 m_struct_set(desc
, dst
, opts
[r
], opts
[r
+ 1]);
1690 const m_option_type_t m_option_type_obj_params
= {
1703 /// Some predefined types as a definition would be quite lengthy
1706 static const m_span_t m_span_params_dflts
= {
1709 static const m_option_t m_span_params_fields
[] = {
1710 {"start", M_ST_OFF(m_span_t
, start
), CONF_TYPE_INT
, M_OPT_MIN
, 1, 0, NULL
},
1711 {"end", M_ST_OFF(m_span_t
, end
), CONF_TYPE_INT
, M_OPT_MIN
, 1, 0, NULL
},
1712 { NULL
, NULL
, 0, 0, 0, 0, NULL
}
1714 static const struct m_struct_st m_span_opts
= {
1717 &m_span_params_dflts
,
1718 m_span_params_fields
1720 const m_obj_params_t m_span_params_def
= {
1725 static int parse_obj_settings(const char *opt
, char *str
,
1726 const m_obj_list_t
*list
,
1727 m_obj_settings_t
**_ret
, int ret_n
)
1730 char *param
, **plist
= NULL
;
1731 const m_struct_t
*desc
;
1732 m_obj_settings_t
*ret
= _ret
? *_ret
: NULL
;
1735 // Now check that the object exists
1736 param
= strchr(str
, '=');
1740 if (strlen(param
) <= 0)
1745 if (!find_obj_desc(str
, list
, &desc
)) {
1746 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option %s: %s doesn't exist.\n",
1748 return M_OPT_INVALID
;
1752 if (!desc
&& _ret
) {
1753 if (!strcmp(param
, "help")) {
1754 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
,
1755 "Option %s: %s have no option description.\n", opt
, str
);
1756 return M_OPT_EXIT
- 1;
1758 plist
= talloc_zero_array(NULL
, char *, 4);
1759 plist
[0] = talloc_strdup(NULL
, "_oldargs_");
1760 plist
[1] = talloc_strdup(NULL
, param
);
1762 r
= get_obj_params(opt
, str
, param
, desc
, ':',
1763 _ret
? &plist
: NULL
);
1771 ret
= talloc_realloc(NULL
, ret
, struct m_obj_settings
, ret_n
+ 2);
1772 memset(&ret
[ret_n
], 0, 2 * sizeof(m_obj_settings_t
));
1773 ret
[ret_n
].name
= talloc_strdup(NULL
, str
);
1774 ret
[ret_n
].attribs
= plist
;
1780 static int obj_settings_list_del(const char *opt_name
, const char *param
,
1783 char **str_list
= NULL
;
1784 int r
, i
, idx_max
= 0;
1785 char *rem_id
= "_removed_marker_";
1786 const m_option_t list_opt
= {
1787 opt_name
, NULL
, CONF_TYPE_STRING_LIST
,
1790 m_obj_settings_t
*obj_list
= dst
? VAL(dst
) : NULL
;
1792 if (dst
&& !obj_list
) {
1793 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
, "Option %s: the list is empty.\n",
1796 } else if (obj_list
) {
1797 for (idx_max
= 0; obj_list
[idx_max
].name
!= NULL
; idx_max
++)
1801 r
= m_option_parse(&list_opt
, opt_name
, param
, &str_list
, src
);
1802 if (r
< 0 || !str_list
)
1805 for (r
= 0; str_list
[r
]; r
++) {
1808 id
= strtol(str_list
[r
], &endptr
, 0);
1809 if (endptr
== str_list
[r
]) {
1810 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
);
1811 m_option_free(&list_opt
, &str_list
);
1812 return M_OPT_INVALID
;
1816 if (id
>= idx_max
|| id
< -idx_max
) {
1817 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
1818 "Option %s: Index %d is out of range.\n", opt_name
, id
);
1823 talloc_free(obj_list
[id
].name
);
1824 free_str_list(&(obj_list
[id
].attribs
));
1825 obj_list
[id
].name
= rem_id
;
1829 m_option_free(&list_opt
, &str_list
);
1833 for (i
= 0; obj_list
[i
].name
; i
++) {
1834 while (obj_list
[i
].name
== rem_id
) {
1835 memmove(&obj_list
[i
], &obj_list
[i
+ 1],
1836 sizeof(m_obj_settings_t
) * (idx_max
- i
));
1840 obj_list
= talloc_realloc(NULL
, obj_list
, struct m_obj_settings
,
1842 VAL(dst
) = obj_list
;
1847 static void free_obj_settings_list(void *dst
)
1850 m_obj_settings_t
*d
;
1852 if (!dst
|| !VAL(dst
))
1856 for (n
= 0; d
[n
].name
; n
++) {
1857 talloc_free(d
[n
].name
);
1858 free_str_list(&(d
[n
].attribs
));
1864 static int parse_obj_settings_list(const m_option_t
*opt
, const char *name
,
1865 const char *param
, void *dst
, int src
)
1867 int n
= 0, r
, len
= strlen(opt
->name
);
1869 char *ptr
, *last_ptr
;
1870 m_obj_settings_t
*res
= NULL
, *queue
= NULL
, *head
= NULL
;
1873 // We need the objects list
1875 return M_OPT_INVALID
;
1877 if (opt
->name
[len
- 1] == '*' && ((int)strlen(name
) > len
- 1)) {
1878 const char *n
= &name
[len
- 1];
1879 if (strcasecmp(n
, "-add") == 0)
1881 else if (strcasecmp(n
, "-pre") == 0)
1883 else if (strcasecmp(n
, "-del") == 0)
1885 else if (strcasecmp(n
, "-clr") == 0)
1889 strncpy(prefix
, opt
->name
, len
- 1);
1890 prefix
[len
- 1] = '\0';
1891 mp_msg(MSGT_VFILTER
, MSGL_ERR
, "Option %s: unknown postfix %s\n"
1892 "Supported postfixes are:\n"
1894 " Append the given list to the current list\n\n"
1896 " Prepend the given list to the current list\n\n"
1898 " Remove the given elements. Take the list element index (starting from 0).\n"
1899 " Negative index can be used (i.e. -1 is the last element)\n\n"
1901 " Clear the current list.\n",
1902 name
, n
, prefix
, prefix
, prefix
, prefix
);
1904 return M_OPT_UNKNOWN
;
1908 // Clear the list ??
1911 free_obj_settings_list(dst
);
1915 if (param
== NULL
|| strlen(param
) == 0)
1916 return M_OPT_MISSING_PARAM
;
1928 return obj_settings_list_del(name
, param
, dst
, src
);
1930 if (dst
&& VAL(dst
))
1931 free_obj_settings_list(dst
);
1934 mp_msg(MSGT_VFILTER
, MSGL_ERR
, "Option %s: FIXME\n", name
);
1935 return M_OPT_UNKNOWN
;
1938 if (!strcmp(param
, "help")) {
1939 m_obj_list_t
*ol
= opt
->priv
;
1940 mp_msg(MSGT_VFILTER
, MSGL_INFO
, "Available video filters:\n");
1941 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VIDEO_FILTERS\n");
1942 for (n
= 0; ol
->list
[n
]; n
++)
1943 mp_msg(MSGT_VFILTER
, MSGL_INFO
, " %-15s: %s\n",
1944 M_ST_MB(char *, ol
->list
[n
], ol
->name_off
),
1945 M_ST_MB(char *, ol
->list
[n
], ol
->info_off
));
1946 mp_msg(MSGT_VFILTER
, MSGL_INFO
, "\n");
1947 return M_OPT_EXIT
- 1;
1949 ptr
= str
= talloc_strdup(NULL
, param
);
1951 while (ptr
[0] != '\0') {
1953 ptr
= get_nextsep(ptr
, OPTION_LIST_SEPARATOR
, 1);
1956 r
= parse_obj_settings(name
, last_ptr
, opt
->priv
,
1957 dst
? &res
: NULL
, n
);
1966 r
= parse_obj_settings(name
, last_ptr
, opt
->priv
, dst
? &res
: NULL
, n
);
1976 return M_OPT_INVALID
;
1978 if (((opt
->flags
& M_OPT_MIN
) && (n
< opt
->min
)) ||
1979 ((opt
->flags
& M_OPT_MAX
) && (n
> opt
->max
)))
1980 return M_OPT_OUT_OF_RANGE
;
1985 for (qsize
= 0; queue
[qsize
].name
; qsize
++)
1987 res
= talloc_realloc(NULL
, res
, struct m_obj_settings
,
1989 memcpy(&res
[n
], queue
, (qsize
+ 1) * sizeof(m_obj_settings_t
));
1995 for (hsize
= 0; head
[hsize
].name
; hsize
++)
1997 head
= talloc_realloc(NULL
, head
, struct m_obj_settings
,
1999 memcpy(&head
[hsize
], res
, (n
+ 1) * sizeof(m_obj_settings_t
));
2008 static void copy_obj_settings_list(const m_option_t
*opt
, void *dst
,
2011 m_obj_settings_t
*d
, *s
;
2020 free_obj_settings_list(dst
);
2026 for (n
= 0; s
[n
].name
; n
++)
2028 d
= talloc_array(NULL
, struct m_obj_settings
, n
+ 1);
2029 for (n
= 0; s
[n
].name
; n
++) {
2030 d
[n
].name
= talloc_strdup(NULL
, s
[n
].name
);
2031 d
[n
].attribs
= NULL
;
2032 copy_str_list(NULL
, &(d
[n
].attribs
), &(s
[n
].attribs
));
2035 d
[n
].attribs
= NULL
;
2039 const m_option_type_t m_option_type_obj_settings_list
= {
2040 "Object settings list",
2042 sizeof(m_obj_settings_t
*),
2043 M_OPT_TYPE_DYNAMIC
| M_OPT_TYPE_ALLOW_WILDCARD
,
2044 parse_obj_settings_list
,
2046 copy_obj_settings_list
,
2047 copy_obj_settings_list
,
2048 copy_obj_settings_list
,
2049 free_obj_settings_list
,
2054 static int parse_obj_presets(const m_option_t
*opt
, const char *name
,
2055 const char *param
, void *dst
, int src
)
2057 m_obj_presets_t
*obj_p
= (m_obj_presets_t
*)opt
->priv
;
2058 const m_struct_t
*in_desc
;
2059 const m_struct_t
*out_desc
;
2061 const unsigned char *pre
;
2062 char *pre_name
= NULL
;
2065 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option %s: Presets need a "
2066 "pointer to a m_obj_presets_t in the priv field.\n", name
);
2067 return M_OPT_PARSER_ERR
;
2071 return M_OPT_MISSING_PARAM
;
2073 pre
= obj_p
->presets
;
2074 in_desc
= obj_p
->in_desc
;
2075 out_desc
= obj_p
->out_desc
? obj_p
->out_desc
: obj_p
->in_desc
;
2078 if (!strcmp(param
, "help")) {
2079 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
, "Available presets for %s->%s:",
2080 out_desc
->name
, name
);
2081 for (pre
= obj_p
->presets
;
2082 (pre_name
= M_ST_MB(char *, pre
, obj_p
->name_off
)); pre
+= s
)
2083 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, " %s", pre_name
);
2084 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "\n");
2085 return M_OPT_EXIT
- 1;
2088 for (pre_name
= M_ST_MB(char *, pre
, obj_p
->name_off
); pre_name
;
2089 pre
+= s
, pre_name
= M_ST_MB(char *, pre
, obj_p
->name_off
))
2090 if (!strcmp(pre_name
, param
))
2093 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2094 "Option %s: There is no preset named %s\n"
2095 "Available presets are:", name
, param
);
2096 for (pre
= obj_p
->presets
;
2097 (pre_name
= M_ST_MB(char *, pre
, obj_p
->name_off
)); pre
+= s
)
2098 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, " %s", pre_name
);
2099 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "\n");
2100 return M_OPT_INVALID
;
2106 for (i
= 0; in_desc
->fields
[i
].name
; i
++) {
2107 const m_option_t
*out_opt
= m_option_list_find(out_desc
->fields
,
2108 in_desc
->fields
[i
].name
);
2110 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2111 "Option %s: Unable to find the target option for field %s.\n"
2112 "Please report this to the developers.\n",
2113 name
, in_desc
->fields
[i
].name
);
2114 return M_OPT_PARSER_ERR
;
2116 m_option_copy(out_opt
, M_ST_MB_P(dst
, out_opt
->p
),
2117 M_ST_MB_P(pre
, in_desc
->fields
[i
].p
));
2123 const m_option_type_t m_option_type_obj_presets
= {
2136 static int parse_custom_url(const m_option_t
*opt
, const char *name
,
2137 const char *url
, void *dst
, int src
)
2139 int pos1
, pos2
, r
, v6addr
= 0;
2140 char *ptr1
= NULL
, *ptr2
= NULL
, *ptr3
= NULL
, *ptr4
= NULL
;
2141 m_struct_t
*desc
= opt
->priv
;
2144 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "Option %s: Custom URL needs "
2145 "a pointer to a m_struct_t in the priv field.\n", name
);
2146 return M_OPT_PARSER_ERR
;
2149 // extract the protocol
2150 ptr1
= strstr(url
, "://");
2153 if (m_option_list_find(desc
->fields
, "filename")) {
2154 m_struct_set(desc
, dst
, "filename", url
);
2157 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2158 "Option %s: URL doesn't have a valid protocol!\n", name
);
2159 return M_OPT_INVALID
;
2161 if (m_option_list_find(desc
->fields
, "string")) {
2162 if (strlen(ptr1
) > 3) {
2163 m_struct_set(desc
, dst
, "string", ptr1
+ 3);
2168 if (dst
&& m_option_list_find(desc
->fields
, "protocol")) {
2170 r
= m_struct_set(desc
, dst
, "protocol", url
);
2173 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2174 "Option %s: Error while setting protocol.\n", name
);
2183 // check if a username:password is given
2184 ptr2
= strstr(ptr1
, "@");
2185 ptr3
= strstr(ptr1
, "/");
2186 if (ptr3
!= NULL
&& ptr3
< ptr2
) {
2187 // it isn't really a username but rather a part of the path
2192 // We got something, at least a username...
2193 if (!m_option_list_find(desc
->fields
, "username")) {
2194 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
2195 "Option %s: This URL doesn't have a username part.\n", name
);
2198 ptr3
= strstr(ptr1
, ":");
2199 if (ptr3
!= NULL
&& ptr3
< ptr2
) {
2200 // We also have a password
2201 if (!m_option_list_find(desc
->fields
, "password")) {
2202 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
2203 "Option %s: This URL doesn't have a password part.\n",
2206 } else { // Username and password
2209 r
= m_struct_set(desc
, dst
, "username", ptr1
);
2212 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2213 "Option %s: Error while setting username.\n",
2218 r
= m_struct_set(desc
, dst
, "password", ptr3
+ 1);
2221 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2222 "Option %s: Error while setting password.\n",
2228 } else { // User name only
2230 r
= m_struct_set(desc
, dst
, "username", ptr1
);
2233 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2234 "Option %s: Error while setting username.\n", name
);
2243 // Before looking for a port number check if we have an IPv6 type
2245 // In an IPv6 URL the numeric address should be inside square braces.
2246 ptr2
= strstr(ptr1
, "[");
2247 ptr3
= strstr(ptr1
, "]");
2248 // If the [] is after the first it isn't the hostname
2249 ptr4
= strstr(ptr1
, "/");
2250 if (ptr2
!= NULL
&& ptr3
!= NULL
&& (ptr2
< ptr3
)
2251 && (!ptr4
|| ptr4
> ptr3
)) {
2252 // we have an IPv6 numeric address
2260 // look if the port is given
2261 ptr2
= strstr(ptr2
, ":");
2262 // If the : is after the first / it isn't the port
2263 ptr3
= strstr(ptr1
, "/");
2264 if (ptr3
&& ptr3
- ptr2
< 0)
2268 // Look if a path is given
2271 // So we have an URL like http://www.hostname.com
2274 // We have an URL like http://www.hostname.com/file.txt
2278 // We have an URL beginning like http://www.hostname.com:1212
2279 // Get the port number
2280 if (!m_option_list_find(desc
->fields
, "port")) {
2281 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
2282 "Option %s: This URL doesn't have a port part.\n", name
);
2286 int p
= atoi(ptr2
+ 1);
2288 snprintf(tmp
, 99, "%d", p
);
2289 r
= m_struct_set(desc
, dst
, "port", tmp
);
2291 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2292 "Option %s: Error while setting port.\n", name
);
2302 if (pos2
- pos1
> 0) {
2303 if (!m_option_list_find(desc
->fields
, "hostname")) {
2304 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
2305 "Option %s: This URL doesn't have a hostname part.\n", name
);
2308 char tmp
[pos2
- pos1
+ 1];
2309 strncpy(tmp
, ptr1
, pos2
- pos1
);
2310 tmp
[pos2
- pos1
] = '\0';
2311 r
= m_struct_set(desc
, dst
, "hostname", tmp
);
2313 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2314 "Option %s: Error while setting hostname.\n", name
);
2319 // Look if a path is given
2320 ptr2
= strstr(ptr1
, "/");
2322 // A path/filename is given
2323 // check if it's not a trailing '/'
2324 if (strlen(ptr2
) > 1) {
2325 // copy the path/filename in the URL container
2326 if (!m_option_list_find(desc
->fields
, "filename")) {
2327 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
2328 "Option %s: This URL doesn't have a hostname part.\n",
2333 int l
= strlen(ptr2
+ 1) + 1;
2334 char *fname
= ptr2
+ 1;
2336 fname
= talloc_size(NULL
, l
);
2337 url_unescape_string(fname
, ptr2
+ 1);
2339 r
= m_struct_set(desc
, dst
, "filename", fname
);
2340 if (fname
!= ptr2
+ 1)
2343 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
2344 "Option %s: Error while setting filename.\n",
2355 /// TODO : Write the other needed funcs for 'normal' options
2356 const m_option_type_t m_option_type_custom_url
= {