1
0
mirror of https://github.com/mpv-player/mpv synced 2025-02-05 14:42:24 +00:00

client API: make mpv_set_option set options natively

This should fix some issues, such as not being able to set the
"no-video" option with MPV_FORMAT_FLAG.

Note that this changes semantics a bit. Now setting an option strictly
overwrite it, even if the corresponding command line option does not.
For example, if we change --sub to append by default, then setting the
"sub" option via the client API would still never append. (Oddly, this
also applies to --vf-add, which will overwrite the old value when using
the client API.)

I'm doing this because there's no proper separation between the command
line parser and setting an option using the MPV_FORMAT_STRING format.
Maybe the solution to this mess would be adding format aware code (i.e.
m_option_set_node) to every option type, and falling back to strings
only if needed - but this would mean that you couldn't set e.g. an
integer option using MPV_FORMAT_STRING, which doesn't seem to be ideal
either.

In conclusion, the current approach seems to be most robust, but I'm
open to suggestions should someone find that these semantics are a
problem.
This commit is contained in:
wm4 2014-04-21 23:52:14 +02:00
parent bdfe02158f
commit b430c886aa
3 changed files with 27 additions and 24 deletions

View File

@ -609,31 +609,34 @@ int m_config_set_option(struct m_config *config, struct bstr name,
}
int m_config_set_option_node(struct m_config *config, bstr name,
struct mpv_node *data, int flags)
struct mpv_node *data)
{
char *value = NULL;
if (data->format == MPV_FORMAT_STRING) {
value = *(char **)data;
} else {
// This is pretty lame, but the simplest for now. It will fail very
// hard for string lists with items that contain ',' characters.
union m_option_value val = {0};
const struct m_option *opt = m_config_get_option(config, name);
if (!opt)
return M_OPT_UNKNOWN;
if (m_option_set_node(opt, &val, data) < 0)
return M_OPT_INVALID;
value = m_option_print(opt, &val);
m_option_free(opt, &val);
}
struct m_config_option *co = m_config_get_co(config, name);
if (!co)
return M_OPT_UNKNOWN;
// This affects some special options like "include", "profile". Maybe these
// should work, or maybe not. For now they would require special code.
if (!co->data)
return M_OPT_UNKNOWN;
int r;
if (value) {
r = m_config_set_option_ext(config, name, bstr0(value), flags);
// Do this on an "empty" type to make setting the option strictly overwrite
// the old value, as opposed to e.g. appending to lists.
union m_option_value val = {0};
if (data->format == MPV_FORMAT_STRING) {
bstr param = bstr0(data->u.string);
r = m_option_parse(mp_null_log, co->opt, name, param, &val);
} else {
r = M_OPT_OUT_OF_RANGE;
r = m_option_set_node(co->opt, &val, data);
}
if (data->format != MPV_FORMAT_STRING)
talloc_free(value);
if (r >= 0)
m_option_copy(co->opt, co->data, &val);
m_option_free(co->opt, &val);
return r;
}

View File

@ -139,10 +139,10 @@ static inline int m_config_set_option0(struct m_config *config,
return m_config_set_option(config, bstr0(name), bstr0(param));
}
// Same as m_config_set_option_ext(), but set as data using mpv_node.
// Similar to m_config_set_option_ext(), but set as data using mpv_node.
struct mpv_node;
int m_config_set_option_node(struct m_config *config, bstr name,
struct mpv_node *data, int flags);
struct mpv_node *data);
int m_config_parse_suboptions(struct m_config *config, char *name,

View File

@ -652,7 +652,7 @@ int mpv_set_option(mpv_handle *ctx, const char *name, mpv_format format,
data = &tmp;
}
int err = m_config_set_option_node(ctx->mpctx->mconfig, bstr0(name),
data, 0);
data);
switch (err) {
case M_OPT_MISSING_PARAM:
case M_OPT_INVALID: