mirror of https://github.com/mpv-player/mpv
command: avoid going through prop->opt bridge from opt->prop bridge
The option->property bridge can't (and shouldn't) preserve option flags.
This is a problem if the flags are actually used by the option
implementation, beyond calling m_config_mark_co_flags().
This was true so far, but b8193e4071
changed this. Now setting the
--profile option (usually from a config file or as recursive profile)
can have side-effects that depend on the flags contents. Solve this by
avoiding going through the "double bridge" altogether.
This fixes a regression if an auto-profile is active, and the user
specifies an option on the command line that is supposed to override an
item in a profile recursively referenced by the auto-profile. The
command line option will not override it, because the auto-profile is
set later, and during application of the auto-profile, the
M_SETOPT_PRESERVE_CMDLINE flag gets lost.
Having to add something to m_property is not nice, and I'll probbaly
regret later. On the other hand, there is a chance that this helps
towards true option/property unification.
This commit is contained in:
parent
b7d9b72686
commit
986e10901d
|
@ -132,6 +132,8 @@ struct m_property {
|
||||||
// returns: one of enum mp_property_return
|
// returns: one of enum mp_property_return
|
||||||
int (*call)(void *ctx, struct m_property *prop, int action, void *arg);
|
int (*call)(void *ctx, struct m_property *prop, int action, void *arg);
|
||||||
void *priv;
|
void *priv;
|
||||||
|
// Special-case: mark options for which command.c uses the option-bridge
|
||||||
|
bool is_option;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct m_property *m_property_list_find(const struct m_property *list,
|
struct m_property *m_property_list_find(const struct m_property *list,
|
||||||
|
|
|
@ -348,6 +348,7 @@ static char *format_delay(double time)
|
||||||
int mp_on_set_option(void *ctx, struct m_config_option *co, void *data, int flags)
|
int mp_on_set_option(void *ctx, struct m_config_option *co, void *data, int flags)
|
||||||
{
|
{
|
||||||
struct MPContext *mpctx = ctx;
|
struct MPContext *mpctx = ctx;
|
||||||
|
struct command_ctx *cmd = mpctx->command_ctx;
|
||||||
|
|
||||||
// Normalize "vf*" to "vf"
|
// Normalize "vf*" to "vf"
|
||||||
const char *name = co->name;
|
const char *name = co->name;
|
||||||
|
@ -358,6 +359,14 @@ int mp_on_set_option(void *ctx, struct m_config_option *co, void *data, int flag
|
||||||
name = tmp;
|
name = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip going through mp_property_generic_option (typically), because the
|
||||||
|
// property implementation is trivial, and can break some obscure features
|
||||||
|
// like --profile and --include if non-trivial flags are involved (which
|
||||||
|
// the bridge would drop).
|
||||||
|
struct m_property *prop = m_property_list_find(cmd->properties, name);
|
||||||
|
if (prop && prop->is_option)
|
||||||
|
goto direct_option;
|
||||||
|
|
||||||
struct m_option type = {0};
|
struct m_option type = {0};
|
||||||
|
|
||||||
int r = mp_property_do_silent(name, M_PROPERTY_GET_TYPE, &type, mpctx);
|
int r = mp_property_do_silent(name, M_PROPERTY_GET_TYPE, &type, mpctx);
|
||||||
|
@ -5680,11 +5689,13 @@ void command_init(struct MPContext *mpctx)
|
||||||
.call = co->opt->deprecation_message ?
|
.call = co->opt->deprecation_message ?
|
||||||
mp_property_deprecated_alias : mp_property_alias,
|
mp_property_deprecated_alias : mp_property_alias,
|
||||||
.priv = (void *)alias,
|
.priv = (void *)alias,
|
||||||
|
.is_option = true,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
prop = (struct m_property){
|
prop = (struct m_property){
|
||||||
.name = co->name,
|
.name = co->name,
|
||||||
.call = mp_property_generic_option,
|
.call = mp_property_generic_option,
|
||||||
|
.is_option = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
bstr bname = bstr0(prop.name);
|
bstr bname = bstr0(prop.name);
|
||||||
|
|
Loading…
Reference in New Issue