summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-11-25 21:00:39 +0100
committerwm4 <wm4@nowhere>2016-11-25 21:17:25 +0100
commit1a2319f3e4cc42c680e2fd3ba30022c7a9adf3fe (patch)
tree37261ccac2acc614777ba4c790cfed78b96fb58f
parent98a257b3a871587a97f51ef1b09800959a94ed1e (diff)
downloadmpv-1a2319f3e4cc42c680e2fd3ba30022c7a9adf3fe.tar.bz2
mpv-1a2319f3e4cc42c680e2fd3ba30022c7a9adf3fe.tar.xz
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.)
-rw-r--r--DOCS/interface-changes.rst4
-rw-r--r--DOCS/man/ao.rst5
-rw-r--r--DOCS/man/vo.rst5
-rw-r--r--audio/out/ao.c23
-rw-r--r--audio/out/ao_alsa.c10
-rw-r--r--audio/out/ao_audiounit.m3
-rw-r--r--audio/out/ao_coreaudio.c9
-rw-r--r--audio/out/ao_jack.c8
-rw-r--r--audio/out/ao_null.c2
-rw-r--r--audio/out/ao_openal.c2
-rw-r--r--audio/out/ao_opensles.c2
-rw-r--r--audio/out/ao_oss.c2
-rw-r--r--audio/out/ao_pcm.c2
-rw-r--r--audio/out/ao_pulse.c2
-rw-r--r--audio/out/ao_rsound.c2
-rw-r--r--audio/out/ao_sdl.c2
-rw-r--r--audio/out/ao_sndio.c2
-rw-r--r--audio/out/ao_wasapi.c7
-rw-r--r--audio/out/ao_wasapi.h2
-rw-r--r--audio/out/ao_wasapi_utils.c5
-rw-r--r--audio/out/internal.h2
-rw-r--r--options/m_config.c165
-rw-r--r--options/m_config.h3
-rw-r--r--options/m_option.c17
-rw-r--r--options/m_option.h15
-rw-r--r--options/options.c4
-rw-r--r--options/options.h4
-rw-r--r--video/out/opengl/video.c89
-rw-r--r--video/out/opengl/video.h1
-rw-r--r--video/out/vo.c16
-rw-r--r--video/out/vo.h16
-rw-r--r--video/out/vo_direct3d.c2
-rw-r--r--video/out/vo_drm.c1
-rw-r--r--video/out/vo_image.c12
-rw-r--r--video/out/vo_null.c2
-rw-r--r--video/out/vo_opengl.c110
-rw-r--r--video/out/vo_opengl_cb.c10
-rw-r--r--video/out/vo_rpi.c2
-rw-r--r--video/out/vo_sdl.c2
-rw-r--r--video/out/vo_vaapi.c2
-rw-r--r--video/out/vo_vdpau.c2
-rw-r--r--video/out/vo_wayland.c2
-rw-r--r--video/out/vo_xv.c2
43 files changed, 219 insertions, 361 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index 6504db556a..cf53a934a1 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -30,6 +30,10 @@ Interface changes
- "audio-channels" (use "audio-params/channel-count")
- "audio-format" (use "audio-codec-name")
(the properties equivalent to the old semantics are in parentheses)
+ - remove deprecated --vo and --ao sub-options (like --vo=opengl:...), and
+ replace them with global options. A somewhat complete list can be found
+ here: https://github.com/mpv-player/mpv/wiki/Option-replacement-list#mpv-0210
+ - remove --vo-defaults and --ao-defaults as well
- remove deprecated global sub-options (like -demuxer-rawaudio format=...),
use flat options (like --demuxer-rawaudio-format=...)
--- mpv 0.22.0 ---
diff --git a/DOCS/man/ao.rst b/DOCS/man/ao.rst
index 0e45b1e96e..5984abaa1c 100644
--- a/DOCS/man/ao.rst
+++ b/DOCS/man/ao.rst
@@ -10,11 +10,6 @@ syntax is:
If the list has a trailing ',', mpv will fall back on drivers not contained
in the list.
-``--ao-defaults=<driver1[:parameter1:parameter2:...],driver2,...>``
- Set defaults for each driver.
-
- Deprecated. No replacement.
-
.. note::
See ``--ao=help`` for a list of compiled-in audio output drivers. The
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index f695ba0f6f..6ff4b42604 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -10,11 +10,6 @@ syntax is:
If the list has a trailing ``,``, mpv will fall back on drivers not contained
in the list.
-``--vo-defaults=<driver1[:parameter1:parameter2:...],driver2,...>``
- Set defaults for each driver.
-
- Deprecated. No replacement.
-
.. note::
See ``--vo=help`` for a list of compiled-in video output drivers.
diff --git a/audio/out/ao.c b/audio/out/ao.c
index b624f4196c..6cf8de2d88 100644
--- a/audio/out/ao.c
+++ b/audio/out/ao.c
@@ -112,8 +112,8 @@ static bool get_desc(struct m_obj_desc *dst, int index)
.priv_size = ao->priv_size,
.priv_defaults = ao->priv_defaults,
.options = ao->options,
+ .options_prefix = ao->options_prefix,
.global_opts = ao->global_opts,
- .legacy_prefix = ao->legacy_prefix,
.hidden = ao->encode,
.p = ao,
};
@@ -127,11 +127,12 @@ const struct m_obj_list ao_obj_list = {
.allow_unknown_entries = true,
.allow_trailer = true,
.disallow_positional_parameters = true,
+ .use_global_options = true,
};
static struct ao *ao_alloc(bool probing, struct mpv_global *global,
void (*wakeup_cb)(void *ctx), void *wakeup_ctx,
- char *name, char **args)
+ char *name)
{
assert(wakeup_cb);
@@ -155,12 +156,9 @@ static struct ao *ao_alloc(bool probing, struct mpv_global *global,
.def_buffer = opts->audio_buffer,
.client_name = talloc_strdup(ao, opts->audio_client_name),
};
- struct m_config *config =
- m_config_from_obj_desc_and_args(ao, ao->log, global, &desc,
- name, opts->ao_defs, args);
- if (!config)
+ ao->priv = m_config_group_from_desc(ao, ao->log, global, &desc, name);
+ if (!ao->priv)
goto error;
- ao->priv = config->optstruct;
return ao;
error:
talloc_free(ao);
@@ -171,9 +169,9 @@ static struct ao *ao_init(bool probing, struct mpv_global *global,
void (*wakeup_cb)(void *ctx), void *wakeup_ctx,
struct encode_lavc_context *encode_lavc_ctx, int flags,
int samplerate, int format, struct mp_chmap channels,
- char *dev, char *name, char **args)
+ char *dev, char *name)
{
- struct ao *ao = ao_alloc(probing, global, wakeup_cb, wakeup_ctx, name, args);
+ struct ao *ao = ao_alloc(probing, global, wakeup_cb, wakeup_ctx, name);
if (!ao)
return NULL;
ao->samplerate = samplerate;
@@ -206,7 +204,7 @@ static struct ao *ao_init(bool probing, struct mpv_global *global,
talloc_free(ao);
return ao_init(probing, global, wakeup_cb, wakeup_ctx,
encode_lavc_ctx, flags, samplerate, format, channels,
- rdevice, redirect, NULL);
+ rdevice, redirect);
}
goto fail;
}
@@ -313,8 +311,7 @@ struct ao *ao_init_best(struct mpv_global *global,
mp_verbose(log, "Using preferred device '%s'\n", dev);
}
ao = ao_init(probing, global, wakeup_cb, wakeup_ctx, encode_lavc_ctx,
- init_flags, samplerate, format, channels, dev,
- entry->name, entry->attribs);
+ init_flags, samplerate, format, channels, dev, entry->name);
if (ao)
break;
if (!probing)
@@ -571,7 +568,7 @@ struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp)
break; // don't add unsafe/special entries
struct ao *ao = ao_alloc(true, hp->global, hp->wakeup_cb, hp->wakeup_ctx,
- (char *)d->name, NULL);
+ (char *)d->name);
if (!ao)
continue;
diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c
index 91c8e2d3fc..d63a760d73 100644
--- a/audio/out/ao_alsa.c
+++ b/audio/out/ao_alsa.c
@@ -1196,15 +1196,5 @@ const struct ao_driver audio_out_alsa = {
.wakeup = ao_wakeup_poll,
.list_devs = list_devs,
.priv_size = sizeof(struct priv),
- .options = (const struct m_option[]) {
- OPT_SUBOPT_LEGACY("device", "alsa-device"),
- OPT_SUBOPT_LEGACY("resample", "alsa-resample"),
- OPT_SUBOPT_LEGACY("mixer-device", "alsa-mixer-device"),
- OPT_SUBOPT_LEGACY("mixer-name", "alsa-mixer-name"),
- OPT_SUBOPT_LEGACY("mixer-index", "alsa-mixer-index"),
- OPT_SUBOPT_LEGACY("non-interleaved", "alsa-non-interleaved"),
- OPT_SUBOPT_LEGACY("ignore-chmap", "alsa-ignore-chmap"),
- {0}
- },
.global_opts = &ao_alsa_conf,
};
diff --git a/audio/out/ao_audiounit.m b/audio/out/ao_audiounit.m
index 7411a1a1dd..31703525a9 100644
--- a/audio/out/ao_audiounit.m
+++ b/audio/out/ao_audiounit.m
@@ -195,7 +195,4 @@ const struct ao_driver audio_out_audiounit = {
.pause = stop,
.resume = start,
.priv_size = sizeof(struct priv),
- .options = (const struct m_option[]){
- {0}
- },
};
diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c
index 3a7aa2eac1..ba0dd9b0ba 100644
--- a/audio/out/ao_coreaudio.c
+++ b/audio/out/ao_coreaudio.c
@@ -39,7 +39,6 @@ struct priv {
AudioStreamID original_asbd_stream;
int change_physical_format;
- int exclusive;
};
static int64_t ca_get_hardware_latency(struct ao *ao) {
@@ -143,9 +142,7 @@ static int init(struct ao *ao)
{
struct priv *p = ao->priv;
- p->exclusive |= ao->init_flags & AO_INIT_EXCLUSIVE;
-
- if (!af_fmt_is_pcm(ao->format) || p->exclusive) {
+ if (!af_fmt_is_pcm(ao->format) || (ao->init_flags & AO_INIT_EXCLUSIVE)) {
MP_VERBOSE(ao, "redirecting to coreaudio_exclusive\n");
ao->redirect = "coreaudio_exclusive";
return CONTROL_ERROR;
@@ -429,9 +426,7 @@ const struct ao_driver audio_out_coreaudio = {
.priv_size = sizeof(struct priv),
.options = (const struct m_option[]){
OPT_FLAG("change-physical-format", change_physical_format, 0),
- OPT_FLAG("exclusive", exclusive, 0,
- .deprecation_message = "use --audio-exclusive"),
{0}
},
- .legacy_prefix = "coreaudio",
+ .options_prefix = "coreaudio",
};
diff --git a/audio/out/ao_jack.c b/audio/out/ao_jack.c
index 56c7e28544..2ad3cad586 100644
--- a/audio/out/ao_jack.c
+++ b/audio/out/ao_jack.c
@@ -246,13 +246,5 @@ const struct ao_driver audio_out_jack = {
.uninit = uninit,
.resume = resume,
.priv_size = sizeof(struct priv),
- .options = (const struct m_option[]) {
- OPT_SUBOPT_LEGACY("port", "jack-port"),
- OPT_SUBOPT_LEGACY("name", "jack-name"),
- OPT_SUBOPT_LEGACY("autostart", "jack-autostart"),
- OPT_SUBOPT_LEGACY("connect", "jack-connect"),
- OPT_SUBOPT_LEGACY("std-channel-layout", "jack-std-channel-layout"),
- {0}
- },
.global_opts = &ao_jack_conf,
};
diff --git a/audio/out/ao_null.c b/audio/out/ao_null.c
index 7c0c745b12..7b288a8245 100644
--- a/audio/out/ao_null.c
+++ b/audio/out/ao_null.c
@@ -241,5 +241,5 @@ const struct ao_driver audio_out_null = {
OPT_CHANNELS("channel-layouts", channel_layouts, 0),
{0}
},
- .legacy_prefix = "ao-null",
+ .options_prefix = "ao-null",
};
diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c
index aba049445d..a1fd95ab18 100644
--- a/audio/out/ao_openal.c
+++ b/audio/out/ao_openal.c
@@ -374,5 +374,5 @@ const struct ao_driver audio_out_openal = {
DEVICE_OPT_DEPRECATION),
{0}
},
- .legacy_prefix = "ao-openal",
+ .options_prefix = "ao-openal",
};
diff --git a/audio/out/ao_opensles.c b/audio/out/ao_opensles.c
index dd20dbf1d0..5357ab4920 100644
--- a/audio/out/ao_opensles.c
+++ b/audio/out/ao_opensles.c
@@ -246,5 +246,5 @@ const struct ao_driver audio_out_opensles = {
OPT_INTRANGE("sample-rate", cfg_sample_rate, 0, 1000, 100000),
{0}
},
- .legacy_prefix = "opensles",
+ .options_prefix = "opensles",
};
diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c
index 5bf5fec29b..c0446eb2aa 100644
--- a/audio/out/ao_oss.c
+++ b/audio/out/ao_oss.c
@@ -653,5 +653,5 @@ const struct ao_driver audio_out_oss = {
OPT_STRING("mixer-channel", cfg_oss_mixer_channel, 0),
{0}
},
- .legacy_prefix = "oss",
+ .options_prefix = "oss",
};
diff --git a/audio/out/ao_pcm.c b/audio/out/ao_pcm.c
index 169a1b94a1..4e5ec0a319 100644
--- a/audio/out/ao_pcm.c
+++ b/audio/out/ao_pcm.c
@@ -224,5 +224,5 @@ const struct ao_driver audio_out_pcm = {
OPT_FLAG("append", append, 0),
{0}
},
- .legacy_prefix = "ao-pcm",
+ .options_prefix = "ao-pcm",
};
diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c
index 5a68553e88..6c6a517f2a 100644
--- a/audio/out/ao_pulse.c
+++ b/audio/out/ao_pulse.c
@@ -841,5 +841,5 @@ const struct ao_driver audio_out_pulse = {
OPT_FLAG("latency-hacks", cfg_latency_hacks, 0),
{0}
},
- .legacy_prefix = "pulse",
+ .options_prefix = "pulse",
};
diff --git a/audio/out/ao_rsound.c b/audio/out/ao_rsound.c
index 5ecb39b9d3..9689a9e0b8 100644
--- a/audio/out/ao_rsound.c
+++ b/audio/out/ao_rsound.c
@@ -162,6 +162,6 @@ const struct ao_driver audio_out_rsound = {
.deprecation_message = "request --audio-device support on issue tracker"),
{0}
},
- .legacy_prefix = "rsound",
+ .options_prefix = "rsound",
};
diff --git a/audio/out/ao_sdl.c b/audio/out/ao_sdl.c
index d9d00628b6..1564e26120 100644
--- a/audio/out/ao_sdl.c
+++ b/audio/out/ao_sdl.c
@@ -212,5 +212,5 @@ const struct ao_driver audio_out_sdl = {
OPT_FLOAT("buflen", buflen, 0),
{0}
},
- .legacy_prefix = "sdl",
+ .options_prefix = "sdl",
};
diff --git a/audio/out/ao_sndio.c b/audio/out/ao_sndio.c
index f60fa303e5..e0fd9f0296 100644
--- a/audio/out/ao_sndio.c
+++ b/audio/out/ao_sndio.c
@@ -324,5 +324,5 @@ const struct ao_driver audio_out_sndio = {
DEVICE_OPT_DEPRECATION),
{0}
},
- .legacy_prefix = "ao-sndio",
+ .options_prefix = "ao-sndio",
};
diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c
index 17f3e98653..b2e035d3dc 100644
--- a/audio/out/ao_wasapi.c
+++ b/audio/out/ao_wasapi.c
@@ -496,11 +496,4 @@ const struct ao_driver audio_out_wasapi = {
.hotplug_init = hotplug_init,
.hotplug_uninit = hotplug_uninit,
.priv_size = sizeof(wasapi_state),
- .options = (const struct m_option[]) {
- OPT_FLAG("exclusive", opt_exclusive, 0,
- .deprecation_message = "use --audio-exclusive"),
- OPT_STRING("device", opt_device, 0, DEVICE_OPT_DEPRECATION),
- {NULL},
- },
- .legacy_prefix = "ao-wasapi",
};
diff --git a/audio/out/ao_wasapi.h b/audio/out/ao_wasapi.h
index 6dd130b50f..ea9f5c2bad 100644
--- a/audio/out/ao_wasapi.h
+++ b/audio/out/ao_wasapi.h
@@ -92,8 +92,6 @@ typedef struct wasapi_state {
// ao options
int opt_exclusive;
- int opt_list;
- char *opt_device;
// format info
WAVEFORMATEXTENSIBLE format;
diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c
index 320bb6767b..8b12ef4d5c 100644
--- a/audio/out/ao_wasapi_utils.c
+++ b/audio/out/ao_wasapi_utils.c
@@ -858,10 +858,7 @@ static LPWSTR select_device(struct mp_log *l, struct device_desc *d)
bstr wasapi_get_specified_device_string(struct ao *ao)
{
struct wasapi_state *state = ao->priv;
- bstr device = bstr_strip(bstr0(state->opt_device));
- if (!device.len)
- device = bstr_strip(bstr0(ao->device));
- return device;
+ return bstr_strip(bstr0(ao->device));
}
LPWSTR wasapi_find_deviceID(struct ao *ao)
diff --git a/audio/out/internal.h b/audio/out/internal.h
index 3ddc1becb9..b35f20fba2 100644
--- a/audio/out/internal.h
+++ b/audio/out/internal.h
@@ -182,8 +182,8 @@ struct ao_driver {
int priv_size;
const void *priv_defaults;
const struct m_option *options;
+ const char *options_prefix;
const struct m_sub_options *global_opts;
- const char *legacy_prefix;
};
// These functions can be called by AOs.
diff --git a/options/m_config.c b/options/m_config.c
index dea7a4dd10..256e4653e7 100644
--- a/options/m_config.c
+++ b/options/m_config.c
@@ -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);
diff --git a/options/m_config.h b/options/m_config.h
index 16eba317f0..1e199cacd9 100644
--- a/options/m_config.h
+++ b/options/m_config.h
@@ -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);
diff --git a/options/m_option.c b/options/m_option.c
index 4ef5481ceb..6baa87c163 100644
--- a/options/m_option.c
+++ b/options/m_option.c
@@ -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)
{