diff options
Diffstat (limited to 'options')
-rw-r--r-- | options/m_config.h | 2 | ||||
-rw-r--r-- | options/m_config_frontend.c | 2 | ||||
-rw-r--r-- | options/m_option.c | 40 | ||||
-rw-r--r-- | options/m_option.h | 43 | ||||
-rw-r--r-- | options/m_property.c | 7 | ||||
-rw-r--r-- | options/m_property.h | 6 | ||||
-rw-r--r-- | options/options.c | 91 | ||||
-rw-r--r-- | options/options.h | 31 | ||||
-rw-r--r-- | options/parse_commandline.c | 7 | ||||
-rw-r--r-- | options/path.c | 193 | ||||
-rw-r--r-- | options/path.h | 43 |
11 files changed, 166 insertions, 299 deletions
diff --git a/options/m_config.h b/options/m_config.h index d2ce2b4..a6bade9 100644 --- a/options/m_config.h +++ b/options/m_config.h @@ -1 +1 @@ -#include "m_config_core.h"
\ No newline at end of file +#include "m_config_core.h" diff --git a/options/m_config_frontend.c b/options/m_config_frontend.c index 9b54389..d800cdb 100644 --- a/options/m_config_frontend.c +++ b/options/m_config_frontend.c @@ -871,7 +871,7 @@ void m_config_print_option_list(const struct m_config *config, const char *name) if (!defptr) defptr = &m_option_value_default; if (defptr) - def = m_option_pretty_print(opt, defptr); + def = m_option_pretty_print(opt, defptr, false); if (def) { MP_INFO(config, " (default: %s)", def); talloc_free(def); diff --git a/options/m_option.c b/options/m_option.c index 1b1ac0a..4646510 100644 --- a/options/m_option.c +++ b/options/m_option.c @@ -1023,17 +1023,12 @@ static char *print_double(const m_option_t *opt, const void *val) return talloc_asprintf(NULL, "%f", f); } -static char *print_double_7g(const m_option_t *opt, const void *val) +static char *pretty_print_double(const m_option_t *opt, const void *val) { double f = VAL(val); if (isnan(f)) return print_double(opt, val); - // Truncate anything < 1e-4 to avoid switching to scientific notation - if (fabs(f) < 1e-4) { - return talloc_strdup(NULL, "0"); - } else { - return talloc_asprintf(NULL, "%.7g", f); - } + return mp_format_double(NULL, f, 4, false, false, !(opt->flags & M_OPT_FIXED_LEN_PRINT)); } static void add_double(const m_option_t *opt, void *val, double add, bool wrap) @@ -1105,7 +1100,7 @@ const m_option_type_t m_option_type_double = { .size = sizeof(double), .parse = parse_double, .print = print_double, - .pretty_print = print_double_7g, + .pretty_print = pretty_print_double, .copy = copy_opt, .add = add_double, .multiply = multiply_double, @@ -1131,7 +1126,7 @@ const m_option_type_t m_option_type_aspect = { .flags = M_OPT_TYPE_CHOICE | M_OPT_TYPE_USES_RANGE, .parse = parse_double_aspect, .print = print_double, - .pretty_print = print_double_7g, + .pretty_print = pretty_print_double, .copy = copy_opt, .add = add_double, .multiply = multiply_double, @@ -1159,10 +1154,10 @@ static char *print_float(const m_option_t *opt, const void *val) return print_double(opt, &tmp); } -static char *print_float_f3(const m_option_t *opt, const void *val) +static char *pretty_print_float(const m_option_t *opt, const void *val) { double tmp = VAL(val); - return print_double_7g(opt, &tmp); + return pretty_print_double(opt, &tmp); } static void add_float(const m_option_t *opt, void *val, double add, bool wrap) @@ -1207,7 +1202,7 @@ const m_option_type_t m_option_type_float = { .size = sizeof(float), .parse = parse_float, .print = print_float, - .pretty_print = print_float_f3, + .pretty_print = pretty_print_float, .copy = copy_opt, .add = add_float, .multiply = multiply_float, @@ -1517,6 +1512,7 @@ static char *print_str_list(const m_option_t *opt, const void *src) { char **lst = NULL; char *ret = NULL; + const char sep = opt->priv ? *(char *)opt->priv : OPTION_LIST_SEPARATOR; if (!(src && VAL(src))) return talloc_strdup(NULL, ""); @@ -1524,7 +1520,7 @@ static char *print_str_list(const m_option_t *opt, const void *src) for (int i = 0; lst[i]; i++) { if (ret) - ret = talloc_strdup_append_buffer(ret, ","); + ret = talloc_strndup_append_buffer(ret, &sep, 1); ret = talloc_strdup_append_buffer(ret, lst[i]); } return ret; @@ -2826,8 +2822,7 @@ static char *print_rel_time(const m_option_t *opt, const void *val) case REL_TIME_ABSOLUTE: return talloc_asprintf(NULL, "%g", t->pos); case REL_TIME_RELATIVE: - return talloc_asprintf(NULL, "%s%g", - (t->pos >= 0) ? "+" : "-", fabs(t->pos)); + return talloc_asprintf(NULL, "%+g", t->pos); case REL_TIME_CHAPTER: return talloc_asprintf(NULL, "#%g", t->pos); case REL_TIME_PERCENT: @@ -3398,15 +3393,21 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, if (r == 0) { r = parse_obj_settings(log, name, op, ¶m, ol, dst ? &res : NULL); } - if (r < 0) + if (r < 0) { + free_obj_settings_list(&res); return r; + } if (param.len > 0) { const char sep[2] = {OPTION_LIST_SEPARATOR, 0}; - if (!bstr_eatstart0(¶m, sep)) + if (!bstr_eatstart0(¶m, sep)) { + free_obj_settings_list(&res); return M_OPT_INVALID; + } if (param.len == 0) { - if (!ol->allow_trailer) + if (!ol->allow_trailer) { + free_obj_settings_list(&res); return M_OPT_INVALID; + } if (dst) { m_obj_settings_t item = { .name = talloc_strdup(NULL, ""), @@ -3421,6 +3422,7 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, if (op == OP_APPEND) { mp_err(log, "Option %.*s: -append takes only 1 filter (no ',').\n", BSTR_P(name)); + free_obj_settings_list(&res); return M_OPT_INVALID; } mp_warn(log, "Passing more than 1 argument to %.*s is deprecated!\n", @@ -3784,7 +3786,7 @@ static void dup_node(void *ta_parent, struct mpv_node *node) static void copy_node(const m_option_t *opt, void *dst, const void *src) { - assert(sizeof(struct mpv_node) <= sizeof(union m_option_value)); + static_assert(sizeof(struct mpv_node) <= sizeof(union m_option_value), ""); if (!(dst && src)) return; diff --git a/options/m_option.h b/options/m_option.h index e62fa0f..530c0a3 100644 --- a/options/m_option.h +++ b/options/m_option.h @@ -189,15 +189,20 @@ struct m_opt_choice_alternatives { const char *m_opt_choice_str(const struct m_opt_choice_alternatives *choices, int value); -// Validator function signatures. Required to properly type the param value. typedef int (*m_opt_generic_validate_fn)(struct mp_log *log, const m_option_t *opt, struct bstr name, void *value); -typedef int (*m_opt_string_validate_fn)(struct mp_log *log, const m_option_t *opt, - struct bstr name, const char **value); -typedef int (*m_opt_int_validate_fn)(struct mp_log *log, const m_option_t *opt, - struct bstr name, const int *value); - +#define OPT_FUNC(name) name +#define OPT_FUNC_IN(name, suffix) name ## _ ## suffix +#define OPT_VALIDATE_FUNC(func, value_type, suffix) \ +int OPT_FUNC(func)(struct mp_log *log, const m_option_t *opt, \ + struct bstr name, value_type value); \ +static inline int OPT_FUNC_IN(func, suffix)(struct mp_log *log, const m_option_t *opt, \ + struct bstr name, void *value) { \ + return OPT_FUNC(func)(log, opt, name, value); \ +} \ +int OPT_FUNC(func)(struct mp_log *log, const m_option_t *opt, \ + struct bstr name, value_type value) // m_option.priv points to this if OPT_SUBSTRUCT is used struct m_sub_options { @@ -442,7 +447,8 @@ char *format_file_size(int64_t size); #define UPDATE_DVB_PROG (1 << 21) // some --dvbin-... #define UPDATE_SUB_HARD (1 << 22) // subtitle opts. that need full reinit #define UPDATE_SUB_EXTS (1 << 23) // update internal list of sub exts -#define UPDATE_OPT_LAST (1 << 23) +#define UPDATE_VIDEO (1 << 24) // force redraw if needed +#define UPDATE_OPT_LAST (1 << 24) // All bits between _FIRST and _LAST (inclusive) #define UPDATE_OPTS_MASK \ @@ -457,6 +463,9 @@ char *format_file_size(int64_t size); // type channels: disallow "auto" (still accept ""), limit list to at most 1 item. #define M_OPT_CHANNELS_LIMITED (1 << 27) +// type_float/type_double: controls if pretty print should trim trailing zeros +#define M_OPT_FIXED_LEN_PRINT (1 << 28) + // Like M_OPT_TYPE_OPTIONAL_PARAM. #define M_OPT_OPTIONAL_PARAM (1 << 30) @@ -530,12 +539,16 @@ static inline char *m_option_print(const m_option_t *opt, const void *val_ptr) } static inline char *m_option_pretty_print(const m_option_t *opt, - const void *val_ptr) + const void *val_ptr, + bool fixed_len) { + m_option_t o = *opt; + if (fixed_len) + o.flags |= M_OPT_FIXED_LEN_PRINT; if (opt->type->pretty_print) - return opt->type->pretty_print(opt, val_ptr); + return opt->type->pretty_print(&o, val_ptr); else - return m_option_print(opt, val_ptr); + return m_option_print(&o, val_ptr); } // Helper around \ref m_option_type::copy. @@ -684,15 +697,17 @@ extern const char m_option_path_separator; #define OPT_CHANNELS(field) \ OPT_TYPED_FIELD(m_option_type_channels, struct m_channels, field) +#define OPT_INT_VALIDATE_FUNC(func) OPT_VALIDATE_FUNC(func, const int *, int) + #define OPT_INT_VALIDATE(field, validate_fn) \ OPT_TYPED_FIELD(m_option_type_int, int, field), \ - .validate = (m_opt_generic_validate_fn) \ - MP_EXPECT_TYPE(m_opt_int_validate_fn, validate_fn) + .validate = OPT_FUNC_IN(validate_fn, int) + +#define OPT_STRING_VALIDATE_FUNC(func) OPT_VALIDATE_FUNC(func, const char **, str) #define OPT_STRING_VALIDATE(field, validate_fn) \ OPT_TYPED_FIELD(m_option_type_string, char*, field), \ - .validate = (m_opt_generic_validate_fn) \ - MP_EXPECT_TYPE(m_opt_string_validate_fn, validate_fn) + .validate = OPT_FUNC_IN(validate_fn, str) #define M_CHOICES(...) \ .priv = (void *)&(const struct m_opt_choice_alternatives[]){ __VA_ARGS__, {0}} diff --git a/options/m_property.c b/options/m_property.c index 1b76f05..eb3f78e 100644 --- a/options/m_property.c +++ b/options/m_property.c @@ -108,13 +108,14 @@ int m_property_do(struct mp_log *log, const struct m_property *prop_list, assert(opt.type); switch (action) { + case M_PROPERTY_FIXED_LEN_PRINT: case M_PROPERTY_PRINT: { - if ((r = do_action(prop_list, name, M_PROPERTY_PRINT, arg, ctx)) >= 0) + if ((r = do_action(prop_list, name, action, arg, ctx)) >= 0) return r; // Fallback to m_option if ((r = do_action(prop_list, name, M_PROPERTY_GET, &val, ctx)) <= 0) return r; - char *str = m_option_pretty_print(&opt, &val); + char *str = m_option_pretty_print(&opt, &val, action == M_PROPERTY_FIXED_LEN_PRINT); m_option_free(&opt, &val); *(char **)arg = str; return str != NULL; @@ -258,11 +259,13 @@ static int expand_property(const struct m_property *prop_list, char **ret, bool cond_no = !cond_yes && bstr_eatstart0(&prop, "!"); bool test = cond_yes || cond_no; bool raw = bstr_eatstart0(&prop, "="); + bool fixed_len = !raw && bstr_eatstart0(&prop, ">"); bstr comp_with = {0}; bool comp = test && bstr_split_tok(prop, "==", &prop, &comp_with); if (test && !comp) raw = true; int method = raw ? M_PROPERTY_GET_STRING : M_PROPERTY_PRINT; + method = fixed_len ? M_PROPERTY_FIXED_LEN_PRINT : method; char *s = NULL; int r = m_property_do_bstr(prop_list, prop, method, &s, ctx); diff --git a/options/m_property.h b/options/m_property.h index 0dce246..9fa01e0 100644 --- a/options/m_property.h +++ b/options/m_property.h @@ -48,6 +48,12 @@ enum mp_property_action { // arg: char** M_PROPERTY_PRINT, + // Get human readable fixed length string representing the current value. + // If unimplemented, the property wrapper uses the property type as + // fallback. + // arg: char** + M_PROPERTY_FIXED_LEN_PRINT, + // Like M_PROPERTY_GET_TYPE, but get a type that is compatible to the real // type, but reflect practical limits, such as runtime-available values. // This is mostly used for "UI" related things. diff --git a/options/options.c b/options/options.c index 7c6ffa5..8640ecb 100644 --- a/options/options.c +++ b/options/options.c @@ -42,6 +42,7 @@ #include "input/event.h" #include "stream/stream.h" #include "video/csputils.h" +#include "video/filter/refqueue.h" #include "video/hwdec.h" #include "video/image_writer.h" #include "sub/osd.h" @@ -75,6 +76,7 @@ extern const struct m_sub_options input_config; extern const struct m_sub_options encode_config; extern const struct m_sub_options ra_ctx_conf; extern const struct m_sub_options gl_video_conf; +extern const struct m_sub_options gl_next_conf; extern const struct m_sub_options ao_alsa_conf; extern const struct m_sub_options demux_conf; @@ -111,7 +113,9 @@ static const m_option_t mp_vo_opt_list[] = { {"vo", OPT_SETTINGSLIST(video_driver_list, &vo_obj_list)}, {"taskbar-progress", OPT_BOOL(taskbar_progress)}, {"drag-and-drop", OPT_CHOICE(drag_and_drop, {"no", -2}, {"auto", -1}, - {"replace", DND_REPLACE}, {"append", DND_APPEND})}, + {"replace", DND_REPLACE}, + {"append", DND_APPEND}, + {"insert-next", DND_INSERT_NEXT})}, {"snap-window", OPT_BOOL(snap_window)}, {"ontop", OPT_BOOL(ontop)}, {"ontop-level", OPT_CHOICE(ontop_level, {"window", -1}, {"system", -2}, @@ -127,7 +131,8 @@ static const m_option_t mp_vo_opt_list[] = { {"window-scale", OPT_DOUBLE(window_scale), M_RANGE(0.001, 100)}, {"window-minimized", OPT_BOOL(window_minimized)}, {"window-maximized", OPT_BOOL(window_maximized)}, - {"focus-on-open", OPT_BOOL(focus_on_open)}, + {"focus-on-open", OPT_REMOVED("Replaced by --focus-on")}, + {"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)}, @@ -236,7 +241,6 @@ const struct m_sub_options vo_sub_opts = { .auto_window_resize = true, .keepaspect = true, .keepaspect_window = true, - .hidpi_window_scale = true, .native_fs = true, .taskbar_progress = true, .border = true, @@ -251,7 +255,7 @@ const struct m_sub_options vo_sub_opts = { .ontop_level = -1, .timing_offset = 0.050, .swapchain_depth = 3, - .focus_on_open = true, + .focus_on = 1, }, }; @@ -262,6 +266,7 @@ const struct m_sub_options mp_sub_filter_opts = { .opts = (const struct m_option[]){ {"sub-filter-sdh", OPT_BOOL(sub_filter_SDH)}, {"sub-filter-sdh-harder", OPT_BOOL(sub_filter_SDH_harder)}, + {"sub-filter-sdh-enclosures", OPT_STRING(sub_filter_SDH_enclosures)}, {"sub-filter-regex-enable", OPT_BOOL(rf_enable)}, {"sub-filter-regex-plain", OPT_BOOL(rf_plain)}, {"sub-filter-regex", OPT_STRINGLIST(rf_items)}, @@ -271,6 +276,7 @@ const struct m_sub_options mp_sub_filter_opts = { }, .size = sizeof(OPT_BASE_STRUCT), .defaults = &(OPT_BASE_STRUCT){ + .sub_filter_SDH_enclosures = "([\uFF08", .rf_enable = true, }, .change_flags = UPDATE_SUB_FILT, @@ -281,18 +287,14 @@ const struct m_sub_options mp_sub_filter_opts = { const struct m_sub_options mp_subtitle_sub_opts = { .opts = (const struct m_option[]){ - {"sub-delay", OPT_FLOAT(sub_delay)}, {"sub-fps", OPT_FLOAT(sub_fps)}, {"sub-speed", OPT_FLOAT(sub_speed)}, - {"sub-visibility", OPT_BOOL(sub_visibility)}, - {"secondary-sub-visibility", OPT_BOOL(sec_sub_visibility)}, {"sub-forced-events-only", OPT_BOOL(sub_forced_events_only)}, {"stretch-dvd-subs", OPT_BOOL(stretch_dvd_subs)}, {"stretch-image-subs-to-screen", OPT_BOOL(stretch_image_subs)}, {"image-subs-video-resolution", OPT_BOOL(image_subs_video_res)}, {"sub-fix-timing", OPT_BOOL(sub_fix_timing)}, {"sub-stretch-durations", OPT_BOOL(sub_stretch_durations)}, - {"sub-pos", OPT_FLOAT(sub_pos), M_RANGE(0.0, 150.0)}, {"sub-gauss", OPT_FLOAT(sub_gauss), M_RANGE(0.0, 3.0)}, {"sub-gray", OPT_BOOL(sub_gray)}, {"sub-ass", OPT_BOOL(ass_enabled), .flags = UPDATE_SUB_HARD}, @@ -315,35 +317,29 @@ const struct m_sub_options mp_subtitle_sub_opts = { {"sub-ass-shaper", OPT_CHOICE(ass_shaper, {"simple", 0}, {"complex", 1})}, {"sub-ass-justify", OPT_BOOL(ass_justify)}, - {"sub-ass-override", OPT_CHOICE(ass_style_override, - {"no", 0}, {"yes", 1}, {"force", 3}, {"scale", 4}, {"strip", 5}), - .flags = UPDATE_SUB_HARD}, {"sub-scale-by-window", OPT_BOOL(sub_scale_by_window)}, {"sub-scale-with-window", OPT_BOOL(sub_scale_with_window)}, {"sub-ass-scale-with-window", OPT_BOOL(ass_scale_with_window)}, {"sub", OPT_SUBSTRUCT(sub_style, sub_style_conf)}, {"sub-clear-on-seek", OPT_BOOL(sub_clear_on_seek)}, - {"teletext-page", OPT_INT(teletext_page), M_RANGE(1, 999)}, + {"teletext-page", OPT_INT(teletext_page), M_RANGE(-1, 999)}, {"sub-past-video-end", OPT_BOOL(sub_past_video_end)}, {"sub-ass-force-style", OPT_REPLACED("sub-ass-style-overrides")}, + {"sub-lavc-o", OPT_KEYVALUELIST(sub_avopts)}, {0} }, .size = sizeof(OPT_BASE_STRUCT), .defaults = &(OPT_BASE_STRUCT){ - .sub_visibility = true, - .sec_sub_visibility = true, - .sub_pos = 100, .sub_speed = 1.0, .ass_enabled = true, .sub_scale_by_window = true, .sub_use_margins = true, .sub_scale_with_window = true, - .teletext_page = 100, + .teletext_page = 0, .sub_scale = 1, .ass_vsfilter_aspect_compat = true, .ass_vsfilter_color_compat = 1, .ass_vsfilter_blur_compat = true, - .ass_style_override = 1, .ass_shaper = 1, .use_embedded_fonts = true, }, @@ -351,6 +347,36 @@ const struct m_sub_options mp_subtitle_sub_opts = { }; #undef OPT_BASE_STRUCT +#define OPT_BASE_STRUCT struct mp_subtitle_shared_opts + +const struct m_sub_options mp_subtitle_shared_sub_opts = { + .opts = (const struct m_option[]){ + {"sub-delay", OPT_FLOAT(sub_delay[0])}, + {"secondary-sub-delay", OPT_FLOAT(sub_delay[1])}, + {"sub-pos", OPT_FLOAT(sub_pos[0]), M_RANGE(0.0, 150.0)}, + {"secondary-sub-pos", OPT_FLOAT(sub_pos[1]), M_RANGE(0.0, 150.0)}, + {"sub-visibility", OPT_BOOL(sub_visibility[0])}, + {"secondary-sub-visibility", OPT_BOOL(sub_visibility[1])}, + {"sub-ass-override", OPT_CHOICE(ass_style_override[0], + {"no", 0}, {"yes", 1}, {"force", 3}, {"scale", 4}, {"strip", 5}), + .flags = UPDATE_SUB_HARD}, + {"secondary-sub-ass-override", OPT_CHOICE(ass_style_override[1], + {"no", 0}, {"yes", 1}, {"force", 3}, {"scale", 4}, {"strip", 5}), + .flags = UPDATE_SUB_HARD}, + {0} + }, + .size = sizeof(OPT_BASE_STRUCT), + .defaults = &(OPT_BASE_STRUCT){ + .sub_visibility[0] = true, + .sub_visibility[1] = true, + .sub_pos[0] = 100, + .ass_style_override[0] = 1, + .ass_style_override[1] = 5, + }, + .change_flags = UPDATE_OSD, +}; + +#undef OPT_BASE_STRUCT #define OPT_BASE_STRUCT struct mp_osd_render_opts const struct m_sub_options mp_osd_render_sub_opts = { @@ -359,6 +385,7 @@ const struct m_sub_options mp_osd_render_sub_opts = { {"osd-bar-align-y", OPT_FLOAT(osd_bar_align_y), M_RANGE(-1.0, +1.0)}, {"osd-bar-w", OPT_FLOAT(osd_bar_w), M_RANGE(1, 100)}, {"osd-bar-h", OPT_FLOAT(osd_bar_h), M_RANGE(0.1, 50)}, + {"osd-bar-border-size", OPT_FLOAT(osd_bar_border_size), M_RANGE(0, 1000.0)}, {"osd", OPT_SUBSTRUCT(osd_style, osd_style_conf)}, {"osd-scale", OPT_FLOAT(osd_scale), M_RANGE(0, 100)}, {"osd-scale-by-window", OPT_BOOL(osd_scale_by_window)}, @@ -370,6 +397,7 @@ const struct m_sub_options mp_osd_render_sub_opts = { .osd_bar_align_y = 0.5, .osd_bar_w = 75.0, .osd_bar_h = 3.125, + .osd_bar_border_size = 0.5, .osd_scale = 1, .osd_scale_by_window = true, }, @@ -412,10 +440,18 @@ const struct m_sub_options dvd_conf = { const struct m_sub_options filter_conf = { .opts = (const struct m_option[]){ - {"deinterlace", OPT_BOOL(deinterlace)}, + {"deinterlace", OPT_CHOICE(deinterlace, + {"no", 0}, {"yes", 1}, {"auto", -1})}, + {"deinterlace-field-parity", OPT_CHOICE(field_parity, + {"tff", MP_FIELD_PARITY_TFF}, + {"bff", MP_FIELD_PARITY_BFF}, + {"auto", MP_FIELD_PARITY_AUTO})}, {0} }, .size = sizeof(OPT_BASE_STRUCT), + .defaults = &(const struct filter_opts){ + .field_parity = MP_FIELD_PARITY_AUTO, + }, .change_flags = UPDATE_IMGPAR, }; @@ -562,7 +598,8 @@ static const m_option_t mp_opts[] = { {"slang", OPT_STRINGLIST(stream_lang[STREAM_SUB])}, {"vlang", OPT_STRINGLIST(stream_lang[STREAM_VIDEO])}, {"track-auto-selection", OPT_BOOL(stream_auto_sel)}, - {"subs-with-matching-audio", OPT_BOOL(subs_with_matching_audio)}, + {"subs-with-matching-audio", OPT_CHOICE(subs_with_matching_audio, {"no", 0}, + {"forced", 1}, {"yes", 2})}, {"subs-match-os-language", OPT_BOOL(subs_match_os_language)}, {"subs-fallback", OPT_CHOICE(subs_fallback, {"no", 0}, {"default", 1}, {"yes", 2})}, {"subs-fallback-forced", OPT_CHOICE(subs_fallback_forced, {"no", 0}, @@ -662,6 +699,7 @@ static const m_option_t mp_opts[] = { {"cover-art-whitelist", OPT_BOOL(coverart_whitelist)}, {"", OPT_SUBSTRUCT(subs_rend, mp_subtitle_sub_opts)}, + {"", OPT_SUBSTRUCT(subs_shared, mp_subtitle_shared_sub_opts)}, {"", OPT_SUBSTRUCT(subs_filt, mp_sub_filter_opts)}, {"", OPT_SUBSTRUCT(osd_rend, mp_osd_render_sub_opts)}, @@ -680,6 +718,10 @@ static const m_option_t mp_opts[] = { // values <0 for volume and mute are legacy and ignored {"volume", OPT_FLOAT(softvol_volume), .flags = UPDATE_VOL, M_RANGE(-1, 1000)}, + {"volume-gain-max", OPT_FLOAT(softvol_gain_max), M_RANGE(0, 150)}, + {"volume-gain-min", OPT_FLOAT(softvol_gain_min), M_RANGE(-150, 0)}, + {"volume-gain", OPT_FLOAT(softvol_gain), .flags = UPDATE_VOL, + M_RANGE(-150, 150)}, {"mute", OPT_CHOICE(softvol_mute, {"no", 0}, {"auto", 0}, @@ -794,7 +836,6 @@ static const m_option_t mp_opts[] = { {"term-osd-bar", OPT_BOOL(term_osd_bar), .flags = UPDATE_OSD}, {"term-osd-bar-chars", OPT_STRING(term_osd_bar_chars), .flags = UPDATE_OSD}, - {"term-remaining-playtime", OPT_BOOL(term_remaining_playtime), .flags = UPDATE_OSD}, {"term-title", OPT_STRING(term_title), .flags = UPDATE_OSD}, {"term-playing-msg", OPT_STRING(playing_msg)}, @@ -812,6 +853,7 @@ static const m_option_t mp_opts[] = { {"idle", OPT_CHOICE(player_idle_mode, {"no", 0}, {"once", 1}, {"yes", 2})}, + {"input-commands", OPT_STRINGLIST(input_commands)}, {"input-terminal", OPT_BOOL(consolecontrols), .flags = UPDATE_TERM}, {"input-ipc-server", OPT_STRING(ipc_path), .flags = M_OPT_FILE}, @@ -837,6 +879,7 @@ static const m_option_t mp_opts[] = { {"", OPT_SUBSTRUCT(ra_ctx_opts, ra_ctx_conf)}, {"", OPT_SUBSTRUCT(gl_video_opts, gl_video_conf)}, + {"", OPT_SUBSTRUCT(gl_next_opts, gl_next_conf)}, {"", OPT_SUBSTRUCT(spirv_opts, spirv_conf)}, #if HAVE_GL @@ -903,6 +946,9 @@ static const struct MPOpts mp_default_opts = { .msg_color = true, .softvol_max = 130, .softvol_volume = 100, + .softvol_gain_max = 12, + .softvol_gain_min = -96, + .softvol_gain = 0, .gapless_audio = -1, .wintitle = "${?media-title:${media-title}}${!media-title:No file} - mpv", .stop_screensaver = 1, @@ -946,7 +992,6 @@ static const struct MPOpts mp_default_opts = { .frame_dropping = 1, .term_osd = 2, .term_osd_bar_chars = "[-+-]", - .term_remaining_playtime = true, .consolecontrols = true, .playlist_pos = -1, .play_frames = -1, @@ -960,7 +1005,7 @@ static const struct MPOpts mp_default_opts = { [STREAM_VIDEO] = -2, [STREAM_SUB] = -2, }, }, .stream_auto_sel = true, - .subs_with_matching_audio = true, + .subs_with_matching_audio = 2, .subs_match_os_language = true, .subs_fallback = 1, .subs_fallback_forced = 1, @@ -1063,12 +1108,14 @@ static const struct MPOpts mp_default_opts = { "sub-delay", "sub-speed", "sub-pos", + "secondary-sub-pos", "sub-visibility", "sub-scale", "sub-use-margins", "sub-ass-force-margins", "sub-ass-vsfilter-aspect-compat", "sub-ass-override", + "secondary-sub-ass-override", "secondary-sub-visibility", "ab-loop-a", "ab-loop-b", diff --git a/options/options.h b/options/options.h index aa071b2..69a50b3 100644 --- a/options/options.h +++ b/options/options.h @@ -20,7 +20,7 @@ typedef struct mp_vo_opts { bool all_workspaces; bool window_minimized; bool window_maximized; - bool focus_on_open; + int focus_on; int screen_id; char *screen_name; @@ -82,10 +82,6 @@ typedef struct mp_vo_opts { // Subtitle options needed by the subtitle decoders/renderers. struct mp_subtitle_opts { - bool sub_visibility; - bool sec_sub_visibility; - float sub_pos; - float sub_delay; float sub_fps; float sub_speed; bool sub_forced_events_only; @@ -111,18 +107,27 @@ struct mp_subtitle_opts { bool use_embedded_fonts; char **ass_style_override_list; char *ass_styles_file; - int ass_style_override; int ass_hinting; int ass_shaper; bool ass_justify; bool sub_clear_on_seek; int teletext_page; bool sub_past_video_end; + char **sub_avopts; +}; + +// Options for both primary and secondary subs. +struct mp_subtitle_shared_opts { + float sub_delay[2]; + float sub_pos[2]; + bool sub_visibility[2]; + int ass_style_override[2]; }; struct mp_sub_filter_opts { bool sub_filter_SDH; bool sub_filter_SDH_harder; + char *sub_filter_SDH_enclosures; bool rf_enable; bool rf_plain; char **rf_items; @@ -135,6 +140,7 @@ struct mp_osd_render_opts { float osd_bar_align_y; float osd_bar_w; float osd_bar_h; + float osd_bar_border_size; float osd_scale; bool osd_scale_by_window; struct osd_style_opts *osd_style; @@ -181,6 +187,9 @@ typedef struct MPOpts { float rgain_fallback; int softvol_mute; float softvol_max; + float softvol_gain; + float softvol_gain_min; + float softvol_gain_max; int gapless_audio; mp_vo_opts *vo; @@ -196,6 +205,7 @@ typedef struct MPOpts { bool cursor_autohide_fs; struct mp_subtitle_opts *subs_rend; + struct mp_subtitle_shared_opts *subs_shared; struct mp_sub_filter_opts *subs_filt; struct mp_osd_render_opts *osd_rend; @@ -238,7 +248,6 @@ typedef struct MPOpts { int term_osd; bool term_osd_bar; char *term_osd_bar_chars; - bool term_remaining_playtime; char *term_title; char *playing_msg; char *osd_playing_msg; @@ -247,6 +256,7 @@ typedef struct MPOpts { char *osd_status_msg; char *osd_msg[3]; int player_idle_mode; + char **input_commands; bool consolecontrols; int playlist_pos; struct m_rel_time play_start; @@ -273,7 +283,7 @@ typedef struct MPOpts { int stream_id[2][STREAM_TYPE_COUNT]; char **stream_lang[STREAM_TYPE_COUNT]; bool stream_auto_sel; - bool subs_with_matching_audio; + int subs_with_matching_audio; bool subs_match_os_language; int subs_fallback; int subs_fallback_forced; @@ -357,6 +367,7 @@ typedef struct MPOpts { struct ra_ctx_opts *ra_ctx_opts; struct gl_video_opts *gl_video_opts; + struct gl_next_opts *gl_next_opts; struct angle_opts *angle_opts; struct opengl_opts *opengl_opts; struct vulkan_opts *vulkan_opts; @@ -388,13 +399,15 @@ struct dvd_opts { }; struct filter_opts { - bool deinterlace; + int deinterlace; + int field_parity; }; extern const struct m_sub_options vo_sub_opts; extern const struct m_sub_options cuda_conf; extern const struct m_sub_options dvd_conf; extern const struct m_sub_options mp_subtitle_sub_opts; +extern const struct m_sub_options mp_subtitle_shared_sub_opts; extern const struct m_sub_options mp_sub_filter_opts; extern const struct m_sub_options mp_osd_render_sub_opts; extern const struct m_sub_options filter_conf; diff --git a/options/parse_commandline.c b/options/parse_commandline.c index 93120d3..ded8531 100644 --- a/options/parse_commandline.c +++ b/options/parse_commandline.c @@ -103,10 +103,10 @@ static void process_non_option(struct playlist *files, const char *arg) // Glob filenames on Windows (cmd.exe doesn't do this automatically) if (glob(arg, 0, NULL, &gg)) { - playlist_add_file(files, arg); + playlist_append_file(files, arg); } else { for (int i = 0; i < gg.gl_pathc; i++) - playlist_add_file(files, gg.gl_pathv[i]); + playlist_append_file(files, gg.gl_pathv[i]); globfree(&gg); } @@ -114,7 +114,7 @@ static void process_non_option(struct playlist *files, const char *arg) #else static void process_non_option(struct playlist *files, const char *arg) { - playlist_add_file(files, arg); + playlist_append_file(files, arg); } #endif @@ -201,7 +201,6 @@ int m_config_parse_mp_command_line(m_config_t *config, struct playlist *files, goto err_out; } playlist_transfer_entries(files, pl); - playlist_populate_playlist_path(files, param0); talloc_free(param0); talloc_free(pl); continue; diff --git a/options/path.c b/options/path.c index 52dc113..7c7d31c 100644 --- a/options/path.c +++ b/options/path.c @@ -29,6 +29,7 @@ #include "config.h" +#include "misc/path_utils.h" #include "common/common.h" #include "common/global.h" #include "common/msg.h" @@ -42,7 +43,7 @@ // In order of decreasing priority: the first has highest priority. static const mp_get_platform_path_cb path_resolvers[] = { #if HAVE_COCOA - mp_get_platform_path_osx, + mp_get_platform_path_mac, #endif #if HAVE_DARWIN mp_get_platform_path_darwin, @@ -75,10 +76,14 @@ static const char *mp_get_platform_path(void *talloc_ctx, assert(talloc_ctx); if (global->configdir) { + // Return NULL for all platform paths if --no-config is passed + if (!global->configdir[0]) + return NULL; + // force all others to NULL, only first returns the path for (int n = 0; n < MP_ARRAY_SIZE(config_dirs); n++) { if (strcmp(config_dirs[n], type) == 0) - return (n == 0 && global->configdir[0]) ? global->configdir : NULL; + return (n == 0) ? global->configdir : NULL; } } @@ -217,190 +222,6 @@ char *mp_get_user_path(void *talloc_ctx, struct mpv_global *global, return res; } -char *mp_basename(const char *path) -{ - char *s; - -#if HAVE_DOS_PATHS - if (!mp_is_url(bstr0(path))) { - s = strrchr(path, '\\'); - if (s) - path = s + 1; - s = strrchr(path, ':'); - if (s) - path = s + 1; - } -#endif - s = strrchr(path, '/'); - return s ? s + 1 : (char *)path; -} - -struct bstr mp_dirname(const char *path) -{ - struct bstr ret = { - (uint8_t *)path, mp_basename(path) - path - }; - if (ret.len == 0) - return bstr0("."); - return ret; -} - - -#if HAVE_DOS_PATHS -static const char mp_path_separators[] = "\\/"; -#else -static const char mp_path_separators[] = "/"; -#endif - -// Mutates path and removes a trailing '/' (or '\' on Windows) -void mp_path_strip_trailing_separator(char *path) -{ - size_t len = strlen(path); - if (len > 0 && strchr(mp_path_separators, path[len - 1])) - path[len - 1] = '\0'; -} - -char *mp_splitext(const char *path, bstr *root) -{ - assert(path); - int skip = (*path == '.'); // skip leading dot for "hidden" unix files - const char *split = strrchr(path + skip, '.'); - if (!split || !split[1] || strchr(split, '/')) - return NULL; - if (root) - *root = (bstr){(char *)path, split - path}; - return (char *)split + 1; -} - -bool mp_path_is_absolute(struct bstr path) -{ - if (path.len && strchr(mp_path_separators, path.start[0])) - return true; - -#if HAVE_DOS_PATHS - // Note: "X:filename" is a path relative to the current working directory - // of drive X, and thus is not an absolute path. It needs to be - // followed by \ or /. - if (path.len >= 3 && path.start[1] == ':' && - strchr(mp_path_separators, path.start[2])) - return true; -#endif - - return false; -} - -char *mp_path_join_bstr(void *talloc_ctx, struct bstr p1, struct bstr p2) -{ - if (p1.len == 0) - return bstrdup0(talloc_ctx, p2); - if (p2.len == 0) - return bstrdup0(talloc_ctx, p1); - - if (mp_path_is_absolute(p2)) - return bstrdup0(talloc_ctx, p2); - - bool have_separator = strchr(mp_path_separators, p1.start[p1.len - 1]); -#if HAVE_DOS_PATHS - // "X:" only => path relative to "X:" current working directory. - if (p1.len == 2 && p1.start[1] == ':') - have_separator = true; -#endif - - return talloc_asprintf(talloc_ctx, "%.*s%s%.*s", BSTR_P(p1), - have_separator ? "" : "/", BSTR_P(p2)); -} - -char *mp_path_join(void *talloc_ctx, const char *p1, const char *p2) -{ - return mp_path_join_bstr(talloc_ctx, bstr0(p1), bstr0(p2)); -} - -char *mp_getcwd(void *talloc_ctx) -{ - char *e_wd = getenv("PWD"); - if (e_wd) - return talloc_strdup(talloc_ctx, e_wd); - - char *wd = talloc_array(talloc_ctx, char, 20); - while (getcwd(wd, talloc_get_size(wd)) == NULL) { - if (errno != ERANGE) { - talloc_free(wd); - return NULL; - } - wd = talloc_realloc(talloc_ctx, wd, char, talloc_get_size(wd) * 2); - } - return wd; -} - -char *mp_normalize_path(void *talloc_ctx, const char *path) -{ - if (mp_is_url(bstr0(path))) - return talloc_strdup(talloc_ctx, path); - - return mp_path_join(talloc_ctx, mp_getcwd(talloc_ctx), path); -} - -bool mp_path_exists(const char *path) -{ - struct stat st; - return path && stat(path, &st) == 0; -} - -bool mp_path_isdir(const char *path) -{ - struct stat st; - return stat(path, &st) == 0 && S_ISDIR(st.st_mode); -} - -// Return false if it's considered a normal local filesystem path. -bool mp_is_url(bstr path) -{ - int proto = bstr_find0(path, "://"); - if (proto < 1) - return false; - // Per RFC3986, the first character of the protocol must be alphabetic. - // The rest must be alphanumeric plus -, + and . - for (int i = 0; i < proto; i++) { - unsigned char c = path.start[i]; - if ((i == 0 && !mp_isalpha(c)) || - (!mp_isalnum(c) && c != '.' && c != '-' && c != '+')) - { - return false; - } - } - return true; -} - -// Return the protocol part of path, e.g. "http" if path is "http://...". -// On success, out_url (if not NULL) is set to the part after the "://". -bstr mp_split_proto(bstr path, bstr *out_url) -{ - if (!mp_is_url(path)) - return (bstr){0}; - bstr r; - bstr_split_tok(path, "://", &r, out_url ? out_url : &(bstr){0}); - return r; -} - -void mp_mkdirp(const char *dir) -{ - char *path = talloc_strdup(NULL, dir); - char *cdir = path + 1; - - while (cdir) { - cdir = strchr(cdir, '/'); - if (cdir) - *cdir = 0; - - mkdir(path, 0700); - - if (cdir) - *cdir++ = '/'; - } - - talloc_free(path); -} - void mp_mk_user_dir(struct mpv_global *global, const char *type, char *subdir) { char *dir = mp_find_user_file(NULL, global, type, subdir); diff --git a/options/path.h b/options/path.h index 7ec8f7b..a665e67 100644 --- a/options/path.h +++ b/options/path.h @@ -22,6 +22,7 @@ #include <stdbool.h> #include "misc/bstr.h" +#include "misc/path_utils.h" struct mpv_global; struct MPOpts; @@ -30,7 +31,7 @@ void mp_init_paths(struct mpv_global *global, struct MPOpts *opts); // Search for the input filename in several paths. These include user and global // config locations by default. Some platforms may implement additional platform -// related lookups (i.e.: OSX inside an application bundle). +// related lookups (i.e.: macOS inside an application bundle). char *mp_find_config_file(void *talloc_ctx, struct mpv_global *global, const char *filename); @@ -53,46 +54,6 @@ char **mp_find_all_config_files(void *talloc_ctx, struct mpv_global *global, char *mp_get_user_path(void *talloc_ctx, struct mpv_global *global, const char *path); -// Return pointer to filename part of path - -char *mp_basename(const char *path); - -/* Return file extension, excluding the '.'. If root is not NULL, set it to the - * part of the path without extension. So: path == root + "." + extension - * Don't consider it a file extension if the only '.' is the first character. - * Return NULL if no extension and don't set *root in this case. - */ -char *mp_splitext(const char *path, bstr *root); - -/* Return struct bstr referencing directory part of path, or if that - * would be empty, ".". - */ -struct bstr mp_dirname(const char *path); - -void mp_path_strip_trailing_separator(char *path); - -/* Join two path components and return a newly allocated string - * for the result. '/' is inserted between the components if needed. - * If p2 is an absolute path then the value of p1 is ignored. - */ -char *mp_path_join(void *talloc_ctx, const char *p1, const char *p2); -char *mp_path_join_bstr(void *talloc_ctx, struct bstr p1, struct bstr p2); - -// Return whether the path is absolute. -bool mp_path_is_absolute(struct bstr path); - -char *mp_getcwd(void *talloc_ctx); - -char *mp_normalize_path(void *talloc_ctx, const char *path); - -bool mp_path_exists(const char *path); -bool mp_path_isdir(const char *path); - -bool mp_is_url(bstr path); - -bstr mp_split_proto(bstr path, bstr *out_url); - -void mp_mkdirp(const char *dir); void mp_mk_user_dir(struct mpv_global *global, const char *type, char *subdir); #endif /* MPLAYER_PATH_H */ |