From 4c56baba4048f8a881253d4fe2f49c2715c77376 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 23 Jan 2013 10:56:11 +0100 Subject: [PATCH] options: move -geometry parsing to m_option.c This also means the option is verified on program start, not when the VO is created. The actual code becomes a bit more complex, because the screen width/height is not available at program start. The actual parsing code is still the same, with its unusual sscanf() usage. --- Makefile | 1 - core/cfg-mplayer.h | 4 +- core/m_option.c | 128 ++++++++++++++++++++++++++++++++++++++ core/m_option.h | 12 ++++ core/options.h | 1 + video/out/aspect.c | 3 +- video/out/geometry.c | 112 --------------------------------- video/out/geometry.h | 29 --------- video/out/vo.c | 7 +-- video/out/vo_opengl.c | 1 - video/out/vo_opengl_old.c | 1 - video/out/vo_sdl.c | 11 ++-- video/out/x11_common.c | 6 +- 13 files changed, 153 insertions(+), 163 deletions(-) delete mode 100644 video/out/geometry.c delete mode 100644 video/out/geometry.h diff --git a/Makefile b/Makefile index 0ba142d698..ed29fb4cc6 100644 --- a/Makefile +++ b/Makefile @@ -266,7 +266,6 @@ SOURCES = talloc.c \ video/out/bitmap_packer.c \ video/out/aspect.c \ video/out/filter_kernels.c \ - video/out/geometry.c \ video/out/vo.c \ video/out/vo_null.c \ video/out/vo_image.c \ diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h index 8ef7e9abdd..5264784a56 100644 --- a/core/cfg-mplayer.h +++ b/core/cfg-mplayer.h @@ -37,7 +37,6 @@ extern char *lirc_configfile; /* only used at startup (setting these values from configfile) */ -extern char *vo_geometry; extern int stop_xscreensaver; extern int mp_msg_color; @@ -586,8 +585,7 @@ const m_option_t mplayer_opts[]={ // set screen dimensions (when not detectable or virtual!=visible) OPT_INTRANGE("screenw", vo_screenwidth, CONF_GLOBAL, 0, 4096), OPT_INTRANGE("screenh", vo_screenheight, CONF_GLOBAL, 0, 4096), - // Geometry string - {"geometry", &vo_geometry, CONF_TYPE_STRING, 0, 0, 0, NULL}, + OPT_GEOMETRY("geometry", vo_geometry, 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 82f6265124..0811e99a79 100644 --- a/core/m_option.c +++ b/core/m_option.c @@ -1165,6 +1165,134 @@ const m_option_type_t m_option_type_color = { .parse = parse_color, }; + + +static bool parse_geometry_str(struct m_geometry *gm, char *s) +{ + if (s == NULL) + return true; + char xsign[2], ysign[2], dummy[2]; + int width, height, xoff, yoff, xper, yper; + int ok = 0; + for (int i = 0; !ok && i < 9; i++) { + width = height = xoff = yoff = xper = yper = INT_MIN; + strcpy(xsign, "+"); + strcpy(ysign, "+"); + switch (i) { + case 0: + ok = sscanf(s, "%ix%i%1[+-]%i%1[+-]%i%c", + &width, &height, xsign, &xoff, ysign, + &yoff, dummy) == 6; + break; + case 1: + ok = sscanf(s, "%ix%i%c", &width, &height, dummy) == 2; + break; + case 2: + ok = sscanf(s, "%1[+-]%i%1[+-]%i%c", + xsign, &xoff, ysign, &yoff, dummy) == 4; + break; + case 3: + ok = sscanf(s, "%i%%:%i%1[%]%c", &xper, &yper, dummy, dummy) == 3; + break; + case 4: + ok = sscanf(s, "%i:%i%1[%]%c", &xoff, &yper, dummy, dummy) == 3; + break; + case 5: + ok = sscanf(s, "%i%%:%i%c", &xper, &yoff, dummy) == 2; + break; + case 6: + ok = sscanf(s, "%i:%i%c", &xoff, &yoff, dummy) == 2; + break; + case 7: + ok = sscanf(s, "%i%1[%]%c", &xper, dummy, dummy) == 2; + break; + case 8: + ok = sscanf(s, "%i%c", &xoff, dummy) == 1; + break; + } + } + if (!ok) + return false; + + gm->x_per = xper >= 0 && xper <= 100; + gm->x = gm->x_per ? xper : xoff; + gm->x_sign = xsign[0] == '-'; + gm->y_per = yper >= 0 && yper <= 100; + gm->y = gm->y_per ? yper : yoff; + gm->y_sign = ysign[0] == '-'; + gm->xy_valid = gm->x != INT_MIN || gm->y != INT_MIN; + + gm->w = width; + gm->h = height; + gm->wh_valid = gm->w > 0 || gm->h > 0; + + return true; +} + +// xpos,ypos: position of the left upper corner +// widw,widh: width and height of the window +// scrw,scrh: width and height of the current screen +// The input parameters should be set to a centered window (default fallbacks). +void m_geometry_apply(int *xpos, int *ypos, int *widw, int *widh, + int scrw, int scrh, struct m_geometry *gm) +{ + if (gm->wh_valid) { + if (gm->w > 0) + *widw = gm->w; + if (gm->h > 0) + *widh = gm->h; + } + + if (gm->xy_valid) { + if (gm->x != INT_MIN) { + *xpos = gm->x; + if (gm->x_per) + *xpos = (scrw - *widw) * (*xpos / 100.0); + if (gm->x_sign) + *xpos = scrw - *widw - *xpos; + } + if (gm->y != INT_MIN) { + *ypos = gm->y; + if (gm->y_per) + *ypos = (scrh - *widh) * (*ypos / 100.0); + if (gm->x_sign) + *ypos = scrh - *widh - *ypos; + } + } +} + +static int parse_geometry(const m_option_t *opt, struct bstr name, + struct bstr param, void *dst) +{ + char *s = bstrdup0(NULL, param); + struct m_geometry gm = {0}; + bool res = parse_geometry_str(&gm, s); + talloc_free(s); + if (!res) + goto error; + + if (dst) + *((struct m_geometry *)dst) = gm; + + return 1; + +error: + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: invalid geometry: '%.*s'\n", + BSTR_P(name), BSTR_P(param)); + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Valid format: [WxH][[+-]X[+-]Y] | [X[%%]:[Y[%%]]]\n"); + return M_OPT_INVALID; +} + +const m_option_type_t m_option_type_geometry = { + .name = "Window geometry", + .size = sizeof(struct m_geometry), + .parse = parse_geometry, +}; + + + + #include "video/img_format.h" static int parse_imgfmt(const m_option_t *opt, struct bstr name, diff --git a/core/m_option.h b/core/m_option.h index f6c346521a..ca75d494bb 100644 --- a/core/m_option.h +++ b/core/m_option.h @@ -56,6 +56,7 @@ extern const m_option_type_t m_option_type_imgfmt; 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; // Callback used by m_option_type_print_func options. typedef int (*m_opt_func_full_t)(const m_option_t *, const char *, const char *); @@ -77,6 +78,15 @@ struct m_color { uint8_t r, g, b, a; }; +struct m_geometry { + int x, y, w, h; + bool xy_valid : 1, wh_valid : 1; + bool x_sign : 1, y_sign : 1, x_per : 1, y_per : 1; +}; + +void m_geometry_apply(int *xpos, int *ypos, int *widw, int *widh, + int scrw, int scrh, struct m_geometry *gm); + // Extra definition needed for \ref m_option_type_obj_settings_list options. typedef struct { // Pointer to an array of pointer to some object type description struct. @@ -207,6 +217,7 @@ union m_option_value { double time; struct m_rel_time rel_time; struct m_color color; + struct m_geometry geometry; }; //////////////////////////////////////////////////////////////////////////// @@ -521,6 +532,7 @@ static inline void m_option_free(const m_option_t *opt, void *dst) #define OPT_TIME(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_time) #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_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 6edbb79ac8..10932a4edf 100644 --- a/core/options.h +++ b/core/options.h @@ -20,6 +20,7 @@ typedef struct MPOpts { int screen_size_y; int vo_screenwidth; int vo_screenheight; + struct m_geometry vo_geometry; int force_window_position; char *vo_winname; char *vo_wintitle; diff --git a/video/out/aspect.c b/video/out/aspect.c index 454f865d37..05e40a73e9 100644 --- a/video/out/aspect.c +++ b/video/out/aspect.c @@ -18,7 +18,6 @@ /* Stuff for correct aspect scaling. */ #include "aspect.h" -#include "geometry.h" #include "vo.h" #include "core/mp_msg.h" #include "core/options.h" @@ -102,7 +101,7 @@ void aspect(struct vo *vo, int *srcw, int *srch, int zoom) int fitw; int fith; get_max_dims(vo, &fitw, &fith, zoom); - if (!zoom && geometry_wh_changed) { + if (!zoom && vo->opts->vo_geometry.wh_valid) { mp_msg(MSGT_VO, MSGL_DBG2, "aspect(0) no aspect forced!\n"); return; // the user doesn't want to fix aspect } diff --git a/video/out/geometry.c b/video/out/geometry.c deleted file mode 100644 index c90f0c9a0c..0000000000 --- a/video/out/geometry.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * copyright (C) 2002 Mark Zealey - * - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include "geometry.h" -#include "core/mp_msg.h" - -/* A string of the form [WxH][+X+Y] or xpos[%]:ypos[%] */ -char *vo_geometry; -// set when either width or height is changed -int geometry_wh_changed; -int geometry_xy_changed; - -// xpos,ypos: position of the left upper corner -// widw,widh: width and height of the window -// scrw,scrh: width and height of the current screen -int geometry(int *xpos, int *ypos, int *widw, int *widh, int scrw, int scrh) -{ - if(vo_geometry != NULL) { - char xsign[2], ysign[2], dummy[2]; - int width, height, xoff, yoff, xper, yper; - int i; - int ok = 0; - for (i = 0; !ok && i < 9; i++) { - width = height = xoff = yoff = xper = yper = INT_MIN; - strcpy(xsign, "+"); - strcpy(ysign, "+"); - switch (i) { - case 0: - ok = sscanf(vo_geometry, "%ix%i%1[+-]%i%1[+-]%i%c", - &width, &height, xsign, &xoff, ysign, - &yoff, dummy) == 6; - break; - case 1: - ok = sscanf(vo_geometry, "%ix%i%c", &width, &height, dummy) == 2; - break; - case 2: - ok = sscanf(vo_geometry, "%1[+-]%i%1[+-]%i%c", - xsign, &xoff, ysign, &yoff, dummy) == 4; - break; - case 3: - ok = sscanf(vo_geometry, "%i%%:%i%1[%]%c", &xper, &yper, dummy, dummy) == 3; - break; - case 4: - ok = sscanf(vo_geometry, "%i:%i%1[%]%c", &xoff, &yper, dummy, dummy) == 3; - break; - case 5: - ok = sscanf(vo_geometry, "%i%%:%i%c", &xper, &yoff, dummy) == 2; - break; - case 6: - ok = sscanf(vo_geometry, "%i:%i%c", &xoff, &yoff, dummy) == 2; - break; - case 7: - ok = sscanf(vo_geometry, "%i%1[%]%c", &xper, dummy, dummy) == 2; - break; - case 8: - ok = sscanf(vo_geometry, "%i%c", &xoff, dummy) == 1; - break; - } - } - if (!ok) { - mp_msg(MSGT_VO, MSGL_ERR, - "-geometry must be in [WxH][[+-]X[+-]Y] | [X[%%]:[Y[%%]]] format, incorrect (%s)\n", vo_geometry); - return 0; - } - - mp_msg(MSGT_VO, MSGL_V,"geometry window parameter: widw: %i," - " widh: %i, scrw: %i, scrh: %i\n",*widw, *widh, scrw, scrh); - - mp_msg(MSGT_VO, MSGL_V,"geometry set to width: %i," - "height: %i, xoff: %s%i, yoff: %s%i, xper: %i, yper: %i\n", - width, height, xsign, xoff, ysign, yoff, xper, yper); - - if (width > 0) *widw = width; - if (height > 0) *widh = height; - - if(xoff != INT_MIN && xsign[0] == '-') xoff = scrw - *widw - xoff; - if(yoff != INT_MIN && ysign[0] == '-') yoff = scrh - *widh - yoff; - if(xper >= 0 && xper <= 100) xoff = (scrw - *widw) * ((float)xper / 100.0); - if(yper >= 0 && yper <= 100) yoff = (scrh - *widh) * ((float)yper / 100.0); - - mp_msg(MSGT_VO, MSGL_V,"geometry set to width: %i," - "height: %i, xoff: %i, yoff: %i, xper: %i, yper: %i\n", - width, height, xoff, yoff, xper, yper); - - if (xoff != INT_MIN && xpos) *xpos = xoff; - if (yoff != INT_MIN && ypos) *ypos = yoff; - - geometry_wh_changed = width > 0 || height > 0; - geometry_xy_changed = xoff != INT_MIN || yoff != INT_MIN; - } - return 1; -} diff --git a/video/out/geometry.h b/video/out/geometry.h deleted file mode 100644 index 77868a5aad..0000000000 --- a/video/out/geometry.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * copyright (C) 2002 Mark Zealey - * - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPLAYER_GEOMETRY_H -#define MPLAYER_GEOMETRY_H - -extern char *vo_geometry; -extern int geometry_wh_changed; -extern int geometry_xy_changed; -int geometry(int *xpos, int *ypos, int *widw, int *widh, int scrw, int scrh); - -#endif /* MPLAYER_GEOMETRY_H */ diff --git a/video/out/vo.c b/video/out/vo.c index 9163367eb9..29307b7218 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -33,7 +33,6 @@ #include "core/bstr.h" #include "vo.h" #include "aspect.h" -#include "geometry.h" #include "core/input/input.h" #include "core/mp_fifo.h" #include "core/m_config.h" @@ -403,9 +402,9 @@ static void determine_window_geometry(struct vo *vo, int d_w, int d_h) vo->dx = (int)(opts->vo_screenwidth - d_w) / 2; vo->dy = (int)(opts->vo_screenheight - d_h) / 2; - geometry(&vo->dx, &vo->dy, &d_w, &d_h, - opts->vo_screenwidth, opts->vo_screenheight); - geometry_xy_changed |= xinerama_screen >= 0; + m_geometry_apply(&vo->dx, &vo->dy, &d_w, &d_h, + opts->vo_screenwidth, opts->vo_screenheight, + &opts->vo_geometry); vo->dx += xinerama_x; vo->dy += xinerama_y; diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 4cb9fb76e1..a44c467b64 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -44,7 +44,6 @@ #include "vo.h" #include "video/vfcap.h" #include "video/mp_image.h" -#include "geometry.h" #include "sub/sub.h" #include "bitmap_packer.h" diff --git a/video/out/vo_opengl_old.c b/video/out/vo_opengl_old.c index 5943df10b4..c7a7312974 100644 --- a/video/out/vo_opengl_old.c +++ b/video/out/vo_opengl_old.c @@ -36,7 +36,6 @@ #include "vo.h" #include "video/vfcap.h" #include "video/mp_image.h" -#include "geometry.h" #include "sub/sub.h" #include "gl_common.h" diff --git a/video/out/vo_sdl.c b/video/out/vo_sdl.c index 99af9355ed..ec4cc97ca0 100644 --- a/video/out/vo_sdl.c +++ b/video/out/vo_sdl.c @@ -46,7 +46,6 @@ #include "aspect.h" #include "config.h" #include "vo.h" -#include "geometry.h" struct formatmap_entry { Uint32 sdl; @@ -272,14 +271,12 @@ static bool try_create_renderer(struct vo *vo, int i, const char *driver, if (!is_good_renderer(&ri, driver, vc->allow_sw, NULL)) return false; + bool xy_valid = vo->opts->vo_geometry.xy_valid; + // then actually try vc->window = SDL_CreateWindow("MPV", - geometry_xy_changed - ? vo->dx - : SDL_WINDOWPOS_UNDEFINED, - geometry_xy_changed - ? vo->dy - : SDL_WINDOWPOS_UNDEFINED, + xy_valid ? vo->dx : SDL_WINDOWPOS_UNDEFINED, + xy_valid ? vo->dy : SDL_WINDOWPOS_UNDEFINED, w, h, SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN); if (!vc->window) { diff --git a/video/out/x11_common.c b/video/out/x11_common.c index 7986817f68..9176165b8b 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -37,7 +37,6 @@ #include "vo.h" #include "aspect.h" -#include "geometry.h" #include "osdep/timer.h" #include @@ -1105,6 +1104,7 @@ void vo_x11_create_vo_window(struct vo *vo, XVisualInfo *vis, int x, int y, struct MPOpts *opts = vo->opts; struct vo_x11_state *x11 = vo->x11; Display *mDisplay = vo->x11->display; + bool force_change_xy = opts->vo_geometry.xy_valid || xinerama_screen >= 0; if (WinID >= 0) { vo_fs = flags & VOFLAG_FULLSCREEN; x11->window = WinID ? (Window)WinID : x11->rootwin; @@ -1148,7 +1148,7 @@ void vo_x11_create_vo_window(struct vo *vo, XVisualInfo *vis, int x, int y, hint.x = x; hint.y = y; hint.width = width; hint.height = height; hint.flags = PSize; - if (geometry_xy_changed) + if (force_change_xy) hint.flags |= PPosition; XSetWMNormalHints(mDisplay, x11->window, &hint); if (!vo_border) vo_x11_decoration(vo, 0); @@ -1167,7 +1167,7 @@ void vo_x11_create_vo_window(struct vo *vo, XVisualInfo *vis, int x, int y, } vo_x11_update_window_title(vo); if (opts->vo_ontop) vo_x11_setlayer(vo, x11->window, opts->vo_ontop); - vo_x11_update_geometry(vo, !geometry_xy_changed); + vo_x11_update_geometry(vo, !force_change_xy); vo_x11_nofs_sizepos(vo, vo->dx, vo->dy, width, height); if (!!vo_fs != !!(flags & VOFLAG_FULLSCREEN)) vo_x11_fullscreen(vo);