From dc2a4863af9b0e587ac4ec3e2096639098e99a8f Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Thu, 17 May 2012 03:31:11 +0300 Subject: options: support parsing values into substructs Add an alternate mode for option parser objects (struct m_config) which is not inherently tied to any particular instance of an option value struct. Instead, this type or parsers can be used to initialize defaults in or parse values into a struct given as a parameter. They do not have the save slot functionality used for main player configuration. The new functionality will be used to replace the separate subopt_helper.c parsing code that is currently used to parse per-object suboptions in VOs etc. Previously, option default values were handled by initializing them in external code before creating a parser. This initialization was done with constants even for dynamically-allocated types like strings. Because trying to free a pointer to a constant would cause a crash when trying to replace the default with another value, parser initialization code then replaced all the original defaults with dynamically-allocated copies. This replace-with-copy behavior is no longer supported for new-style options; instead the option definition itself may contain a default value (new OPTDEF macros), and the new function m_config_initialize() is used to set all options to their default values. Convert the existing initialized dynamically allocated options in main config (the string options --dumpfile, --term-osd-esc, --input=conf) to use this. Other non-dynamic ones could be later converted to use this style of initialization too. There's currently no public call to free all dynamically allocated options in a given option struct because I intend to use talloc functionality for that (make them children of the struct and free with it). --- cfg-mplayer.h | 4 +- defaultopts.c | 3 -- input/input.c | 2 +- m_config.c | 132 +++++++++++++++++++++++++++++++++++++--------------------- m_config.h | 8 ++++ m_option.c | 19 ++------- m_option.h | 50 +++++++++++++++------- mplayer.c | 1 + 8 files changed, 135 insertions(+), 84 deletions(-) diff --git a/cfg-mplayer.h b/cfg-mplayer.h index 66b381a920..5440de9946 100644 --- a/cfg-mplayer.h +++ b/cfg-mplayer.h @@ -863,7 +863,7 @@ const m_option_t mplayer_opts[]={ OPT_FLAG_ON("benchmark", benchmark, 0), // dump some stream out instead of playing the file - OPT_STRING("dumpfile", stream_dump_name, 0), + OPT_STRING("dumpfile", stream_dump_name, 0, OPTDEF_STR("stream.dump")), {"dumpaudio", &stream_dump_type, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"dumpvideo", &stream_dump_type, CONF_TYPE_FLAG, 0, 0, 2, NULL}, {"dumpsub", &stream_dump_type, CONF_TYPE_FLAG, 0, 0, 3, NULL}, @@ -912,7 +912,7 @@ const m_option_t mplayer_opts[]={ #endif OPT_MAKE_FLAGS("term-osd", term_osd, 0), - OPT_STRING("term-osd-esc", term_osd_esc, 0), + OPT_STRING("term-osd-esc", term_osd_esc, 0, OPTDEF_STR("\x1b[A\r\x1b[K")), OPT_STRING("playing-msg", playing_msg, 0), {"slave", &slave_mode, CONF_TYPE_FLAG,CONF_GLOBAL , 0, 1, NULL}, diff --git a/defaultopts.c b/defaultopts.c index da557117bf..da19528838 100644 --- a/defaultopts.c +++ b/defaultopts.c @@ -22,7 +22,6 @@ void set_default_mplayer_options(struct MPOpts *opts) .vo_gamma_hue = 1000, .osd_level = 1, .osd_duration = 1000, - .stream_dump_name = "stream.dump", .loop_times = -1, .ordered_chapters = 1, .chapter_merge_threshold = 100, @@ -33,7 +32,6 @@ void set_default_mplayer_options(struct MPOpts *opts) .user_correct_pts = -1, .initial_audio_sync = 1, .term_osd = 1, - .term_osd_esc = "\x1b[A\r\x1b[K", .consolecontrols = 1, .doubleclick_time = 300, .audio_id = -1, @@ -60,7 +58,6 @@ void set_default_mplayer_options(struct MPOpts *opts) .error_concealment = 3, }, .input = { - .config_file = "input.conf", .key_fifo_size = 7, .ar_delay = 100, .ar_rate = 8, diff --git a/input/input.c b/input/input.c index a6da6f324c..af78314153 100644 --- a/input/input.c +++ b/input/input.c @@ -638,7 +638,7 @@ static int print_cmd_list(m_option_t *cfg, char *optname, char *optparam); // Our command line options static const m_option_t input_conf[] = { - OPT_STRING("conf", input.config_file, CONF_GLOBAL), + OPT_STRING("conf", input.config_file, CONF_GLOBAL, OPTDEF_STR("input.conf")), OPT_INT("ar-delay", input.ar_delay, CONF_GLOBAL), OPT_INT("ar-rate", input.ar_rate, CONF_GLOBAL), { "keylist", print_key_list, CONF_TYPE_PRINT_FUNC, CONF_NOCFG }, diff --git a/m_config.c b/m_config.c index 3da7707f14..e8996670f4 100644 --- a/m_config.c +++ b/m_config.c @@ -148,11 +148,11 @@ static void m_option_save(const struct m_config *config, } } -static void m_option_set(const struct m_config *config, +static void m_option_set(void *optstruct, const struct m_option *opt, const void *src) { if (opt->type->copy) { - void *dst = m_option_get_ptr(opt, config->optstruct); + void *dst = m_option_get_ptr(opt, optstruct); opt->type->copy(opt, dst, src); } } @@ -176,6 +176,7 @@ struct m_config *m_config_new(void *optstruct, }; config = talloc_zero(NULL, struct m_config); + config->full = true; config->lvl = 1; // 0 Is the defaults struct m_option *self_opts = talloc_memdup(config, ref_opts, sizeof(ref_opts)); @@ -195,8 +196,16 @@ struct m_config *m_config_new(void *optstruct, return config; } +struct m_config *m_config_simple(const struct m_option *options) +{ + struct m_config *config = talloc_zero(NULL, struct m_config); + m_config_register_options(config, options); + return config; +} + void m_config_free(struct m_config *config) { + assert(config->full); // use talloc_free() for simple struct m_config_option *copt; for (copt = config->opts; copt; copt = copt->next) { if (copt->flags & M_CFG_OPT_ALIAS) @@ -213,6 +222,17 @@ void m_config_free(struct m_config *config) talloc_free(config); } +void m_config_initialize(struct m_config *config, void *optstruct) +{ + struct m_config_option *copt; + for (copt = config->opts; copt; copt = copt->next) { + const struct m_option *opt = copt->opt; + if (!opt->defval) + continue; + m_option_set(optstruct, opt, opt->defval); + } +} + void m_config_push(struct m_config *config) { struct m_config_option *co; @@ -278,7 +298,7 @@ void m_config_pop(struct m_config *config) pop++; } if (pop) // We removed some ctx -> set the previous value - m_option_set(config, co->opt, co->slots->data); + m_option_set(config->optstruct, co->opt, co->slots->data); } config->lvl--; @@ -314,7 +334,7 @@ static void m_config_add_option(struct m_config *config, struct m_config_save_slot *sl; assert(config != NULL); - assert(config->lvl > 0); + assert(config->lvl > 0 || !config->full); assert(arg != NULL); // Allocate a new entry for this option @@ -346,18 +366,18 @@ static void m_config_add_option(struct m_config *config, } } } - if (!(co->flags & M_CFG_OPT_ALIAS)) { + if (config->full && !(co->flags & M_CFG_OPT_ALIAS)) { // Allocate a slot for the defaults sl = talloc_zero_size(co, sizeof(struct m_config_save_slot) + arg->type->size); m_option_save(config, arg, sl->data); // Hack to avoid too much trouble with dynamically allocated data: // We replace original default and always use a dynamic version - if ((arg->type->flags & M_OPT_TYPE_DYNAMIC)) { + if (!arg->new && (arg->type->flags & M_OPT_TYPE_DYNAMIC)) { char **hackptr = m_option_get_ptr(arg, config->optstruct); if (hackptr && *hackptr) { *hackptr = NULL; - m_option_set(config, arg, sl->data); + m_option_set(config->optstruct, arg, sl->data); } } sl->lvl = 0; @@ -377,7 +397,7 @@ int m_config_register_options(struct m_config *config, const struct m_option *args) { assert(config != NULL); - assert(config->lvl > 0); + assert(config->lvl > 0 || !config->full); assert(args != NULL); add_options(config, args, NULL, NULL); @@ -403,12 +423,15 @@ static struct m_config_option *m_config_get_co(const struct m_config *config, return NULL; } -static int m_config_parse_option(struct m_config *config, +static int parse_subopts(struct m_config *config, void *optstruct, char *name, + char *prefix, struct bstr param, bool set); + +static int m_config_parse_option(struct m_config *config, void *optstruct, struct bstr name, struct bstr param, bool ambiguous_param, bool set) { assert(config != NULL); - assert(config->lvl > 0); + assert(config->lvl > 0 || !config->full); assert(name.len != 0); struct m_config_option *co = m_config_get_co(config, name); @@ -453,43 +476,13 @@ static int m_config_parse_option(struct m_config *config, // Option with children are a bit different to parse if (co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) { - char **lst = NULL; - // Parse the child options - int r = m_option_parse(co->opt, name, param, false, &lst); - // Set them now - if (r >= 0) - for (int i = 0; lst && lst[2 * i]; i++) { - int l = strlen(co->name) + 1 + strlen(lst[2 * i]) + 1; - if (r >= 0) { - // Build the full name - char n[l]; - sprintf(n, "%s:%s", co->name, lst[2 * i]); - int sr = m_config_parse_option(config, bstr(n), - bstr(lst[2 * i + 1]), false, - set); - if (sr < 0) { - if (sr == M_OPT_UNKNOWN) { - mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, - "Error: option '%s' has no suboption '%s'.\n", - co->name, lst[2 * i]); - r = M_OPT_INVALID; - } else if (sr == M_OPT_MISSING_PARAM) { - mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, - "Error: suboption '%s' of '%s' must have " - "a parameter!\n", lst[2 * i], co->name); - r = M_OPT_INVALID; - } else - r = sr; - } - } - talloc_free(lst[2 * i]); - talloc_free(lst[2 * i + 1]); - } - talloc_free(lst); - return r; + char prefix[110]; + assert(strlen(co->name) < 100); + sprintf(prefix, "%s:", co->name); + return parse_subopts(config, optstruct, co->name, prefix, param, set); } - void *dst = set ? m_option_get_ptr(co->opt, config->optstruct) : NULL; + void *dst = set ? m_option_get_ptr(co->opt, optstruct) : NULL; int r = m_option_parse(co->opt, name, param, ambiguous_param, dst); // Parsing failed ? if (r < 0) @@ -500,12 +493,49 @@ static int m_config_parse_option(struct m_config *config, return r; } +static int parse_subopts(struct m_config *config, void *optstruct, char *name, + char *prefix, struct bstr param, bool set) +{ + char **lst = NULL; + // Split the argument into child options + int r = m_option_type_subconfig.parse(NULL, bstr(""), param, false, &lst); + if (r < 0) + return r; + // Parse the child options + for (int i = 0; lst && lst[2 * i]; i++) { + // Build the full name + char n[110]; + if (snprintf(n, 110, "%s%s", prefix, lst[2 * i]) > 100) + abort(); + int sr = m_config_parse_option(config, optstruct, bstr(n), + bstr(lst[2 * i + 1]), false, set); + if (sr < 0) { + if (sr == M_OPT_UNKNOWN) { + mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, + "Error: option '%s' has no suboption '%s'.\n", + name, lst[2 * i]); + r = M_OPT_INVALID; + } else if (sr == M_OPT_MISSING_PARAM) { + mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, + "Error: suboption '%s' of '%s' must have " + "a parameter!\n", lst[2 * i], name); + r = M_OPT_INVALID; + } else + r = sr; + break; + } + } + talloc_free(lst); + return r; +} + int m_config_set_option(struct m_config *config, struct bstr name, struct bstr param, bool ambiguous_param) { mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Setting %.*s=%.*s\n", BSTR_P(name), BSTR_P(param)); - return m_config_parse_option(config, name, param, ambiguous_param, 1); + return m_config_parse_option(config, config->optstruct, name, param, + ambiguous_param, true); } int m_config_check_option(struct m_config *config, struct bstr name, @@ -514,7 +544,7 @@ int m_config_check_option(struct m_config *config, struct bstr name, int r; mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Checking %.*s=%.*s\n", BSTR_P(name), BSTR_P(param)); - r = m_config_parse_option(config, name, param, ambiguous_param, 0); + r = m_config_parse_option(config, NULL, name, param, ambiguous_param, 0); if (r == M_OPT_MISSING_PARAM) { mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, "Error: option '%.*s' must have a parameter!\n", BSTR_P(name)); @@ -523,6 +553,14 @@ int m_config_check_option(struct m_config *config, struct bstr name, return r; } +int m_config_parse_suboptions(struct m_config *config, void *optstruct, + char *name, char *subopts) +{ + if (!subopts || !*subopts) + return 0; + return parse_subopts(config, optstruct, name, "", bstr(subopts), true); +} + const struct m_option *m_config_get_option(const struct m_config *config, struct bstr name) diff --git a/m_config.h b/m_config.h index ff54aae8b2..24e80eb538 100644 --- a/m_config.h +++ b/m_config.h @@ -96,6 +96,7 @@ typedef struct m_config { void *optstruct; // struct mpopts or other int (*includefunc)(struct m_config *conf, char *filename); + bool full; // main config with save slot handling etc } m_config_t; @@ -110,6 +111,10 @@ struct m_config * m_config_new(void *optstruct, int includefunc(struct m_config *conf, char *filename)); +struct m_config *m_config_simple(const struct m_option *options); + +void m_config_initialize(struct m_config *conf, void *optstruct); + // Free a config object. void m_config_free(struct m_config *config); @@ -162,6 +167,9 @@ static inline int m_config_check_option0(struct m_config *config, return m_config_check_option(config, bstr(name), bstr(param), ambiguous); } +int m_config_parse_suboptions(struct m_config *config, void *optstruct, + char *name, char *subopts); + /* Get the option matching the given name. * \param config The config object. diff --git a/m_option.c b/m_option.c index 55a58fc35c..7e701765b7 100644 --- a/m_option.c +++ b/m_option.c @@ -821,14 +821,13 @@ const m_option_type_t m_option_type_print_func = { static int parse_subconf(const m_option_t *opt, struct bstr name, struct bstr param, bool ambiguous_param, void *dst) { - int nr = 0, i; + int nr = 0; char **lst = NULL; if (param.len == 0) return M_OPT_MISSING_PARAM; struct bstr p = param; - const struct m_option *subopts = opt->p; while (p.len) { int optlen = bstrcspn(p, ":="); @@ -874,23 +873,11 @@ static int parse_subconf(const m_option_t *opt, struct bstr name, return M_OPT_INVALID; } - for (i = 0; subopts[i].name; i++) - if (!bstrcmp0(subopt, subopts[i].name)) - break; - if (!subopts[i].name) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, - "Option %.*s: Unknown suboption %.*s\n", - BSTR_P(name), BSTR_P(subopt)); - return M_OPT_UNKNOWN; - } - int r = m_option_parse(&subopts[i], subopt, subparam, false, NULL); - if (r < 0) - return r; if (dst) { lst = talloc_realloc(NULL, lst, char *, 2 * (nr + 2)); - lst[2 * nr] = bstrdup0(NULL, subopt); + lst[2 * nr] = bstrdup0(lst, subopt); lst[2 * nr + 1] = subparam.len == 0 ? NULL : - bstrdup0(NULL, subparam); + bstrdup0(lst, subparam); memset(&lst[2 * (nr + 1)], 0, 2 * sizeof(char *)); nr++; } diff --git a/m_option.h b/m_option.h index 879b9d6563..9b355ff3e0 100644 --- a/m_option.h +++ b/m_option.h @@ -256,6 +256,9 @@ struct m_option { int new; int offset; + + // Initialize variable to given default before parsing options + void *defval; }; @@ -424,22 +427,39 @@ static inline void m_option_free(const m_option_t *opt, void *dst) #define OPT_START_CONDITIONAL(enable, featurename) OPT_START_CONDITIONAL_AFTERMACROEVAL(enable, featurename) #define OPT_START_CONDITIONAL_AFTERMACROEVAL(enable, featurename) {"conditional functionality: " #enable, .p = featurename} -#define OPT_FLAG_ON(optname, varname, flags) {optname, NULL, &m_option_type_flag, flags, 0, 1, NULL, 1, offsetof(struct MPOpts, varname)} -#define OPT_FLAG_OFF(optname, varname, flags) {optname, NULL, &m_option_type_flag, flags, 1, 0, NULL, 1, offsetof(struct MPOpts, varname)} +#define OPTDEF_STR(s) .defval = (void *)&(char * const){s} +#define OPTDEF_INT(i) .defval = (void *)&(const int){i} + +#define OPT_GENERAL(optname, varname, flagv, ...) {.name = optname, .flags = flagv, .new = 1, .offset = offsetof(OPT_BASE_STRUCT, varname), __VA_ARGS__} + +/* The OPT_FLAG_CONSTANTS->OPT_FLAG_CONSTANTS_ kind of redirection exists to + * make the code fully standard-conforming: the C standard requires that + * __VA_ARGS__ has at least one argument (though GCC for example would accept + * 0). Thus the first OPT_FLAG_CONSTANTS is a wrapper which just adds one + * argument to ensure __VA_ARGS__ is not empty when calling the next macro. + */ +#define OPT_FLAG_ON(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_flag, .max = 1) +#define OPT_FLAG_OFF(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_flag, .min = 1) #define OPT_MAKE_FLAGS(optname, varname, flags) OPT_FLAG_ON(optname, varname, flags), OPT_FLAG_OFF("no" optname, varname, flags) -#define OPT_FLAG_CONSTANTS(optname, varname, flags, offvalue, value) {optname, NULL, &m_option_type_flag, flags, offvalue, value, NULL, 1, offsetof(struct MPOpts, varname)} -#define OPT_STRINGLIST(optname, varname, flags) {optname, NULL, &m_option_type_string_list, flags, 0, 0, NULL, 1, offsetof(struct MPOpts, varname)} -#define OPT_PATHLIST(optname, varname, flags) {optname, NULL, &m_option_type_string_list, flags, 0, 0, (void *)&(const char){OPTION_PATH_SEPARATOR}, 1, offsetof(struct MPOpts, varname)} -#define OPT_INT(optname, varname, flags) {optname, NULL, &m_option_type_int, flags, 0, 0, NULL, 1, offsetof(struct MPOpts, varname)} -#define OPT_INTRANGE(optname, varname, flags, min, max) {optname, NULL, &m_option_type_int, (flags) | CONF_RANGE, min, max, NULL, 1, offsetof(struct MPOpts, varname)} -#define OPT_INTPAIR(optname, varname, flags) {optname, NULL, &m_option_type_intpair, (flags), 0, 0, NULL, 1, offsetof(struct MPOpts, varname)} -#define OPT_FLOATRANGE(optname, varname, flags, min, max) {optname, NULL, &m_option_type_float, (flags) | CONF_RANGE, min, max, NULL, 1, offsetof(struct MPOpts, varname)} -#define OPT_STRING(optname, varname, flags) {optname, NULL, &m_option_type_string, flags, 0, 0, NULL, 1, offsetof(struct MPOpts, varname)} -#define OPT_SETTINGSLIST(optname, varname, flags, objlist) {optname, NULL, &m_option_type_obj_settings_list, flags, 0, 0, objlist, 1, offsetof(struct MPOpts, varname)} -#define OPT_AUDIOFORMAT(optname, varname, flags) {optname, NULL, &m_option_type_afmt, flags, 0, 0, NULL, 1, offsetof(struct MPOpts, varname)} +#define OPT_FLAG_CONSTANTS(...) OPT_FLAG_CONSTANTS_(__VA_ARGS__, .type = &m_option_type_flag) +#define OPT_FLAG_CONSTANTS_(optname, varname, flags, offvalue, value, ...) OPT_GENERAL(optname, varname, flags, .min = offvalue, .max = value, __VA_ARGS__) +#define OPT_STRINGLIST(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_string_list) +#define OPT_PATHLIST(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_string_list, .priv = (void *)&(const char){OPTION_PATH_SEPARATOR}) +#define OPT_INT(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_int) +#define OPT_INTRANGE(...) OPT_RANGE_(__VA_ARGS__, .type = &m_option_type_int) +#define OPT_RANGE_(optname, varname, flags, minval, maxval, ...) OPT_GENERAL(optname, varname, (flags) | CONF_RANGE, .min = minval, .max = maxval, __VA_ARGS__) +#define OPT_INTPAIR(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_intpair) +#define OPT_FLOAT(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_float) +#define OPT_FLOATRANGE(...) OPT_RANGE_(__VA_ARGS__, .type = &m_option_type_float) +#define OPT_STRING(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_string) +#define OPT_SETTINGSLIST(optname, varname, flags, objlist) OPT_GENERAL(optname, varname, flags, .type = &m_option_type_obj_settings_list, .priv = objlist) +#define OPT_AUDIOFORMAT(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_afmt) #define OPT_HELPER_REMOVEPAREN(...) __VA_ARGS__ -#define OPT_CHOICE(optname, varname, flags, choices) {optname, NULL, &m_option_type_choice, flags, 0, 0, (void *)&(const struct m_opt_choice_alternatives[]){OPT_HELPER_REMOVEPAREN choices, {NULL}}, 1, offsetof(struct MPOpts, varname)} -#define OPT_TIME(optname, varname, flags) {optname, NULL, &m_option_type_time, flags, 0, 0, NULL, 1, offsetof(struct MPOpts, varname)} -#define OPT_ERRORMESSAGE(optname, message) {optname, message, CONF_TYPE_PRINT} +#define OPT_CHOICE(...) OPT_CHOICE_(__VA_ARGS__, .type = &m_option_type_choice) +#define OPT_CHOICE_(optname, varname, flags, choices, ...) OPT_GENERAL(optname, varname, flags, .priv = (void *)&(const struct m_opt_choice_alternatives[]){OPT_HELPER_REMOVEPAREN choices, {NULL}}, __VA_ARGS__) +#define OPT_TIME(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_time) +#define OPT_ERRORMESSAGE(optname, message) {.name = optname, .p = message, .type = &m_option_type_print} + +#define OPT_BASE_STRUCT struct MPOpts #endif /* MPLAYER_M_OPTION_H */ diff --git a/mplayer.c b/mplayer.c index 5aa6f4cde0..5a2e7be1b3 100644 --- a/mplayer.c +++ b/mplayer.c @@ -3942,6 +3942,7 @@ int main(int argc, char *argv[]) m_config_register_options(mpctx->mconfig, mplayer_opts); m_config_register_options(mpctx->mconfig, common_opts); mp_input_register_options(mpctx->mconfig); + m_config_initialize(mpctx->mconfig, opts); // Preparse the command line m_config_preparse_command_line(mpctx->mconfig, argc, argv, &verbose); -- cgit v1.2.3 From 48f0692ab973448de5faa323478d1cba3d42e2af Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Sun, 20 May 2012 01:26:38 +0300 Subject: options: make option struct the talloc parent of options Allocate dynamically-allocated option values as talloc children of the option struct. This will allow implementing per-object (VO etc) options so that simply freeing the object will free associated options too. This doesn't change quite every allocation in m_option.c, but the exceptions are legacy types which will not matter for new per-object options. --- m_config.c | 13 +++++---- m_option.c | 91 ++++++++++++++++++++++++++++++++++++++------------------------ m_option.h | 11 +++++--- m_struct.c | 2 +- 4 files changed, 72 insertions(+), 45 deletions(-) diff --git a/m_config.c b/m_config.c index e8996670f4..7545cdb4eb 100644 --- a/m_config.c +++ b/m_config.c @@ -67,7 +67,8 @@ static int parse_profile(struct m_config *config, const struct m_option *opt, } char **list = NULL; - int r = m_option_type_string_list.parse(opt, name, param, false, &list); + int r = m_option_type_string_list.parse(opt, name, param, false, &list, + NULL); if (r < 0) return r; if (!list || !list[0]) @@ -144,7 +145,7 @@ static void m_option_save(const struct m_config *config, { if (opt->type->copy) { const void *src = m_option_get_ptr(opt, config->optstruct); - opt->type->copy(opt, dst, src); + opt->type->copy(opt, dst, src, NULL); } } @@ -153,7 +154,7 @@ static void m_option_set(void *optstruct, { if (opt->type->copy) { void *dst = m_option_get_ptr(opt, optstruct); - opt->type->copy(opt, dst, src); + opt->type->copy(opt, dst, src, optstruct); } } @@ -483,7 +484,8 @@ static int m_config_parse_option(struct m_config *config, void *optstruct, } void *dst = set ? m_option_get_ptr(co->opt, optstruct) : NULL; - int r = m_option_parse(co->opt, name, param, ambiguous_param, dst); + int r = co->opt->type->parse(co->opt, name, param, ambiguous_param, dst, + optstruct); // Parsing failed ? if (r < 0) return r; @@ -498,7 +500,8 @@ static int parse_subopts(struct m_config *config, void *optstruct, char *name, { char **lst = NULL; // Split the argument into child options - int r = m_option_type_subconfig.parse(NULL, bstr(""), param, false, &lst); + int r = m_option_type_subconfig.parse(NULL, bstr(""), param, false, &lst, + optstruct); if (r < 0) return r; // Parse the child options diff --git a/m_option.c b/m_option.c index 7e701765b7..23343c73a6 100644 --- a/m_option.c +++ b/m_option.c @@ -77,7 +77,8 @@ const m_option_t *m_option_list_find(const m_option_t *list, const char *name) // Default function that just does a memcpy -static void copy_opt(const m_option_t *opt, void *dst, const void *src) +static void copy_opt(const m_option_t *opt, void *dst, const void *src, + void *talloc_ctx) { if (dst && src) memcpy(dst, src, opt->type->size); @@ -88,7 +89,8 @@ static void copy_opt(const m_option_t *opt, void *dst, const void *src) #define VAL(x) (*(int *)(x)) static int parse_flag(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { if (param.len && !ambiguous_param) { char * const enable[] = { "yes", "on", "ja", "si", "igen", "y", "j", @@ -177,7 +179,8 @@ static int parse_longlong(const m_option_t *opt, struct bstr name, } static int parse_int(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { long long tmp; int r = parse_longlong(opt, name, param, false, &tmp); @@ -187,7 +190,8 @@ static int parse_int(const m_option_t *opt, struct bstr name, } static int parse_int64(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { long long tmp; int r = parse_longlong(opt, name, param, false, &tmp); @@ -221,7 +225,8 @@ const m_option_type_t m_option_type_int64 = { }; static int parse_intpair(const struct m_option *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { if (param.len == 0) return M_OPT_MISSING_PARAM; @@ -264,7 +269,8 @@ const struct m_option_type m_option_type_intpair = { }; static int parse_choice(const struct m_option *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { if (param.len == 0) return M_OPT_MISSING_PARAM; @@ -313,7 +319,8 @@ const struct m_option_type m_option_type_choice = { #define VAL(x) (*(double *)(x)) static int parse_double(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { if (param.len == 0) return M_OPT_MISSING_PARAM; @@ -387,10 +394,11 @@ const m_option_type_t m_option_type_double = { #define VAL(x) (*(float *)(x)) static int parse_float(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { double tmp; - int r = parse_double(opt, name, param, false, &tmp); + int r = parse_double(opt, name, param, false, &tmp, NULL); if (r == 1 && dst) VAL(dst) = tmp; return r; @@ -416,7 +424,8 @@ const m_option_type_t m_option_type_float = { #define VAL(x) (*(off_t *)(x)) static int parse_position(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { long long tmp; int r = parse_longlong(opt, name, param, false, &tmp); @@ -446,7 +455,8 @@ const m_option_type_t m_option_type_position = { #define VAL(x) (*(char **)(x)) static int parse_str(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { if ((opt->flags & M_OPT_MIN) && (param.len < opt->min)) { mp_msg(MSGT_CFGPARSER, MSGL_ERR, @@ -464,7 +474,7 @@ static int parse_str(const m_option_t *opt, struct bstr name, if (dst) { talloc_free(VAL(dst)); - VAL(dst) = bstrdup0(NULL, param); + VAL(dst) = bstrdup0(talloc_ctx, param); } return 1; @@ -476,11 +486,12 @@ static char *print_str(const m_option_t *opt, const void *val) return (val && VAL(val)) ? talloc_strdup(NULL, VAL(val)) : NULL; } -static void copy_str(const m_option_t *opt, void *dst, const void *src) +static void copy_str(const m_option_t *opt, void *dst, const void *src, + void *talloc_ctx) { if (dst && src) { talloc_free(VAL(dst)); - VAL(dst) = talloc_strdup(NULL, VAL(src)); + VAL(dst) = talloc_strdup(talloc_ctx, VAL(src)); } } @@ -528,7 +539,7 @@ static void free_str_list(void *dst) VAL(dst) = NULL; } -static int str_list_add(char **add, int n, void *dst, int pre) +static int str_list_add(char **add, int n, void *dst, int pre, void *talloc_ctx) { char **lst = VAL(dst); int ln; @@ -632,7 +643,8 @@ static struct bstr get_nextsep(struct bstr *ptr, char sep, bool modify) } static int parse_str_list(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { char **res; int op = OP_NONE; @@ -681,14 +693,14 @@ static int parse_str_list(const m_option_t *opt, struct bstr name, if (!dst) return 1; - res = talloc_array(NULL, char *, n + 2); + res = talloc_array(talloc_ctx, char *, n + 2); str = bstrdup(NULL, param); char *ptr = str.start; n = 0; while (1) { struct bstr el = get_nextsep(&str, separator, 1); - res[n] = bstrdup0(NULL, el); + res[n] = bstrdup0(talloc_ctx, el); n++; if (!str.len) break; @@ -699,9 +711,9 @@ static int parse_str_list(const m_option_t *opt, struct bstr name, switch (op) { case OP_ADD: - return str_list_add(res, n, dst, 0); + return str_list_add(res, n, dst, 0, talloc_ctx); case OP_PRE: - return str_list_add(res, n, dst, 1); + return str_list_add(res, n, dst, 1, talloc_ctx); case OP_DEL: return str_list_del(res, n, dst); } @@ -713,7 +725,8 @@ static int parse_str_list(const m_option_t *opt, struct bstr name, return 1; } -static void copy_str_list(const m_option_t *opt, void *dst, const void *src) +static void copy_str_list(const m_option_t *opt, void *dst, const void *src, + void *talloc_ctx) { int n; char **d, **s; @@ -732,9 +745,9 @@ static void copy_str_list(const m_option_t *opt, void *dst, const void *src) for (n = 0; s[n] != NULL; n++) /* NOTHING */; - d = talloc_array(NULL, char *, n + 1); + d = talloc_array(talloc_ctx, char *, n + 1); for (; n >= 0; n--) - d[n] = talloc_strdup(NULL, s[n]); + d[n] = talloc_strdup(talloc_ctx, s[n]); VAL(dst) = d; } @@ -778,7 +791,8 @@ const m_option_type_t m_option_type_string_list = { /////////////////// Print static int parse_print(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { if (opt->type == CONF_TYPE_PRINT_INDIRECT) mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", *(char **) opt->p); @@ -819,7 +833,8 @@ const m_option_type_t m_option_type_print_func = { #define VAL(x) (*(char ***)(x)) static int parse_subconf(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { int nr = 0; char **lst = NULL; @@ -977,7 +992,8 @@ static struct { }; static int parse_imgfmt(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { uint32_t fmt = 0; int i; @@ -1067,7 +1083,8 @@ static struct { }; static int parse_afmt(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { uint32_t fmt = 0; int i; @@ -1135,7 +1152,8 @@ static int parse_timestring(struct bstr str, double *time, char endchar) static int parse_time(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { double time; @@ -1165,7 +1183,8 @@ const m_option_type_t m_option_type_time = { // Time or size (-endpos) static int parse_time_size(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { m_time_size_t ts; char unit[4]; @@ -1397,7 +1416,8 @@ static int get_obj_params(struct bstr opt_name, struct bstr name, } static int parse_obj_params(const m_option_t *opt, struct bstr name, - struct bstr param, bool ambiguous_param, void *dst) + struct bstr param, bool ambiguous_param, void *dst, + void *talloc_ctx) { char **opts; int r; @@ -1595,7 +1615,7 @@ static void free_obj_settings_list(void *dst) static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, struct bstr param, bool ambiguous_param, - void *dst) + void *dst, void *talloc_ctx) { int len = strlen(opt->name); m_obj_settings_t *res = NULL, *queue = NULL, *head = NULL; @@ -1726,7 +1746,7 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, } static void copy_obj_settings_list(const m_option_t *opt, void *dst, - const void *src) + const void *src, void *talloc_ctx) { m_obj_settings_t *d, *s; int n; @@ -1749,7 +1769,7 @@ static void copy_obj_settings_list(const m_option_t *opt, void *dst, for (n = 0; s[n].name; n++) { d[n].name = talloc_strdup(NULL, s[n].name); d[n].attribs = NULL; - copy_str_list(NULL, &(d[n].attribs), &(s[n].attribs)); + copy_str_list(NULL, &(d[n].attribs), &(s[n].attribs), NULL); } d[n].name = NULL; d[n].attribs = NULL; @@ -1769,7 +1789,7 @@ const m_option_type_t m_option_type_obj_settings_list = { static int parse_obj_presets(const m_option_t *opt, struct bstr name, struct bstr param, bool ambiguous_param, - void *dst) + void *dst, void *talloc_ctx) { m_obj_presets_t *obj_p = (m_obj_presets_t *)opt->priv; const m_struct_t *in_desc; @@ -1844,7 +1864,8 @@ const m_option_type_t m_option_type_obj_presets = { }; static int parse_custom_url(const m_option_t *opt, struct bstr name, - struct bstr url, bool ambiguous_param, void *dst) + struct bstr url, bool ambiguous_param, void *dst, + void *talloc_ctx) { int r; m_struct_t *desc = opt->priv; diff --git a/m_option.h b/m_option.h index 9b355ff3e0..648c560305 100644 --- a/m_option.h +++ b/m_option.h @@ -192,11 +192,12 @@ struct m_option_type { * may not be an argument meant for this option * \param dst Pointer to the memory where the data should be written. * If NULL the parameter validity should still be checked. + * talloc_ctx: talloc context if value type requires allocations * \return On error a negative value is returned, on success the number * of arguments consumed. For details see \ref OptionParserReturn. */ int (*parse)(const m_option_t *opt, struct bstr name, struct bstr param, - bool ambiguous_param, void *dst); + bool ambiguous_param, void *dst, void *talloc_ctx); // Print back a value in string form. /** \param opt The option to print. @@ -210,8 +211,10 @@ struct m_option_type { /** \param opt The option to copy. * \param dst Pointer to the destination memory. * \param src Pointer to the source memory. + * talloc_ctx: talloc context to use in deep copy */ - void (*copy)(const m_option_t *opt, void *dst, const void *src); + void (*copy)(const m_option_t *opt, void *dst, const void *src, + void *talloc_ctx); // Free the data allocated for a save slot. /** This is only needed for dynamic types like strings. @@ -385,7 +388,7 @@ static inline int m_option_parse(const m_option_t *opt, struct bstr name, struct bstr param, bool ambiguous_param, void *dst) { - return opt->type->parse(opt, name, param, ambiguous_param, dst); + return opt->type->parse(opt, name, param, ambiguous_param, dst, NULL); } // Helper to print options, see \ref m_option_type::print. @@ -402,7 +405,7 @@ static inline void m_option_copy(const m_option_t *opt, void *dst, const void *src) { if (opt->type->copy) - opt->type->copy(opt, dst, src); + opt->type->copy(opt, dst, src, NULL); } // Helper around \ref m_option_type::free. diff --git a/m_struct.c b/m_struct.c index 8b34cea359..6e32bf32c8 100644 --- a/m_struct.c +++ b/m_struct.c @@ -71,7 +71,7 @@ int m_struct_set(const m_struct_t *st, void *obj, const char *field, return 0; } - if(f->type->parse(f, bstr(field), param, false, M_ST_MB_P(obj,f->p)) < 0) { + if(f->type->parse(f, bstr(field), param, false, M_ST_MB_P(obj,f->p), NULL) < 0) { mp_msg(MSGT_CFGPARSER, MSGL_ERR,"Struct %s, field %s parsing error: %.*s\n", st->name, field, BSTR_P(param)); return 0; -- cgit v1.2.3 From 9426c5f92aab4b561c568e4250f5b250e2aa45c5 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Mon, 25 Jun 2012 23:12:03 +0300 Subject: VO: implement shared option handling, use for vdpau Add infrastructure that allows VOs to specify the suboptions they take, and get the values directly parsed into their private struct. The option functionality available with the new system is the same as for top-level player options. Convert vo_vdpau to use the new system instead of the old subopt_helper. --- libvo/video_out.c | 18 ++++++++++-- libvo/video_out.h | 6 ++++ libvo/vo_vdpau.c | 84 +++++++++++++++++++------------------------------------ 3 files changed, 50 insertions(+), 58 deletions(-) diff --git a/libvo/video_out.c b/libvo/video_out.c index 96a5220645..b604a52391 100644 --- a/libvo/video_out.c +++ b/libvo/video_out.c @@ -36,8 +36,7 @@ #include "old_vo_wrapper.h" #include "input/input.h" #include "mp_fifo.h" - - +#include "m_config.h" #include "mp_msg.h" #include "osdep/shmem.h" @@ -254,8 +253,21 @@ const struct vo_driver *video_out_drivers[] = }; -static int vo_preinit(struct vo *vo, const char *arg) +static int vo_preinit(struct vo *vo, char *arg) { + if (vo->driver->privsize) + vo->priv = talloc_zero_size(vo, vo->driver->privsize); + if (vo->driver->options) { + struct m_config *cfg = m_config_simple(vo->driver->options); + m_config_initialize(cfg, vo->priv); + char n[50]; + int l = snprintf(n, sizeof(n), "vo/%s", vo->driver->info->short_name); + assert(l < sizeof(n)); + int r = m_config_parse_suboptions(cfg, vo->priv, n, arg); + talloc_free(cfg); + if (r < 0) + return r; + } return vo->driver->preinit(vo, arg); } diff --git a/libvo/video_out.h b/libvo/video_out.h index 3dd3ca8a8d..10a3891b7b 100644 --- a/libvo/video_out.h +++ b/libvo/video_out.h @@ -239,6 +239,12 @@ struct vo_driver { * Closes driver. Should restore the original state of the system. */ void (*uninit)(struct vo *vo); + + // Size of private struct for automatic allocation + int privsize; + + // List of options to parse into priv struct (requires privsize to be set) + const struct m_option *options; }; struct vo_old_functions { diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c index 0971ae47ea..a99cfeea7d 100644 --- a/libvo/vo_vdpau.c +++ b/libvo/vo_vdpau.c @@ -43,7 +43,7 @@ #include "aspect.h" #include "csputils.h" #include "sub/sub.h" -#include "subopt-helper.h" +#include "m_option.h" #include "libmpcodecs/vfcap.h" #include "libmpcodecs/mp_image.h" #include "osdep/timer.h" @@ -1633,66 +1633,16 @@ static void uninit(struct vo *vo) static int preinit(struct vo *vo, const char *arg) { - int i; - int user_colorspace = 0; - int studio_levels = 0; - - struct vdpctx *vc = talloc_zero(vo, struct vdpctx); - vo->priv = vc; + struct vdpctx *vc = vo->priv; // Mark everything as invalid first so uninit() can tell what has been // allocated mark_vdpau_objects_uninitialized(vo); vc->colorspace = (struct mp_csp_details) MP_CSP_DETAILS_DEFAULTS; - vc->deint_type = 3; - vc->chroma_deint = 1; - vc->flip_offset_window = 50; - vc->flip_offset_fs = 50; - vc->num_output_surfaces = 3; vc->video_eq.capabilities = MP_CSP_EQ_CAPS_COLORMATRIX; - const opt_t subopts[] = { - {"deint", OPT_ARG_INT, &vc->deint, NULL}, - {"chroma-deint", OPT_ARG_BOOL, &vc->chroma_deint, NULL}, - {"pullup", OPT_ARG_BOOL, &vc->pullup, NULL}, - {"denoise", OPT_ARG_FLOAT, &vc->denoise, NULL}, - {"sharpen", OPT_ARG_FLOAT, &vc->sharpen, NULL}, - {"colorspace", OPT_ARG_INT, &user_colorspace, NULL}, - {"studio", OPT_ARG_BOOL, &studio_levels, NULL}, - {"hqscaling", OPT_ARG_INT, &vc->hqscaling, NULL}, - {"fps", OPT_ARG_FLOAT, &vc->user_fps, NULL}, - {"queuetime_windowed", OPT_ARG_INT, &vc->flip_offset_window, NULL}, - {"queuetime_fs", OPT_ARG_INT, &vc->flip_offset_fs, NULL}, - {"output_surfaces", OPT_ARG_INT, &vc->num_output_surfaces, NULL}, - {NULL} - }; - if (subopt_parse(arg, subopts) != 0) { - mp_msg(MSGT_VO, MSGL_FATAL, "[vdpau] Could not parse suboptions.\n"); - return -1; - } - if (vc->hqscaling < 0 || vc->hqscaling > 9) { - mp_msg(MSGT_VO, MSGL_FATAL, "[vdpau] Invalid value for suboption " - "hqscaling\n"); - return -1; - } - if (vc->num_output_surfaces < 2) { - mp_msg(MSGT_VO, MSGL_FATAL, "[vdpau] Invalid suboption " - "output_surfaces: can't use less than 2 surfaces\n"); - return -1; - } - if (user_colorspace != 0 || studio_levels != 0) { - mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] \"colorspace\" and \"studio\"" - " suboptions have been removed. Use options --colormatrix and" - " --colormatrix-output-range=limited instead.\n"); - return -1; - } - if (vc->num_output_surfaces > MAX_OUTPUT_SURFACES) { - mp_msg(MSGT_VO, MSGL_WARN, "[vdpau] Number of output surfaces " - "is limited to %d.\n", MAX_OUTPUT_SURFACES); - vc->num_output_surfaces = MAX_OUTPUT_SURFACES; - } - if (vc->deint) - vc->deint_type = FFABS(vc->deint); + + vc->deint_type = vc->deint ? FFABS(vc->deint) : 3; if (vc->deint < 0) vc->deint = 0; @@ -1709,7 +1659,7 @@ static int preinit(struct vo *vo, const char *arg) } // full grayscale palette. - for (i = 0; i < PALETTE_SIZE; ++i) + for (int i = 0; i < PALETTE_SIZE; ++i) vc->palette[i] = (i << 16) | (i << 8) | i; return 0; @@ -1869,6 +1819,9 @@ static int control(struct vo *vo, uint32_t request, void *data) return VO_NOTIMPL; } +#undef OPT_BASE_STRUCT +#define OPT_BASE_STRUCT struct vdpctx + const struct vo_driver video_out_vdpau = { .is_new = true, .buffer_frames = true, @@ -1888,4 +1841,25 @@ const struct vo_driver video_out_vdpau = { .flip_page_timed = flip_page_timed, .check_events = check_events, .uninit = uninit, + .privsize = sizeof(struct vdpctx), + .options = (const struct m_option []){ + OPT_INTRANGE("deint", deint, 0, -4, 4), + OPT_FLAG_ON("chroma-deint", chroma_deint, 0, OPTDEF_INT(1)), + OPT_FLAG_OFF("nochroma-deint", chroma_deint, 0), + OPT_MAKE_FLAGS("pullup", pullup, 0), + OPT_FLOATRANGE("denoise", denoise, 0, 0, 1), + OPT_FLOATRANGE("sharpen", sharpen, 0, -1, 1), + OPT_ERRORMESSAGE("colorspace", "vo_vdpau suboption \"colorspace\" has " + "been removed. Use --colormatrix instead.\n"), + OPT_ERRORMESSAGE("studio", "vo_vdpau suboption \"studio\" has been " + "removed. Use --colormatrix-output-range=limited " + "instead.\n"), + OPT_INTRANGE("hqscaling", hqscaling, 0, 0, 9), + OPT_FLOAT("fps", user_fps, 0), + OPT_INT("queuetime_windowed", flip_offset_window, 0, OPTDEF_INT(50)), + OPT_INT("queuetime_fs", flip_offset_fs, 0, OPTDEF_INT(50)), + OPT_INTRANGE("output_surfaces", num_output_surfaces, 0, + 2, MAX_OUTPUT_SURFACES, OPTDEF_INT(3)), + {NULL}, + } }; -- cgit v1.2.3 From 86571435baf116a91a31451d26224600f3575270 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Fri, 29 Jun 2012 05:14:26 +0300 Subject: options: fix specifying string options without parameter Specifying a string option with no parameter, as in "--dumpfile" with no '=', erroneously set the corresponding variable to NULL. Fix this to give an error about missing parameter instead. Suboption parsing explicitly treated empty option values as if the option had been specified with no value (no '='). Thus it was not possible to specify empty strings as values. I think this behavior was originally added only because of other limitations in the old implementation. Remove it, so that suboptions now behave the same as top-level ones in this regard. Document the NULL-distinguishing property of bstrdup0() that the code depends on, and also make bstrdup() behave consistently. --- bstr.h | 6 +++++- m_option.c | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bstr.h b/bstr.h index b3f942535e..99b7eea578 100644 --- a/bstr.h +++ b/bstr.h @@ -36,14 +36,18 @@ struct bstr { // demux_rtp.cpp (live555) C++ compilation workaround #ifndef __cplusplus +// If str.start is NULL, return NULL. static inline char *bstrdup0(void *talloc_ctx, struct bstr str) { return talloc_strndup(talloc_ctx, (char *)str.start, str.len); } +// Return start = NULL iff that is true for the original. static inline struct bstr bstrdup(void *talloc_ctx, struct bstr str) { - struct bstr r = { talloc_strndup(talloc_ctx, str.start, str.len), str.len }; + struct bstr r = { NULL, str.len }; + if (str.start) + r.start = talloc_memdup(talloc_ctx, str.start, str.len); return r; } diff --git a/m_option.c b/m_option.c index 23343c73a6..18f94dc7a9 100644 --- a/m_option.c +++ b/m_option.c @@ -458,6 +458,9 @@ static int parse_str(const m_option_t *opt, struct bstr name, struct bstr param, bool ambiguous_param, void *dst, void *talloc_ctx) { + if (param.start == NULL) + return M_OPT_MISSING_PARAM; + if ((opt->flags & M_OPT_MIN) && (param.len < opt->min)) { mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Parameter must be >= %d chars: %.*s\n", @@ -891,8 +894,7 @@ static int parse_subconf(const m_option_t *opt, struct bstr name, if (dst) { lst = talloc_realloc(NULL, lst, char *, 2 * (nr + 2)); lst[2 * nr] = bstrdup0(lst, subopt); - lst[2 * nr + 1] = subparam.len == 0 ? NULL : - bstrdup0(lst, subparam); + lst[2 * nr + 1] = bstrdup0(lst, subparam); memset(&lst[2 * (nr + 1)], 0, 2 * sizeof(char *)); nr++; } -- cgit v1.2.3 From 39a45c7a175acf7ef5546073f62f5b9b7f83a893 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Mon, 2 Jul 2012 02:09:03 +0300 Subject: build: use python3 to generate some files previously in git Some files used during build are generated with Python scripts in TOOLS/. Before, the generated files were included in the git tree. Start creating them at build time. This introduces a build-dependency on python3. The files in question are: libvo/vdpau_template.c libmpdemux/ebml_types.h libmpdemux/ebml_defs.c --- .gitignore | 3 + Makefile | 18 +- TOOLS/matroska.py | 2 +- TOOLS/vdpau_functions.py | 2 + libmpdemux/ebml_defs.c | 424 ----------------------------------------- libmpdemux/ebml_types.h | 477 ----------------------------------------------- libvo/vdpau_template.c | 43 ----- 7 files changed, 20 insertions(+), 949 deletions(-) mode change 100644 => 100755 TOOLS/vdpau_functions.py delete mode 100644 libmpdemux/ebml_defs.c delete mode 100644 libmpdemux/ebml_types.h delete mode 100644 libvo/vdpau_template.c diff --git a/.gitignore b/.gitignore index e90239351c..5a4994fca2 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ /TAGS /locale /po +/libmpdemux/ebml_defs.c +/libmpdemux/ebml_types.h +/libvo/vdpau_template.c diff --git a/Makefile b/Makefile index eb81564ce0..f90aa5e906 100644 --- a/Makefile +++ b/Makefile @@ -598,6 +598,15 @@ codec-cfg$(EXESUF): codec-cfg.c codec-cfg.h codecs.conf.h: codec-cfg$(EXESUF) etc/codecs.conf ./$^ > $@ +libvo/vdpau_template.c: TOOLS/vdpau_functions.py + ./$< > $@ + +libmpdemux/ebml_types.h: TOOLS/matroska.py + ./$< --generate-header > $@ + +libmpdemux/ebml_defs.c: TOOLS/matroska.py + ./$< --generate-definitions > $@ + # ./configure must be rerun if it changed config.mak: configure @echo "############################################################" @@ -631,6 +640,9 @@ checkheaders: $(ALLHEADERS:.h=.ho) # Make sure all generated header files are created. codec-cfg.o: codecs.conf.h mpcommon.o osdep/mplayer-rc.o: version.h +libvo/vo_vdpau.o: libvo/vdpau_template.c +libmpdemux/ebml.o libmpdemux/demux_mkv.o: libmpdemux/ebml_types.h +libmpdemux/ebml.o: libmpdemux/ebml_defs.c # Files that depend on libavcodec internals libmpcodecs/vf_fspp.o libmpcodecs/vf_mcdeint.o libmpcodecs/vf_spp.o: CFLAGS := -I$(FFMPEG_SOURCE_PATH) $(CFLAGS) @@ -702,6 +714,8 @@ distclean: clean testsclean toolsclean driversclean -$(RM) -r locale -$(RM) $(call ADD_ALL_DIRS,/*.d) -$(RM) config.log config.mak config.h codecs.conf.h version.h TAGS tags + -$(RM) libvo/vdpau_template.c + -$(RM) libmpdemux/ebml_types.h libmpdemux/ebml_defs.c -$(RM) $(call ADD_ALL_EXESUFS,codec-cfg cpuinfo) doxygen: @@ -713,10 +727,6 @@ TAGS: tags: $(RM) $@; find . -name '*.[chS]' -o -name '*.asm' | xargs ctags -a -generated_ebml: - TOOLS/matroska.py --generate-header >libmpdemux/ebml_types.h - TOOLS/matroska.py --generate-definitions >libmpdemux/ebml_defs.c - ###### tests / tools ####### TEST_OBJS = mp_msg.o mp_fifo.o osdep/$(GETCH) osdep/$(TIMER) -ltermcap -lm diff --git a/TOOLS/matroska.py b/TOOLS/matroska.py index 375fb8b279..ffa388e47b 100755 --- a/TOOLS/matroska.py +++ b/TOOLS/matroska.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 """ Generate C definitions for parsing Matroska files. Can also be used to directly parse Matroska files and display their contents. diff --git a/TOOLS/vdpau_functions.py b/TOOLS/vdpau_functions.py old mode 100644 new mode 100755 index 27d6ff45f3..39e38a8bbe --- a/TOOLS/vdpau_functions.py +++ b/TOOLS/vdpau_functions.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + # Generate vdpau_template.c functions = """ diff --git a/libmpdemux/ebml_defs.c b/libmpdemux/ebml_defs.c deleted file mode 100644 index b683312079..0000000000 --- a/libmpdemux/ebml_defs.c +++ /dev/null @@ -1,424 +0,0 @@ -// Generated by TOOLS/matroska.py, do not edit manually - - -E("TagString", tag_string, EBML_TYPE_STR) - -E("TagLanguage", tag_language, EBML_TYPE_STR) - -E("TagName", tag_name, EBML_TYPE_STR) - -#define N simple_tag -E_S("SimpleTag", 3) -F(MATROSKA_ID_TAGNAME, tag_name, 0) -F(MATROSKA_ID_TAGLANGUAGE, tag_language, 0) -F(MATROSKA_ID_TAGSTRING, tag_string, 0) -}}; -#undef N - -E("TargetAttachmentUID", target_attachment_uid, EBML_TYPE_UINT) - -E("TargetChapterUID", target_chapter_uid, EBML_TYPE_UINT) - -E("TargetEditionUID", target_edition_uid, EBML_TYPE_UINT) - -E("TargetTrackUID", target_track_uid, EBML_TYPE_UINT) - -E("TargetTypeValue", target_type_value, EBML_TYPE_UINT) - -#define N targets -E_S("Targets", 5) -F(MATROSKA_ID_TARGETTYPEVALUE, target_type_value, 0) -F(MATROSKA_ID_TARGETTRACKUID, target_track_uid, 0) -F(MATROSKA_ID_TARGETEDITIONUID, target_edition_uid, 0) -F(MATROSKA_ID_TARGETCHAPTERUID, target_chapter_uid, 0) -F(MATROSKA_ID_TARGETATTACHMENTUID, target_attachment_uid, 0) -}}; -#undef N - -#define N tag -E_S("Tag", 2) -F(MATROSKA_ID_TARGETS, targets, 0) -F(MATROSKA_ID_SIMPLETAG, simple_tag, 1) -}}; -#undef N - -#define N tags -E_S("Tags", 1) -F(MATROSKA_ID_TAG, tag, 1) -}}; -#undef N - -E("ChapCountry", chap_country, EBML_TYPE_STR) - -E("ChapLanguage", chap_language, EBML_TYPE_STR) - -E("ChapString", chap_string, EBML_TYPE_STR) - -#define N chapter_display -E_S("ChapterDisplay", 3) -F(MATROSKA_ID_CHAPSTRING, chap_string, 0) -F(MATROSKA_ID_CHAPLANGUAGE, chap_language, 1) -F(MATROSKA_ID_CHAPCOUNTRY, chap_country, 1) -}}; -#undef N - -E("ChapterSegmentEditionUID", chapter_segment_edition_uid, EBML_TYPE_UINT) - -E("ChapterSegmentUID", chapter_segment_uid, EBML_TYPE_BINARY) - -E("ChapterFlagEnabled", chapter_flag_enabled, EBML_TYPE_UINT) - -E("ChapterFlagHidden", chapter_flag_hidden, EBML_TYPE_UINT) - -E("ChapterTimeEnd", chapter_time_end, EBML_TYPE_UINT) - -E("ChapterTimeStart", chapter_time_start, EBML_TYPE_UINT) - -E("ChapterUID", chapter_uid, EBML_TYPE_UINT) - -#define N chapter_atom -E_S("ChapterAtom", 8) -F(MATROSKA_ID_CHAPTERUID, chapter_uid, 0) -F(MATROSKA_ID_CHAPTERTIMESTART, chapter_time_start, 0) -F(MATROSKA_ID_CHAPTERTIMEEND, chapter_time_end, 0) -F(MATROSKA_ID_CHAPTERFLAGHIDDEN, chapter_flag_hidden, 0) -F(MATROSKA_ID_CHAPTERFLAGENABLED, chapter_flag_enabled, 0) -F(MATROSKA_ID_CHAPTERSEGMENTUID, chapter_segment_uid, 0) -F(MATROSKA_ID_CHAPTERSEGMENTEDITIONUID, chapter_segment_edition_uid, 0) -F(MATROSKA_ID_CHAPTERDISPLAY, chapter_display, 1) -}}; -#undef N - -E("EditionFlagOrdered", edition_flag_ordered, EBML_TYPE_UINT) - -E("EditionFlagDefault", edition_flag_default, EBML_TYPE_UINT) - -E("EditionFlagHidden", edition_flag_hidden, EBML_TYPE_UINT) - -E("EditionUID", edition_uid, EBML_TYPE_UINT) - -#define N edition_entry -E_S("EditionEntry", 5) -F(MATROSKA_ID_EDITIONUID, edition_uid, 0) -F(MATROSKA_ID_EDITIONFLAGHIDDEN, edition_flag_hidden, 0) -F(MATROSKA_ID_EDITIONFLAGDEFAULT, edition_flag_default, 0) -F(MATROSKA_ID_EDITIONFLAGORDERED, edition_flag_ordered, 0) -F(MATROSKA_ID_CHAPTERATOM, chapter_atom, 1) -}}; -#undef N - -#define N chapters -E_S("Chapters", 1) -F(MATROSKA_ID_EDITIONENTRY, edition_entry, 1) -}}; -#undef N - -E("FileUID", file_uid, EBML_TYPE_UINT) - -E("FileData", file_data, EBML_TYPE_BINARY) - -E("FileMimeType", file_mime_type, EBML_TYPE_STR) - -E("FileName", file_name, EBML_TYPE_STR) - -E("FileDescription", file_description, EBML_TYPE_STR) - -#define N attached_file -E_S("AttachedFile", 5) -F(MATROSKA_ID_FILEDESCRIPTION, file_description, 0) -F(MATROSKA_ID_FILENAME, file_name, 0) -F(MATROSKA_ID_FILEMIMETYPE, file_mime_type, 0) -F(MATROSKA_ID_FILEDATA, file_data, 0) -F(MATROSKA_ID_FILEUID, file_uid, 0) -}}; -#undef N - -#define N attachments -E_S("Attachments", 1) -F(MATROSKA_ID_ATTACHEDFILE, attached_file, 1) -}}; -#undef N - -E("CueClusterPosition", cue_cluster_position, EBML_TYPE_UINT) - -E("CueTrack", cue_track, EBML_TYPE_UINT) - -#define N cue_track_positions -E_S("CueTrackPositions", 2) -F(MATROSKA_ID_CUETRACK, cue_track, 0) -F(MATROSKA_ID_CUECLUSTERPOSITION, cue_cluster_position, 0) -}}; -#undef N - -E("CueTime", cue_time, EBML_TYPE_UINT) - -#define N cue_point -E_S("CuePoint", 2) -F(MATROSKA_ID_CUETIME, cue_time, 0) -F(MATROSKA_ID_CUETRACKPOSITIONS, cue_track_positions, 1) -}}; -#undef N - -#define N cues -E_S("Cues", 1) -F(MATROSKA_ID_CUEPOINT, cue_point, 1) -}}; -#undef N - -E("ContentCompSettings", content_comp_settings, EBML_TYPE_BINARY) - -E("ContentCompAlgo", content_comp_algo, EBML_TYPE_UINT) - -#define N content_compression -E_S("ContentCompression", 2) -F(MATROSKA_ID_CONTENTCOMPALGO, content_comp_algo, 0) -F(MATROSKA_ID_CONTENTCOMPSETTINGS, content_comp_settings, 0) -}}; -#undef N - -E("ContentEncodingType", content_encoding_type, EBML_TYPE_UINT) - -E("ContentEncodingScope", content_encoding_scope, EBML_TYPE_UINT) - -E("ContentEncodingOrder", content_encoding_order, EBML_TYPE_UINT) - -#define N content_encoding -E_S("ContentEncoding", 4) -F(MATROSKA_ID_CONTENTENCODINGORDER, content_encoding_order, 0) -F(MATROSKA_ID_CONTENTENCODINGSCOPE, content_encoding_scope, 0) -F(MATROSKA_ID_CONTENTENCODINGTYPE, content_encoding_type, 0) -F(MATROSKA_ID_CONTENTCOMPRESSION, content_compression, 0) -}}; -#undef N - -#define N content_encodings -E_S("ContentEncodings", 1) -F(MATROSKA_ID_CONTENTENCODING, content_encoding, 1) -}}; -#undef N - -E("BitDepth", bit_depth, EBML_TYPE_UINT) - -E("Channels", channels, EBML_TYPE_UINT) - -E("OutputSamplingFrequency", output_sampling_frequency, EBML_TYPE_FLOAT) - -E("SamplingFrequency", sampling_frequency, EBML_TYPE_FLOAT) - -#define N audio -E_S("Audio", 4) -F(MATROSKA_ID_SAMPLINGFREQUENCY, sampling_frequency, 0) -F(MATROSKA_ID_OUTPUTSAMPLINGFREQUENCY, output_sampling_frequency, 0) -F(MATROSKA_ID_CHANNELS, channels, 0) -F(MATROSKA_ID_BITDEPTH, bit_depth, 0) -}}; -#undef N - -E("FrameRate", frame_rate, EBML_TYPE_FLOAT) - -E("DisplayUnit", display_unit, EBML_TYPE_UINT) - -E("DisplayHeight", display_height, EBML_TYPE_UINT) - -E("DisplayWidth", display_width, EBML_TYPE_UINT) - -E("PixelHeight", pixel_height, EBML_TYPE_UINT) - -E("PixelWidth", pixel_width, EBML_TYPE_UINT) - -E("FlagInterlaced", flag_interlaced, EBML_TYPE_UINT) - -#define N video -E_S("Video", 7) -F(MATROSKA_ID_FLAGINTERLACED, flag_interlaced, 0) -F(MATROSKA_ID_PIXELWIDTH, pixel_width, 0) -F(MATROSKA_ID_PIXELHEIGHT, pixel_height, 0) -F(MATROSKA_ID_DISPLAYWIDTH, display_width, 0) -F(MATROSKA_ID_DISPLAYHEIGHT, display_height, 0) -F(MATROSKA_ID_DISPLAYUNIT, display_unit, 0) -F(MATROSKA_ID_FRAMERATE, frame_rate, 0) -}}; -#undef N - -E("CodecDecodeAll", codec_decode_all, EBML_TYPE_UINT) - -E("CodecPrivate", codec_private, EBML_TYPE_BINARY) - -E("CodecID", codec_id, EBML_TYPE_STR) - -E("Language", language, EBML_TYPE_STR) - -E("Name", name, EBML_TYPE_STR) - -E("MaxBlockAdditionID", max_block_addition_id, EBML_TYPE_UINT) - -E("TrackTimecodeScale", track_timecode_scale, EBML_TYPE_FLOAT) - -E("DefaultDuration", default_duration, EBML_TYPE_UINT) - -E("MaxCache", max_cache, EBML_TYPE_UINT) - -E("MinCache", min_cache, EBML_TYPE_UINT) - -E("FlagLacing", flag_lacing, EBML_TYPE_UINT) - -E("FlagForced", flag_forced, EBML_TYPE_UINT) - -E("FlagDefault", flag_default, EBML_TYPE_UINT) - -E("FlagEnabled", flag_enabled, EBML_TYPE_UINT) - -E("TrackType", track_type, EBML_TYPE_UINT) - -E("TrackUID", track_uid, EBML_TYPE_UINT) - -E("TrackNumber", track_number, EBML_TYPE_UINT) - -#define N track_entry -E_S("TrackEntry", 20) -F(MATROSKA_ID_TRACKNUMBER, track_number, 0) -F(MATROSKA_ID_TRACKUID, track_uid, 0) -F(MATROSKA_ID_TRACKTYPE, track_type, 0) -F(MATROSKA_ID_FLAGENABLED, flag_enabled, 0) -F(MATROSKA_ID_FLAGDEFAULT, flag_default, 0) -F(MATROSKA_ID_FLAGFORCED, flag_forced, 0) -F(MATROSKA_ID_FLAGLACING, flag_lacing, 0) -F(MATROSKA_ID_MINCACHE, min_cache, 0) -F(MATROSKA_ID_MAXCACHE, max_cache, 0) -F(MATROSKA_ID_DEFAULTDURATION, default_duration, 0) -F(MATROSKA_ID_TRACKTIMECODESCALE, track_timecode_scale, 0) -F(MATROSKA_ID_MAXBLOCKADDITIONID, max_block_addition_id, 0) -F(MATROSKA_ID_NAME, name, 0) -F(MATROSKA_ID_LANGUAGE, language, 0) -F(MATROSKA_ID_CODECID, codec_id, 0) -F(MATROSKA_ID_CODECPRIVATE, codec_private, 0) -F(MATROSKA_ID_CODECDECODEALL, codec_decode_all, 0) -F(MATROSKA_ID_VIDEO, video, 0) -F(MATROSKA_ID_AUDIO, audio, 0) -F(MATROSKA_ID_CONTENTENCODINGS, content_encodings, 0) -}}; -#undef N - -#define N tracks -E_S("Tracks", 1) -F(MATROSKA_ID_TRACKENTRY, track_entry, 1) -}}; -#undef N - -E("SimpleBlock", simple_block, EBML_TYPE_BINARY) - -E("ReferenceBlock", reference_block, EBML_TYPE_SINT) - -E("BlockDuration", block_duration, EBML_TYPE_UINT) - -E("Block", block, EBML_TYPE_BINARY) - -#define N block_group -E_S("BlockGroup", 3) -F(MATROSKA_ID_BLOCK, block, 0) -F(MATROSKA_ID_BLOCKDURATION, block_duration, 0) -F(MATROSKA_ID_REFERENCEBLOCK, reference_block, 1) -}}; -#undef N - -E("Timecode", timecode, EBML_TYPE_UINT) - -#define N cluster -E_S("Cluster", 3) -F(MATROSKA_ID_TIMECODE, timecode, 0) -F(MATROSKA_ID_BLOCKGROUP, block_group, 1) -F(MATROSKA_ID_SIMPLEBLOCK, simple_block, 1) -}}; -#undef N - -E("Duration", duration, EBML_TYPE_FLOAT) - -E("WritingApp", writing_app, EBML_TYPE_STR) - -E("MuxingApp", muxing_app, EBML_TYPE_STR) - -E("Title", title, EBML_TYPE_STR) - -E("DateUTC", date_utc, EBML_TYPE_SINT) - -E("TimecodeScale", timecode_scale, EBML_TYPE_UINT) - -E("NextUID", next_uid, EBML_TYPE_BINARY) - -E("PrevUID", prev_uid, EBML_TYPE_BINARY) - -E("