Skip to content

Commit

Permalink
options: convert some guarded options to new warning mechanism
Browse files Browse the repository at this point in the history
mpv has an internal inconsistency where some options are guarded at
compile time and others are not. One advantage of guarding certain
options is that it prevents users from using something that can't
possibly work (e.g. windows-specific options on a linux machine).
However, this hurts the portability of mpv config files and means it's
possible for configs to break depending on a machine. This is not so
nice.

Attempt to have our cake and eat it too by introducing a new
not_available boolean which can optionally be set when defining options.
Naturally, you just set this to the negation of the preprocessor that
applies. Instead of doing a hard error, mpv will print out a generic
warning message that you are trying to use an option that cannot ever
work with the binary. As a downside of this new approach, a bunch of
windows-specific defines have to be explicitly handled which is ugly.
  • Loading branch information
Dudemanguy committed Aug 3, 2024
1 parent 7f49e87 commit 29d5ad8
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 68 deletions.
4 changes: 1 addition & 3 deletions input/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,7 @@ const struct m_sub_options input_config = {
{"input-preprocess-wheel", OPT_BOOL(preprocess_wheel)},
{"input-touch-emulate-mouse", OPT_BOOL(touch_emulate_mouse)},
{"input-dragging-deadzone", OPT_INT(dragging_deadzone)},
#if HAVE_SDL2_GAMEPAD
{"input-gamepad", OPT_BOOL(use_gamepad)},
#endif
{"input-gamepad", OPT_BOOL(use_gamepad), .not_available = !HAVE_SDL2_GAMEPAD},
{"window-dragging", OPT_BOOL(allow_win_drag)},
{0}
},
Expand Down
25 changes: 25 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,31 @@ foreach feature, allowed: features
endif
endforeach

# Add some dummy Windows defines for non-win32 platforms.
if not win32
win32_defines = ['DWMWCP_DEFAULT',
'DWMWCP_DONOTROUND',
'DWMWCP_ROUND',
'DWMWCP_ROUNDSMALL',
'DWMSBT_AUTO',
'DWMSBT_NONE',
'DWMSBT_MAINWINDOW',
'DWMSBT_TRANSIENTWINDOW',
'DWMSBT_TABBEDWINDOW',
'WDA_NONE',
'WDA_MONITOR',
'WDA_EXCLUDEFROMCAPTURE',
'REALTIME_PRIORITY_CLASS',
'HIGH_PRIORITY_CLASS',
'ABOVE_NORMAL_PRIORITY_CLASS',
'NORMAL_PRIORITY_CLASS',
'BELOW_NORMAL_PRIORITY_CLASS',
'IDLE_PRIORITY_CLASS']
foreach define: win32_defines
conf_data.set10(define, false)
endforeach
endif


