summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2015-07-16 18:56:00 +0200
committerWim Taymans <wtaymans@redhat.com>2015-08-08 14:47:08 +0200
commitb51d3a622ca35425bea7d83c5818515ed655a3fd (patch)
tree454674e3b0038d0ee322198df84ebf07f571e12d
parent0eb9dde1e803cfff490632553a13f705693710b6 (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.
-rw-r--r--gst/gstdevicemonitor.c91
-rw-r--r--gst/gstdeviceprovider.c141
-rw-r--r--gst/gstdeviceprovider.h8
-rw-r--r--win32/common/libgstreamer.def3
4 files changed, 236 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 */
diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def
index 0e6963a2c..c280600dc 100644
--- a/win32/common/libgstreamer.def
+++ b/win32/common/libgstreamer.def
@@ -441,6 +441,7 @@ EXPORTS
gst_device_monitor_remove_filter
gst_device_monitor_start
gst_device_monitor_stop
+ gst_device_provider_add_hidden_provider
gst_device_provider_can_monitor
gst_device_provider_class_add_metadata
gst_device_provider_class_add_static_metadata
@@ -462,8 +463,10 @@ EXPORTS
gst_device_provider_get_bus
gst_device_provider_get_devices
gst_device_provider_get_factory
+ gst_device_provider_get_hidden_providers
gst_device_provider_get_type
gst_device_provider_register
+ gst_device_provider_remove_hidden_provider
gst_device_provider_start
gst_device_provider_stop
gst_device_reconfigure_element