summaryrefslogtreecommitdiffstats
path: root/options/m_option.c
diff options
context:
space:
mode:
Diffstat (limited to 'options/m_option.c')
-rw-r--r--options/m_option.c717
1 files changed, 374 insertions, 343 deletions
diff --git a/options/m_option.c b/options/m_option.c
index c55ca06bc8..3d9ae26669 100644
--- a/options/m_option.c
+++ b/options/m_option.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdarg.h>
@@ -42,7 +43,7 @@
#include "misc/json.h"
#include "misc/node.h"
#include "m_option.h"
-#include "m_config.h"
+#include "m_config_frontend.h"
#if HAVE_DOS_PATHS
#define OPTION_PATH_SEPARATOR ';'
@@ -52,6 +53,39 @@
const char m_option_path_separator = OPTION_PATH_SEPARATOR;
+// For integer types: since min/max are floats and may not be able to represent
+// the real min/max, and since opt.min/.max may use +/-INFINITY, some care has
+// to be taken. (Also tricky rounding.)
+#define OPT_INT_MIN(opt, T, Tm) ((opt)->min < (opt)->max \
+ ? ((opt)->min <= (double)(Tm) ? (Tm) : (T)((opt)->min)) : (Tm))
+#define OPT_INT_MAX(opt, T, Tm) ((opt)->min < (opt)->max \
+ ? ((opt)->max >= (double)(Tm) ? (Tm) : (T)((opt)->max)) : (Tm))
+
+int m_option_parse(struct mp_log *log, const m_option_t *opt,
+ struct bstr name, struct bstr param, void *dst)
+{
+ int r = M_OPT_INVALID;
+ if (bstr_equals0(param, "help") && opt->help) {
+ r = opt->help(log, opt, name);
+ if (r < 0)
+ return r;
+ }
+
+ r = opt->type->parse(log, opt, name, param, dst);
+ if (r < 0)
+ return r;
+
+ if (opt->validate) {
+ r = opt->validate(log, opt, name, dst);
+ if (r < 0) {
+ if (opt->type->free)
+ opt->type->free(dst);
+ return r;
+ }
+ }
+ return 1;
+}
+
char *m_option_strerror(int code)
{
switch (code) {
@@ -77,7 +111,7 @@ int m_option_required_params(const m_option_t *opt)
if (opt->flags & M_OPT_OPTIONAL_PARAM)
return 0;
if (opt->type == &m_option_type_choice) {
- struct m_opt_choice_alternatives *alt;
+ const struct m_opt_choice_alternatives *alt;
for (alt = opt->priv; alt->name; alt++) {
if (strcmp(alt->name, "yes") == 0)
return 0;
@@ -109,11 +143,11 @@ static void copy_opt(const m_option_t *opt, void *dst, const void *src)
memcpy(dst, src, opt->type->size);
}
-// Flag
+// Bool
-#define VAL(x) (*(int *)(x))
+#define VAL(x) (*(bool *)(x))
-static int parse_flag(struct mp_log *log, const m_option_t *opt,
+static int parse_bool(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
if (bstr_equals0(param, "yes") || !param.len) {
@@ -140,12 +174,12 @@ static int parse_flag(struct mp_log *log, const m_option_t *opt,
return is_help ? M_OPT_EXIT : M_OPT_INVALID;
}
-static char *print_flag(const m_option_t *opt, const void *val)
+static char *print_bool(const m_option_t *opt, const void *val)
{
return talloc_strdup(NULL, VAL(val) ? "yes" : "no");
}
-static void add_flag(const m_option_t *opt, void *val, double add, bool wrap)
+static void add_bool(const m_option_t *opt, void *val, double add, bool wrap)
{
if (fabs(add) < 0.5)
return;
@@ -154,7 +188,7 @@ static void add_flag(const m_option_t *opt, void *val, double add, bool wrap)
VAL(val) = state ? 1 : 0;
}
-static int flag_set(const m_option_t *opt, void *dst, struct mpv_node *src)
+static int bool_set(const m_option_t *opt, void *dst, struct mpv_node *src)
{
if (src->format != MPV_FORMAT_FLAG)
return M_OPT_UNKNOWN;
@@ -162,7 +196,7 @@ static int flag_set(const m_option_t *opt, void *dst, struct mpv_node *src)
return 1;
}
-static int flag_get(const m_option_t *opt, void *ta_parent,
+static int bool_get(const m_option_t *opt, void *ta_parent,
struct mpv_node *dst, void *src)
{
dst->format = MPV_FORMAT_FLAG;
@@ -170,11 +204,73 @@ static int flag_get(const m_option_t *opt, void *ta_parent,
return 1;
}
+static bool bool_equal(const m_option_t *opt, void *a, void *b)
+{
+ return VAL(a) == VAL(b);
+}
+
+const m_option_type_t m_option_type_bool = {
+ .name = "Flag", // same as m_option_type_flag; transparent to user
+ .size = sizeof(bool),
+ .flags = M_OPT_TYPE_OPTIONAL_PARAM | M_OPT_TYPE_CHOICE,
+ .parse = parse_bool,
+ .print = print_bool,
+ .copy = copy_opt,
+ .add = add_bool,
+ .set = bool_set,
+ .get = bool_get,
+ .equal = bool_equal,
+};
+
+#undef VAL
+
+// Flag
+
+#define VAL(x) (*(int *)(x))
+
+static int parse_flag(struct mp_log *log, const m_option_t *opt,
+ struct bstr name, struct bstr param, void *dst)
+{
+ bool bdst = false;
+ int r = parse_bool(log, opt, name, param, &bdst);
+ if (dst)
+ VAL(dst) = bdst;
+ return r;
+}
+
+static char *print_flag(const m_option_t *opt, const void *val)
+{
+ return print_bool(opt, &(bool){VAL(val)});
+}
+
+static void add_flag(const m_option_t *opt, void *val, double add, bool wrap)
+{
+ bool bval = VAL(val);
+ add_bool(opt, &bval, add, wrap);
+ VAL(val) = bval;
+}
+
+static int flag_set(const m_option_t *opt, void *dst, struct mpv_node *src)
+{
+ bool bdst = false;
+ int r = bool_set(opt, &bdst, src);
+ if (r >= 0)
+ VAL(dst) = bdst;
+ return r;
+}
+
+static int flag_get(const m_option_t *opt, void *ta_parent,
+ struct mpv_node *dst, void *src)
+{
+ return bool_get(opt, ta_parent, dst, &(bool){VAL(src)});
+}
+
static bool flag_equal(const m_option_t *opt, void *a, void *b)
{
return VAL(a) == VAL(b);
}
+// Only exists for libmpv interopability and should not be used anywhere.
const m_option_type_t m_option_type_flag = {
// need yes or no in config files
.name = "Flag",
@@ -193,16 +289,19 @@ const m_option_type_t m_option_type_flag = {
#undef VAL
-static int clamp_longlong(const m_option_t *opt, void *val)
+static int clamp_longlong(const m_option_t *opt, long long i_min, long long i_max,
+ void *val)
{
long long v = *(long long *)val;
int r = 0;
- if ((opt->flags & M_OPT_MAX) && (v > opt->max)) {
- v = opt->max;
+ long long min = OPT_INT_MIN(opt, long long, i_min);
+ long long max = OPT_INT_MAX(opt, long long, i_max);
+ if (v > max) {
+ v = max;
r = M_OPT_OUT_OF_RANGE;
}
- if ((opt->flags & M_OPT_MIN) && (v < opt->min)) {
- v = opt->min;
+ if (v < min) {
+ v = min;
r = M_OPT_OUT_OF_RANGE;
}
*(long long *)val = v;
@@ -210,6 +309,7 @@ static int clamp_longlong(const m_option_t *opt, void *val)
}
static int parse_longlong(struct mp_log *log, const m_option_t *opt,
+ long long i_min, long long i_max,
struct bstr name, struct bstr param, void *dst)
{
if (param.len == 0)
@@ -225,15 +325,17 @@ static int parse_longlong(struct mp_log *log, const m_option_t *opt,
return M_OPT_INVALID;
}
- if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) {
- mp_err(log, "The %.*s option must be >= %d: %.*s\n",
- BSTR_P(name), (int) opt->min, BSTR_P(param));
+ long long min = OPT_INT_MIN(opt, long long, i_min);
+ if (tmp_int < min) {
+ mp_err(log, "The %.*s option must be >= %lld: %.*s\n",
+ BSTR_P(name), min, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
- if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) {
- mp_err(log, "The %.*s option must be <= %d: %.*s\n",
- BSTR_P(name), (int) opt->max, BSTR_P(param));
+ long long max = OPT_INT_MAX(opt, long long, i_max);
+ if (tmp_int > max) {
+ mp_err(log, "The %.*s option must be <= %lld: %.*s\n",
+ BSTR_P(name), max, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
@@ -246,7 +348,7 @@ static int parse_longlong(struct mp_log *log, const m_option_t *opt,
static int clamp_int64(const m_option_t *opt, void *val)
{
long long tmp = *(int64_t *)val;
- int r = clamp_longlong(opt, &tmp);
+ int r = clamp_longlong(opt, INT64_MIN, INT64_MAX, &tmp);
*(int64_t *)val = tmp;
return r;
}
@@ -255,7 +357,7 @@ static int parse_int(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
long long tmp;
- int r = parse_longlong(log, opt, name, param, &tmp);
+ int r = parse_longlong(log, opt, INT_MIN, INT_MAX, name, param, &tmp);
if (r >= 0 && dst)
*(int *)dst = tmp;
return r;
@@ -265,7 +367,7 @@ static int parse_int64(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
long long tmp;
- int r = parse_longlong(log, opt, name, param, &tmp);
+ int r = parse_longlong(log, opt, INT64_MIN, INT64_MAX, name, param, &tmp);
if (r >= 0 && dst)
*(int64_t *)dst = tmp;
return r;
@@ -290,8 +392,8 @@ static void add_int64(const m_option_t *opt, void *val, double add, bool wrap)
int64_t nmin = is64 ? INT64_MIN : INT_MIN;
int64_t nmax = is64 ? INT64_MAX : INT_MAX;
- int64_t min = (opt->flags & M_OPT_MIN) ? opt->min : nmin;
- int64_t max = (opt->flags & M_OPT_MAX) ? opt->max : nmax;
+ int64_t min = OPT_INT_MIN(opt, int64_t, nmin);
+ int64_t max = OPT_INT_MAX(opt, int64_t, nmax);
if (v < min)
v = wrap ? max : min;
@@ -314,7 +416,7 @@ static void multiply_int64(const m_option_t *opt, void *val, double f)
int64_t iv = v;
if (v < INT64_MIN)
iv = INT64_MIN;
- if (v > INT64_MAX)
+ if (v >= (double)INT64_MAX)
iv = INT64_MAX;
*(int64_t *)val = iv;
clamp_int64(opt, val);
@@ -332,9 +434,9 @@ static int int64_set(const m_option_t *opt, void *dst, struct mpv_node *src)
if (src->format != MPV_FORMAT_INT64)
return M_OPT_UNKNOWN;
int64_t val = src->u.int64;
- if ((opt->flags & M_OPT_MIN) && val < opt->min)
+ if (val < OPT_INT_MIN(opt, int64_t, INT64_MIN))
return M_OPT_OUT_OF_RANGE;
- if ((opt->flags & M_OPT_MAX) && val > opt->max)
+ if (val > OPT_INT_MAX(opt, int64_t, INT64_MAX))
return M_OPT_OUT_OF_RANGE;
*(int64_t *)dst = val;
return 1;
@@ -380,6 +482,7 @@ static bool int64_equal(const m_option_t *opt, void *a, void *b)
const m_option_type_t m_option_type_int = {
.name = "Integer",
+ .flags = M_OPT_TYPE_USES_RANGE,
.size = sizeof(int),
.parse = parse_int,
.print = print_int,
@@ -393,6 +496,7 @@ const m_option_type_t m_option_type_int = {
const m_option_type_t m_option_type_int64 = {
.name = "Integer64",
+ .flags = M_OPT_TYPE_USES_RANGE,
.size = sizeof(int64_t),
.parse = parse_int64,
.print = print_int,
@@ -447,15 +551,17 @@ static int parse_byte_size(struct mp_log *log, const m_option_t *opt,
tmp_int *= unit;
- if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) {
- mp_err(log, "The %.*s option must be >= %d: %.*s\n",
- BSTR_P(name), (int) opt->min, BSTR_P(param));
+ int64_t min = OPT_INT_MIN(opt, int64_t, INT64_MIN);
+ if (tmp_int < min) {
+ mp_err(log, "The %.*s option must be >= %"PRId64": %.*s\n",
+ BSTR_P(name), min, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
- if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) {
- mp_err(log, "The %.*s option must be <= %d: %.*s\n",
- BSTR_P(name), (int) opt->max, BSTR_P(param));
+ int64_t max = OPT_INT_MAX(opt, int64_t, INT64_MAX);
+ if (tmp_int > max) {
+ mp_err(log, "The %.*s option must be <= %"PRId64": %.*s\n",
+ BSTR_P(name), max, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
@@ -490,6 +596,7 @@ static char *pretty_print_byte_size(const m_option_t *opt, const void *val)
const m_option_type_t m_option_type_byte_size = {
.name = "ByteSize",
+ .flags = M_OPT_TYPE_USES_RANGE,
.size = sizeof(int64_t),
.parse = parse_byte_size,
.print = print_int,
@@ -502,59 +609,6 @@ const m_option_type_t m_option_type_byte_size = {
.equal = int64_equal,
};
-static int parse_intpair(struct mp_log *log, const struct m_option *opt,
- struct bstr name, struct bstr param, void *dst)
-{
- if (param.len == 0)
- return M_OPT_MISSING_PARAM;
-
- struct bstr s = param;
- int end = -1;
- int start = bstrtoll(s, &s, 10);
- if (s.len == param.len)
- goto bad;
- if (s.len > 0) {
- if (!bstr_startswith0(s, "-"))
- goto bad;
- s = bstr_cut(s, 1);
- }
- if (s.len > 0)
- end = bstrtoll(s, &s, 10);
- if (s.len > 0)
- goto bad;
-
- if (dst) {
- int *p = dst;
- p[0] = start;
- p[1] = end;
- }
-
- return 1;
-
-bad:
- mp_err(log, "Invalid integer range "
- "specification for option %.*s: %.*s\n",
- BSTR_P(name), BSTR_P(param));
- return M_OPT_INVALID;
-}
-
-static char *print_intpair(const m_option_t *opt, const void *val)
-{
- const int *p = val;
- char *res = talloc_asprintf(NULL, "%d", p[0]);
- if (p[1] != -1)
- res = talloc_asprintf_append(res, "-%d", p[1]);
- return res;
-}
-
-const struct m_option_type m_option_type_intpair = {
- .name = "Int[-Int]",
- .size = sizeof(int[2]),
- .parse = parse_intpair,
- .print = print_intpair,
- .copy = copy_opt,
-};
-
const char *m_opt_choice_str(const struct m_opt_choice_alternatives *choices,
int value)
{
@@ -567,17 +621,17 @@ const char *m_opt_choice_str(const struct m_opt_choice_alternatives *choices,
static void print_choice_values(struct mp_log *log, const struct m_option *opt)
{
- struct m_opt_choice_alternatives *alt = opt->priv;
+ const struct m_opt_choice_alternatives *alt = opt->priv;
for ( ; alt->name; alt++)
mp_info(log, " %s\n", alt->name[0] ? alt->name : "(passing nothing)");
- if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX))
+ if (opt->min < opt->max)
mp_info(log, " %g-%g (integer range)\n", opt->min, opt->max);
}
static int parse_choice(struct mp_log *log, const struct m_option *opt,
struct bstr name, struct bstr param, void *dst)
{
- struct m_opt_choice_alternatives *alt = opt->priv;
+ const struct m_opt_choice_alternatives *alt = opt->priv;
for ( ; alt->name; alt++) {
if (!bstrcmp0(param, alt->name))
break;
@@ -597,9 +651,11 @@ static int parse_choice(struct mp_log *log, const struct m_option *opt,
}
if (param.len == 0)
return M_OPT_MISSING_PARAM;
- if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
+ if (opt->min < opt->max) {
long long val;
- if (parse_longlong(mp_null_log, opt, name, param, &val) == 1) {
+ if (parse_longlong(mp_null_log, opt, INT_MIN, INT_MAX, name, param,
+ &val) == 1)
+ {
if (dst)
*(int *)dst = val;
return 1;
@@ -622,11 +678,11 @@ static void choice_get_min_max(const struct m_option *opt, int *min, int *max)
assert(opt->type == &m_option_type_choice);
*min = INT_MAX;
*max = INT_MIN;
- for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) {
+ for (const struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) {
*min = MPMIN(*min, alt->value);
*max = MPMAX(*max, alt->value);
}
- if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
+ if (opt->min < opt->max) {
*min = MPMIN(*min, opt->min);
*max = MPMAX(*max, opt->max);
}
@@ -653,7 +709,7 @@ static void add_choice(const m_option_t *opt, void *val, double add, bool wrap)
if (fabs(add) < 0.5)
return;
- if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
+ if (opt->min < opt->max) {
int newval = ival + add;
if (ival >= opt->min && ival <= opt->max &&
newval >= opt->min && newval <= opt->max)
@@ -666,7 +722,7 @@ static void add_choice(const m_option_t *opt, void *val, double add, bool wrap)
}
}
- for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++)
+ for (const struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++)
check_choice(dir, ival, &found, &best, alt->value);
if (!found) {
@@ -699,29 +755,30 @@ static int choice_set(const m_option_t *opt, void *dst, struct mpv_node *src)
return r;
}
-static struct m_opt_choice_alternatives *get_choice(const m_option_t *opt,
- const void *val, int *out_val)
+static const struct m_opt_choice_alternatives *get_choice(const m_option_t *opt,
+ const void *val,
+ int *out_val)
{
int v = *(int *)val;
- struct m_opt_choice_alternatives *alt;
+ const struct m_opt_choice_alternatives *alt;
for (alt = opt->priv; alt->name; alt++) {
if (alt->value == v)
return alt;
}
- if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
+ if (opt->min < opt->max) {
if (v >= opt->min && v <= opt->max) {
*out_val = v;
return NULL;
}
}
- abort();
+ MP_ASSERT_UNREACHABLE();
}
static int choice_get(const m_option_t *opt, void *ta_parent,
struct mpv_node *dst, void *src)
{
int ival = 0;
- struct m_opt_choice_alternatives *alt = get_choice(opt, src, &ival);
+ const struct m_opt_choice_alternatives *alt = get_choice(opt, src, &ival);
// If a choice string looks like a number, return it as number
if (alt) {
char *end = NULL;
@@ -753,7 +810,7 @@ static int choice_get(const m_option_t *opt, void *ta_parent,
static char *print_choice(const m_option_t *opt, const void *val)
{
int ival = 0;
- struct m_opt_choice_alternatives *alt = get_choice(opt, val, &ival);
+ const struct m_opt_choice_alternatives *alt = get_choice(opt, val, &ival);
return alt ? talloc_strdup(NULL, alt->name)
: talloc_asprintf(NULL, "%d", ival);
}
@@ -761,7 +818,7 @@ static char *print_choice(const m_option_t *opt, const void *val)
const struct m_option_type m_option_type_choice = {
.name = "Choice",
.size = sizeof(int),
- .flags = M_OPT_TYPE_CHOICE,
+ .flags = M_OPT_TYPE_CHOICE | M_OPT_TYPE_USES_RANGE,
.parse = parse_choice,
.print = print_choice,
.copy = copy_opt,
@@ -773,7 +830,7 @@ const struct m_option_type m_option_type_choice = {
static int apply_flag(const struct m_option *opt, int *val, bstr flag)
{
- struct m_opt_choice_alternatives *alt;
+ const struct m_opt_choice_alternatives *alt;
for (alt = opt->priv; alt->name; alt++) {
if (bstr_equals0(flag, alt->name)) {
if (*val & alt->value)
@@ -787,8 +844,8 @@ static int apply_flag(const struct m_option *opt, int *val, bstr flag)
static const char *find_next_flag(const struct m_option *opt, int *val)
{
- struct m_opt_choice_alternatives *best = NULL;
- struct m_opt_choice_alternatives *alt;
+ const struct m_opt_choice_alternatives *best = NULL;
+ const struct m_opt_choice_alternatives *alt;
for (alt = opt->priv; alt->name; alt++) {
if (alt->value && (alt->value & (*val)) == alt->value) {
if (!best || av_popcount64(alt->value) > av_popcount64(best->value))
@@ -815,7 +872,7 @@ static int parse_flags(struct mp_log *log, const struct m_option *opt,
mp_fatal(log, "Invalid flag for option %.*s: %.*s\n",
BSTR_P(name), BSTR_P(flag));
mp_info(log, "Valid flags are:\n");
- struct m_opt_choice_alternatives *alt;
+ const struct m_opt_choice_alternatives *alt;
for (alt = opt->priv; alt->name; alt++)
mp_info(log, " %s\n", alt->name);
mp_info(log, "Flags can usually be combined with '+'.\n");
@@ -903,13 +960,15 @@ static int clamp_double(const m_option_t *opt, void *val)
{
double v = VAL(val);
int r = 0;
- if ((opt->flags & M_OPT_MAX) && (v > opt->max)) {
- v = opt->max;
- r = M_OPT_OUT_OF_RANGE;
- }
- if ((opt->flags & M_OPT_MIN) && (v < opt->min)) {
- v = opt->min;
- r = M_OPT_OUT_OF_RANGE;
+ if (opt->min < opt->max) {
+ if (v > opt->max) {
+ v = opt->max;
+ r = M_OPT_OUT_OF_RANGE;
+ }
+ if (v < opt->min) {
+ v = opt->min;
+ r = M_OPT_OUT_OF_RANGE;
+ }
}
// (setting max/min to INFINITY/-INFINITY is allowed)
if (!isfinite(v) && v != opt->max && v != opt->min) {
@@ -964,12 +1023,12 @@ static char *print_double(const m_option_t *opt, const void *val)
return talloc_asprintf(NULL, "%f", f);
}
-static char *print_double_f3(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);
- return talloc_asprintf(NULL, "%.3f", 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)
@@ -978,8 +1037,8 @@ static void add_double(const m_option_t *opt, void *val, double add, bool wrap)
v = v + add;
- double min = (opt->flags & M_OPT_MIN) ? opt->min : -INFINITY;
- double max = (opt->flags & M_OPT_MAX) ? opt->max : +INFINITY;
+ double min = opt->min < opt->max ? opt->min : -INFINITY;
+ double max = opt->min < opt->max ? opt->max : +INFINITY;
if (v < min)
v = wrap ? max : min;
@@ -1037,10 +1096,37 @@ static bool double_equal(const m_option_t *opt, void *a, void *b)
const m_option_type_t m_option_type_double = {
// double precision float or ratio (numerator[:/]denominator)
.name = "Double",
+ .flags = M_OPT_TYPE_USES_RANGE,
.size = sizeof(double),
.parse = parse_double,
.print = print_double,
- .pretty_print = print_double_f3,
+ .pretty_print = pretty_print_double,
+ .copy = copy_opt,
+ .add = add_double,
+ .multiply = multiply_double,
+ .set = double_set,
+ .get = double_get,
+ .equal = double_equal,
+};
+
+static int parse_double_aspect(struct mp_log *log, const m_option_t *opt,
+ struct bstr name, struct bstr param, void *dst)
+{
+ if (bstr_equals0(param, "no")) {
+ if (dst)
+ VAL(dst) = 0.0;
+ return 1;
+ }
+ return parse_double(log, opt, name, param, dst);
+}
+
+const m_option_type_t m_option_type_aspect = {
+ .name = "Aspect",
+ .size = sizeof(double),
+ .flags = M_OPT_TYPE_CHOICE | M_OPT_TYPE_USES_RANGE,
+ .parse = parse_double_aspect,
+ .print = print_double,
+ .pretty_print = pretty_print_double,
.copy = copy_opt,
.add = add_double,
.multiply = multiply_double,
@@ -1068,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_f3(opt, &tmp);
+ return pretty_print_double(opt, &tmp);
}
static void add_float(const m_option_t *opt, void *val, double add, bool wrap)
@@ -1112,36 +1198,11 @@ static bool float_equal(const m_option_t *opt, void *a, void *b)
const m_option_type_t m_option_type_float = {
// floating point number or ratio (numerator[:/]denominator)
.name = "Float",
+ .flags = M_OPT_TYPE_USES_RANGE,
.size = sizeof(float),
.parse = parse_float,
.print = print_float,
- .pretty_print = print_float_f3,
- .copy = copy_opt,
- .add = add_float,
- .multiply = multiply_float,
- .set = float_set,
- .get = float_get,
- .equal = float_equal,
-};
-
-static int parse_float_aspect(struct mp_log *log, const m_option_t *opt,
- struct bstr name, struct bstr param, void *dst)
-{
- if (bstr_equals0(param, "no")) {
- if (dst)
- VAL(dst) = 0.0f;
- return 1;
- }
- return parse_float(log, opt, name, param, dst);
-}
-
-const m_option_type_t m_option_type_aspect = {
- .name = "Aspect",
- .size = sizeof(float),
- .flags = M_OPT_TYPE_CHOICE,
- .parse = parse_float_aspect,
- .print = print_float,
- .pretty_print = print_float_f3,
+ .pretty_print = pretty_print_float,
.copy = copy_opt,
.add = add_float,
.multiply = multiply_float,
@@ -1155,39 +1216,9 @@ const m_option_type_t m_option_type_aspect = {
#undef VAL
#define VAL(x) (*(char **)(x))
-static int clamp_str(const m_option_t *opt, void *val)
-{
- char *v = VAL(val);
- int len = v ? strlen(v) : 0;
- if ((opt->flags & M_OPT_MIN) && (len < opt->min))
- return M_OPT_OUT_OF_RANGE;
- if ((opt->flags & M_OPT_MAX) && (len > opt->max))
- return M_OPT_OUT_OF_RANGE;
- return 0;
-}
-
static int parse_str(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
- m_opt_string_validate_fn validate = opt->priv;
- if (validate) {
- int r = validate(log, opt, name, param);
- if (r < 0)
- return r;
- }
-
- if ((opt->flags & M_OPT_MIN) && (param.len < opt->min)) {
- mp_err(log, "Parameter must be >= %d chars: %.*s\n",
- (int) opt->min, BSTR_P(param));
- return M_OPT_OUT_OF_RANGE;
- }
-
- if ((opt->flags & M_OPT_MAX) && (param.len > opt->max)) {
- mp_err(log, "Parameter must be <= %d chars: %.*s\n",
- (int) opt->max, BSTR_P(param));
- return M_OPT_OUT_OF_RANGE;
- }
-
if (dst) {
talloc_free(VAL(dst));
VAL(dst) = bstrdup0(NULL, param);
@@ -1214,7 +1245,7 @@ static int str_set(const m_option_t *opt, void *dst, struct mpv_node *src)
if (src->format != MPV_FORMAT_STRING)
return M_OPT_UNKNOWN;
char *s = src->u.string;
- int r = s ? clamp_str(opt, &s) : M_OPT_INVALID;
+ int r = s ? 0 : M_OPT_INVALID;
if (r >= 0)
copy_str(opt, dst, &s);
return r;
@@ -1261,11 +1292,10 @@ const m_option_type_t m_option_type_string = {
#define OP_NONE 0
#define OP_ADD 1
#define OP_PRE 2
-#define OP_DEL 3
-#define OP_CLR 4
-#define OP_TOGGLE 5
-#define OP_APPEND 6
-#define OP_REMOVE 7
+#define OP_CLR 3
+#define OP_TOGGLE 4
+#define OP_APPEND 5
+#define OP_REMOVE 6
static void free_str_list(void *dst)
{
@@ -1307,55 +1337,6 @@ static int str_list_add(char **add, int n, void *dst, int pre)
return 1;
}
-static int str_list_del(struct mp_log *log, char **del, int n, void *dst)
-{
- char **lst, *ep;
- int i, ln, s;
- long idx;
-
- lst = VAL(dst);
-
- for (ln = 0; lst && lst[ln]; ln++)
- /**/;
- s = ln;
-
- for (i = 0; del[i] != NULL; i++) {
- idx = strtol(del[i], &ep, 0);
- if (*ep) {
- mp_err(log, "Invalid index: %s\n", del[i]);
- talloc_free(del[i]);
- continue;
- }
- talloc_free(del[i]);
- if (idx < 0 || idx >= ln) {
- mp_err(log, "Index %ld is out of range.\n", idx);
- continue;
- } else if (!lst[idx])
- continue;
- talloc_free(lst[idx]);
- lst[idx] = NULL;
- s--;
- }
- talloc_free(del);
-
- if (s == 0) {
- talloc_free(lst);
- VAL(dst) = NULL;
- return 1;
- }
-
- // Don't bother shrinking the list allocation
- for (i = 0, n = 0; i < ln; i++) {
- if (!lst[i])
- continue;
- lst[n] = lst[i];
- n++;
- }
- lst[s] = NULL;
-
- return 1;
-}
-
static struct bstr get_nextsep(struct bstr *ptr, char sep, bool modify)
{
struct bstr str = *ptr;
@@ -1402,11 +1383,6 @@ static int parse_str_list_impl(struct mp_log *log, const m_option_t *opt,
multi = false;
} else if (bstr_endswith0(name, "-pre")) {
op = OP_PRE;
- } else if (bstr_endswith0(name, "-del")) {
- op = OP_DEL;
- mp_warn(log, "Option %.*s: -del is deprecated! "
- "Use -remove (removes by content instead of by index).\n",
- BSTR_P(name));
} else if (bstr_endswith0(name, "-clr")) {
op = OP_CLR;
} else if (bstr_endswith0(name, "-set")) {
@@ -1420,14 +1396,20 @@ static int parse_str_list_impl(struct mp_log *log, const m_option_t *opt,
if (op == OP_TOGGLE || op == OP_REMOVE) {
if (dst) {
char **list = VAL(dst);
- int index = find_list_bstr(list, param);
- if (index >= 0) {
- char *old = list[index];
- for (int n = index; list[n]; n++)
- list[n] = list[n + 1];
- talloc_free(old);
+ bool found = false;
+ int index = 0;
+ do {
+ index = find_list_bstr(list, param);
+ if (index >= 0) {
+ found = true;
+ char *old = list[index];
+ for (int n = index; list[n]; n++)
+ list[n] = list[n + 1];
+ talloc_free(old);
+ }
+ } while (index >= 0);
+ if (found)
return 1;
- }
}
if (op == OP_REMOVE)
return 1; // ignore if not found
@@ -1458,9 +1440,6 @@ static int parse_str_list_impl(struct mp_log *log, const m_option_t *opt,
}
if (n == 0 && op != OP_NONE)
return M_OPT_INVALID;
- if (((opt->flags & M_OPT_MIN) && (n < opt->min)) ||
- ((opt->flags & M_OPT_MAX) && (n > opt->max)))
- return M_OPT_OUT_OF_RANGE;
if (!dst)
return 1;
@@ -1491,8 +1470,6 @@ static int parse_str_list_impl(struct mp_log *log, const m_option_t *opt,
return str_list_add(res, n, dst, 0);
case OP_PRE:
return str_list_add(res, n, dst, 1);
- case OP_DEL:
- return str_list_del(log, res, n, dst);
}
if (VAL(dst))
@@ -1535,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, "");
@@ -1542,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;
@@ -1622,7 +1600,6 @@ const m_option_type_t m_option_type_string_list = {
{"add"},
{"append"},
{"clr", M_OPT_TYPE_OPTIONAL_PARAM},
- {"del"},
{"pre"},
{"set"},
{"toggle"},
@@ -1702,7 +1679,7 @@ static int parse_keyvalue_list(struct mp_log *log, const m_option_t *opt,
val = param;
param.len = 0;
} else {
- r = read_subparam(log, name, ",:", &param, &val);
+ r = read_subparam(log, name, ",", &param, &val);
if (r < 0)
break;
}
@@ -1728,7 +1705,7 @@ static int parse_keyvalue_list(struct mp_log *log, const m_option_t *opt,
}
if (param.len) {
- mp_err(log, "Unparseable garbage at end of option value: '%.*s'\n",
+ mp_err(log, "Unparsable garbage at end of option value: '%.*s'\n",
BSTR_P(param));
r = M_OPT_INVALID;
}
@@ -1838,7 +1815,7 @@ static int parse_msglevels(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
if (bstr_equals0(param, "help")) {
- mp_info(log, "Syntax:\n\n --msglevel=module1=level,module2=level,...\n\n"
+ mp_info(log, "Syntax:\n\n --msg-level=module1=level,module2=level,...\n\n"
"'module' is output prefix as shown with -v, or a prefix\n"
"of it. level is one of:\n\n"
" fatal error warn info status v debug trace\n\n"
@@ -1920,7 +1897,7 @@ const m_option_type_t m_option_type_dummy_flag = {
// Read s sub-option name, or a positional sub-opt value.
// termset is a string containing the set of chars that terminate an option.
-// Return 0 on succes, M_OPT_ error code otherwise.
+// Return 0 on success, M_OPT_ error code otherwise.
// optname is for error reporting.
static int read_subparam(struct mp_log *log, bstr optname, char *termset,
bstr *str, bstr *out_subparam)
@@ -2137,7 +2114,7 @@ static bool parse_geometry_str(struct m_geometry *gm, bstr s)
if (s.len == 0)
return true;
// Approximate grammar:
- // [[W][xH]][{+-}X{+-}Y] | [X:Y]
+ // [[W][xH]][{+-}X{+-}Y][/WS] | [X:Y]
// (meaning: [optional] {one character of} one|alternative)
// Every number can be followed by '%'
int num;
@@ -2173,6 +2150,14 @@ static bool parse_geometry_str(struct m_geometry *gm, bstr s)
READ_SIGN(y_sign);
READ_NUM(y, y_per);
}
+ if (bstr_eatstart0(&s, "/")) {
+ bstr rest;
+ long long v = bstrtoll(s, &rest, 10);
+ if (s.len == rest.len || v < 1 || v > INT_MAX)
+ goto error;
+ s = rest;
+ gm->ws = v;
+ }
} else {
gm->xy_valid = true;
READ_NUM(x, x_per);
@@ -2209,6 +2194,8 @@ static char *print_geometry(const m_option_t *opt, const void *val)
res = talloc_asprintf_append(res, gm->y_sign ? "-" : "+");
APPEND_PER(y, y_per);
}
+ if (gm->ws > 0)
+ res = talloc_asprintf_append(res, "/%d", gm->ws);
}
return res;
}
@@ -2236,7 +2223,7 @@ void m_geometry_apply(int *xpos, int *ypos, int *widw, int *widh,
*widw = *widh * asp;
}
// Center window after resize. If valid x:y values are passed to
- // geometry, then those values will be overriden.
+ // geometry, then those values will be overridden.
*xpos += prew / 2 - *widw / 2;
*ypos += preh / 2 - *widh / 2;
}
@@ -2293,7 +2280,8 @@ static bool geometry_equal(const m_option_t *opt, void *a, void *b)
ga->xy_valid == gb->xy_valid && ga->wh_valid == gb->wh_valid &&
ga->w_per == gb->w_per && ga->h_per == gb->h_per &&
ga->x_per == gb->x_per && ga->y_per == gb->y_per &&
- ga->x_sign == gb->x_sign && ga->y_sign == gb->y_sign;
+ ga->x_sign == gb->x_sign && ga->y_sign == gb->y_sign &&
+ ga->ws == gb->ws;
}
con