diff options
author | Wim Taymans <wtaymans@redhat.com> | 2015-07-16 18:56:00 +0200 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2015-08-08 14:47:08 +0200 |
commit | b51d3a622ca35425bea7d83c5818515ed655a3fd (patch) | |
tree | 454674e3b0038d0ee322198df84ebf07f571e12d /gst | |
parent | 0eb9dde1e803cfff490632553a13f705693710b6 (diff) |
deviceprovider: Add method to hide devices from a provider
Add methods to add/remove the providers that should be hidden by this
provider. Also make a method to get a list of hidden providers.
This makes it possible to have multiple systems monitor the same devices
and remove duplicates.
Diffstat (limited to 'gst')
-rw-r--r-- | gst/gstdevicemonitor.c | 91 | ||||
-rw-r--r-- | gst/gstdeviceprovider.c | 141 | ||||
-rw-r--r-- | gst/gstdeviceprovider.h | 8 |
3 files changed, 233 insertions, 7 deletions
diff --git a/gst/gstdevicemonitor.c b/gst/gstdevicemonitor.c index 9784232ac..5d3c3ee7d 100644 --- a/gst/gstdevicemonitor.c +++ b/gst/gstdevicemonitor.c @@ -108,6 +108,7 @@ struct _GstDeviceMonitorPrivate GPtrArray *filters; guint last_id; + GList *hidden; }; @@ -142,6 +143,37 @@ gst_device_monitor_class_init (GstDeviceMonitorClass * klass) object_class->dispose = gst_device_monitor_dispose; } +/* must be called with monitor lock */ +static gboolean +is_provider_hidden (GList * hidden, GstDeviceProvider * provider) +{ + GstDeviceProviderFactory *factory; + + factory = gst_device_provider_get_factory (provider); + if (g_list_find_custom (hidden, GST_OBJECT_NAME (factory), + (GCompareFunc) g_strcmp0)) + return TRUE; + + return FALSE; +} + +/* must be called with monitor lock */ +static void +update_hidden_list (GList ** hidden, GstDeviceProvider * provider) +{ + gchar **obs; + + obs = gst_device_provider_get_hidden (provider); + if (obs) { + gint i; + + for (i = 0; obs[i]; i++) + *hidden = g_list_prepend (*hidden, obs[i]); + + g_free (obs); + } +} + static void bus_sync_message (GstBus * bus, GstMessage * message, GstDeviceMonitor * monitor) @@ -151,6 +183,7 @@ bus_sync_message (GstBus * bus, GstMessage * message, if (type == GST_MESSAGE_DEVICE_ADDED || type == GST_MESSAGE_DEVICE_REMOVED) { gboolean matches; GstDevice *device; + GstDeviceProvider *provider; if (type == GST_MESSAGE_DEVICE_ADDED) gst_message_parse_device_added (message, &device); @@ -158,7 +191,11 @@ bus_sync_message (GstBus * bus, GstMessage * message, gst_message_parse_device_removed (message, &device); GST_OBJECT_LOCK (monitor); - if (monitor->priv->filters->len) { + provider = + GST_DEVICE_PROVIDER (gst_object_get_parent (GST_OBJECT (device))); + if (is_provider_hidden (monitor->priv->hidden, provider)) { + matches = FALSE; + } else if (monitor->priv->filters->len) { guint i; for (i = 0; i < monitor->priv->filters->len; i++) { @@ -258,7 +295,7 @@ gst_device_monitor_dispose (GObject * object) GList * gst_device_monitor_get_devices (GstDeviceMonitor * monitor) { - GList *devices = NULL; + GList *devices = NULL, *hidden = NULL; guint i; guint cookie; @@ -281,7 +318,9 @@ gst_device_monitor_get_devices (GstDeviceMonitor * monitor) again: g_list_free_full (devices, gst_object_unref); + g_list_free_full (hidden, g_free); devices = NULL; + hidden = NULL; cookie = monitor->priv->cookie; @@ -291,11 +330,17 @@ again: gst_object_ref (g_ptr_array_index (monitor->priv->providers, i)); GList *item; - GST_OBJECT_UNLOCK (monitor); + if (!is_provider_hidden (hidden, provider)) { + GST_OBJECT_UNLOCK (monitor); - tmpdev = gst_device_provider_get_devices (provider); + tmpdev = gst_device_provider_get_devices (provider); + + GST_OBJECT_LOCK (monitor); + update_hidden_list (&hidden, provider); + } else { + tmpdev = NULL; + } - GST_OBJECT_LOCK (monitor); for (item = tmpdev; item; item = item->next) { GstDevice *dev = GST_DEVICE (item->data); @@ -305,6 +350,7 @@ again: for (j = 0; j < monitor->priv->filters->len; j++) { struct DeviceFilter *filter = g_ptr_array_index (monitor->priv->filters, j); + if (gst_caps_can_intersect (filter->caps, caps) && gst_device_has_classesv (dev, filter->classesv)) { devices = g_list_prepend (devices, gst_object_ref (dev)); @@ -317,10 +363,10 @@ again: g_list_free_full (tmpdev, gst_object_unref); gst_object_unref (provider); - if (monitor->priv->cookie != cookie) goto again; } + g_list_free_full (hidden, g_free); GST_OBJECT_UNLOCK (monitor); @@ -478,6 +524,33 @@ gst_device_monitor_stop (GstDeviceMonitor * monitor) } +static void +hidden_added (GstDeviceProvider * provider, const gchar * hidden, + GstDeviceMonitor * monitor) +{ + GST_OBJECT_LOCK (monitor); + monitor->priv->hidden = + g_list_prepend (monitor->priv->hidden, g_strdup (hidden)); + GST_OBJECT_UNLOCK (monitor); +} + +static void +hidden_removed (GstDeviceProvider * provider, const gchar * hidden, + GstDeviceMonitor * monitor) +{ + GList *find; + + GST_OBJECT_LOCK (monitor); + find = + g_list_find_custom (monitor->priv->hidden, hidden, + (GCompareFunc) g_strcmp0); + if (find) { + g_free (find->data); + monitor->priv->hidden = g_list_delete_link (monitor->priv->hidden, find); + } + GST_OBJECT_UNLOCK (monitor); +} + /** * gst_device_monitor_add_filter: * @monitor: a device monitor @@ -543,6 +616,12 @@ gst_device_monitor_add_filter (GstDeviceMonitor * monitor, if (provider) { GstBus *bus = gst_device_provider_get_bus (provider); + update_hidden_list (&monitor->priv->hidden, provider); + g_signal_connect (provider, "hidden-added", + (GCallback) hidden_added, monitor); + g_signal_connect (provider, "hidden-removed", + (GCallback) hidden_removed, monitor); + matched = TRUE; gst_bus_enable_sync_message_emission (bus); g_signal_connect (bus, "sync-message", diff --git a/gst/gstdeviceprovider.c b/gst/gstdeviceprovider.c index 995c2ff8a..1d9df962f 100644 --- a/gst/gstdeviceprovider.c +++ b/gst/gstdeviceprovider.c @@ -55,8 +55,19 @@ struct _GstDeviceProviderPrivate GMutex start_lock; gboolean started_count; + + GList *hidden_providers; +}; + +enum +{ + HIDDEN_PROVIDER_ADDED, + HIDDEN_PROVIDER_REMOVED, + LAST_SIGNAL }; +static guint gst_device_provider_signals[LAST_SIGNAL] = { 0 }; + /* this is used in gstelementfactory.c:gst_element_register() */ GQuark __gst_deviceproviderclass_factory = 0; @@ -134,6 +145,16 @@ gst_device_provider_class_init (GstDeviceProviderClass * klass) gobject_class->dispose = gst_device_provider_dispose; gobject_class->finalize = gst_device_provider_finalize; + + gst_device_provider_signals[HIDDEN_PROVIDER_ADDED] = + g_signal_new ("hidden-provider-added", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_STRING); + + gst_device_provider_signals[HIDDEN_PROVIDER_REMOVED] = + g_signal_new ("hidden-provider-removed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_STRING); } static void @@ -598,3 +619,123 @@ gst_device_provider_device_remove (GstDeviceProvider * provider, if (item) gst_object_unparent (GST_OBJECT (device)); } + +/** + * gst_device_provider_get_hidden_providers: + * @provider: a #GstDeviceProvider + * + * Get the provider factory names of the #GstDeviceProvider instances that + * are hidden by @provider. + * + * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*): + * a list of hidden providers factory names or %NULL when + * nothing is hidden by @provider. Free with g_strfreev. + * + * Since: 1.6 + */ +gchar ** +gst_device_provider_get_hidden_providers (GstDeviceProvider * provider) +{ + GList *walk; + guint i, len; + gchar **res = NULL; + + g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), NULL); + + GST_OBJECT_LOCK (provider); + len = g_list_length (provider->priv->hidden_providers); + if (len == 0) + goto done; + + res = g_new (gchar *, len + 1); + for (i = 0, walk = provider->priv->hidden_providers; walk; + walk = g_list_next (walk), i++) + res[i] = g_strdup (walk->data); + res[i] = NULL; + +done: + GST_OBJECT_UNLOCK (provider); + + return res; +} + +/** + * gst_device_provider_add_hidden_provider: + * @provider: a #GstDeviceProvider + * @hidden: an hidden provider factory name + * + * Add the @hidden factory name to @provider. + * + * This function is used when @provider will also provide the devices reported + * by @hidden provider factory name. A monitor should stop monitoring the + * device provider with name @hidden to avoid duplicate devices. + * + * Since: 1.6 + */ +void +gst_device_provider_add_hidden_provider (GstDeviceProvider * provider, + const gchar * hidden) +{ + GList *find; + const gchar *name = NULL; + + g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider)); + g_return_if_fail (hidden != NULL); + + GST_OBJECT_LOCK (provider); + find = + g_list_find_custom (provider->priv->hidden_providers, hidden, + (GCompareFunc) g_strcmp0); + if (find == NULL) { + name = hidden; + provider->priv->hidden_providers = + g_list_prepend (provider->priv->hidden_providers, g_strdup (hidden)); + } + GST_OBJECT_UNLOCK (provider); + + if (name) + g_signal_emit (provider, gst_device_provider_signals[HIDDEN_PROVIDER_ADDED], + 0, name); +} + +/** + * gst_device_provider_remove_hidden_provider: + * @provider: a #GstDeviceProvider + * @hidden: an hidden provider factory name + * + * Remove the @hidden factory name from @provider. + * + * This function is used when @provider will no longer provide the devices + * reported by @hidden provider factory name. A monitor should start + * monitoring the devices from @hidden provider factory in order to see + * all devices again. + * + * Since: 1.6 + */ +void +gst_device_provider_remove_hidden_provider (GstDeviceProvider * provider, + const gchar * hidden) +{ + GList *find; + gchar *name = NULL; + + g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider)); + g_return_if_fail (hidden != NULL); + + GST_OBJECT_LOCK (provider); + find = + g_list_find_custom (provider->priv->hidden_providers, hidden, + (GCompareFunc) g_strcmp0); + if (find) { + name = find->data; + provider->priv->hidden_providers = + g_list_delete_link (provider->priv->hidden_providers, find); + } + GST_OBJECT_UNLOCK (provider); + + if (name) { + g_signal_emit (provider, + gst_device_provider_signals[HIDDEN_PROVIDER_REMOVED], 0, name); + g_free (name); + } +} diff --git a/gst/gstdeviceprovider.h b/gst/gstdeviceprovider.h index 3982f3b89..57d1c596a 100644 --- a/gst/gstdeviceprovider.h +++ b/gst/gstdeviceprovider.h @@ -113,7 +113,13 @@ GstBus * gst_device_provider_get_bus (GstDeviceProvider * provider); void gst_device_provider_device_add (GstDeviceProvider * provider, GstDevice * device); void gst_device_provider_device_remove (GstDeviceProvider * provider, - GstDevice * device); + GstDevice * device); + +gchar ** gst_device_provider_get_hidden_providers (GstDeviceProvider * provider); +void gst_device_provider_add_hidden_provider (GstDeviceProvider * provider, + const gchar * hidden); +void gst_device_provider_remove_hidden_provider (GstDeviceProvider * provider, + const gchar * hidden); /* device provider class meta data */ |