mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-28 05:33:14 +00:00
options: remove deprecated sub-option handling for --vo and --ao
Long planned. Leads to some sanity. There still are some rather gross things. Especially g_groups is ugly, and a hack that can hopefully be removed. (There is a plan for it, but whether it's implemented depends on how much energy is left.)
This commit is contained in:
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "m_config.h"
|
||||
#include "options/m_option.h"
|
||||
#include "common/common.h"
|
||||
#include "common/global.h"
|
||||
#include "common/msg.h"
|
||||
#include "common/msg_control.h"
|
||||
@@ -268,6 +269,39 @@ struct m_config *m_config_from_obj_desc_noalloc(void *talloc_ctx,
|
||||
return m_config_new(talloc_ctx, log, 0, desc->priv_defaults, desc->options);
|
||||
}
|
||||
|
||||
static struct m_config_group *find_group(struct mpv_global *global,
|
||||
const struct m_option *cfg)
|
||||
{
|
||||
struct m_config_shadow *shadow = global->config;
|
||||
struct m_config *root = shadow->root;
|
||||
|
||||
for (int n = 0; n < root->num_groups; n++) {
|
||||
if (cfg && root->groups[n].group && root->groups[n].group->opts == cfg)
|
||||
return &root->groups[n];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate a priv struct that is backed by global options (like AOs and VOs,
|
||||
// anything that uses m_obj_list.use_global_options == true).
|
||||
// The result contains a snapshot of the current option values of desc->options.
|
||||
// For convenience, desc->options can be NULL; then priv struct is allocated
|
||||
// with just zero (or priv_defaults if set).
|
||||
void *m_config_group_from_desc(void *ta_parent, struct mp_log *log,
|
||||
struct mpv_global *global, struct m_obj_desc *desc, const char *name)
|
||||
{
|
||||
struct m_config_group *group = find_group(global, desc->options);
|
||||
if (group) {
|
||||
return mp_get_config_group(ta_parent, global, group->group);
|
||||
} else {
|
||||
void *d = talloc_zero_size(ta_parent, desc->priv_size);
|
||||
if (desc->priv_defaults)
|
||||
memcpy(d, desc->priv_defaults, desc->priv_size);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
static struct m_config_option *m_config_find_negation_opt(struct m_config *config,
|
||||
struct bstr *name);
|
||||
|
||||
@@ -277,40 +311,8 @@ static int m_config_set_obj_params(struct m_config *config, struct mp_log *log,
|
||||
{
|
||||
for (int n = 0; args && args[n * 2 + 0]; n++) {
|
||||
bstr opt = bstr0(args[n * 2 + 0]);
|
||||
const char *val = args[n * 2 + 1];
|
||||
struct m_config_option *co = m_config_get_co(config, opt);
|
||||
if (!co) {
|
||||
co = m_config_find_negation_opt(config, &opt);
|
||||
if (!co)
|
||||
continue;
|
||||
|
||||
if (val && val[0])
|
||||
return -1; // no parameter allowed
|
||||
|
||||
val = "no";
|
||||
}
|
||||
struct m_config *target = config;
|
||||
bool is_legacy = co->opt->type == &m_option_type_subopt_legacy;
|
||||
bool force_legacy = !!desc->legacy_prefix;
|
||||
if (is_legacy || force_legacy) {
|
||||
// Legacy: redirect deprecated sub-options to global ones.
|
||||
char tmp[100];
|
||||
const char *newopt;
|
||||
if (is_legacy) {
|
||||
newopt = co->opt->priv;
|
||||
} else {
|
||||
snprintf(tmp, sizeof(tmp), "%s-%.*s", desc->legacy_prefix,
|
||||
BSTR_P(opt));
|
||||
newopt = tmp;
|
||||
}
|
||||
assert(global);
|
||||
target = mp_get_root_config(global);
|
||||
mp_warn(log, "Using suboptions is deprecated. Use the global '--%s' "
|
||||
"option instead of '%.*s' suboption.\n", newopt,
|
||||
BSTR_P(opt));
|
||||
opt = bstr0(newopt);
|
||||
}
|
||||
if (m_config_set_option(target, opt, bstr0(val)) < 0)
|
||||
bstr val = bstr0(args[n * 2 + 1]);
|
||||
if (m_config_set_option(config, opt, val) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -334,21 +336,6 @@ struct m_config *m_config_from_obj_desc_and_args(void *ta_parent,
|
||||
if (m_config_set_obj_params(config, log, global, desc, args) < 0)
|
||||
goto error;
|
||||
|
||||
if (desc->legacy_prefix) {
|
||||
assert(global);
|
||||
struct m_config *root = mp_get_root_config(global);
|
||||
// In this mode, the AO/VO will still access the options via its priv
|
||||
// struct (like with real sub-options). We have to copy them over.
|
||||
for (int n = 0; n < config->num_opts; n++) {
|
||||
struct m_config_option *co = &config->opts[n];
|
||||
char opt[100];
|
||||
snprintf(opt, sizeof(opt), "%s-%s", desc->legacy_prefix, co->name);
|
||||
struct m_config_option *g = m_config_get_co_raw(root, bstr0(opt));
|
||||
assert(g);
|
||||
m_option_copy(co->opt, co->data, g->data);
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
error:
|
||||
talloc_free(config);
|
||||
@@ -457,34 +444,83 @@ static void add_sub_options(struct m_config *config,
|
||||
};
|
||||
|
||||
struct m_config_option next = {
|
||||
.name = parent ? parent->name : "",
|
||||
.name = "",
|
||||
.group = group,
|
||||
};
|
||||
if (parent && parent->name && parent->name[0])
|
||||
next.name = parent->name;
|
||||
if (subopts->prefix && subopts->prefix[0]) {
|
||||
assert(next.name);
|
||||
next.name = subopts->prefix;
|
||||
}
|
||||
add_options(config, &next, new_optstruct, new_optstruct_def, subopts->opts);
|
||||
}
|
||||
|
||||
static void add_global_subopts(struct m_config *config,
|
||||
const struct m_obj_list *list)
|
||||
#define MAX_VO_AO 16
|
||||
|
||||
struct group_entry {
|
||||
const struct m_obj_list *entry;
|
||||
struct m_sub_options subs[MAX_VO_AO];
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
static struct group_entry g_groups[2]; // limited by max. m_obj_list overall
|
||||
static int g_num_groups = 0;
|
||||
static pthread_mutex_t g_group_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static const struct m_sub_options *get_cached_group(const struct m_obj_list *list,
|
||||
int n, struct m_sub_options *v)
|
||||
{
|
||||
pthread_mutex_lock(&g_group_mutex);
|
||||
|
||||
struct group_entry *group = NULL;
|
||||
for (int i = 0; i < g_num_groups; i++) {
|
||||
if (g_groups[i].entry == list) {
|
||||
group = &g_groups[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!group) {
|
||||
assert(g_num_groups < MP_ARRAY_SIZE(g_groups));
|
||||
group = &g_groups[g_num_groups++];
|
||||
group->entry = list;
|
||||
}
|
||||
|
||||
if (!group->initialized) {
|
||||
if (!v) {
|
||||
n = -1;
|
||||
group->initialized = true;
|
||||
} else {
|
||||
assert(n < MAX_VO_AO); // simply increase this if it fails
|
||||
group->subs[n] = *v;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&g_group_mutex);
|
||||
|
||||
return n >= 0 ? &group->subs[n] : NULL;
|
||||
}
|
||||
|
||||
static void init_obj_settings_list(struct m_config *config,
|
||||
const struct m_obj_list *list)
|
||||
{
|
||||
struct m_obj_desc desc;
|
||||
for (int n = 0; ; n++) {
|
||||
if (!list->get_desc(&desc, n))
|
||||
if (!list->get_desc(&desc, n)) {
|
||||
if (list->use_global_options)
|
||||
get_cached_group(list, n, NULL);
|
||||
break;
|
||||
}
|
||||
if (desc.global_opts)
|
||||
add_sub_options(config, NULL, desc.global_opts);
|
||||
if (desc.legacy_prefix && desc.options) {
|
||||
// Legacy: auto-add sub-options as global options (using the prefix).
|
||||
struct m_config_option parent = {
|
||||
.name = desc.legacy_prefix,
|
||||
.group = 0,
|
||||
};
|
||||
struct m_sub_options *conf = talloc(config, struct m_sub_options);
|
||||
*conf = (struct m_sub_options){
|
||||
if (list->use_global_options && desc.options) {
|
||||
struct m_sub_options conf = {
|
||||
.prefix = desc.options_prefix,
|
||||
.opts = desc.options,
|
||||
.defaults = desc.priv_defaults,
|
||||
.size = desc.priv_size,
|
||||
};
|
||||
add_sub_options(config, &parent, conf);
|
||||
add_sub_options(config, NULL, get_cached_group(list, n, &conf));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -560,9 +596,8 @@ static void m_config_add_option(struct m_config *config,
|
||||
init_opt_inplace(arg, co.data, co.default_data);
|
||||
}
|
||||
|
||||
// (The deprecation_message check is a hack to exclude --vo-defaults etc.)
|
||||
if (arg->type == &m_option_type_obj_settings_list && !arg->deprecation_message)
|
||||
add_global_subopts(config, (const struct m_obj_list *)arg->priv);
|
||||
if (arg->type == &m_option_type_obj_settings_list)
|
||||
init_obj_settings_list(config, (const struct m_obj_list *)arg->priv);
|
||||
|
||||
if (arg->name[0]) // no own name -> hidden
|
||||
MP_TARRAY_APPEND(config, config->opts, config->num_opts, co);
|
||||
|
||||
@@ -134,6 +134,9 @@ struct m_config *m_config_from_obj_desc_and_args(void *ta_parent,
|
||||
struct mp_log *log, struct mpv_global *global, struct m_obj_desc *desc,
|
||||
const char *name, struct m_obj_settings *defaults, char **args);
|
||||
|
||||
void *m_config_group_from_desc(void *ta_parent, struct mp_log *log,
|
||||
struct mpv_global *global, struct m_obj_desc *desc, const char *name);
|
||||
|
||||
// Make sure the option is backed up. If it's already backed up, do nothing.
|
||||
// All backed up options can be restored with m_config_restore_backups().
|
||||
void m_config_backup_opt(struct m_config *config, const char *opt);
|
||||
|
||||
@@ -2719,7 +2719,8 @@ static int get_obj_param(struct mp_log *log, bstr opt_name, bstr obj_name,
|
||||
static int m_obj_parse_sub_config(struct mp_log *log, struct bstr opt_name,
|
||||
struct bstr name, struct bstr *pstr,
|
||||
struct m_config *config, int flags, bool nopos,
|
||||
struct m_obj_desc *desc, char ***ret)
|
||||
struct m_obj_desc *desc,
|
||||
const struct m_obj_list *list, char ***ret)
|
||||
{
|
||||
int nold = 0;
|
||||
char **args = NULL;
|
||||
@@ -2737,6 +2738,16 @@ static int m_obj_parse_sub_config(struct mp_log *log, struct bstr opt_name,
|
||||
r = split_subconf(log, opt_name, pstr, &fname, &fval);
|
||||
if (r < 0)
|
||||
goto exit;
|
||||
|
||||
if (list->use_global_options) {
|
||||
mp_err(log, "Option %.*s: this option does not accept sub-options.\n",
|
||||
BSTR_P(opt_name));
|
||||
mp_err(log, "Sub-options for --vo and --ao were removed from mpv in "
|
||||
"release 0.23.0.\nSee https://0x0.st/uM for details.\n");
|
||||
r = M_OPT_INVALID;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (bstr_equals0(fname, "help"))
|
||||
goto print_help;
|
||||
r = get_obj_param(log, opt_name, name, config, fname, fval, flags,
|
||||
@@ -2831,7 +2842,7 @@ static int parse_obj_settings(struct mp_log *log, struct bstr opt,
|
||||
struct m_config *config = m_config_from_obj_desc_noalloc(NULL, log, &desc);
|
||||
bstr s = bstr0(desc.init_options);
|
||||
m_obj_parse_sub_config(log, opt, str, &s, config,
|
||||
M_SETOPT_CHECK_ONLY, nopos, NULL, &plist);
|
||||
M_SETOPT_CHECK_ONLY, nopos, NULL, list, &plist);
|
||||
assert(s.len == 0);
|
||||
talloc_free(config);
|
||||
}
|
||||
@@ -2841,7 +2852,7 @@ static int parse_obj_settings(struct mp_log *log, struct bstr opt,
|
||||
if (!skip)
|
||||
config = m_config_from_obj_desc_noalloc(NULL, log, &desc);
|
||||
r = m_obj_parse_sub_config(log, opt, str, pstr, config,
|
||||
M_SETOPT_CHECK_ONLY, nopos, &desc,
|
||||
M_SETOPT_CHECK_ONLY, nopos, &desc, list,
|
||||
_ret ? &plist : NULL);
|
||||
talloc_free(config);
|
||||
if (r < 0)
|
||||
|
||||
@@ -117,6 +117,8 @@ struct m_obj_desc {
|
||||
const void *priv_defaults;
|
||||
// Options which refer to members in the private struct
|
||||
const struct m_option *options;
|
||||
// Prefix for each of the above options (none if NULL).
|
||||
const char *options_prefix;
|
||||
// For free use by the implementer of m_obj_list.get_desc
|
||||
const void *p;
|
||||
// If not NULL, options which should be set before applying other options.
|
||||
@@ -132,10 +134,6 @@ struct m_obj_desc {
|
||||
const char *replaced_name;
|
||||
// For convenience: these are added as global command-line options.
|
||||
const struct m_sub_options *global_opts;
|
||||
// Evil hack to essentially force-move .options to global_opts. All options
|
||||
// will be added as global options with the given prefix, and using
|
||||
// sub-options will be treated as deprecated and redirected.
|
||||
const char *legacy_prefix;
|
||||
};
|
||||
|
||||
// Extra definition needed for \ref m_option_type_obj_settings_list options.
|
||||
@@ -151,6 +149,8 @@ struct m_obj_list {
|
||||
bool allow_unknown_entries;
|
||||
// This helps with confusing error messages if unknown flag options are used.
|
||||
bool disallow_positional_parameters;
|
||||
// Each sub-item is backed by global options (for AOs and VOs).
|
||||
bool use_global_options;
|
||||
};
|
||||
|
||||
// Find entry by name
|
||||
@@ -188,6 +188,7 @@ typedef int (*m_opt_string_validate_fn)(struct mp_log *log, const m_option_t *op
|
||||
|
||||
// m_option.priv points to this if OPT_SUBSTRUCT is used
|
||||
struct m_sub_options {
|
||||
const char *prefix;
|
||||
const struct m_option *opts;
|
||||
size_t size;
|
||||
const void *defaults;
|
||||
@@ -714,12 +715,6 @@ extern const char m_option_path_separator;
|
||||
.type = &m_option_type_subconfig, \
|
||||
.priv = (void*)&subconf)
|
||||
|
||||
// Same as above, but for legacy suboption usage, which have no associated
|
||||
// field (no actual data anywhere).
|
||||
#define OPT_SUBSTRUCT_LEGACY(optname, subconf) \
|
||||
{.name = optname, .offset = -1, .type = &m_option_type_subconfig, \
|
||||
.priv = (void*)&subconf}
|
||||
|
||||
// Provide a another name for the option.
|
||||
#define OPT_ALIAS(optname, newname) \
|
||||
{.name = optname, .type = &m_option_type_alias, .priv = newname, \
|
||||
|
||||
@@ -150,8 +150,6 @@ const struct m_sub_options stream_cache_conf = {
|
||||
|
||||
static const m_option_t mp_vo_opt_list[] = {
|
||||
OPT_SETTINGSLIST("vo", video_driver_list, 0, &vo_obj_list, ),
|
||||
OPT_SETTINGSLIST("vo-defaults", vo_defs, 0, &vo_obj_list,
|
||||
.deprecation_message = "deprecated, use global options"),
|
||||
OPT_CHOICE_C("hwdec-preload", hwdec_preload_api, 0, mp_hwdec_names),
|
||||
OPT_SUBSTRUCT("sws", sws_opts, sws_conf, 0),
|
||||
OPT_FLAG("taskbar-progress", taskbar_progress, 0),
|
||||
@@ -510,8 +508,6 @@ const m_option_t mp_opts[] = {
|
||||
|
||||
//---------------------- libao/libvo options ------------------------
|
||||
OPT_SETTINGSLIST("ao", audio_driver_list, 0, &ao_obj_list, ),
|
||||
OPT_SETTINGSLIST("ao-defaults", ao_defs, 0, &ao_obj_list,
|
||||
.deprecation_message = "deprecated, use global options"),
|
||||
OPT_STRING("audio-device", audio_device, UPDATE_AUDIO),
|
||||
OPT_FLAG("audio-exclusive", audio_exclusive, UPDATE_AUDIO),
|
||||
OPT_STRING("audio-client-name", audio_client_name, UPDATE_AUDIO),
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "common/common.h"
|
||||
|
||||
typedef struct mp_vo_opts {
|
||||
struct m_obj_settings *video_driver_list, *vo_defs;
|
||||
struct m_obj_settings *video_driver_list;
|
||||
|
||||
int taskbar_progress;
|
||||
int ontop;
|
||||
@@ -90,7 +90,7 @@ typedef struct MPOpts {
|
||||
|
||||
int auto_load_scripts;
|
||||
|
||||
struct m_obj_settings *audio_driver_list, *ao_defs;
|
||||
struct m_obj_settings *audio_driver_list;
|
||||
char *audio_device;
|
||||
int audio_exclusive;
|
||||
char *audio_client_name;
|
||||
|
||||
Reference in New Issue
Block a user