# Script to sort the feature_keys object.
feature_sort = '''
Expand Down
10 changes: 10 additions & 0 deletions options/m_config_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,16 @@ static void get_opt_from_id(struct m_config_shadow *shadow, int32_t id,
*out_opt_index = opt_index;
}

bool m_config_shadow_opt_not_available(struct m_config_shadow *shadow,
int32_t id)
{
int group_index, opt_index;
get_opt_from_id(shadow, id, &group_index, &opt_index);

return shadow->groups[group_index].group->not_available ||
shadow->groups[group_index].group->opts[opt_index].not_available;
}

const struct m_option *m_config_shadow_get_opt(struct m_config_shadow *shadow,
int32_t id)
{
Expand Down
5 changes: 5 additions & 0 deletions options/m_config_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ bool m_config_shadow_get_next_opt(struct m_config_shadow *shadow, int32_t *p_id)
// covered by the m_config_cache.
bool m_config_cache_get_next_opt(struct m_config_cache *cache, int32_t *p_id);


// Check if the option is flagged as not available.
bool m_config_shadow_opt_not_available(struct m_config_shadow *shadow,
int32_t id);

// Return the m_option that was used to declare this option.
// id must be a valid option ID as returned by m_config_shadow_get_next_opt() or
// m_config_cache_get_next_opt().
Expand Down
10 changes: 10 additions & 0 deletions options/m_config_frontend.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,13 @@ static struct m_config_option *m_config_get_co_any(const struct m_config *config
return NULL;

const char *prefix = config->is_toplevel ? "--" : "";
if (co->not_available) {
if (!co->warning_was_printed) {
MP_WARN(config, "Warning: support for option %s%s is not compiled in the mpv binary.\n",
prefix, co->name);
co->warning_was_printed = true;
}
}
if (co->opt->type == &m_option_type_alias) {
char buf[M_CONFIG_MAX_OPT_NAME_LEN];
const char *alias = m_config_shadow_get_alias_from_opt(config->shadow, co->opt_id,
Expand Down Expand Up @@ -556,6 +563,7 @@ struct m_config *m_config_new(void *talloc_ctx, struct mp_log *log,

struct m_config_option co = {
.name = talloc_strdup(config, opt_name),
.not_available = m_config_shadow_opt_not_available(config->shadow, optid),
.opt = m_config_shadow_get_opt(config->shadow, optid),
.opt_id = optid,
};
Expand Down Expand Up @@ -844,6 +852,8 @@ void m_config_print_option_list(const struct m_config *config, const char *name)
const struct m_option *opt = co->opt;
if (strcmp(name, "*") != 0 && !strstr(co->name, name))
continue;
if (co->not_available)
continue;
MP_INFO(config, " %s%-30s", prefix, co->name);
if (opt->type == &m_option_type_choice) {
MP_INFO(config, " Choices:");
Expand Down
1 change: 1 addition & 0 deletions options/m_config_frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct m_config_option {
bool is_set_from_config : 1; // Set by a config file
bool is_set_locally : 1; // Has a backup entry
bool warning_was_printed : 1;
bool not_available; // Option is missing compile-time support
int32_t opt_id; // For some m_config APIs
const char *name; // Full name (ie option-subopt)
const struct m_option *opt; // Option description
Expand Down
6 changes: 6 additions & 0 deletions options/m_option.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ struct m_sub_options {
// Change flags passed to mp_option_change_callback() if any option that is
// directly or indirectly part of this group is changed.
int change_flags;
// If all sub_options require something during compile to work.
bool not_available;
// Return further sub-options, for example for optional components. If set,
// this is called with increasing index (starting from 0), as long as true
// is returned. If true is returned and *sub is set in any of these calls,
Expand Down Expand Up @@ -393,6 +395,10 @@ struct m_option {
// If the option is an alias, use the prefix of sub option.
bool alias_use_prefix;

// If the option requires something during compile time to work potentially
// flag it is as not not_available.
bool not_available;

int offset;

// Most numeric types restrict the range to [min, max] if min<max (this
Expand Down
140 changes: 75 additions & 65 deletions options/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ static const m_option_t mp_vo_opt_list[] = {
{"focus-on", OPT_CHOICE(focus_on, {"never", 0}, {"open", 1}, {"all", 2})},
{"force-render", OPT_BOOL(force_render)},
{"force-window-position", OPT_BOOL(force_window_position)},
{"x11-name", OPT_STRING(winname)},
{"wayland-app-id", OPT_STRING(appid)},
{"monitoraspect", OPT_FLOAT(force_monitor_aspect), M_RANGE(0.0, 9.0)},
{"monitorpixelaspect", OPT_FLOAT(monitor_pixel_aspect),
Expand Down Expand Up @@ -185,53 +184,50 @@ static const m_option_t mp_vo_opt_list[] = {
{"display-vdrop", VS_DISP_VDROP},
{"display-desync", VS_DISP_NONE},
{"desync", VS_NONE})},
#if HAVE_X11
{"x11-netwm", OPT_CHOICE(x11_netwm, {"auto", 0}, {"no", -1}, {"yes", 1})},

// X11 options
{"x11-name", OPT_STRING(winname), .not_available = !HAVE_X11},
{"x11-netwm", OPT_CHOICE(x11_netwm, {"auto", 0}, {"no", -1}, {"yes", 1}),
.not_available = !HAVE_X11},
{"x11-bypass-compositor", OPT_CHOICE(x11_bypass_compositor,
{"no", 0}, {"yes", 1}, {"fs-only", 2}, {"never", 3})},
{"no", 0}, {"yes", 1}, {"fs-only", 2}, {"never", 3}),
.not_available = !HAVE_X11},
{"x11-present", OPT_CHOICE(x11_present,
{"no", 0}, {"auto", 1}, {"yes", 2})},
{"x11-wid-title", OPT_BOOL(x11_wid_title)},
#endif
#if HAVE_WAYLAND
{"no", 0}, {"auto", 1}, {"yes", 2}), .not_available = !HAVE_X11},
{"x11-wid-title", OPT_BOOL(x11_wid_title), .not_available = !HAVE_X11},

// Wayland options
{"wayland-configure-bounds", OPT_CHOICE(wl_configure_bounds,
{"auto", -1}, {"no", 0}, {"yes", 1})},
{"auto", -1}, {"no", 0}, {"yes", 1}), .not_available = !HAVE_WAYLAND},
{"wayland-content-type", OPT_CHOICE(wl_content_type, {"auto", -1}, {"none", 0},
{"photo", 1}, {"video", 2}, {"game", 3})},
{"wayland-disable-vsync", OPT_BOOL(wl_disable_vsync)},
{"photo", 1}, {"video", 2}, {"game", 3}), .not_available = !HAVE_WAYLAND},
{"wayland-disable-vsync", OPT_BOOL(wl_disable_vsync),
.not_available = !HAVE_WAYLAND},
{"wayland-edge-pixels-pointer", OPT_INT(wl_edge_pixels_pointer),
M_RANGE(0, INT_MAX)},
M_RANGE(0, INT_MAX), .not_available = !HAVE_WAYLAND},
{"wayland-edge-pixels-touch", OPT_INT(wl_edge_pixels_touch),
M_RANGE(0, INT_MAX)},
{"wayland-present", OPT_BOOL(wl_present)},
#endif
#if HAVE_WIN32_DESKTOP
// For old MinGW-w64 compatibility
#define DWMWCP_DEFAULT 0
#define DWMWCP_DONOTROUND 1
#define DWMWCP_ROUND 2
#define DWMWCP_ROUNDSMALL 3

#define DWMSBT_AUTO 0
#define DWMSBT_NONE 1
#define DWMSBT_MAINWINDOW 2
#define DWMSBT_TRANSIENTWINDOW 3
#define DWMSBT_TABBEDWINDOW 4
M_RANGE(0, INT_MAX), .not_available = !HAVE_WAYLAND},
{"wayland-present", OPT_BOOL(wl_present), .not_available = !HAVE_WAYLAND},

// Windows Desktop options
{"backdrop-type", OPT_CHOICE(backdrop_type, {"auto", DWMSBT_AUTO}, {"none", DWMSBT_NONE},
{"mica", DWMSBT_MAINWINDOW}, {"acrylic", DWMSBT_TRANSIENTWINDOW}, {"mica-alt", DWMSBT_TABBEDWINDOW})},
{"window-affinity", OPT_CHOICE(window_affinity, {"default", WDA_NONE},
{"excludefromcapture", WDA_EXCLUDEFROMCAPTURE}, {"monitor", WDA_MONITOR})},
{"vo-mmcss-profile", OPT_STRING(mmcss_profile)},
{"mica", DWMSBT_MAINWINDOW}, {"acrylic", DWMSBT_TRANSIENTWINDOW}, {"mica-alt", DWMSBT_TABBEDWINDOW}),
.not_available = !HAVE_WIN32_DESKTOP},
{"window-affinity", OPT_CHOICE(window_affinity, {"default", 0},
{"excludefromcapture", 0}, {"monitor", WDA_MONITOR}),
.not_available = !HAVE_WIN32_DESKTOP},
{"vo-mmcss-profile", OPT_STRING(mmcss_profile), .not_available = !HAVE_WIN32_DESKTOP},
{"window-corners", OPT_CHOICE(window_corners,
{"default", DWMWCP_DEFAULT},
{"donotround", DWMWCP_DONOTROUND},
{"round", DWMWCP_ROUND},
{"roundsmall", DWMWCP_ROUNDSMALL})},
#endif
#if HAVE_EGL_ANDROID
{"android-surface-size", OPT_SIZE_BOX(android_surface_size)},
#endif
{"roundsmall", DWMWCP_ROUNDSMALL}),
.not_available = !HAVE_WIN32_DESKTOP},

// EGL Android Options
{"android-surface-size", OPT_SIZE_BOX(android_surface_size),
.not_available = !HAVE_EGL_ANDROID},

{"swapchain-depth", OPT_INT(swapchain_depth), M_RANGE(1, VO_MAX_SWAPCHAIN_DEPTH)},
{"override-display-fps", OPT_REPLACED("display-fps-override")},
{0}
Expand Down Expand Up @@ -439,6 +435,7 @@ const struct m_sub_options cuda_conf = {
M_RANGE(0, INT_MAX)},
{0}
},
.not_available = !HAVE_CUDA_HWACCEL,
.size = sizeof(struct cuda_opts),
.defaults = &(const struct cuda_opts){
.cuda_device = -1,
Expand All @@ -455,6 +452,7 @@ const struct m_sub_options dvd_conf = {
{"dvd-angle", OPT_INT(angle), M_RANGE(1, 99)},
{0}
},
.not_available = !HAVE_DVDNAV,
.size = sizeof(struct dvd_opts),
.defaults = &(const struct dvd_opts){
.angle = 1,
Expand Down Expand Up @@ -532,7 +530,8 @@ static const m_option_t mp_opts[] = {
.flags = CONF_PRE_PARSE | M_OPT_FILE | UPDATE_TERM},
{"msg-module", OPT_BOOL(msg_module), .flags = UPDATE_TERM},
{"msg-time", OPT_BOOL(msg_time), .flags = UPDATE_TERM},
#if HAVE_WIN32_DESKTOP

// Windows Desktop
{"priority", OPT_CHOICE(w32_priority,
{"no", 0},
{"realtime", REALTIME_PRIORITY_CLASS},
Expand All @@ -541,44 +540,56 @@ static const m_option_t mp_opts[] = {
{"normal", NORMAL_PRIORITY_CLASS},
{"belownormal", BELOW_NORMAL_PRIORITY_CLASS},
{"idle", IDLE_PRIORITY_CLASS}),
.flags = UPDATE_PRIORITY},
#endif
.flags = UPDATE_PRIORITY,
.not_available = !HAVE_WIN32_DESKTOP},

// Windows Medial Controls
{"media-controls", OPT_CHOICE(media_controls,
{"no", 0}, {"player", 1}, {"yes", 2})},
{"no", 0}, {"player", 1}, {"yes", 2}),
.not_available = !HAVE_WIN32_SMTC},

{"config", OPT_BOOL(load_config), .flags = CONF_PRE_PARSE},
{"config-dir", OPT_STRING(force_configdir),
.flags = CONF_NOCFG | CONF_PRE_PARSE | M_OPT_FILE},
{"reset-on-next-file", OPT_STRINGLIST(reset_options)},

#if HAVE_LUA || HAVE_JAVASCRIPT || HAVE_CPLUGINS
{"scripts", OPT_PATHLIST(script_files), .flags = M_OPT_FILE},
{"script", OPT_CLI_ALIAS("scripts-append")},
{"script-opts", OPT_KEYVALUELIST(script_opts)},
{"load-scripts", OPT_BOOL(auto_load_scripts)},
#endif
#if HAVE_JAVASCRIPT
{"js-memory-report", OPT_BOOL(js_memory_report)},
#endif
#if HAVE_LUA
{"osc", OPT_BOOL(lua_load_osc), .flags = UPDATE_BUILTIN_SCRIPTS},
{"ytdl", OPT_BOOL(lua_load_ytdl), .flags = UPDATE_BUILTIN_SCRIPTS},
{"ytdl-format", OPT_STRING(lua_ytdl_format)},
{"ytdl-raw-options", OPT_KEYVALUELIST(lua_ytdl_raw_options)},
{"load-stats-overlay", OPT_BOOL(lua_load_stats),
.flags = UPDATE_BUILTIN_SCRIPTS},
{"load-osd-console", OPT_BOOL(lua_load_console),
.flags = UPDATE_BUILTIN_SCRIPTS},
// Scripting
{"scripts", OPT_PATHLIST(script_files), .flags = M_OPT_FILE,
.not_available = !HAVE_LUA && !HAVE_JAVASCRIPT && !HAVE_CPLUGINS},
{"script", OPT_CLI_ALIAS("scripts-append"),
.not_available = !HAVE_LUA && !HAVE_JAVASCRIPT && !HAVE_CPLUGINS},
{"script-opts", OPT_KEYVALUELIST(script_opts),
.not_available = !HAVE_LUA && !HAVE_JAVASCRIPT && !HAVE_CPLUGINS},
{"load-scripts", OPT_BOOL(auto_load_scripts),
.not_available = !HAVE_LUA && !HAVE_JAVASCRIPT && !HAVE_CPLUGINS},

// Javascript
{"js-memory-report", OPT_BOOL(js_memory_report), .not_available = !HAVE_JAVASCRIPT},

// Lua
{"osc", OPT_BOOL(lua_load_osc), .flags = UPDATE_BUILTIN_SCRIPTS,
.not_available = !HAVE_LUA},
{"ytdl", OPT_BOOL(lua_load_ytdl), .flags = UPDATE_BUILTIN_SCRIPTS,
.not_available = !HAVE_LUA},
{"ytdl-format", OPT_STRING(lua_ytdl_format),
.not_available = !HAVE_LUA},
{"ytdl-raw-options", OPT_KEYVALUELIST(lua_ytdl_raw_options),
.not_available = !HAVE_LUA},
{"load-stats-overlay", OPT_BOOL(lua_load_stats), .flags = UPDATE_BUILTIN_SCRIPTS,
.not_available = !HAVE_LUA},
{"load-osd-console", OPT_BOOL(lua_load_console), .flags = UPDATE_BUILTIN_SCRIPTS,
.not_available = !HAVE_LUA},
{"load-auto-profiles",
OPT_CHOICE(lua_load_auto_profiles, {"no", 0}, {"yes", 1}, {"auto", -1}),
.flags = UPDATE_BUILTIN_SCRIPTS},
{"load-select", OPT_BOOL(lua_load_select), .flags = UPDATE_BUILTIN_SCRIPTS},
#endif
.flags = UPDATE_BUILTIN_SCRIPTS, .not_available = !HAVE_LUA},
{"load-select", OPT_BOOL(lua_load_select), .flags = UPDATE_BUILTIN_SCRIPTS,
.not_available = !HAVE_LUA},

// ------------------------- stream options --------------------

#if HAVE_DVDNAV
// DVD
{"", OPT_SUBSTRUCT(dvd_opts, dvd_conf)},
#endif

{"edition", OPT_CHOICE(edition_id, {"auto", -1}), M_RANGE(0, 8190)},
#if HAVE_LIBBLURAY
{"bluray", OPT_SUBSTRUCT(stream_bluray_opts, stream_bluray_conf)},
Expand Down Expand Up @@ -944,9 +955,8 @@ static const m_option_t mp_opts[] = {
{"", OPT_SUBSTRUCT(wingl_opts, wingl_conf)},
#endif

#if HAVE_CUDA_HWACCEL
// CUDA
{"cuda", OPT_SUBSTRUCT(cuda_opts, cuda_conf)},
#endif

#if HAVE_VAAPI
{"vaapi", OPT_SUBSTRUCT(vaapi_opts, vaapi_conf)},
Expand Down

0 comments on commit 29d5ad8

Please sign in to comment.