m_property: add a sub-property mechanism

This adds a mechanism for easier export of sub-properties. The following
commits will make use of it to export fine grained information about
certain things. The sub-property mechanism reduces the amount of code
needed to export a data value to 1 line.
This commit is contained in:
wm4 2014-02-15 16:41:48 +01:00
parent ccfbe43455
commit 309ae76e0b
2 changed files with 88 additions and 1 deletions

View File

@ -386,3 +386,64 @@ int m_property_strdup_ro(const struct m_option* prop, int action, void* arg,
}
return M_PROPERTY_NOT_IMPLEMENTED;
}
// This allows you to make a list of values (like from a struct) available
// as a number of sub-properties. The property list is set up with the current
// property values on the stack before calling this function.
// This does not support write access.
int m_property_read_sub(const struct m_sub_property *props, int action, void *arg)
{
switch (action) {
case M_PROPERTY_GET_TYPE:
*(struct m_option *)arg = (struct m_option){
.name = "",
.type = CONF_TYPE_STRING,
};
return M_PROPERTY_OK;
case M_PROPERTY_GET:
case M_PROPERTY_PRINT: {
// Output "something" - what it really should return is not yet decided.
// It should probably be something that is easy to consume by slave
// mode clients. (M_PROPERTY_PRINT on the other hand can return this
// as human readable version just fine).
char *res = NULL;
for (int n = 0; props && props[n].name; n++) {
const struct m_sub_property *prop = &props[n];
if (prop->unavailable)
continue;
struct m_option type = { .name = "", .type = prop->type, };
char *s = m_option_print(&type, &prop->value);
ta_xasprintf_append(&res, "%s=%s\n", prop->name, s);
talloc_free(s);
}
*(char **)arg = res;
return M_PROPERTY_OK;
}
case M_PROPERTY_KEY_ACTION: {
struct m_property_action_arg *ka = arg;
const struct m_sub_property *prop = NULL;
for (int n = 0; props && props[n].name; n++) {
if (strcmp(props[n].name, ka->key) == 0) {
prop = &props[n];
break;
}
}
if (!prop)
return M_PROPERTY_UNKNOWN;
if (prop->unavailable)
return M_PROPERTY_UNAVAILABLE;
struct m_option type = { .name = "", .type = prop->type, };
switch (ka->action) {
case M_PROPERTY_GET: {
memset(ka->arg, 0, type.type->size);
m_option_copy(&type, ka->arg, &prop->value);
return M_PROPERTY_OK;
}
case M_PROPERTY_GET_TYPE:
*(struct m_option *)ka->arg = type;
return M_PROPERTY_OK;
}
}
}
return M_PROPERTY_NOT_IMPLEMENTED;
}

View File

@ -22,7 +22,8 @@
#include <stdbool.h>
#include <stdint.h>
struct m_option;
#include "m_option.h"
struct mp_log;
extern const struct m_option_type m_option_type_dummy;
@ -141,4 +142,29 @@ int m_property_double_ro(const struct m_option* prop, int action, void* arg,
int m_property_strdup_ro(const struct m_option* prop, int action, void* arg,
const char *var);
struct m_sub_property {
// Name of the sub-property - this will be prefixed with the parent
// property's name.
const char *name;
// Type of the data stored in the value member. See m_option.
const struct m_option_type *type;
// Data returned by the sub-property. m_property_read_sub() will make a
// copy of this if needed. It will never write or free the data.
union m_option_value value;
// This can be set to true if the property should be hidden.
bool unavailable;
};
// Convenience macros which can be used as part of a sub_property entry.
#define SUB_PROP_INT(i) \
.type = CONF_TYPE_INT, .value = {.int_ = (i)}
#define SUB_PROP_STR(s) \
.type = CONF_TYPE_STRING, .value = {.string = (char *)(s)}
#define SUB_PROP_FLOAT(f) \
.type = CONF_TYPE_FLOAT, .value = {.float_ = (f)}
#define SUB_PROP_FLAG(f) \
.type = CONF_TYPE_FLAG, .value = {.flag = (f)}
int m_property_read_sub(const struct m_sub_property *props, int action, void *arg);
#endif /* MPLAYER_M_PROPERTY_H */