m_config: refactor some things

Change how m_config is initialized. Make it more uniform; now all
m_config structs are intialized in exactly the same way. Make sure
there's only a single m_option[] array defining the options, and keep
around the pointer to the optstruct default value, and the optstruct
size as well. This will allow reconstructing the option default values
in the following commit.

In particular, stop pretending that the handling of some special options
(like --profile, --v, and some others) is in any way elegant, and make
them explicit hacks. This is really more readable and easier to
understand than what was before, and simplifies the code.
This commit is contained in:
wm4 2013-07-27 21:26:00 +02:00
parent da2b4aa587
commit c070fa865f
8 changed files with 127 additions and 152 deletions

View File

@ -497,6 +497,9 @@ struct cmd_queue {
};
struct input_ctx {
bool using_ar;
bool using_cocoa_media_keys;
// Autorepeat stuff
short ar_state;
int64_t last_ar;
@ -572,7 +575,7 @@ static const m_option_t input_config[] = {
{ NULL, NULL, 0, 0, 0, 0, NULL}
};
static const m_option_t mp_input_opts[] = {
const m_option_t mp_input_opts[] = {
{ "input", (void *)&input_config, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
OPT_INTRANGE("doubleclick-time", input.doubleclick_time, 0, 0, 1000),
OPT_FLAG("joystick", input.use_joystick, CONF_GLOBAL),
@ -2069,9 +2072,10 @@ void mp_input_define_section(struct input_ctx *ictx, char *name, char *location,
}
}
struct input_ctx *mp_input_init(struct input_conf *input_conf,
bool load_default_conf)
struct input_ctx *mp_input_init(struct MPOpts *opts)
{
struct input_conf *input_conf = &opts->input;
struct input_ctx *ictx = talloc_ptrtype(NULL, ictx);
*ictx = (struct input_ctx){
.key_fifo_size = input_conf->key_fifo_size,
@ -2106,7 +2110,7 @@ struct input_ctx *mp_input_init(struct input_conf *input_conf,
bool config_ok = false;
if (input_conf->config_file)
config_ok = parse_config_file(ictx, input_conf->config_file, true);
if (!config_ok && load_default_conf) {
if (!config_ok && opts->load_config) {
// Try global conf dir
char *file = mp_find_config_file("input.conf");
config_ok = file && parse_config_file(ictx, file, false);
@ -2148,10 +2152,12 @@ struct input_ctx *mp_input_init(struct input_conf *input_conf,
#ifdef CONFIG_COCOA
if (input_conf->use_ar) {
cocoa_init_apple_remote();
ictx->using_ar = true;
}
if (input_conf->use_media_keys) {
cocoa_init_media_keys();
ictx->using_cocoa_media_keys = true;
}
#endif
@ -2186,17 +2192,17 @@ static void clear_queue(struct cmd_queue *queue)
}
}
void mp_input_uninit(struct input_ctx *ictx, struct input_conf *input_conf)
void mp_input_uninit(struct input_ctx *ictx)
{
if (!ictx)
return;
#ifdef CONFIG_COCOA
if (input_conf->use_ar) {
if (ictx->using_ar) {
cocoa_uninit_apple_remote();
}
if (input_conf->use_media_keys) {
if (ictx->using_cocoa_media_keys) {
cocoa_uninit_media_keys();
}
#endif
@ -2215,11 +2221,6 @@ void mp_input_uninit(struct input_ctx *ictx, struct input_conf *input_conf)
talloc_free(ictx);
}
void mp_input_register_options(m_config_t *cfg)
{
m_config_register_options(cfg, mp_input_opts);
}
static int print_key_list(m_option_t *cfg, char *optname, char *optparam)
{
int i;

View File

@ -257,14 +257,10 @@ bool mp_input_test_mouse_active(struct input_ctx *ictx, int x, int y);
bool mp_input_test_dragging(struct input_ctx *ictx, int x, int y);
// Initialize the input system
struct input_conf;
struct input_ctx *mp_input_init(struct input_conf *input_conf,
bool load_default_conf);
struct MPOpts;
struct input_ctx *mp_input_init(struct MPOpts *opts);
void mp_input_uninit(struct input_ctx *ictx, struct input_conf *input_conf);
struct m_config;
void mp_input_register_options(struct m_config *cfg);
void mp_input_uninit(struct input_ctx *ictx);
// Wake up sleeping input loop from another thread.
void mp_input_wakeup(struct input_ctx *ictx);

View File

@ -73,7 +73,7 @@ static int parse_profile(struct m_config *config, const struct m_option *opt,
if (!list || !list[0])
return M_OPT_INVALID;
for (int i = 0; list[i]; i++) {
struct m_profile *p = m_config_get_profile(config, list[i]);
struct m_profile *p = m_config_get_profile0(config, list[i]);
if (!p) {
mp_tmsg(MSGT_CFGPARSER, MSGL_WARN, "Unknown profile '%s'.\n",
list[i]);
@ -85,19 +85,19 @@ static int parse_profile(struct m_config *config, const struct m_option *opt,
return r;
}
static int show_profile(struct m_option *opt, char *name, char *param)
static int show_profile(struct m_config *config, bstr param)
{
struct m_config *config = opt->priv;
struct m_profile *p;
int i, j;
if (!param)
if (!param.len)
return M_OPT_MISSING_PARAM;
if (!(p = m_config_get_profile(config, param))) {
mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, "Unknown profile '%s'.\n", param);
mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, "Unknown profile '%.*s'.\n",
BSTR_P(param));
return M_OPT_EXIT - 1;
}
if (!config->profile_depth)
mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, "Profile %s: %s\n", param,
mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, "Profile %s: %s\n", p->name,
p->desc ? p->desc : "");
config->profile_depth++;
for (i = 0; i < p->num_opts; i++) {
@ -119,11 +119,11 @@ static int show_profile(struct m_option *opt, char *name, char *param)
continue;
memcpy(tmp, list, l);
tmp[l] = '\0';
show_profile(opt, name, tmp);
show_profile(config, bstr0(tmp));
list = e + 1;
}
if (list[0] != '\0')
show_profile(opt, name, list);
show_profile(config, bstr0(list));
}
}
config->profile_depth--;
@ -132,9 +132,8 @@ static int show_profile(struct m_option *opt, char *name, char *param)
return M_OPT_EXIT - 1;
}
static int list_options(struct m_option *opt, char *name, char *param)
static int list_options(struct m_config *config)
{
struct m_config *config = opt->priv;
m_config_print_option_list(config);
return M_OPT_EXIT;
}
@ -158,6 +157,10 @@ static void m_config_add_option(struct m_config *config,
struct m_config_option *parent,
const struct m_option *arg);
static void add_options(struct m_config *config,
struct m_config_option *parent,
const struct m_option *defs);
static int config_destroy(void *p)
{
struct m_config *config = p;
@ -173,27 +176,32 @@ static int config_destroy(void *p)
return 0;
}
struct m_config *m_config_simple(void *optstruct)
struct m_config *m_config_new(void *talloc_parent, size_t size,
const void *defaults,
const struct m_option *options)
{
struct m_config *config = talloc_struct(NULL, struct m_config, {
.optstruct = optstruct,
});
struct m_config *config = talloc(talloc_parent, struct m_config);
talloc_set_destructor(config, config_destroy);
*config = (struct m_config) {
.optstruct_size = size,
.optstruct_defaults = defaults,
.options = options,
};
if (size) { // size==0 means a dummy object is created
config->optstruct = talloc_zero_size(config, size);
if (defaults)
memcpy(config->optstruct, defaults, size);
if (options)
add_options(config, NULL, options);
}
return config;
}
struct m_config *m_config_from_obj_desc(void *talloc_parent,
struct m_obj_desc *desc)
{
struct m_config *config = m_config_simple(NULL);
talloc_steal(talloc_parent, config);
if (desc->priv_size) {
config->optstruct = talloc_zero_size(config, desc->priv_size);
if (desc->priv_defaults)
memcpy(config->optstruct, desc->priv_defaults, desc->priv_size);
m_config_register_options(config, desc->options);
}
return config;
return m_config_new(talloc_parent, desc->priv_size, desc->priv_defaults,
desc->options);
}
int m_config_set_obj_params(struct m_config *conf, char **args)
@ -225,44 +233,6 @@ int m_config_initialize_obj(struct m_config *config, struct m_obj_desc *desc,
return 0;
}
struct m_config *m_config_new(void *optstruct,
int includefunc(struct m_config *conf,
char *filename))
{
static const struct m_option ref_opts[] = {
{ "profile", NULL, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL },
{ "show-profile", show_profile, &m_option_type_print_func_param,
CONF_NOCFG },
{ "list-options", list_options, CONF_TYPE_PRINT_FUNC, CONF_NOCFG },
{ NULL }
};
struct m_config *config = m_config_simple(optstruct);
struct m_option *self_opts = talloc_memdup(config, ref_opts,
sizeof(ref_opts));
for (int i = 1; self_opts[i].name; i++)
self_opts[i].priv = config;
m_config_register_options(config, self_opts);
if (includefunc) {
struct m_option *p = talloc_ptrtype(config, p);
*p = (struct m_option){
"include", NULL, CONF_TYPE_STRING, 0,
};
m_config_add_option(config, "", NULL, p);
config->includefunc = includefunc;
}
config->use_profiles = true;
return config;
}
void m_config_free(struct m_config *config)
{
talloc_free(config);
}
static void ensure_backup(struct m_config *config, struct m_config_option *co)
{
while (co->alias_owner)
@ -472,15 +442,6 @@ static void m_config_add_option(struct m_config *config,
add_negation_option(config, parent, arg);
}
int m_config_register_options(struct m_config *config,
const struct m_option *args)
{
assert(config != NULL);
if (args)
add_options(config, NULL, args);
return 1;
}
struct m_config_option *m_config_get_co(const struct m_config *config,
struct bstr name)
{
@ -542,10 +503,14 @@ static int m_config_parse_option(struct m_config *config, void *optstruct,
return M_OPT_INVALID;
}
if (config->includefunc && !bstrcmp0(name, "include")) {
if (config->includefunc && bstr_equals0(name, "include"))
return parse_include(config, param, set);
} else if (config->use_profiles && !bstrcmp0(name, "profile"))
if (config->use_profiles && bstr_equals0(name, "profile"))
return parse_profile(config, co->opt, name, param, set);
if (config->use_profiles && bstr_equals0(name, "show-profile"))
return show_profile(config, param);
if (bstr_equals0(name, "list-options"))
return list_options(config);
// Option with children are a bit different to parse
if (co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) {
@ -692,19 +657,24 @@ void m_config_print_option_list(const struct m_config *config)
mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, "\nTotal: %d options\n", count);
}
struct m_profile *m_config_get_profile(const struct m_config *config,
char *name)
struct m_profile *m_config_get_profile(const struct m_config *config, bstr name)
{
struct m_profile *p;
for (p = config->profiles; p; p = p->next)
if (!strcmp(p->name, name))
for (struct m_profile *p = config->profiles; p; p = p->next) {
if (bstr_equals0(name, p->name))
return p;
}
return NULL;
}
struct m_profile *m_config_get_profile0(const struct m_config *config,
char *name)
{
return m_config_get_profile(config, bstr0(name));
}
struct m_profile *m_config_add_profile(struct m_config *config, char *name)
{
struct m_profile *p = m_config_get_profile(config, name);
struct m_profile *p = m_config_get_profile0(config, name);
if (p)
return p;
p = talloc_zero(config, struct m_profile);

View File

@ -19,6 +19,7 @@
#ifndef MPLAYER_M_CONFIG_H
#define MPLAYER_M_CONFIG_H
#include <stddef.h>
#include <stdbool.h>
#include "core/bstr.h"
@ -71,10 +72,9 @@ struct m_profile {
/** \ingroup Config */
typedef struct m_config {
// Registered options.
/** This contains all options and suboptions.
*/
struct m_config_option *opts;
struct m_config_option *opts; // all options, even suboptions
int num_pos_opts;
// When options are set (via m_config_set_option or m_config_set_profile),
// back up the old value (unless it's already backed up). Used for restoring
// global options when per-file options are set.
@ -85,17 +85,27 @@ typedef struct m_config {
// Depth when recursively including profiles.
int profile_depth;
void *optstruct; // struct mpopts or other
int (*includefunc)(struct m_config *conf, char *filename);
bool use_profiles;
int (*includefunc)(struct m_config *conf, char *filename);
const void *optstruct_defaults;
size_t optstruct_size;
const struct m_option *options; // top-level options
void *optstruct; // struct mpopts or other
} m_config_t;
// Create a new config object.
struct m_config *
m_config_new(void *optstruct,
int includefunc(struct m_config *conf, char *filename));
struct m_config *m_config_simple(void *optstruct);
// talloc_parent: talloc parent context for the m_config allocation
// size: size of the optstruct (where option values are stored)
// defaults: if not NULL, points to a struct of same type as optstruct, which
// contains default values for all options
// options: list of options. Each option defines a member of the optstruct
// and a corresponding option switch or sub-option field.
// Note that the m_config object will keep pointers to defaults and options.
struct m_config *m_config_new(void *talloc_parent, size_t size,
const void *defaults,
const struct m_option *options);
struct m_config *m_config_from_obj_desc(void *talloc_parent,
struct m_obj_desc *desc);
@ -107,22 +117,11 @@ int m_config_set_obj_params(struct m_config *conf, char **args);
int m_config_initialize_obj(struct m_config *config, struct m_obj_desc *desc,
void **ppriv, char ***pargs);
// Free a config object.
void m_config_free(struct m_config *config);
void m_config_enter_file_local(struct m_config *config);
void m_config_leave_file_local(struct m_config *config);
void m_config_mark_file_local(struct m_config *config, const char *opt);
void m_config_mark_all_file_local(struct m_config *config);
/* Register some options to be used.
* \param config The config object.
* \param args An array of \ref m_option struct.
* \return 1 on success, 0 on failure.
*/
int m_config_register_options(struct m_config *config,
const struct m_option *args);
enum {
M_SETOPT_PRE_PARSE_ONLY = 1, // Silently ignore non-M_OPT_PRE_PARSE opt.
M_SETOPT_CHECK_ONLY = 2, // Don't set, just check name/value
@ -186,8 +185,9 @@ void m_config_print_option_list(const struct m_config *config);
* \param arg The profile's name.
* \return The profile object or NULL.
*/
struct m_profile *m_config_get_profile(const struct m_config *config,
char *name);
struct m_profile *m_config_get_profile0(const struct m_config *config,
char *name);
struct m_profile *m_config_get_profile(const struct m_config *config, bstr name);
/* Get the profile with the given name, creating it if necessary.
* \param config The config object.

View File

@ -563,7 +563,7 @@ static MP_NORETURN void exit_player(struct MPContext *mpctx,
timeEndPeriod(1);
#endif
mp_input_uninit(mpctx->input, &mpctx->opts->input);
mp_input_uninit(mpctx->input);
osd_free(mpctx->osd);
@ -585,10 +585,6 @@ static MP_NORETURN void exit_player(struct MPContext *mpctx,
// must be last since e.g. mp_msg uses option values
// that will be freed by this.
if (mpctx->mconfig)
m_config_free(mpctx->mconfig);
mpctx->mconfig = NULL;
talloc_free(mpctx);
#ifdef CONFIG_COCOA
@ -661,7 +657,7 @@ static void load_per_protocol_config(m_config_t *conf, const char * const file)
sprintf(protocol, "%s%s", PROFILE_CFG_PROTOCOL, file);
protocol[strlen(PROFILE_CFG_PROTOCOL) + strlen(file) - strlen(str)] = '\0';
p = m_config_get_profile(conf, protocol);
p = m_config_get_profile0(conf, protocol);
if (p) {
mp_tmsg(MSGT_CPLAYER, MSGL_INFO,
"Loading protocol-related profile '%s'\n", protocol);
@ -684,7 +680,7 @@ static void load_per_extension_config(m_config_t *conf, const char * const file)
sprintf(extension, PROFILE_CFG_EXTENSION);
strncat(extension, ++str, 7);
p = m_config_get_profile(conf, extension);
p = m_config_get_profile0(conf, extension);
if (p) {
mp_tmsg(MSGT_CPLAYER, MSGL_INFO,
"Loading extension-related profile '%s'\n", extension);
@ -704,7 +700,7 @@ static void load_per_output_config(m_config_t *conf, char *cfg, char *out)
return;
sprintf(profile, "%s%s", cfg, out);
p = m_config_get_profile(conf, profile);
p = m_config_get_profile0(conf, profile);
if (p) {
mp_tmsg(MSGT_CPLAYER, MSGL_INFO,
"Loading extension-related profile '%s'\n", profile);
@ -3872,7 +3868,7 @@ static int read_keys(void *ctx, int fd)
static void init_input(struct MPContext *mpctx)
{
mpctx->input = mp_input_init(&mpctx->opts->input, mpctx->opts->load_config);
mpctx->input = mp_input_init(mpctx->opts);
if (mpctx->opts->slave_mode)
mp_input_add_cmd_fd(mpctx->input, 0, USE_FD0_CMD_SELECT, MP_INPUT_SLAVE_CMD_FUNC, NULL);
else if (mpctx->opts->consolecontrols)
@ -4597,7 +4593,6 @@ static int mpv_main(int argc, char *argv[])
struct MPContext *mpctx = talloc(NULL, MPContext);
*mpctx = (struct MPContext){
.opts = talloc(mpctx, struct MPOpts),
.last_dvb_step = 1,
.terminal_osd_text = talloc_strdup(mpctx, ""),
.playlist = talloc_struct(mpctx, struct playlist, {0}),
@ -4607,12 +4602,14 @@ static int mpv_main(int argc, char *argv[])
init_libav();
screenshot_init(mpctx);
struct MPOpts *opts = mpctx->opts;
// Create the config context and register the options
*opts = mp_default_opts;
mpctx->mconfig = m_config_new(opts, cfg_include);
m_config_register_options(mpctx->mconfig, mp_opts);
mp_input_register_options(mpctx->mconfig);
mpctx->mconfig = m_config_new(mpctx, sizeof(struct MPOpts),
&mp_default_opts, mp_opts);
mpctx->opts = mpctx->mconfig->optstruct;
mpctx->mconfig->includefunc = cfg_include;
mpctx->mconfig->use_profiles = true;
struct MPOpts *opts = mpctx->opts;
// Preparse the command line
m_config_preparse_command_line(mpctx->mconfig, argc, argv);

View File

@ -313,12 +313,30 @@ static const m_option_t screenshot_conf[] = {
extern const m_option_t lavc_decode_opts_conf[];
extern const m_option_t ad_lavc_decode_opts_conf[];
extern const m_option_t mp_input_opts[];
const m_option_t mp_opts[] = {
// handled in command line pre-parser (parser-mpcmd.c)
{"v", NULL, CONF_TYPE_STORE, CONF_GLOBAL | CONF_NOCFG, 0, 0, NULL},
// handled in command line parser (parser-mpcmd.c)
{"playlist", NULL, CONF_TYPE_STRING, CONF_NOCFG | M_OPT_MIN, 1, 0, NULL},
{"shuffle", NULL, CONF_TYPE_FLAG, CONF_NOCFG, 0, 0, NULL},
{"{", NULL, CONF_TYPE_STORE, CONF_NOCFG, 0, 0, NULL},
{"}", NULL, CONF_TYPE_STORE, CONF_NOCFG, 0, 0, NULL},
// handled in m_config.c
{ "include", NULL, CONF_TYPE_STRING },
{ "profile", NULL, CONF_TYPE_STRING_LIST },
{ "show-profile", NULL, CONF_TYPE_STRING, CONF_NOCFG },
{ "list-options", NULL, CONF_TYPE_STORE, CONF_NOCFG },
// handled in mplayer.c (looks at the raw argv[])
{"leak-report", "", CONF_TYPE_STORE, CONF_GLOBAL | CONF_NOCFG },
// ------------------------- common options --------------------
OPT_FLAG("quiet", quiet, CONF_GLOBAL),
{"really-quiet", &verbose, CONF_TYPE_STORE, CONF_GLOBAL|CONF_PRE_PARSE, 0, -10, NULL},
// -v is handled in command line preparser
{"v", NULL, CONF_TYPE_STORE, CONF_GLOBAL | CONF_NOCFG, 0, 0, NULL},
{"msglevel", (void *) msgl_config, CONF_TYPE_SUBCONFIG, CONF_GLOBAL, 0, 0, NULL},
{"msgcolor", &mp_msg_color, CONF_TYPE_FLAG, CONF_GLOBAL | CONF_PRE_PARSE, 0, 1, NULL},
{"msgmodule", &mp_msg_module, CONF_TYPE_FLAG, CONF_GLOBAL, 0, 1, NULL},
@ -630,17 +648,10 @@ const m_option_t mp_opts[] = {
{"lircconf", &lirc_configfile, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL},
#endif
{"leak-report", "", CONF_TYPE_PRINT, 0, 0, 0, (void*)1},
OPT_CHOICE_OR_INT("loop", loop_times, M_OPT_GLOBAL, 1, 10000,
({"no", -1}, {"0", -1},
{"inf", 0})),
{"playlist", NULL, CONF_TYPE_STRING, CONF_NOCFG | M_OPT_MIN, 1, 0, NULL},
{"shuffle", NULL, CONF_TYPE_FLAG, CONF_NOCFG, 0, 0, NULL},
{"{", NULL, CONF_TYPE_STORE, CONF_NOCFG, 0, 0, NULL},
{"}", NULL, CONF_TYPE_STORE, CONF_NOCFG, 0, 0, NULL},
OPT_FLAG("resume-playback", position_resume, 0),
OPT_FLAG("save-position-on-quit", position_save_on_quit, 0),
@ -682,6 +693,8 @@ const m_option_t mp_opts[] = {
{"screenshot", (void *) screenshot_conf, CONF_TYPE_SUBCONFIG},
{"", (void *) mp_input_opts, CONF_TYPE_SUBCONFIG},
OPT_FLAG("list-properties", list_properties, CONF_GLOBAL),
{"identify", &mp_msg_levels[MSGT_IDENTIFY], CONF_TYPE_FLAG, CONF_GLOBAL, 0, MSGL_V, NULL},
{"help", (void *) mp_help_text, CONF_TYPE_PRINT, CONF_NOCFG|CONF_GLOBAL, 0, 0, NULL},

View File

@ -234,10 +234,8 @@ typedef struct MPOpts {
int use_joystick;
int use_lirc;
int use_lircc;
#ifdef CONFIG_COCOA
int use_ar;
int use_media_keys;
#endif
int default_bindings;
int test;
} input;

View File

@ -192,15 +192,15 @@ static int reconfig(struct vo *vo, struct mp_image_params *params, int flags)
static bool reparse_cmdline(struct gl_priv *p, char *args)
{
struct m_config *cfg = NULL;
struct gl_video_opts opts;
struct gl_video_opts *opts = NULL;
int r = 0;
if (strcmp(args, "-") == 0) {
opts = *p->renderer_opts;
opts = p->renderer_opts;
} else {
memcpy(&opts, gl_video_conf.defaults, sizeof(opts));
cfg = m_config_simple(&opts);
m_config_register_options(cfg, gl_video_conf.opts);
cfg = m_config_new(NULL, sizeof(*opts), gl_video_conf.defaults,
gl_video_conf.opts);
opts = cfg->optstruct;
const char *init = p->vo->driver->init_option_string;
if (init)
m_config_parse_suboptions(cfg, "opengl", (char *)init);
@ -209,7 +209,7 @@ static bool reparse_cmdline(struct gl_priv *p, char *args)
if (r >= 0) {
mpgl_lock(p->glctx);
gl_video_set_options(p->renderer, &opts);
gl_video_set_options(p->renderer, opts);
resize(p);
mpgl_unlock(p->glctx);
}