summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-02-24 20:07:41 +0100
committerwm4 <wm4@nowhere>2014-02-24 22:50:23 +0100
commite94bab5a998ea35ee196a9296a30636a0a008554 (patch)
tree4035fa5aabe17e7dceb0fd188a3ba0404cb030f5
parent74e065473325c113f67c69b10c2647f0a8c49f4d (diff)
downloadmpv-e94bab5a998ea35ee196a9296a30636a0a008554.tar.bz2
mpv-e94bab5a998ea35ee196a9296a30636a0a008554.tar.xz
m_option: add a way to convert values to/from mpv_node
m_option is basically the mechanism to handle C data types in a dynamic way. Add functions to convert values to and from mpv_node. For example, string lists are turned into mpv_node using MPV_FORMAT_NODE_ARRAY, and so on.
-rw-r--r--options/m_option.c439
-rw-r--r--options/m_option.h38
2 files changed, 462 insertions, 15 deletions
diff --git a/options/m_option.c b/options/m_option.c
index 2d34b59f9d..3c6a1fc946 100644
--- a/options/m_option.c
+++ b/options/m_option.c
@@ -35,6 +35,8 @@
#include <libavutil/common.h>
#include <libavutil/avstring.h>
+#include "libmpv/client.h"
+
#include "talloc.h"
#include "common/common.h"
#include "common/msg.h"
@@ -159,6 +161,22 @@ static void add_flag(const m_option_t *opt, void *val, double add, bool wrap)
VAL(val) = state ? opt->max : opt->min;
}
+static int flag_set(const m_option_t *opt, void *dst, struct mpv_node *src)
+{
+ if (src->format != MPV_FORMAT_FLAG)
+ return M_OPT_UNKNOWN;
+ VAL(dst) = src->u.flag ? opt->max : opt->min;
+ return 1;
+}
+
+static int flag_get(const m_option_t *opt, void *ta_parent,
+ struct mpv_node *dst, void *src)
+{
+ dst->format = MPV_FORMAT_FLAG;
+ dst->u.flag = VAL(src) != opt->min;
+ return 1;
+}
+
const m_option_type_t m_option_type_flag = {
// need yes or no in config files
.name = "Flag",
@@ -169,6 +187,8 @@ const m_option_type_t m_option_type_flag = {
.copy = copy_opt,
.add = add_flag,
.clamp = clamp_flag,
+ .set = flag_set,
+ .get = flag_get,
};
// Single-value, write-only flag
@@ -187,6 +207,16 @@ static int parse_store(struct mp_log *log, const m_option_t *opt,
}
}
+static int store_set(const m_option_t *opt, void *dst, struct mpv_node *src)
+{
+ if (src->format != MPV_FORMAT_FLAG)
+ return M_OPT_UNKNOWN;
+ if (!src->u.flag)
+ return M_OPT_INVALID;
+ VAL(dst) = opt->max;
+ return 1;
+}
+
const m_option_type_t m_option_type_store = {
// can only be activated
.name = "Flag",
@@ -194,6 +224,7 @@ const m_option_type_t m_option_type_store = {
.flags = M_OPT_TYPE_OPTIONAL_PARAM,
.parse = parse_store,
.copy = copy_opt,
+ .set = store_set,
};
// Same for float types
@@ -215,6 +246,16 @@ static int parse_store_float(struct mp_log *log, const m_option_t *opt,
}
}
+static int store_float_set(const m_option_t *opt, void *dst, struct mpv_node *src)
+{
+ if (src->format != MPV_FORMAT_FLAG)
+ return M_OPT_UNKNOWN;
+ if (!src->u.flag)
+ return M_OPT_INVALID;
+ VAL(dst) = opt->max;
+ return 1;
+}
+
const m_option_type_t m_option_type_float_store = {
// can only be activated
.name = "Flag",
@@ -222,6 +263,7 @@ const m_option_type_t m_option_type_float_store = {
.flags = M_OPT_TYPE_OPTIONAL_PARAM,
.parse = parse_store_float,
.copy = copy_opt,
+ .set = store_float_set,
};
// Integer
@@ -368,6 +410,47 @@ static void multiply_int(const m_option_t *opt, void *val, double f)
*(int *)val = MPCLAMP(tmp, INT_MIN, INT_MAX);
}
+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)
+ return M_OPT_OUT_OF_RANGE;
+ if ((opt->flags & M_OPT_MAX) && val > opt->max)
+ return M_OPT_OUT_OF_RANGE;
+ *(int64_t *)dst = val;
+ return 1;
+}
+
+static int int_set(const m_option_t *opt, void *dst, struct mpv_node *src)
+{
+ int64_t val;
+ int r = int64_set(opt, &val, src);
+ if (r >= 0) {
+ if (val < INT_MIN || val > INT_MAX)
+ return M_OPT_OUT_OF_RANGE;
+ *(int *)dst = val;
+ }
+ return r;
+}
+
+static int int64_get(const m_option_t *opt, void *ta_parent,
+ struct mpv_node *dst, void *src)
+{
+ dst->format = MPV_FORMAT_INT64;
+ dst->u.int64 = *(int64_t *)src;
+ return 1;
+}
+
+static int int_get(const m_option_t *opt, void *ta_parent,
+ struct mpv_node *dst, void *src)
+{
+ dst->format = MPV_FORMAT_INT64;
+ dst->u.int64 = *(int *)src;
+ return 1;
+}
+
const m_option_type_t m_option_type_int = {
.name = "Integer",
.size = sizeof(int),
@@ -377,6 +460,8 @@ const m_option_type_t m_option_type_int = {
.add = add_int,
.multiply = multiply_int,
.clamp = clamp_int,
+ .set = int_set,
+ .get = int_get,
};
const m_option_type_t m_option_type_int64 = {
@@ -388,6 +473,8 @@ const m_option_type_t m_option_type_int64 = {
.add = add_int64,
.multiply = multiply_int64,
.clamp = clamp_int64,
+ .set = int64_set,
+ .get = int64_get,
};
static int parse_intpair(struct mp_log *log, const struct m_option *opt,
@@ -482,20 +569,6 @@ static int parse_choice(struct mp_log *log, const struct m_option *opt,
return 1;
}
-static char *print_choice(const m_option_t *opt, const void *val)
-{
- int v = *(int *)val;
- struct m_opt_choice_alternatives *alt;
- for (alt = opt->priv; alt->name; alt++)
- if (alt->value == v)
- return talloc_strdup(NULL, alt->name);
- if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
- if (v >= opt->min && v <= opt->max)
- return talloc_asprintf(NULL, "%d", v);
- }
- abort();
-}
-
static void choice_get_min_max(const struct m_option *opt, int *min, int *max)
{
assert(opt->type == &m_option_type_choice);
@@ -557,6 +630,73 @@ static void add_choice(const m_option_t *opt, void *val, double add, bool wrap)
*(int *)val = best;
}
+static int choice_set(const m_option_t *opt, void *dst, struct mpv_node *src)
+{
+ char buf[80];
+ char *src_str = NULL;
+ if (src->format == MPV_FORMAT_INT64) {
+ snprintf(buf, sizeof(buf), "%" PRId64, src->u.int64);
+ src_str = buf;
+ } else if (src->format == MPV_FORMAT_STRING) {
+ src_str = src->u.string;
+ }
+ if (!src_str)
+ return M_OPT_UNKNOWN;
+ int val = 0;
+ int r = parse_choice(mp_null_log, opt, (bstr){0}, bstr0(src_str), &val);
+ if (r >= 0)
+ *(int *)dst = val;
+ return r;
+}
+
+static 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;
+ 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 (v >= opt->min && v <= opt->max) {
+ *out_val = v;
+ return NULL;
+ }
+ }
+ abort();
+}
+
+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);
+ // If a choice string looks like a number, return it as number
+ if (alt) {
+ char *end = NULL;
+ ival = strtol(alt->name, &end, 10);
+ if (end && !end[0])
+ alt = NULL;
+ }
+ if (alt) {
+ dst->format = MPV_FORMAT_STRING;
+ dst->u.string = talloc_strdup(ta_parent, alt->name);
+ } else {
+ dst->format = MPV_FORMAT_INT64;
+ dst->u.int64 = ival;
+ }
+ return 1;
+}
+
+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);
+ return alt ? talloc_strdup(NULL, alt->name)
+ : talloc_asprintf(NULL, "%d", ival);
+}
+
const struct m_option_type m_option_type_choice = {
.name = "String", // same as arbitrary strings in option list for now
.size = sizeof(int),
@@ -565,6 +705,8 @@ const struct m_option_type m_option_type_choice = {
.copy = copy_opt,
.add = add_choice,
.clamp = clamp_choice,
+ .set = choice_set,
+ .get = choice_get,
};
// Float
@@ -669,6 +811,35 @@ static void multiply_double(const m_option_t *opt, void *val, double f)
clamp_double(opt, val);
}
+static int double_set(const m_option_t *opt, void *dst, struct mpv_node *src)
+{
+ double val;
+ if (src->format == MPV_FORMAT_INT64) {
+ // Can't always be represented exactly, but don't care.
+ val = src->u.int64;
+ } else if (src->format == MPV_FORMAT_DOUBLE) {
+ val = src->u.double_;
+ } else {
+ return M_OPT_UNKNOWN;
+ }
+ if ((opt->flags & M_OPT_MIN) && val < opt->min)
+ return M_OPT_OUT_OF_RANGE;
+ if ((opt->flags & M_OPT_MAX) && val > opt->max)
+ return M_OPT_OUT_OF_RANGE;
+ if (!isfinite(val))
+ return M_OPT_OUT_OF_RANGE;
+ *(double *)dst = val;
+ return 1;
+}
+
+static int double_get(const m_option_t *opt, void *ta_parent,
+ struct mpv_node *dst, void *src)
+{
+ dst->format = MPV_FORMAT_DOUBLE;
+ dst->u.double_ = *(double *)src;
+ return 1;
+}
+
const m_option_type_t m_option_type_double = {
// double precision float or ratio (numerator[:/]denominator)
.name = "Double",
@@ -680,6 +851,8 @@ const m_option_type_t m_option_type_double = {
.clamp = clamp_double,
.add = add_double,
.multiply = multiply_double,
+ .set = double_set,
+ .get = double_get,
};
#undef VAL
@@ -727,6 +900,23 @@ static void multiply_float(const m_option_t *opt, void *val, double f)
VAL(val) = tmp;
}
+static int float_set(const m_option_t *opt, void *dst, struct mpv_node *src)
+{
+ double tmp;
+ int r = double_set(opt, &tmp, src);
+ if (r >= 0)
+ VAL(dst) = tmp;
+ return r;
+}
+
+static int float_get(const m_option_t *opt, void *ta_parent,
+ struct mpv_node *dst, void *src)
+{
+ dst->format = MPV_FORMAT_DOUBLE;
+ dst->u.double_ = VAL(src);
+ return 1;
+}
+
const m_option_type_t m_option_type_float = {
// floating point number or ratio (numerator[:/]denominator)
.name = "Float",
@@ -738,6 +928,8 @@ const m_option_type_t m_option_type_float = {
.add = add_float,
.multiply = multiply_float,
.clamp = clamp_float,
+ .set = float_set,
+ .get = float_get,
};
///////////// String
@@ -802,6 +994,25 @@ static void copy_str(const m_option_t *opt, void *dst, const void *src)
}
}
+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;
+ if (r >= 0)
+ copy_str(opt, dst, &s);
+ return r;
+}
+
+static int str_get(const m_option_t *opt, void *ta_parent,
+ struct mpv_node *dst, void *src)
+{
+ dst->format = MPV_FORMAT_STRING;
+ dst->u.string = talloc_strdup(ta_parent, VAL(src) ? VAL(src) : "");
+ return 1;
+}
+
static void free_str(void *src)
{
if (src && VAL(src)) {
@@ -819,6 +1030,8 @@ const m_option_type_t m_option_type_string = {
.copy = copy_str,
.free = free_str,
.clamp = clamp_str,
+ .set = str_set,
+ .get = str_get,
};
//////////// String list
@@ -1077,6 +1290,40 @@ static char *print_str_list(const m_option_t *opt, const void *src)
return ret;
}
+static int str_list_set(const m_option_t *opt, void *dst, struct mpv_node *src)
+{
+ if (src->format != MPV_FORMAT_NODE_ARRAY)
+ return M_OPT_UNKNOWN;
+ struct mpv_node_list *srclist = src->u.list;
+ for (int n = 0; n < srclist->num; n++) {
+ if (srclist->values[n].format != MPV_FORMAT_STRING)
+ return M_OPT_INVALID;
+ }
+ free_str_list(dst);
+ if (srclist->num > 0) {
+ VAL(dst) = talloc_array(NULL, char*, srclist->num + 1);
+ for (int n = 0; n < srclist->num; n++)
+ VAL(dst)[n] = talloc_strdup(NULL, srclist->values[n].u.string);
+ VAL(dst)[srclist->num] = NULL;
+ }
+ return 1;
+}
+
+static int str_list_get(const m_option_t *opt, void *ta_parent,
+ struct mpv_node *dst, void *src)
+{
+ dst->format = MPV_FORMAT_NODE_ARRAY;
+ dst->u.list = talloc_zero(ta_parent, struct mpv_node_list);
+ struct mpv_node_list *list = dst->u.list;
+ for (int n = 0; VAL(src) && VAL(src)[n]; n++) {
+ struct mpv_node node;
+ node.format = MPV_FORMAT_STRING;
+ node.u.string = talloc_strdup(list, VAL(src)[n]);
+ MP_TARRAY_APPEND(list, list->values, list->num, node);
+ }
+ return 1;
+}
+
const m_option_type_t m_option_type_string_list = {
/* A list of strings separated by ','.
* Option with a name ending in '*' permits using the following suffixes:
@@ -1093,6 +1340,8 @@ const m_option_type_t m_option_type_string_list = {
.print = print_str_list,
.copy = copy_str_list,
.free = free_str_list,
+ .get = str_list_get,
+ .set = str_list_set,
};
static int read_subparam(struct mp_log *log, bstr optname,
@@ -1150,6 +1399,48 @@ static char *print_keyvalue_list(const m_option_t *opt, const void *src)
return ret;
}
+static int keyvalue_list_set(const m_option_t *opt, void *dst,
+ struct mpv_node *src)
+{
+ if (src->format != MPV_FORMAT_NODE_MAP)
+ return M_OPT_UNKNOWN;
+ struct mpv_node_list *srclist = src->u.list;
+ for (int n = 0; n < srclist->num; n++) {
+ if (srclist->values[n].format != MPV_FORMAT_STRING)
+ return M_OPT_INVALID;
+ }
+ free_str_list(dst);
+ if (srclist->num > 0) {
+ VAL(dst) = talloc_array(NULL, char*, (srclist->num + 1) * 2);
+ for (int n = 0; n < srclist->num; n++) {
+ VAL(dst)[n * 2 + 0] = talloc_strdup(NULL, srclist->keys[n]);
+ VAL(dst)[n * 2 + 1] = talloc_strdup(NULL, srclist->values[n].u.string);
+ }
+ VAL(dst)[srclist->num * 2 + 0] = NULL;
+ VAL(dst)[srclist->num * 2 + 1] = NULL;
+ }
+ return 1;
+}
+
+static int keyvalue_list_get(const m_option_t *opt, void *ta_parent,
+ struct mpv_node *dst, void *src)
+{
+ dst->format = MPV_FORMAT_NODE_MAP;
+ dst->u.list = talloc_zero(ta_parent, struct mpv_node_list);
+ struct mpv_node_list *list = dst->u.list;
+ for (int n = 0; VAL(src) && VAL(src)[n * 2 + 0]; n++) {
+ MP_TARRAY_GROW(list, list->values, list->num);
+ MP_TARRAY_GROW(list, list->keys, list->num);
+ list->keys[list->num] = talloc_strdup(list, VAL(src)[n * 2 + 0]);
+ list->values[list->num] = (struct mpv_node){
+ .format = MPV_FORMAT_STRING,
+ .u.string = talloc_strdup(list, VAL(src)[n * 2 + 1]),
+ };
+ list->num++;
+ }
+ return 1;
+}
+
const m_option_type_t m_option_type_keyvalue_list = {
.name = "Key/value list",
.size = sizeof(char **),
@@ -1158,6 +1449,8 @@ const m_option_type_t m_option_type_keyvalue_list = {
.print = print_keyvalue_list,
.copy = copy_str_list,
.free = free_str_list,
+ .get = keyvalue_list_get,
+ .set = keyvalue_list_set,
};
/////////////////// Print
@@ -1825,6 +2118,8 @@ const m_option_type_t m_option_type_time = {
.copy = copy_opt,
.add = add_double,
.clamp = clamp_double,
+ .set = double_set,
+ .get = double_get,
};
@@ -2540,3 +2835,119 @@ const m_option_type_t m_option_type_obj_settings_list = {
.copy = copy_obj_settings_list,
.free = free_obj_settings_list,
};
+
+#undef VAL
+#define VAL(x) (*(struct mpv_node *)(x))
+
+static int parse_node(struct mp_log *log, const m_option_t *opt,
+ struct bstr name, struct bstr param, void *dst)
+{
+ // Maybe use JSON?
+ mp_err(log, "option type doesn't accept strings");
+ return M_OPT_INVALID;
+}
+
+static char *print_node(const m_option_t *opt, const void *val)
+{
+ return talloc_strdup(NULL, "unimplemented");
+}
+
+static void dup_node(void *ta_parent, struct mpv_node *node)
+{
+ switch (node->format) {
+ case MPV_FORMAT_STRING:
+ node->u.string = talloc_strdup(ta_parent, node->u.string);
+ break;
+ case MPV_FORMAT_NODE_ARRAY:
+ case MPV_FORMAT_NODE_MAP: {
+ struct mpv_node_list *oldlist = node->u.list;
+ struct mpv_node_list *new = talloc_zero(ta_parent, struct mpv_node_list);
+ node->u.list = new;
+ if (oldlist->num > 0) {
+ *new = *oldlist;
+ new->values = talloc_array(new, struct mpv_node, new->num);
+ for (int n = 0; n < new->num; n++) {
+ new->values[n] = oldlist->values[n];
+ dup_node(new, &new->values[n]);
+ }
+ if (node->format == MPV_FORMAT_NODE_MAP) {
+ new->keys = talloc_array(new, char*, new->num);
+ for (int n = 0; n < new->num; n++)
+ new->keys[n] = talloc_strdup(new, oldlist->keys[n]);
+ }
+ }
+ break;
+ }
+ case MPV_FORMAT_NONE:
+ case MPV_FORMAT_FLAG:
+ case MPV_FORMAT_INT64:
+ case MPV_FORMAT_DOUBLE:
+ break;
+ default:
+ // unknown entry - mark as invalid
+ node->format = (mpv_format)-1;
+ }
+}
+
+static void copy_node(const m_option_t *opt, void *dst, const void *src)
+{
+ assert(sizeof(struct mpv_node) <= sizeof(union m_option_value));
+
+ if (!(dst && src))
+ return;
+
+ opt->type->free(dst);
+ VAL(dst) = VAL(src);
+ dup_node(NULL, &VAL(dst));
+}
+
+static void *node_get_alloc(struct mpv_node *node)
+{
+ // Assume it was allocated with copy_node(), which allocates all
+ // sub-nodes with the parent node as talloc parent.
+ switch (node->format) {
+ case MPV_FORMAT_STRING:
+ return node->u.string;
+ case MPV_FORMAT_NODE_ARRAY:
+ case MPV_FORMAT_NODE_MAP:
+ return node->u.list;
+ default:
+ return NULL;
+ }
+}
+
+static void free_node(void *src)
+{
+ if (src) {
+ struct mpv_node *node = &VAL(src);
+ talloc_free(node_get_alloc(node));
+ *node = (struct mpv_node){{0}};
+ }
+}
+
+// idempotent functions for convenience
+static int node_set(const m_option_t *opt, void *dst, struct mpv_node *src)
+{
+ copy_node(opt, dst, src);
+ return 1;
+}
+
+static int node_get(const m_option_t *opt, void *ta_parent,
+ struct mpv_node *dst, void *src)
+{
+ *dst = VAL(src);
+ dup_node(ta_parent, dst);
+ return 1;
+}
+
+const m_option_type_t m_option_type_node = {
+ .name = "Complex",
+ .size = sizeof(struct mpv_node),
+ .flags = M_OPT_TYPE_DYNAMIC,
+ .parse = parse_node,
+ .print = print_node,
+ .copy = copy_node,
+ .free = free_node,
+ .set = node_set,
+ .get = node_get,
+};
diff --git a/options/m_option.h b/options/m_option.h
index fc46599483..1a9bf784b6 100644
--- a/options/m_option.h
+++ b/options/m_option.h
@@ -32,6 +32,7 @@ typedef struct m_option_type m_option_type_t;
typedef struct m_option m_option_t;
struct m_config;
struct mp_log;
+struct mpv_node;
///////////////////////////// Options types declarations ////////////////////
@@ -61,6 +62,7 @@ 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;
extern const m_option_type_t m_option_type_chmap;
+extern const m_option_type_t m_option_type_node;
// Callback used by m_option_type_print_fn options.
typedef void (*m_opt_print_fn)(struct mp_log *log);
@@ -168,7 +170,6 @@ struct m_sub_options {
const void *defaults;
};
-// FIXME: backward compatibility
#define CONF_TYPE_FLAG (&m_option_type_flag)
#define CONF_TYPE_STORE (&m_option_type_store)
#define CONF_TYPE_INT (&m_option_type_int)
@@ -185,6 +186,7 @@ struct m_sub_options {
#define CONF_TYPE_TIME (&m_option_type_time)
#define CONF_TYPE_CHOICE (&m_option_type_choice)
#define CONF_TYPE_INT_PAIR (&m_option_type_intpair)
+#define CONF_TYPE_NODE (&m_option_type_node)
// Possible option values. Code is allowed to access option data without going
// through this union. It serves for self-documentation and to get minimal
@@ -253,6 +255,7 @@ struct m_option_type {
char *(*pretty_print)(const m_option_t *opt, const void *val);
// Copy data between two locations. Deep copy if the data has pointers.
+ // The implementation must free *dst if memory allocation is involved.
/** \param opt The option to copy.
* \param dst Pointer to the destination memory.
* \param src Pointer to the source memory.
@@ -281,6 +284,21 @@ struct m_option_type {
// M_OPT_INVALID: val was invalid, and can't be made valid
// 0: val was already valid and is unchanged
int (*clamp)(const m_option_t *opt, void *val);
+
+ // Set the option value in dst to the contents of src.
+ // (If the option is dynamic, the old value in *dst has to be freed.)
+ // Return values:
+ // M_OPT_UNKNOWN: src is in an unknown format
+ // M_OPT_INVALID: src is incorrectly formatted
+ // >= 0: success
+ // other error code: some other error, essentially M_OPT_INVALID refined
+ int (*set)(const m_option_t *opt, void *dst, struct mpv_node *src);
+
+ // Copy the option value in src to dst. Use ta_parent for any dynamic
+ // memory allocations. It's explicitly allowed to have mpv_node reference
+ // static strings (and even mpv_node_list.keys), though.
+ int (*get)(const m_option_t *opt, void *ta_parent, struct mpv_node *dst,
+ void *src);
};
// Option description
@@ -471,6 +489,24 @@ static inline void m_option_free(const m_option_t *opt, void *dst)
opt->type->free(dst);
}
+// see m_option_type.set
+static inline int m_option_set_node(const m_option_t *opt, void *dst,
+ struct mpv_node *src)
+{
+ if (opt->type->set)
+ return opt->type->set(opt, dst, src);
+ return M_OPT_UNKNOWN;
+}
+
+// see m_option_type.get
+static inline int m_option_get_node(const m_option_t *opt, void *ta_parent,
+ struct mpv_node *dst, void *src)
+{
+ if (opt->type->get)
+ return opt->type->get(opt, ta_parent, dst, src);
+ return M_OPT_UNKNOWN;
+}
+
int m_option_required_params(const m_option_t *opt);
extern const char m_option_path_separator;