From 1378a65fb77f84ba755e12e5f1a52ada89faf8b3 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 17 Jul 2015 17:01:46 +0200 Subject: [PATCH] devicemonitor: various improvements Set the active device providers as a property on the daemon. In the device monitor we can then obsolete the already monitored devices. Copy all device properties to the source. Set the device class as a property on the monitored devices. --- src/gst/gstpinosdeviceprovider.c | 108 +++++++++++++++++++++++++++---- src/modules/gst/gst-manager.c | 42 +++++++++++- 2 files changed, 137 insertions(+), 13 deletions(-) diff --git a/src/gst/gstpinosdeviceprovider.c b/src/gst/gstpinosdeviceprovider.c index 2388089dc..1c36c3ab9 100644 --- a/src/gst/gstpinosdeviceprovider.c +++ b/src/gst/gstpinosdeviceprovider.c @@ -44,35 +44,31 @@ enum static GstDevice * gst_pinos_device_new (gpointer id, const gchar * device_name, - GstCaps * caps, const gchar * path, GstPinosDeviceType type) + GstCaps * caps, const gchar * path, const gchar *klass, + GstPinosDeviceType type, GstStructure *props) { GstPinosDevice *gstdev; const gchar *element = NULL; - const gchar *klass = NULL; g_return_val_if_fail (device_name, NULL); g_return_val_if_fail (path, NULL); g_return_val_if_fail (caps, NULL); - switch (type) { case GST_PINOS_DEVICE_TYPE_SOURCE: element = "pinossrc"; - klass = "Video/Source/Pinos"; break; case GST_PINOS_DEVICE_TYPE_SINK: element = "pinossink"; - klass = "Video/Sink/Pinos"; break; default: g_assert_not_reached (); break; } - gstdev = g_object_new (GST_TYPE_PINOS_DEVICE, "display-name", device_name, "caps", caps, "device-class", klass, - "path", path, NULL); + "path", path, "properties", props, NULL); gstdev->id = id; gstdev->type = type; @@ -209,17 +205,39 @@ static GstDevice * new_source (const PinosSourceInfo *info) { GstCaps *caps; + GstStructure *props; + gpointer state = NULL; + const gchar *klass; if (info->formats) caps = gst_caps_from_string (g_bytes_get_data (info->formats, NULL)); else caps = gst_caps_new_any(); + + props = gst_structure_new_empty ("pinos-proplist"); + + while (TRUE) { + const char *key, *val; + + if (!(key = pinos_properties_iterate (info->properties, &state))) + break; + + val = pinos_properties_get (info->properties, key); + gst_structure_set (props, key, G_TYPE_STRING, val, NULL); + } + + klass = pinos_properties_get (info->properties, "gstreamer.device.class"); + if (klass == NULL) + klass = "unknown/unknown"; + return gst_pinos_device_new (info->id, info->name, caps, info->source_path, - GST_PINOS_DEVICE_TYPE_SOURCE); + klass, + GST_PINOS_DEVICE_TYPE_SOURCE, + props); } static gboolean @@ -317,6 +335,30 @@ list_source_info_cb (PinosContext *c, return TRUE; } +static gboolean +get_daemon_info_cb (PinosContext *c, const PinosDaemonInfo *info, gpointer userdata) +{ + GstDeviceProvider *provider = userdata; + const gchar *value; + + if (info == NULL) + return TRUE; + + value = pinos_properties_get (info->properties, "gstreamer.deviceproviders"); + if (value) { + gchar **providers = g_strsplit (value, ",", -1); + gint i; + + GST_DEBUG_OBJECT (provider, "have obsoleted providers: %s\n", value); + + for (i = 0; providers[i]; i++) { + gst_device_provider_add_obsoleted (provider, providers[i]); + } + g_strfreev (providers); + } + return TRUE; +} + static GList * gst_pinos_device_provider_probe (GstDeviceProvider * provider) { @@ -325,6 +367,8 @@ gst_pinos_device_provider_probe (GstDeviceProvider * provider) PinosContext *c = NULL; InfoData data; + GST_DEBUG_OBJECT (self, "starting probe"); + if (!(m = g_main_context_new ())) return NULL; @@ -354,6 +398,13 @@ gst_pinos_device_provider_probe (GstDeviceProvider * provider) } GST_DEBUG_OBJECT (self, "connected"); + pinos_context_get_daemon_info (c, + PINOS_DAEMON_INFO_FLAGS_NONE, + get_daemon_info_cb, + NULL, + self); + + data.end = FALSE; data.devices = NULL; pinos_context_list_source_info (c, @@ -419,6 +470,8 @@ gst_pinos_device_provider_start (GstDeviceProvider * provider) GError *error = NULL; GMainContext *c; + GST_DEBUG_OBJECT (self, "starting provider"); + c = g_main_context_new (); if (!(self->loop = pinos_main_loop_new (c, "pinos-device-monitor"))) { @@ -455,8 +508,32 @@ gst_pinos_device_provider_start (GstDeviceProvider * provider) (GCallback) context_subscribe_cb, self); - pinos_context_connect (self->context, PINOS_CONTEXT_FLAGS_NOFAIL); + pinos_context_connect (self->context, PINOS_CONTEXT_FLAGS_NONE); + for (;;) { + PinosContextState state; + + state = pinos_context_get_state (self->context); + + if (state <= 0) { + GST_WARNING_OBJECT (self, "Failed to connect: %s", + pinos_context_get_error (self->context)->message); + goto not_running; + } + + if (state == PINOS_CONTEXT_STATE_READY) + break; + + /* Wait until something happens */ + pinos_main_loop_wait (self->loop); + } + GST_DEBUG_OBJECT (self, "connected"); + pinos_context_get_daemon_info (self->context, + PINOS_DAEMON_INFO_FLAGS_NONE, + get_daemon_info_cb, + NULL, + self); pinos_main_loop_unlock (self->loop); + g_main_context_unref (c); return TRUE; @@ -466,6 +543,14 @@ failed: g_main_context_unref (c); return FALSE; } +not_running: + { + pinos_main_loop_unlock (self->loop); + pinos_main_loop_stop (self->loop); + g_clear_object (&self->context); + g_clear_object (&self->loop); + return TRUE; + } } static void @@ -476,8 +561,9 @@ gst_pinos_device_provider_stop (GstDeviceProvider * provider) if (self->context) { pinos_context_disconnect (self->context); } - pinos_main_loop_stop (self->loop); - + if (self->loop) { + pinos_main_loop_stop (self->loop); + } g_clear_object (&self->context); g_clear_object (&self->loop); } diff --git a/src/modules/gst/gst-manager.c b/src/modules/gst/gst-manager.c index 62fead91d..c5dacff62 100644 --- a/src/modules/gst/gst-manager.c +++ b/src/modules/gst/gst-manager.c @@ -42,6 +42,21 @@ enum G_DEFINE_TYPE (PinosGstManager, pinos_gst_manager, G_TYPE_OBJECT); +static gboolean +copy_properties (GQuark field_id, + const GValue *value, + gpointer user_data) +{ + PinosProperties *properties = user_data; + + if (G_VALUE_HOLDS_STRING (value)) + pinos_properties_set (properties, + g_quark_to_string (field_id), + g_value_get_string (value)); + + return TRUE; +} + static void device_added (PinosGstManager *manager, GstDevice *device) @@ -50,6 +65,8 @@ device_added (PinosGstManager *manager, gchar *name; GstElement *element; PinosSource *source; + GstStructure *p; + PinosProperties *properties; name = gst_device_get_display_name (device); if (strcmp (name, "gst") == 0) @@ -57,8 +74,15 @@ device_added (PinosGstManager *manager, g_print("Device added: %s\n", name); + properties = pinos_properties_new (NULL); + if ((p = gst_device_get_properties (device))) + gst_structure_foreach (p, copy_properties, properties); + pinos_properties_set (properties, + "gstreamer.device.class", + gst_device_get_device_class (device)); + element = gst_device_create_element (device, NULL); - source = pinos_gst_source_new (priv->daemon, name, element); + source = pinos_gst_source_new (priv->daemon, name, properties, element); g_object_set_data (G_OBJECT (device), "PinosSource", source); g_free (name); } @@ -129,6 +153,9 @@ start_monitor (PinosGstManager *manager) PinosGstManagerPrivate *priv = manager->priv; GstBus *bus; GList *devices; + gchar **providers; + gchar *provided; + PinosProperties *props; disable_pinos_provider (manager); @@ -139,9 +166,20 @@ start_monitor (PinosGstManager *manager) gst_object_unref (bus); gst_device_monitor_add_filter (priv->monitor, "Video/Source", NULL); - + gst_device_monitor_add_filter (priv->monitor, "Audio/Source", NULL); gst_device_monitor_start (priv->monitor); + providers = gst_device_monitor_get_providers (priv->monitor); + provided = g_strjoinv (",", providers); + g_strfreev (providers); + + g_object_get (priv->daemon, "properties", &props, NULL); + pinos_properties_set (props, "gstreamer.deviceproviders", provided); + g_object_set (priv->daemon, "properties", props, NULL); + pinos_properties_free (props); + + g_free (provided); + devices = gst_device_monitor_get_devices (priv->monitor); while (devices != NULL) { GstDevice *device = devices->data;