aboutsummaryrefslogtreecommitdiffhomepage
path: root/options
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2014-02-15 16:49:28 +0100
committerGravatar wm4 <wm4@nowhere>2014-02-16 03:51:02 +0100
commit801de5ac6d16ba87143ff42fe218558ebc37efd3 (patch)
tree370c7244189afeeda1d769063a0a672e22807301 /options
parent486658e5c75a036e1b9eea953021c46d7ecc6b85 (diff)
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.
Diffstat (limited to 'options')
-rw-r--r--options/m_property.c77
-rw-r--r--options/m_property.h12
2 files changed, 89 insertions, 0 deletions
diff --git a/options/m_property.c b/options/m_property.c
index d863a06ab3..308bed55e0 100644
--- a/options/m_property.c
+++ b/options/m_property.c
@@ -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;
+}
diff --git a/options/m_property.h b/options/m_property.h
index cb9f8b5a25..460f8a986c 100644
--- a/options/m_property.h
+++ b/options/m_property.h
@@ -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 */