diff options
-rw-r--r-- | cfg-mplayer.h | 4 | ||||
-rw-r--r-- | defaultopts.c | 3 | ||||
-rw-r--r-- | input/input.c | 2 | ||||
-rw-r--r-- | m_config.c | 132 | ||||
-rw-r--r-- | m_config.h | 8 | ||||
-rw-r--r-- | m_option.c | 19 | ||||
-rw-r--r-- | m_option.h | 50 | ||||
-rw-r--r-- | 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 */ @@ -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); |