From 7885fce7ea68d4c64e034b152f2a0b08bb648adc Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 23 Jan 2013 10:56:36 +0100 Subject: video: add --autofit and --autofit-larger options --autofit=WxH sets the window size to a maximum width and/or height, without changing the window's aspect ratio. --autofit-larger=WxH does the same, but only if the video size is actually larger than the window size that would result when using the --autofit=WxH option with the same arguments. --- DOCS/man/en/options.rst | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ core/cfg-mplayer.h | 2 ++ core/m_option.c | 27 +++++++++++++++++++++++++++ core/m_option.h | 3 +++ core/options.h | 2 ++ etc/example.conf | 3 +++ video/out/vo.c | 35 +++++++++++++++++++++++++++++++++-- 7 files changed, 118 insertions(+), 2 deletions(-) diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst index fb3a96307d..a0995db964 100644 --- a/DOCS/man/en/options.rst +++ b/DOCS/man/en/options.rst @@ -203,6 +203,51 @@ Enables caching for the stream used by ``--audiofile``, using the specified amount of memory. +--autofit=<[W[xH]]> + Set the initial window size to a maximum size specified by WxH, without + changing the window's aspect ratio. The size is measured in pixels, or if + a number is followed by a percentage sign (``%``), in percents of the + screen size. + + This option never changes the aspect ratio of the window. If the aspect + ratio mismatches, the window's size is reduced until it fits into the + specified size. + + Window position is not taken into account, nor is it modified by this + option (the window manager still may place the window differently depending + on size). Use ``--geometry`` to change the window position. Its effects + are applied after this option. + + See ``--geometry`` for details how this is handled with multi-monitor + setups, or if the ``--wid`` option is used. + + Use ``--autofit-larger`` instead if you don't want the window to get larger. + Use ``--geometry`` if you want to force both window width and height to a + specific size. + + *NOTE*: Generally only supported by GUI VOs. Ignored for encoding. + + *EXAMPLE*: + + ``70%`` + Make the window width 70% of the screen size, keeping aspect ratio. + ``1000`` + Set the window width to 1000 pixels, keeping aspect ratio. + ``70%:60%`` + Make the window as large as possible, without being wider than 70% of + the screen width, or higher than 60% of the screen height. + +--autofit-larger=<[W[xH]]> + This option behaves exactly like ``--autofit``, except the window size is + only changed if the window would be larger than the specified size. + + *EXAMPLE*: + + ``90%x80%`` + If the video is larger than 90% of the screen width or 80% of the + screen height, make the window smaller until either its width is 90% + of the screen, or its height is 80% of the screen. + --autosub, --no-autosub Load additional subtitle files matching the video filename. Enabled by default. See also ``--autosub-match``. @@ -718,6 +763,9 @@ Sets the window to half the screen widths, and positions it 10 pixels below/left of the top left corner of the screen. + See also ``--autofit`` and ``--autofit-larger`` for fitting the window into + a given size without changing aspect ratio. + --grabpointer, --no-grabpointer ``--no-grabpointer`` tells the player to not grab the mouse pointer after a video mode change (``--vm``). Useful for multihead setups. diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h index 5264784a56..54fa3f3ab5 100644 --- a/core/cfg-mplayer.h +++ b/core/cfg-mplayer.h @@ -586,6 +586,8 @@ const m_option_t mplayer_opts[]={ OPT_INTRANGE("screenw", vo_screenwidth, CONF_GLOBAL, 0, 4096), OPT_INTRANGE("screenh", vo_screenheight, CONF_GLOBAL, 0, 4096), OPT_GEOMETRY("geometry", vo_geometry, 0), + OPT_SIZE_BOX("autofit", vo_autofit, 0), + OPT_SIZE_BOX("autofit-larger", vo_autofit_larger, 0), OPT_MAKE_FLAGS("force-window-position", force_window_position, 0), // vo name (X classname) and window title strings OPT_STRING("name", vo_winname, 0), diff --git a/core/m_option.c b/core/m_option.c index a55e87a5d3..c1d2ee4fbe 100644 --- a/core/m_option.c +++ b/core/m_option.c @@ -1309,7 +1309,34 @@ const m_option_type_t m_option_type_geometry = { .parse = parse_geometry, }; +static int parse_size_box(const m_option_t *opt, struct bstr name, + struct bstr param, void *dst) +{ + struct m_geometry gm; + if (!parse_geometry_str(&gm, param)) + goto error; + + if (gm.xy_valid) + goto error; + + if (dst) + *((struct m_geometry *)dst) = gm; + return 1; + +error: + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: invalid size: '%.*s'\n", + BSTR_P(name), BSTR_P(param)); + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Valid format: W[%%][xH[%%]] or empty string\n"); + return M_OPT_INVALID; +} + +const m_option_type_t m_option_type_size_box = { + .name = "Window size", + .size = sizeof(struct m_geometry), + .parse = parse_size_box, +}; #include "video/img_format.h" diff --git a/core/m_option.h b/core/m_option.h index 87fa959992..81ab73e98b 100644 --- a/core/m_option.h +++ b/core/m_option.h @@ -57,6 +57,7 @@ extern const m_option_type_t m_option_type_fourcc; extern const m_option_type_t m_option_type_afmt; extern const m_option_type_t m_option_type_color; extern const m_option_type_t m_option_type_geometry; +extern const m_option_type_t m_option_type_size_box; // Callback used by m_option_type_print_func options. typedef int (*m_opt_func_full_t)(const m_option_t *, const char *, const char *); @@ -219,6 +220,7 @@ union m_option_value { struct m_rel_time rel_time; struct m_color color; struct m_geometry geometry; + struct m_geometry size_box; }; //////////////////////////////////////////////////////////////////////////// @@ -534,6 +536,7 @@ static inline void m_option_free(const m_option_t *opt, void *dst) #define OPT_REL_TIME(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_rel_time) #define OPT_COLOR(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_color) #define OPT_GEOMETRY(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_geometry) +#define OPT_SIZE_BOX(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_size_box) #define OPT_TRACKCHOICE(name, var) OPT_CHOICE_OR_INT(name, var, 0, 0, 8190, ({"no", -2}, {"auto", -1})) diff --git a/core/options.h b/core/options.h index 10932a4edf..3cd0132847 100644 --- a/core/options.h +++ b/core/options.h @@ -21,6 +21,8 @@ typedef struct MPOpts { int vo_screenwidth; int vo_screenheight; struct m_geometry vo_geometry; + struct m_geometry vo_autofit; + struct m_geometry vo_autofit_larger; int force_window_position; char *vo_winname; char *vo_wintitle; diff --git a/etc/example.conf b/etc/example.conf index bb37a5e26d..e610b81b4f 100644 --- a/etc/example.conf +++ b/etc/example.conf @@ -28,6 +28,9 @@ # force starting with centered window #geometry=50%:50% +# don't allow a new window to have a size larger than 90% of the screen size +#autofit-larger=90%x90% + # Keep the player window on top of all other windows. #ontop=yes diff --git a/video/out/vo.c b/video/out/vo.c index 29307b7218..484aa20a56 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -355,6 +355,32 @@ struct vo *init_best_video_out(struct MPOpts *opts, return NULL; } +// Fit *w/*h into the size specified by geo. +static void apply_autofit(int *w, int *h, int scr_w, int scr_h, + struct m_geometry *geo, bool allow_upscale) +{ + if (!geo->wh_valid) + return; + + int dummy; + int n_w = *w, n_h = *h; + m_geometry_apply(&dummy, &dummy, &n_w, &n_h, scr_w, scr_h, geo); + + if (!allow_upscale && *w <= n_w && *h <= n_h) + return; + + // If aspect mismatches, always make the window smaller than the fit box + double asp = (double)*w / *h; + double n_asp = (double)n_w / n_h; + if (n_asp <= asp) { + *w = n_w; + *h = n_w / asp; + } else { + *w = n_h * asp; + *h = n_h; + } +} + // Set window size (vo->dwidth/dheight) and position (vo->dx/dy) according to // the video display size d_w/d_h. // NOTE: currently, all GUI backends do their own handling of window geometry @@ -365,6 +391,9 @@ static void determine_window_geometry(struct vo *vo, int d_w, int d_h) { struct MPOpts *opts = vo->opts; + int scr_w = opts->vo_screenwidth; + int scr_h = opts->vo_screenheight; + int vid_w = vo->aspdat.orgw; int vid_h = vo->aspdat.orgh; @@ -400,10 +429,12 @@ static void determine_window_geometry(struct vo *vo, int d_w, int d_h) } } + apply_autofit(&d_w, &d_h, scr_w, scr_h, &opts->vo_autofit, true); + apply_autofit(&d_w, &d_h, scr_w, scr_h, &opts->vo_autofit_larger, false); + vo->dx = (int)(opts->vo_screenwidth - d_w) / 2; vo->dy = (int)(opts->vo_screenheight - d_h) / 2; - m_geometry_apply(&vo->dx, &vo->dy, &d_w, &d_h, - opts->vo_screenwidth, opts->vo_screenheight, + m_geometry_apply(&vo->dx, &vo->dy, &d_w, &d_h, scr_w, scr_h, &opts->vo_geometry); vo->dx += xinerama_x; -- cgit v1.2.3