mirror of https://github.com/mpv-player/mpv
m_property: add a mechanism to organize a list of sub-properties
This automatically adds a "count" sub-property, and for each entry in the range [0, count), a numbered sub-property to access the item.
This commit is contained in:
parent
486658e5c7
commit
801de5ac6d
|
@ -447,3 +447,80 @@ int m_property_read_sub(const struct m_sub_property *props, int action, void *ar
|
|||
}
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
// Make a list of items available as indexed sub-properties. E.g. you can access
|
||||
// item 0 as "property/0", item 1 as "property/1", etc., where each of these
|
||||
// properties is redirected to the get_item(0, ...), get_item(1, ...), callback.
|
||||
// Additionally, the number of entries is made available as "property/count".
|
||||
// action, arg: property access.
|
||||
// count: number of items.
|
||||
// get_item: callback to access a single item.
|
||||
// ctx: userdata passed to get_item.
|
||||
int m_property_read_list(int action, void *arg, int count,
|
||||
m_get_item_cb get_item, void *ctx)
|
||||
{
|
||||
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: {
|
||||
// See m_property_read_sub() remarks.
|
||||
char *res = NULL;
|
||||
for (int n = 0; n < count; n++) {
|
||||
char *s = NULL;
|
||||
int r = get_item(n, M_PROPERTY_PRINT, &s, ctx);
|
||||
if (r != M_PROPERTY_OK) {
|
||||
talloc_free(res);
|
||||
return r;
|
||||
}
|
||||
ta_xasprintf_append(&res, "%d: %s\n", n, s);
|
||||
talloc_free(s);
|
||||
}
|
||||
*(char **)arg = res;
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
case M_PROPERTY_KEY_ACTION: {
|
||||
struct m_property_action_arg *ka = arg;
|
||||
if (strcmp(ka->key, "count") == 0) {
|
||||
switch (ka->action) {
|
||||
case M_PROPERTY_GET_TYPE: {
|
||||
struct m_option opt = {
|
||||
.name = "",
|
||||
.type = CONF_TYPE_INT,
|
||||
};
|
||||
*(struct m_option *)ka->arg = opt;
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
case M_PROPERTY_GET:
|
||||
*(int *)ka->arg = MPMAX(0, count);
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
}
|
||||
// This is expected of the form "123" or "123/rest"
|
||||
char *next = strchr(ka->key, '/');
|
||||
char *end = NULL;
|
||||
long int item = strtol(ka->key, &end, 10);
|
||||
// not a number, trailing characters, etc.
|
||||
if (end != ka->key + strlen(ka->key) && end != next)
|
||||
return M_PROPERTY_UNKNOWN;
|
||||
if (item < 0 || item >= count)
|
||||
return M_PROPERTY_UNKNOWN;
|
||||
if (next) {
|
||||
// Sub-path
|
||||
struct m_property_action_arg n_ka = *ka;
|
||||
n_ka.key = next + 1;
|
||||
return get_item(item, M_PROPERTY_KEY_ACTION, &n_ka, ctx);
|
||||
} else {
|
||||
// Direct query
|
||||
return get_item(item, ka->action, ka->arg, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -167,4 +167,16 @@ struct m_sub_property {
|
|||
|
||||
int m_property_read_sub(const struct m_sub_property *props, int action, void *arg);
|
||||
|
||||
|
||||
// Used with m_property_read_list().
|
||||
// Get an entry. item is the 0-based index of the item. This behaves like a
|
||||
// top-level property request (but you must implement M_PROPERTY_GET_TYPE).
|
||||
// item will be in range [0, count), for count see m_property_read_list()
|
||||
// action, arg are for property access.
|
||||
// ctx is userdata passed to m_property_read_list.
|
||||
typedef int (*m_get_item_cb)(int item, int action, void *arg, void *ctx);
|
||||
|
||||
int m_property_read_list(int action, void *arg, int count,
|
||||
m_get_item_cb get_item, void *ctx);
|
||||
|
||||
#endif /* MPLAYER_M_PROPERTY_H */
|
||||
|
|
Loading…
Reference in New Issue