From 7270986c3aace1c03685f35acd1ddc25aef81956 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 23 Mar 2017 08:54:04 +0100 Subject: [PATCH] monitor: use dynamic types Make the monitor item a POD object and use dynamic types. --- pinos/client/uri.c | 1 + pinos/client/uri.h | 2 + pinos/modules/spa/spa-monitor.c | 90 +++++++++++------- spa/include/spa/monitor.h | 87 +++++++++++------ spa/include/spa/plugin.h | 3 + spa/include/spa/pod-builder.h | 18 ++++ spa/include/spa/pod-iter.h | 6 +- spa/include/spa/pod-utils.h | 12 ++- spa/include/spa/pod.h | 11 +++ spa/lib/debug.c | 8 ++ spa/lib/mapper.c | 2 +- spa/plugins/alsa/alsa-monitor.c | 155 ++++++++++++++++-------------- spa/plugins/v4l2/v4l2-monitor.c | 163 +++++++++++++++++--------------- spa/tools/spa-monitor.c | 50 ++++------ 14 files changed, 360 insertions(+), 248 deletions(-) diff --git a/pinos/client/uri.c b/pinos/client/uri.c index 5ae8becea..500fe13a1 100644 --- a/pinos/client/uri.c +++ b/pinos/client/uri.c @@ -51,4 +51,5 @@ pinos_uri_init (PinosURI *uri) spa_node_events_map (uri->map, &uri->node_events); spa_node_commands_map (uri->map, &uri->node_commands); + spa_monitor_types_map (uri->map, &uri->monitor_types); } diff --git a/pinos/client/uri.h b/pinos/client/uri.h index 109ce5f4f..d8ac1e79e 100644 --- a/pinos/client/uri.h +++ b/pinos/client/uri.h @@ -30,6 +30,7 @@ extern "C" { #include #include #include +#include typedef struct _PinosURI PinosURI; @@ -56,6 +57,7 @@ struct _PinosURI { SpaNodeEvents node_events; SpaNodeCommands node_commands; + SpaMonitorTypes monitor_types; }; void pinos_uri_init (PinosURI *uri); diff --git a/pinos/modules/spa/spa-monitor.c b/pinos/modules/spa/spa-monitor.c index 88fc36ceb..a2b1cdc12 100644 --- a/pinos/modules/spa/spa-monitor.c +++ b/pinos/modules/spa/spa-monitor.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -61,13 +62,24 @@ add_item (PinosSpaMonitor *this, SpaMonitorItem *item) void *node_iface; void *clock_iface; PinosProperties *props = NULL; + const char *name, *id, *klass; + SpaHandleFactory *factory; + SpaPOD *info = NULL; - pinos_log_debug ("monitor %p: add: \"%s\" (%s)", this, item->name, item->id); + spa_pod_object_query (item, + impl->core->uri.monitor_types.name, SPA_POD_TYPE_STRING, &name, + impl->core->uri.monitor_types.id, SPA_POD_TYPE_STRING, &id, + impl->core->uri.monitor_types.klass, SPA_POD_TYPE_STRING, &klass, + impl->core->uri.monitor_types.factory, SPA_POD_TYPE_POINTER, &factory, + impl->core->uri.monitor_types.info, SPA_POD_TYPE_STRUCT, &info, + 0); - handle = calloc (1, item->factory->size); - if ((res = spa_handle_factory_init (item->factory, + pinos_log_debug ("monitor %p: add: \"%s\" (%s)", this, name, id); + + handle = calloc (1, factory->size); + if ((res = spa_handle_factory_init (factory, handle, - item->info, + NULL, //item->info, impl->core->support, impl->core->n_support)) < 0) { pinos_log_error ("can't make factory instance: %d", res); @@ -83,22 +95,23 @@ add_item (PinosSpaMonitor *this, SpaMonitorItem *item) props = pinos_properties_new (NULL, NULL); - if (item->info) { - uint32_t i; + if (info) { + SpaPODIter it; - for (i = 0; i < item->info->n_items; i++) { - pinos_properties_set (props, - item->info->items[i].key, - item->info->items[i].value); + spa_pod_iter_pod (&it, info); + while (true) { + const char *key, *val; + if (!spa_pod_iter_get (&it, SPA_POD_TYPE_STRING, &key, SPA_POD_TYPE_STRING, &val, 0)) + break; + pinos_properties_set (props, key, val); } } - - pinos_properties_set (props, "media.class", item->klass); + pinos_properties_set (props, "media.class", klass); mitem = calloc (1, sizeof (PinosSpaMonitorItem)); - mitem->id = strdup (item->id); + mitem->id = strdup (id); mitem->node = pinos_node_new (impl->core, - item->name, + name, node_iface, clock_iface, props); @@ -133,10 +146,17 @@ destroy_item (PinosSpaMonitorItem *mitem) static void remove_item (PinosSpaMonitor *this, SpaMonitorItem *item) { + PinosSpaMonitorImpl *impl = SPA_CONTAINER_OF (this, PinosSpaMonitorImpl, this); PinosSpaMonitorItem *mitem; + const char *name, *id; - pinos_log_debug ("monitor %p: remove: \"%s\" (%s)", this, item->name, item->id); - mitem = find_item (this, item->id); + spa_pod_object_query (item, + impl->core->uri.monitor_types.name, SPA_POD_TYPE_STRING, &name, + impl->core->uri.monitor_types.id, SPA_POD_TYPE_STRING, &id, + 0); + + pinos_log_debug ("monitor %p: remove: \"%s\" (%s)", this, name, id); + mitem = find_item (this, id); if (mitem) destroy_item (mitem); } @@ -147,27 +167,25 @@ on_monitor_event (SpaMonitor *monitor, void *user_data) { PinosSpaMonitor *this = user_data; + PinosSpaMonitorImpl *impl = SPA_CONTAINER_OF (this, PinosSpaMonitorImpl, this); - switch (event->type) { - case SPA_MONITOR_EVENT_TYPE_ADDED: - { - SpaMonitorItem *item = (SpaMonitorItem *) event; - add_item (this, item); - break; - } - case SPA_MONITOR_EVENT_TYPE_REMOVED: - { - SpaMonitorItem *item = (SpaMonitorItem *) event; - remove_item (this, item); - } - case SPA_MONITOR_EVENT_TYPE_CHANGED: - { - SpaMonitorItem *item = (SpaMonitorItem *) event; - pinos_log_debug ("monitor %p: changed: \"%s\"", this, item->name); - break; - } - default: - break; + if (SPA_EVENT_TYPE (event) == impl->core->uri.monitor_types.Added) { + SpaMonitorItem *item = SPA_POD_CONTENTS (SpaEvent, event); + add_item (this, item); + } + else if (SPA_EVENT_TYPE (event) == impl->core->uri.monitor_types.Removed) { + SpaMonitorItem *item = SPA_POD_CONTENTS (SpaEvent, event); + remove_item (this, item); + } + else if (SPA_EVENT_TYPE (event) == impl->core->uri.monitor_types.Changed) { + SpaMonitorItem *item = SPA_POD_CONTENTS (SpaEvent, event); + const char *name; + + spa_pod_object_query (item, + impl->core->uri.monitor_types.name, SPA_POD_TYPE_STRING, &name, + 0); + + pinos_log_debug ("monitor %p: changed: \"%s\"", this, name); } } diff --git a/spa/include/spa/monitor.h b/spa/include/spa/monitor.h index 864ef26c2..2a5e0609f 100644 --- a/spa/include/spa/monitor.h +++ b/spa/include/spa/monitor.h @@ -31,26 +31,62 @@ typedef struct _SpaMonitor SpaMonitor; #include #include -#include +#include -/** - * SpaMonitorEventType: - * @SPA_MONITOR_EVENT_TYPE_INVALID: invalid event - * @SPA_MONITOR_EVENT_TYPE_ADDED: an item was added, data points to #SpaMonitorItem - * @SPA_MONITOR_EVENT_TYPE_REMOVED: an item was removed, data points to #SpaMonitorItem - * @SPA_MONITOR_EVENT_TYPE_CHANGED: an item was changed, data points to #SpaMonitorItem - */ -typedef enum { - SPA_MONITOR_EVENT_TYPE_INVALID = 0, - SPA_MONITOR_EVENT_TYPE_ADDED, - SPA_MONITOR_EVENT_TYPE_REMOVED, - SPA_MONITOR_EVENT_TYPE_CHANGED, -} SpaMonitorEventType; +typedef SpaEvent SpaMonitorEvent; +#define SPA_MONITOR_EVENT_URI "http://spaplug.in/ns/monitor-event" +#define SPA_MONITOR_EVENT_PREFIX SPA_MONITOR_EVENT_URI "#" + +#define SPA_MONITOR_EVENT__Added SPA_MONITOR_EVENT_PREFIX "Added" +#define SPA_MONITOR_EVENT__Removed SPA_MONITOR_EVENT_PREFIX "Removed" +#define SPA_MONITOR_EVENT__Changed SPA_MONITOR_EVENT_PREFIX "Changed" + +typedef SpaPODObject SpaMonitorItem; +#define SPA_MONITOR_ITEM_URI "http://spaplug.in/ns/monitor-item" +#define SPA_MONITOR_ITEM_PREFIX SPA_MONITOR_ITEM_URI "#" +#define SPA_MONITOR_ITEM__id SPA_MONITOR_ITEM_PREFIX "id" +#define SPA_MONITOR_ITEM__flags SPA_MONITOR_ITEM_PREFIX "flags" +#define SPA_MONITOR_ITEM__state SPA_MONITOR_ITEM_PREFIX "state" +#define SPA_MONITOR_ITEM__name SPA_MONITOR_ITEM_PREFIX "name" +#define SPA_MONITOR_ITEM__class SPA_MONITOR_ITEM_PREFIX "class" +#define SPA_MONITOR_ITEM__info SPA_MONITOR_ITEM_PREFIX "info" +#define SPA_MONITOR_ITEM__factory SPA_MONITOR_ITEM_PREFIX "factory" typedef struct { - SpaMonitorEventType type; - uint32_t size; -} SpaMonitorEvent; + uint32_t Monitor; + + uint32_t Added; + uint32_t Removed; + uint32_t Changed; + + uint32_t MonitorItem; + uint32_t id; + uint32_t flags; + uint32_t state; + uint32_t name; + uint32_t klass; + uint32_t info; + uint32_t factory; +} SpaMonitorTypes; + +static inline void +spa_monitor_types_map (SpaIDMap *map, SpaMonitorTypes *types) +{ + if (types->Added == 0) { + types->Monitor = spa_id_map_get_id (map, SPA_MONITOR_URI); + types->Added = spa_id_map_get_id (map, SPA_MONITOR_EVENT__Added); + types->Removed = spa_id_map_get_id (map, SPA_MONITOR_EVENT__Removed); + types->Changed = spa_id_map_get_id (map, SPA_MONITOR_EVENT__Changed); + types->MonitorItem = spa_id_map_get_id (map, SPA_MONITOR_ITEM_URI); + types->id = spa_id_map_get_id (map, SPA_MONITOR_ITEM__id); + types->flags = spa_id_map_get_id (map, SPA_MONITOR_ITEM__flags); + types->state = spa_id_map_get_id (map, SPA_MONITOR_ITEM__state); + types->name = spa_id_map_get_id (map, SPA_MONITOR_ITEM__name); + types->klass = spa_id_map_get_id (map, SPA_MONITOR_ITEM__class); + types->info = spa_id_map_get_id (map, SPA_MONITOR_ITEM__info); + types->factory = spa_id_map_get_id (map, SPA_MONITOR_ITEM__factory); + } +} typedef enum { SPA_MONITOR_ITEM_FLAG_NONE = 0, @@ -68,17 +104,6 @@ typedef enum { SPA_MONITOR_ITEM_STATE_UNAVAILABLE, } SpaMonitorItemState; -typedef struct { - SpaMonitorEvent event; - const char *id; - SpaMonitorItemFlags flags; - SpaMonitorItemState state; - const char *name; - const char *klass; - const SpaDict *info; - const SpaHandleFactory *factory; -} SpaMonitorItem; - /** * SpaMonitorCallback: * @node: a #SpaMonitor emiting the event @@ -88,9 +113,9 @@ typedef struct { * This will be called when a monitor event is notified * on @monitor. */ -typedef void (*SpaMonitorEventCallback) (SpaMonitor *monitor, - SpaMonitorEvent *event, - void *user_data); +typedef void (*SpaMonitorEventCallback) (SpaMonitor *monitor, + SpaMonitorEvent *event, + void *user_data); /** * SpaMonitor: diff --git a/spa/include/spa/plugin.h b/spa/include/spa/plugin.h index eb1f08901..6c468e810 100644 --- a/spa/include/spa/plugin.h +++ b/spa/include/spa/plugin.h @@ -27,6 +27,9 @@ extern "C" { #include #include +#define SPA_HANDLE_URI "http://spaplug.in/ns/handle" +#define SPA_HANDLE_FACTORY_URI "http://spaplug.in/ns/handle-factory" + typedef struct _SpaHandle SpaHandle; typedef struct _SpaHandleFactory SpaHandleFactory; diff --git a/spa/include/spa/pod-builder.h b/spa/include/spa/pod-builder.h index 9936688b3..e69441914 100644 --- a/spa/include/spa/pod-builder.h +++ b/spa/include/spa/pod-builder.h @@ -233,6 +233,15 @@ spa_pod_builder_bytes (SpaPODBuilder *builder, const void *bytes, uint32_t len) return ref; } +#define SPA_POD_POINTER_INIT(type,value) { { sizeof (SpaPODPointerBody), SPA_POD_TYPE_POINTER }, { type, value } } + +static inline uint32_t +spa_pod_builder_pointer (SpaPODBuilder *builder, uint32_t type, void *val) +{ + const SpaPODPointer p = SPA_POD_POINTER_INIT (type, val); + return spa_pod_builder_primitive (builder, &p.pod); +} + #define SPA_POD_RECTANGLE_INIT(width,height) { { sizeof (SpaRectangle), SPA_POD_TYPE_RECTANGLE }, { width, height } } static inline uint32_t @@ -329,6 +338,7 @@ spa_pod_builder_addv (SpaPODBuilder *builder, SpaPODDouble double_pod; SpaPODString string_pod; SpaPODBytes bytes_pod; + SpaPODPointer pointer_pod; SpaPODRectangle rectangle_pod; SpaPODFraction fraction_pod; SpaPODArray array_pod; @@ -400,6 +410,14 @@ spa_pod_builder_addv (SpaPODBuilder *builder, head.bytes_pod.pod.size = body_size; head_size = sizeof (SpaPOD); goto primitive; + case SPA_POD_TYPE_POINTER: + head.pointer_pod.pod.type = SPA_POD_TYPE_POINTER; + head.pointer_pod.pod.size = body_size = sizeof (SpaPODPointerBody); + head.pointer_pod.body.type = va_arg (args, uint32_t); + head.pointer_pod.body.value = va_arg (args, void *); + head_size = sizeof (SpaPOD); + body = &head.pointer_pod.body; + goto primitive; case SPA_POD_TYPE_RECTANGLE: head.rectangle_pod.pod.type = SPA_POD_TYPE_RECTANGLE; head.rectangle_pod.pod.size = body_size = sizeof (SpaRectangle); diff --git a/spa/include/spa/pod-iter.h b/spa/include/spa/pod-iter.h index a75e41266..86b061041 100644 --- a/spa/include/spa/pod-iter.h +++ b/spa/include/spa/pod-iter.h @@ -116,7 +116,9 @@ spa_pod_iter_getv (SpaPODIter *iter, uint32_t type, va_list args) { - while (type && spa_pod_iter_has_next (iter)) { + bool res = true; + + while (type && (res = spa_pod_iter_has_next (iter))) { SpaPOD *pod = spa_pod_iter_next (iter); if (type != SPA_POD_TYPE_POD && pod->type != type) @@ -126,7 +128,7 @@ spa_pod_iter_getv (SpaPODIter *iter, type = va_arg (args, uint32_t); } - return true; + return res; } static inline bool diff --git a/spa/include/spa/pod-utils.h b/spa/include/spa/pod-utils.h index 4bdfa9cc1..2e0be95a0 100644 --- a/spa/include/spa/pod-utils.h +++ b/spa/include/spa/pod-utils.h @@ -120,6 +120,12 @@ spa_pod_object_find_prop (const SpaPODObject *obj, uint32_t key) *(va_arg (args, void **)) = SPA_POD_CONTENTS (SpaPODBytes, pod); \ *(va_arg (args, uint32_t *)) = SPA_POD_BODY_SIZE (pod); \ break; \ + case SPA_POD_TYPE_POINTER: \ + { \ + SpaPODPointerBody *b = SPA_POD_BODY (pod); \ + *(va_arg (args, void **)) = b->value; \ + break; \ + } \ case SPA_POD_TYPE_RECTANGLE: \ *(va_arg (args, SpaRectangle *)) = SPA_POD_VALUE (SpaPODRectangle, pod); \ break; \ @@ -143,6 +149,7 @@ spa_pod_object_find_prop (const SpaPODObject *obj, uint32_t key) #define SPA_POD_COLLECT_SKIP(type,args) \ switch (type) { \ case SPA_POD_TYPE_BYTES: \ + case SPA_POD_TYPE_POINTER: \ va_arg (args, void*); \ /* fallthrough */ \ case SPA_POD_TYPE_BOOL: \ @@ -177,7 +184,7 @@ spa_pod_contents_queryv (const SpaPOD *pod, uint32_t offset, uint32_t key, va_li type = va_arg (args, uint32_t); if (prop && prop->body.key == key && - prop->body.value.type == type && + (type == SPA_POD_TYPE_POD || prop->body.value.type == type) && !(prop->body.flags & SPA_POD_PROP_FLAG_UNSET)) { SPA_POD_COLLECT (&prop->body.value, type, args); count++; @@ -202,6 +209,9 @@ spa_pod_contents_query (const SpaPOD *pod, uint32_t offset, uint32_t key, ...) return count; } +#define spa_pod_object_query(object,key, ...) \ + spa_pod_contents_query (&object->pod, sizeof (SpaPODObject), key, __VA_ARGS__) + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/include/spa/pod.h b/spa/include/spa/pod.h index 710d95ca6..3f9024e26 100644 --- a/spa/include/spa/pod.h +++ b/spa/include/spa/pod.h @@ -45,6 +45,7 @@ typedef enum { SPA_POD_TYPE_DOUBLE, SPA_POD_TYPE_STRING, SPA_POD_TYPE_BYTES, + SPA_POD_TYPE_POINTER, SPA_POD_TYPE_RECTANGLE, SPA_POD_TYPE_FRACTION, SPA_POD_TYPE_BITMASK, @@ -94,6 +95,16 @@ typedef struct { /* value here */ } SpaPODBytes; +typedef struct { + uint32_t type; + void *value; +} SpaPODPointerBody; + +typedef struct { + SpaPOD pod; + SpaPODPointerBody body; +} SpaPODPointer; + typedef struct { SpaPOD pod; SpaRectangle value; diff --git a/spa/lib/debug.c b/spa/lib/debug.c index 962362e21..9cddd3843 100644 --- a/spa/lib/debug.c +++ b/spa/lib/debug.c @@ -195,6 +195,7 @@ struct pod_type_name { { "float", "Float" }, { "double", "Double" }, { "string", "String" }, + { "pointer", "Pointer" }, { "rectangle", "Rectangle" }, { "fraction", "Fraction" }, { "bitmask", "Bitmask" }, @@ -231,6 +232,13 @@ print_pod_value (uint32_t size, uint32_t type, void *body, int prefix) case SPA_POD_TYPE_STRING: printf ("%-*sString \"%s\"\n", prefix, "", (char *) body); break; + case SPA_POD_TYPE_POINTER: + { + SpaPODPointerBody *b = body; + printf ("%-*sPointer %s %p\n", prefix, "", + spa_id_map_get_uri (spa_id_map_get_default(), b->type), b->value); + break; + } case SPA_POD_TYPE_RECTANGLE: { SpaRectangle *r = body; diff --git a/spa/lib/mapper.c b/spa/lib/mapper.c index 78081e620..ce907e818 100644 --- a/spa/lib/mapper.c +++ b/spa/lib/mapper.c @@ -56,7 +56,7 @@ id_map_get_uri (SpaIDMap *map, uint32_t id) { IDMap *this = SPA_CONTAINER_OF (map, IDMap, map); - if (id < this->n_uris) + if (id <= this->n_uris) return this->uris[id]; return NULL; diff --git a/spa/plugins/alsa/alsa-monitor.c b/spa/plugins/alsa/alsa-monitor.c index bd557e0a9..1f5585cd6 100644 --- a/spa/plugins/alsa/alsa-monitor.c +++ b/spa/plugins/alsa/alsa-monitor.c @@ -39,14 +39,13 @@ extern const SpaHandleFactory spa_alsa_source_factory; typedef struct _SpaALSAMonitor SpaALSAMonitor; typedef struct { - SpaMonitorItem item; + SpaMonitorItem *item; struct udev_device *udevice; - SpaDict info; - SpaDictItem info_items[32]; } ALSAItem; typedef struct { - uint32_t monitor; + uint32_t handle_factory; + SpaMonitorTypes monitor_types; } URI; struct _SpaALSAMonitor { @@ -66,6 +65,7 @@ struct _SpaALSAMonitor { struct udev_enumerate *enumerate; uint32_t index; struct udev_list_entry *devices; + uint8_t item_buffer[4096]; ALSAItem uitem; @@ -107,10 +107,12 @@ static int fill_item (SpaALSAMonitor *this, ALSAItem *item, struct udev_device *udevice) { int err; - uint32_t i; - const char *str; + const char *str, *name; snd_pcm_t *hndl; char device[64]; + SpaPODBuilder b = { NULL, }; + const SpaHandleFactory *factory = NULL; + SpaPODFrame f[3]; if (item->udevice) udev_device_unref (item->udevice); @@ -148,60 +150,72 @@ fill_item (SpaALSAMonitor *this, ALSAItem *item, struct udev_device *udevice) spa_log_error (this->log, "CAPTURE open failed: %s", snd_strerror(err)); return -1; } else { - item->item.factory = &spa_alsa_source_factory; + factory = &spa_alsa_source_factory; snd_pcm_close (hndl); } } else { - item->item.factory = &spa_alsa_sink_factory; + factory = &spa_alsa_sink_factory; snd_pcm_close (hndl); } - item->item.id = udev_device_get_syspath (item->udevice); - item->item.flags = 0; - item->item.state = SPA_MONITOR_ITEM_STATE_AVAILABLE; - item->item.klass = "Audio/Device"; - item->item.info = &item->info; + name = udev_device_get_property_value (item->udevice, "ID_MODEL_FROM_DATABASE"); + if (!(name && *name)) { + name = udev_device_get_property_value (item->udevice, "ID_MODEL_ENC"); + if (!(name && *name)) { + name = udev_device_get_property_value (item->udevice, "ID_MODEL"); + } + } + if (!(str && *str)) + name = "Unknown"; - item->info.items = item->info_items; - i = 0; - item->info_items[i].key = "alsa.card"; - item->info_items[i++].value = str; - item->info_items[i].key = "udev-probed"; - item->info_items[i++].value = "1"; - item->info_items[i].key = "device.api"; - item->info_items[i++].value = "alsa"; + spa_pod_builder_init (&b, this->item_buffer, sizeof (this->item_buffer)); + + spa_pod_builder_push_object (&b, &f[0], 0, this->uri.monitor_types.MonitorItem); + + spa_pod_builder_add (&b, + SPA_POD_PROP (&f[1], this->uri.monitor_types.id, 0, SPA_POD_TYPE_STRING, 1, udev_device_get_syspath (item->udevice)), + SPA_POD_PROP (&f[1], this->uri.monitor_types.flags, 0, SPA_POD_TYPE_INT, 1, 0), + SPA_POD_PROP (&f[1], this->uri.monitor_types.state, 0, SPA_POD_TYPE_INT, 1, SPA_MONITOR_ITEM_STATE_AVAILABLE), + SPA_POD_PROP (&f[1], this->uri.monitor_types.name, 0, SPA_POD_TYPE_STRING, 1, name), + SPA_POD_PROP (&f[1], this->uri.monitor_types.klass, 0, SPA_POD_TYPE_STRING, 1, "Audio/Device"), + SPA_POD_PROP (&f[1], this->uri.monitor_types.factory, 0, SPA_POD_TYPE_POINTER, 1, this->uri.handle_factory, + factory), + 0); + + spa_pod_builder_add (&b, + SPA_POD_TYPE_PROP, &f[1], this->uri.monitor_types.info, 0, + SPA_POD_TYPE_STRUCT, 1, &f[2], 0); + + spa_pod_builder_add (&b, + SPA_POD_TYPE_STRING, "alsa.card", SPA_POD_TYPE_STRING, str, + SPA_POD_TYPE_STRING, "udev-probed", SPA_POD_TYPE_STRING, "1", + SPA_POD_TYPE_STRING, "device.api", SPA_POD_TYPE_STRING, "alsa", + 0); if ((str = udev_device_get_property_value (udevice, "SOUND_CLASS")) && *str) { - item->info_items[i].key = "device.class"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.class", SPA_POD_TYPE_STRING, str, 0); } str = udev_device_get_property_value (item->udevice, "ID_PATH"); if (!(str && *str)) str = udev_device_get_syspath (item->udevice); if (str && *str) { - item->info_items[i].key = "device.bus_path"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.bus_path", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_syspath (item->udevice)) && *str) { - item->info_items[i].key = "sysfs.path"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "sysfs.path", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "ID_ID")) && *str) { - item->info_items[i].key = "udev.id"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "udev.id", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "ID_BUS")) && *str) { - item->info_items[i].key = "device.bus"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.bus", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "SUBSYSTEM")) && *str) { - item->info_items[i].key = "device.subsystem"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.subsystem", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "ID_VENDOR_ID")) && *str) { - item->info_items[i].key = "device.vendor.id"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.vendor.id", SPA_POD_TYPE_STRING, str, 0); } str = udev_device_get_property_value (item->udevice, "ID_VENDOR_FROM_DATABASE"); if (!(str && *str)) { @@ -211,36 +225,28 @@ fill_item (SpaALSAMonitor *this, ALSAItem *item, struct udev_device *udevice) } } if (str && *str) { - item->info_items[i].key = "device.vendor.name"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.vendor.name", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "ID_MODEL_ID")) && *str) { - item->info_items[i].key = "device.product.id"; - item->info_items[i++].value = str; - } - str = udev_device_get_property_value (item->udevice, "ID_MODEL_FROM_DATABASE"); - if (!(str && *str)) { - str = udev_device_get_property_value (item->udevice, "ID_MODEL_ENC"); - if (!(str && *str)) { - str = udev_device_get_property_value (item->udevice, "ID_MODEL"); - } - } - if (str && *str) { - item->info_items[i].key = "device.product.name"; - item->info_items[i++].value = str; - item->item.name = str; - } else { - item->item.name = "Unknown"; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.product.id", SPA_POD_TYPE_STRING, str, 0); } + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.product.name", SPA_POD_TYPE_STRING, name, 0); + if ((str = udev_device_get_property_value (item->udevice, "ID_SERIAL")) && *str) { - item->info_items[i].key = "device.serial"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.serial", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "SOUND_FORM_FACTOR")) && *str) { - item->info_items[i].key = "device.form_factor"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.form_factor", SPA_POD_TYPE_STRING, str, 0); } - item->info.n_items = i; + + spa_pod_builder_add (&b, + -SPA_POD_TYPE_STRUCT, &f[2], + -SPA_POD_TYPE_PROP, &f[1], + 0); + + spa_pod_builder_pop (&b, &f[0]); + + item->item = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaMonitorItem); return 0; } @@ -250,8 +256,12 @@ alsa_on_fd_events (SpaSource *source) { SpaALSAMonitor *this = source->data; struct udev_device *dev; + SpaEvent *event; const char *str; - SpaMonitorItem *item; + uint32_t type; + SpaPODBuilder b = { NULL, }; + SpaPODFrame f[1]; + uint8_t buffer[4096]; dev = udev_monitor_receive_device (this->umonitor); if (fill_item (this, &this->uitem, dev) < 0) @@ -260,17 +270,21 @@ alsa_on_fd_events (SpaSource *source) if ((str = udev_device_get_action (dev)) == NULL) str = "change"; - item = &this->uitem.item; - if (strcmp (str, "add") == 0) { - item->event.type = SPA_MONITOR_EVENT_TYPE_ADDED; + type = this->uri.monitor_types.Added; } else if (strcmp (str, "change") == 0) { - item->event.type = SPA_MONITOR_EVENT_TYPE_CHANGED; + type = this->uri.monitor_types.Changed; } else if (strcmp (str, "remove") == 0) { - item->event.type = SPA_MONITOR_EVENT_TYPE_REMOVED; - } - item->event.size = sizeof (this->uitem); - this->event_cb (&this->monitor, &item->event, this->user_data); + type = this->uri.monitor_types.Removed; + } else + return; + + spa_pod_builder_init (&b, buffer, sizeof (buffer)); + spa_pod_builder_object (&b, &f[0], 0, type, + SPA_POD_TYPE_POD, this->uitem.item); + + event = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaMonitorEvent); + this->event_cb (&this->monitor, event, this->user_data); } static SpaResult @@ -364,7 +378,7 @@ again: this->index++; - *item = &this->uitem.item; + *item = this->uitem.item; return SPA_RESULT_OK; } @@ -388,7 +402,7 @@ spa_alsa_monitor_get_interface (SpaHandle *handle, this = (SpaALSAMonitor *) handle; - if (interface_id == this->uri.monitor) + if (interface_id == this->uri.monitor_types.Monitor) *interface = &this->monitor; else return SPA_RESULT_UNKNOWN_INTERFACE; @@ -436,7 +450,8 @@ alsa_monitor_init (const SpaHandleFactory *factory, spa_log_error (this->log, "a main-loop is needed"); return SPA_RESULT_ERROR; } - this->uri.monitor = spa_id_map_get_id (this->map, SPA_MONITOR_URI); + this->uri.handle_factory = spa_id_map_get_id (this->map, SPA_HANDLE_FACTORY_URI); + spa_monitor_types_map (this->map, &this->uri.monitor_types); this->monitor = alsamonitor; diff --git a/spa/plugins/v4l2/v4l2-monitor.c b/spa/plugins/v4l2/v4l2-monitor.c index 767b84d10..6e3761abf 100644 --- a/spa/plugins/v4l2/v4l2-monitor.c +++ b/spa/plugins/v4l2/v4l2-monitor.c @@ -36,14 +36,13 @@ extern const SpaHandleFactory spa_v4l2_source_factory; typedef struct _SpaV4l2Monitor SpaV4l2Monitor; typedef struct { - SpaMonitorItem item; + SpaMonitorItem *item; struct udev_device *udevice; - SpaDict info; - SpaDictItem info_items[32]; } V4l2Item; typedef struct { - uint32_t monitor; + uint32_t handle_factory; + SpaMonitorTypes monitor_types; } URI; struct _SpaV4l2Monitor { @@ -63,6 +62,7 @@ struct _SpaV4l2Monitor { struct udev_enumerate *enumerate; uint32_t index; struct udev_list_entry *devices; + uint8_t item_buffer[4096]; V4l2Item uitem; @@ -81,10 +81,11 @@ v4l2_udev_open (SpaV4l2Monitor *this) } static void -fill_item (V4l2Item *item, struct udev_device *udevice) +fill_item (SpaV4l2Monitor *this, V4l2Item *item, struct udev_device *udevice) { - uint32_t i; - const char *str; + const char *str, *name; + SpaPODBuilder b = { NULL, }; + SpaPODFrame f[3]; if (item->udevice) udev_device_unref (item->udevice); @@ -92,48 +93,64 @@ fill_item (V4l2Item *item, struct udev_device *udevice) if (udevice == NULL) return; - item->item.id = udev_device_get_syspath (item->udevice); - item->item.flags = 0; - item->item.state = SPA_MONITOR_ITEM_STATE_AVAILABLE; - item->item.klass = "Video/Source"; - item->item.info = &item->info; - item->item.factory = &spa_v4l2_source_factory; + name = udev_device_get_property_value (item->udevice, "ID_V4L_PRODUCT"); + if (!(name && *name)) { + name = udev_device_get_property_value (item->udevice, "ID_MODEL_FROM_DATABASE"); + if (!(name && *name)) { + name = udev_device_get_property_value (item->udevice, "ID_MODEL_ENC"); + if (!(name && *name)) { + name = udev_device_get_property_value (item->udevice, "ID_MODEL"); + } + } + } + if (!(name && *name)) + name = "Unknown"; - item->info.items = item->info_items; - i = 0; - item->info_items[i].key = "udev-probed"; - item->info_items[i++].value = "1"; - item->info_items[i].key = "device.api"; - item->info_items[i++].value = "v4l2"; - item->info_items[i].key = "device.path"; - item->info_items[i++].value = udev_device_get_devnode (item->udevice); + spa_pod_builder_init (&b, this->item_buffer, sizeof (this->item_buffer)); + + spa_pod_builder_push_object (&b, &f[0], 0, this->uri.monitor_types.MonitorItem); + + spa_pod_builder_add (&b, + SPA_POD_PROP (&f[1], this->uri.monitor_types.id, 0, SPA_POD_TYPE_STRING, 1, udev_device_get_syspath (item->udevice)), + SPA_POD_PROP (&f[1], this->uri.monitor_types.flags, 0, SPA_POD_TYPE_INT, 1, 0), + SPA_POD_PROP (&f[1], this->uri.monitor_types.state, 0, SPA_POD_TYPE_INT, 1, SPA_MONITOR_ITEM_STATE_AVAILABLE), + SPA_POD_PROP (&f[1], this->uri.monitor_types.name, 0, SPA_POD_TYPE_STRING, 1, name), + SPA_POD_PROP (&f[1], this->uri.monitor_types.klass, 0, SPA_POD_TYPE_STRING, 1, "Video/Source"), + SPA_POD_PROP (&f[1], this->uri.monitor_types.factory, 0, SPA_POD_TYPE_POINTER, 1, this->uri.handle_factory, + &spa_v4l2_source_factory), + 0); + + spa_pod_builder_add (&b, + SPA_POD_TYPE_PROP, &f[1], this->uri.monitor_types.info, 0, + SPA_POD_TYPE_STRUCT, 1, &f[2], 0); + + + spa_pod_builder_add (&b, + SPA_POD_TYPE_STRING, "udev-probed", SPA_POD_TYPE_STRING, "1", + SPA_POD_TYPE_STRING, "device.api", SPA_POD_TYPE_STRING, "v4l2", + SPA_POD_TYPE_STRING, "device.path", SPA_POD_TYPE_STRING, udev_device_get_devnode (item->udevice), + 0); str = udev_device_get_property_value (item->udevice, "ID_PATH"); if (!(str && *str)) str = udev_device_get_syspath (item->udevice); if (str && *str) { - item->info_items[i].key = "device.bus_path"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.bus_path", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_syspath (item->udevice)) && *str) { - item->info_items[i].key = "sysfs.path"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "sysfs.path", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "ID_ID")) && *str) { - item->info_items[i].key = "udev.id"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "udev.id", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "ID_BUS")) && *str) { - item->info_items[i].key = "device.bus"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.bus", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "SUBSYSTEM")) && *str) { - item->info_items[i].key = "device.subsystem"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.subsystem", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "ID_VENDOR_ID")) && *str) { - item->info_items[i].key = "device.vendor.id"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.vendor.id", SPA_POD_TYPE_STRING, str, 0); } str = udev_device_get_property_value (item->udevice, "ID_VENDOR_FROM_DATABASE"); if (!(str && *str)) { @@ -143,69 +160,64 @@ fill_item (V4l2Item *item, struct udev_device *udevice) } } if (str && *str) { - item->info_items[i].key = "device.vendor.name"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.vendor.name", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "ID_MODEL_ID")) && *str) { - item->info_items[i].key = "device.product.id"; - item->info_items[i++].value = str; - } - str = udev_device_get_property_value (item->udevice, "ID_V4L_PRODUCT"); - if (!(str && *str)) { - str = udev_device_get_property_value (item->udevice, "ID_MODEL_FROM_DATABASE"); - if (!(str && *str)) { - str = udev_device_get_property_value (item->udevice, "ID_MODEL_ENC"); - if (!(str && *str)) { - str = udev_device_get_property_value (item->udevice, "ID_MODEL"); - } - } - } - if (str && *str) { - item->info_items[i].key = "device.product.name"; - item->info_items[i++].value = str; - item->item.name = str; - } else { - item->item.name = "Unknown"; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.product.id", SPA_POD_TYPE_STRING, str, 0); } + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.product.name", SPA_POD_TYPE_STRING, name, 0); if ((str = udev_device_get_property_value (item->udevice, "ID_SERIAL")) && *str) { - item->info_items[i].key = "device.serial"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.serial", SPA_POD_TYPE_STRING, str, 0); } if ((str = udev_device_get_property_value (item->udevice, "ID_V4L_CAPABILITIES")) && *str) { - item->info_items[i].key = "device.capabilities"; - item->info_items[i++].value = str; + spa_pod_builder_add (&b, SPA_POD_TYPE_STRING, "device.capabilities", SPA_POD_TYPE_STRING, str, 0); } - item->info.n_items = i; -} + spa_pod_builder_add (&b, + -SPA_POD_TYPE_STRUCT, &f[2], + -SPA_POD_TYPE_PROP, &f[1], + 0); + + spa_pod_builder_pop (&b, &f[0]); + + item->item = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaMonitorItem); +} static void v4l2_on_fd_events (SpaSource *source) { SpaV4l2Monitor *this = source->data; struct udev_device *dev; + SpaEvent *event; const char *action; - SpaMonitorItem *item; + uint32_t type; + SpaPODBuilder b = { NULL, }; + SpaPODFrame f[1]; + uint8_t buffer[4096]; dev = udev_monitor_receive_device (this->umonitor); - fill_item (&this->uitem, dev); + fill_item (this, &this->uitem, dev); if (dev == NULL) return; if ((action = udev_device_get_action (dev)) == NULL) action = "change"; - item = &this->uitem.item; - if (strcmp (action, "add") == 0) { - item->event.type = SPA_MONITOR_EVENT_TYPE_ADDED; + type = this->uri.monitor_types.Added; } else if (strcmp (action, "change") == 0) { - item->event.type = SPA_MONITOR_EVENT_TYPE_CHANGED; + type = this->uri.monitor_types.Changed; } else if (strcmp (action, "remove") == 0) { - item->event.type = SPA_MONITOR_EVENT_TYPE_REMOVED; - } - item->event.size = sizeof (this->uitem); - this->event_cb (&this->monitor, &item->event, this->user_data); + type = this->uri.monitor_types.Removed; + } else + return; + + spa_pod_builder_init (&b, buffer, sizeof (buffer)); + spa_pod_builder_object (&b, &f[0], 0, type, + SPA_POD_TYPE_POD, this->uitem.item); + + event = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaMonitorEvent); + this->event_cb (&this->monitor, event, this->user_data); } static SpaResult @@ -283,18 +295,18 @@ spa_v4l2_monitor_enum_items (SpaMonitor *monitor, this->index++; } if (this->devices == NULL) { - fill_item (&this->uitem, NULL); + fill_item (this, &this->uitem, NULL); return SPA_RESULT_ENUM_END; } dev = udev_device_new_from_syspath (this->udev, udev_list_entry_get_name (this->devices)); - fill_item (&this->uitem, dev); + fill_item (this, &this->uitem, dev); if (dev == NULL) return SPA_RESULT_ENUM_END; - *item = &this->uitem.item; + *item = this->uitem.item; this->devices = udev_list_entry_get_next (this->devices); this->index++; @@ -321,7 +333,7 @@ spa_v4l2_monitor_get_interface (SpaHandle *handle, this = (SpaV4l2Monitor *) handle; - if (interface_id == this->uri.monitor) + if (interface_id == this->uri.monitor_types.Monitor) *interface = &this->monitor; else return SPA_RESULT_UNKNOWN_INTERFACE; @@ -369,7 +381,8 @@ v4l2_monitor_init (const SpaHandleFactory *factory, spa_log_error (this->log, "a main-loop is needed"); return SPA_RESULT_ERROR; } - this->uri.monitor = spa_id_map_get_id (this->map, SPA_MONITOR_URI); + this->uri.handle_factory = spa_id_map_get_id (this->map, SPA_HANDLE_FACTORY_URI); + spa_monitor_types_map (this->map, &this->uri.monitor_types); this->monitor = v4l2monitor; diff --git a/spa/tools/spa-monitor.c b/spa/tools/spa-monitor.c index 2097f7c12..0a99c37b4 100644 --- a/spa/tools/spa-monitor.c +++ b/spa/tools/spa-monitor.c @@ -33,7 +33,7 @@ #include typedef struct { - uint32_t monitor; + SpaMonitorTypes monitor_types; } URI; typedef struct { @@ -58,41 +58,27 @@ typedef struct { static void inspect_item (SpaMonitorItem *item) { - fprintf (stderr, " name: %s\n", item->name); - fprintf (stderr, " class: %s\n", item->klass); - if (item->info) - spa_debug_dict (item->info); + spa_debug_pod (&item->pod); } static void on_monitor_event (SpaMonitor *monitor, - SpaMonitorEvent *event, + SpaEvent *event, void *user_data) { - switch (event->type) { - case SPA_MONITOR_EVENT_TYPE_ADDED: - { - SpaMonitorItem *item = (SpaMonitorItem *) event; - fprintf (stderr, "added:\n"); - inspect_item (item); - break; - } - case SPA_MONITOR_EVENT_TYPE_REMOVED: - { - SpaMonitorItem *item = (SpaMonitorItem *) event; - fprintf (stderr, "removed:\n"); - inspect_item (item); - break; - } - case SPA_MONITOR_EVENT_TYPE_CHANGED: - { - SpaMonitorItem *item = (SpaMonitorItem *) event; - fprintf (stderr, "changed:\n"); - inspect_item (item); - break; - } - default: - break; + AppData *data = user_data; + + if (SPA_EVENT_TYPE (event) == data->uri.monitor_types.Added) { + fprintf (stderr, "added:\n"); + inspect_item ((SpaMonitorItem*)event); + } + else if (SPA_EVENT_TYPE (event) == data->uri.monitor_types.Removed) { + fprintf (stderr, "removed:\n"); + inspect_item ((SpaMonitorItem*)event); + } + else if (SPA_EVENT_TYPE (event) == data->uri.monitor_types.Changed) { + fprintf (stderr, "changed:\n"); + inspect_item ((SpaMonitorItem*)event); } } @@ -198,7 +184,7 @@ main (int argc, char *argv[]) data.support[2].data = &data.main_loop; data.n_support = 3; - data.uri.monitor = spa_id_map_get_id (data.map, SPA_MONITOR_URI); + spa_monitor_types_map (data.map, &data.uri.monitor_types); if (argc < 2) { printf ("usage: %s \n", argv[0]); @@ -243,7 +229,7 @@ main (int argc, char *argv[]) continue; } - if ((res = spa_handle_get_interface (handle, data.uri.monitor, &interface)) < 0) { + if ((res = spa_handle_get_interface (handle, data.uri.monitor_types.Monitor, &interface)) < 0) { printf ("can't get interface: %d\n", res); continue; }