summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-01-23 10:56:11 +0100
committerwm4 <wm4@nowhere>2013-01-23 10:56:11 +0100
commit4c56baba4048f8a881253d4fe2f49c2715c77376 (patch)
treed75891df8cd30c404072f9b67b6da21188b79ba8 /core
parentf2dcdca0c2dc5f904323659b65b29a2b6f00fd88 (diff)
downloadmpv-4c56baba4048f8a881253d4fe2f49c2715c77376.tar.bz2
mpv-4c56baba4048f8a881253d4fe2f49c2715c77376.tar.xz
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.
Diffstat (limited to 'core')
-rw-r--r--core/cfg-mplayer.h4
-rw-r--r--core/m_option.c128
-rw-r--r--core/m_option.h12
-rw-r--r--core/options.h1
4 files changed, 142 insertions, 3 deletions
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;