e7972bbdf42280daf570cf6b68456b3f3e8a18e6
[platform/upstream/gstreamer.git] / gst / gstdeviceprovider.c
1 /* GStreamer
2  * Copyright (C) 2012 Olivier Crete <olivier.crete@collabora.com>
3  *
4  * gstdeviceprovider.c: Device probing and monitoring
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /**
23  * SECTION:gstdeviceprovider
24  * @short_description: A device provider
25  * @see_also: #GstDevice, #GstDeviceMonitor
26  *
27  * A #GstDeviceProvider subclass is provided by a plugin that handles devices
28  * if there is a way to programatically list connected devices. It can also
29  * optionally provide updates to the list of connected devices.
30  *
31  * Each #GstDeviceProvider subclass is a singleton, a plugin should
32  * normally provide a single subclass for all devices.
33  *
34  * Applications would normally use a #GstDeviceMonitor to monitor devices
35  * from all relevant providers.
36  *
37  * Since: 1.4
38  */
39
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43
44 #include "gst_private.h"
45
46 #include "gstdeviceprovider.h"
47
48 #include "gstelementmetadata.h"
49 #include "gstquark.h"
50
51 struct _GstDeviceProviderPrivate
52 {
53   GstBus *bus;
54
55   GMutex start_lock;
56
57   gboolean started_count;
58
59   GList *hidden_providers;
60 };
61
62 enum
63 {
64   PROVIDER_HIDDEN,
65   PROVIDER_UNHIDDEN,
66   LAST_SIGNAL
67 };
68
69 static guint gst_device_provider_signals[LAST_SIGNAL] = { 0 };
70
71 /* this is used in gstelementfactory.c:gst_element_register() */
72 GQuark __gst_deviceproviderclass_factory = 0;
73
74 static void gst_device_provider_class_init (GstDeviceProviderClass * klass);
75 static void gst_device_provider_init (GstDeviceProvider * element);
76 static void gst_device_provider_base_class_init (gpointer g_class);
77 static void gst_device_provider_dispose (GObject * object);
78 static void gst_device_provider_finalize (GObject * object);
79
80 static gpointer gst_device_provider_parent_class = NULL;
81
82 GType
83 gst_device_provider_get_type (void)
84 {
85   static volatile gsize gst_device_provider_type = 0;
86
87   if (g_once_init_enter (&gst_device_provider_type)) {
88     GType _type;
89     static const GTypeInfo element_info = {
90       sizeof (GstDeviceProviderClass),
91       gst_device_provider_base_class_init,
92       NULL,                     /* base_class_finalize */
93       (GClassInitFunc) gst_device_provider_class_init,
94       NULL,
95       NULL,
96       sizeof (GstDeviceProvider),
97       0,
98       (GInstanceInitFunc) gst_device_provider_init,
99       NULL
100     };
101
102     _type = g_type_register_static (GST_TYPE_OBJECT, "GstDeviceProvider",
103         &element_info, G_TYPE_FLAG_ABSTRACT);
104
105     __gst_deviceproviderclass_factory =
106         g_quark_from_static_string ("GST_DEVICEPROVIDERCLASS_FACTORY");
107     g_once_init_leave (&gst_device_provider_type, _type);
108   }
109   return gst_device_provider_type;
110 }
111
112 static void
113 gst_device_provider_base_class_init (gpointer g_class)
114 {
115   GstDeviceProviderClass *klass = GST_DEVICE_PROVIDER_CLASS (g_class);
116
117   /* Copy the element details here so elements can inherit the
118    * details from their base class and classes only need to set
119    * the details in class_init instead of base_init */
120   klass->metadata =
121       klass->metadata ? gst_structure_copy (klass->metadata) :
122       gst_structure_new_empty ("metadata");
123
124   klass->factory = g_type_get_qdata (G_TYPE_FROM_CLASS (klass),
125       __gst_deviceproviderclass_factory);
126 }
127
128 static void
129 gst_device_provider_class_init (GstDeviceProviderClass * klass)
130 {
131   GObjectClass *gobject_class = (GObjectClass *) klass;
132
133   gst_device_provider_parent_class = g_type_class_peek_parent (klass);
134
135   g_type_class_add_private (klass, sizeof (GstDeviceProviderPrivate));
136
137   gobject_class->dispose = gst_device_provider_dispose;
138   gobject_class->finalize = gst_device_provider_finalize;
139
140   gst_device_provider_signals[PROVIDER_HIDDEN] =
141       g_signal_new ("provider-hidden", G_TYPE_FROM_CLASS (klass),
142       G_SIGNAL_RUN_FIRST, 0, NULL,
143       NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_STRING);
144
145   gst_device_provider_signals[PROVIDER_UNHIDDEN] =
146       g_signal_new ("provider-unhidden", G_TYPE_FROM_CLASS (klass),
147       G_SIGNAL_RUN_FIRST, 0, NULL,
148       NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_STRING);
149 }
150
151 static void
152 gst_device_provider_init (GstDeviceProvider * provider)
153 {
154   provider->priv = G_TYPE_INSTANCE_GET_PRIVATE (provider,
155       GST_TYPE_DEVICE_PROVIDER, GstDeviceProviderPrivate);
156
157   g_mutex_init (&provider->priv->start_lock);
158
159   provider->priv->bus = gst_bus_new ();
160   gst_bus_set_flushing (provider->priv->bus, TRUE);
161 }
162
163
164 static void
165 gst_device_provider_dispose (GObject * object)
166 {
167   GstDeviceProvider *provider = GST_DEVICE_PROVIDER (object);
168
169   gst_object_replace ((GstObject **) & provider->priv->bus, NULL);
170
171   GST_OBJECT_LOCK (provider);
172   g_list_free_full (provider->devices, (GDestroyNotify) gst_object_unparent);
173   provider->devices = NULL;
174   GST_OBJECT_UNLOCK (provider);
175
176   G_OBJECT_CLASS (gst_device_provider_parent_class)->dispose (object);
177 }
178
179 static void
180 gst_device_provider_finalize (GObject * object)
181 {
182   GstDeviceProvider *provider = GST_DEVICE_PROVIDER (object);
183
184   g_mutex_clear (&provider->priv->start_lock);
185
186   G_OBJECT_CLASS (gst_device_provider_parent_class)->finalize (object);
187 }
188
189 /**
190  * gst_device_provider_class_add_metadata:
191  * @klass: class to set metadata for
192  * @key: the key to set
193  * @value: the value to set
194  *
195  * Set @key with @value as metadata in @klass.
196  *
197  * Since: 1.4
198  */
199 void
200 gst_device_provider_class_add_metadata (GstDeviceProviderClass * klass,
201     const gchar * key, const gchar * value)
202 {
203   g_return_if_fail (GST_IS_DEVICE_PROVIDER_CLASS (klass));
204   g_return_if_fail (key != NULL);
205   g_return_if_fail (value != NULL);
206
207   gst_structure_set ((GstStructure *) klass->metadata,
208       key, G_TYPE_STRING, value, NULL);
209 }
210
211 /**
212  * gst_device_provider_class_add_static_metadata:
213  * @klass: class to set metadata for
214  * @key: the key to set
215  * @value: (transfer full): the value to set
216  *
217  * Set @key with @value as metadata in @klass.
218  *
219  * Same as gst_device_provider_class_add_metadata(), but @value must be a static string
220  * or an inlined string, as it will not be copied. (GStreamer plugins will
221  * be made resident once loaded, so this function can be used even from
222  * dynamically loaded plugins.)
223  *
224  * Since: 1.4
225  */
226 void
227 gst_device_provider_class_add_static_metadata (GstDeviceProviderClass * klass,
228     const gchar * key, const gchar * value)
229 {
230   GValue val = G_VALUE_INIT;
231
232   g_return_if_fail (GST_IS_DEVICE_PROVIDER_CLASS (klass));
233   g_return_if_fail (key != NULL);
234   g_return_if_fail (value != NULL);
235
236   g_value_init (&val, G_TYPE_STRING);
237   g_value_set_static_string (&val, value);
238   gst_structure_take_value ((GstStructure *) klass->metadata, key, &val);
239 }
240
241 /**
242  * gst_device_provider_class_set_metadata:
243  * @klass: class to set metadata for
244  * @longname: The long English name of the device provider. E.g. "File Sink"
245  * @classification: String describing the type of device provider, as an
246  *  unordered list separated with slashes ('/'). See draft-klass.txt of the
247  *  design docs
248  * for more details and common types. E.g: "Sink/File"
249  * @description: Sentence describing the purpose of the device provider.
250  * E.g: "Write stream to a file"
251  * @author: Name and contact details of the author(s). Use \n to separate
252  * multiple author metadata. E.g: "Joe Bloggs &lt;joe.blogs at foo.com&gt;"
253  *
254  * Sets the detailed information for a #GstDeviceProviderClass.
255  * <note>This function is for use in _class_init functions only.</note>
256  *
257  * Since: 1.4
258  */
259 void
260 gst_device_provider_class_set_metadata (GstDeviceProviderClass * klass,
261     const gchar * longname, const gchar * classification,
262     const gchar * description, const gchar * author)
263 {
264   g_return_if_fail (GST_IS_DEVICE_PROVIDER_CLASS (klass));
265   g_return_if_fail (longname != NULL && *longname != '\0');
266   g_return_if_fail (classification != NULL && *classification != '\0');
267   g_return_if_fail (description != NULL && *description != '\0');
268   g_return_if_fail (author != NULL && *author != '\0');
269
270   gst_structure_id_set ((GstStructure *) klass->metadata,
271       GST_QUARK (ELEMENT_METADATA_LONGNAME), G_TYPE_STRING, longname,
272       GST_QUARK (ELEMENT_METADATA_KLASS), G_TYPE_STRING, classification,
273       GST_QUARK (ELEMENT_METADATA_DESCRIPTION), G_TYPE_STRING, description,
274       GST_QUARK (ELEMENT_METADATA_AUTHOR), G_TYPE_STRING, author, NULL);
275 }
276
277 /**
278  * gst_device_provider_class_set_static_metadata:
279  * @klass: class to set metadata for
280  * @longname: (transfer full): The long English name of the element. E.g. "File Sink"
281  * @classification: (transfer full): String describing the type of element, as
282  * an unordered list separated with slashes ('/'). See draft-klass.txt of the
283  * design docs for more details and common types. E.g: "Sink/File"
284  * @description: (transfer full): Sentence describing the purpose of the
285  * element.  E.g: "Write stream to a file"
286  * @author: (transfer full): Name and contact details of the author(s). Use \n
287  * to separate multiple author metadata. E.g: "Joe Bloggs &lt;joe.blogs at
288  * foo.com&gt;"
289  *
290  * Sets the detailed information for a #GstDeviceProviderClass.
291  * <note>This function is for use in _class_init functions only.</note>
292  *
293  * Same as gst_device_provider_class_set_metadata(), but @longname, @classification,
294  * @description, and @author must be static strings or inlined strings, as
295  * they will not be copied. (GStreamer plugins will be made resident once
296  * loaded, so this function can be used even from dynamically loaded plugins.)
297  *
298  * Since: 1.4
299  */
300 void
301 gst_device_provider_class_set_static_metadata (GstDeviceProviderClass * klass,
302     const gchar * longname, const gchar * classification,
303     const gchar * description, const gchar * author)
304 {
305   GstStructure *s = (GstStructure *) klass->metadata;
306   GValue val = G_VALUE_INIT;
307
308   g_return_if_fail (GST_IS_DEVICE_PROVIDER_CLASS (klass));
309   g_return_if_fail (longname != NULL && *longname != '\0');
310   g_return_if_fail (classification != NULL && *classification != '\0');
311   g_return_if_fail (description != NULL && *description != '\0');
312   g_return_if_fail (author != NULL && *author != '\0');
313
314   g_value_init (&val, G_TYPE_STRING);
315
316   g_value_set_static_string (&val, longname);
317   gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_LONGNAME), &val);
318
319   g_value_set_static_string (&val, classification);
320   gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_KLASS), &val);
321
322   g_value_set_static_string (&val, description);
323   gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_DESCRIPTION),
324       &val);
325
326   g_value_set_static_string (&val, author);
327   gst_structure_id_take_value (s, GST_QUARK (ELEMENT_METADATA_AUTHOR), &val);
328 }
329
330 /**
331  * gst_device_provider_class_get_metadata:
332  * @klass: class to get metadata for
333  * @key: the key to get
334  *
335  * Get metadata with @key in @klass.
336  *
337  * Returns: the metadata for @key.
338  *
339  * Since: 1.4
340  */
341 const gchar *
342 gst_device_provider_class_get_metadata (GstDeviceProviderClass * klass,
343     const gchar * key)
344 {
345   g_return_val_if_fail (GST_IS_DEVICE_PROVIDER_CLASS (klass), NULL);
346   g_return_val_if_fail (key != NULL, NULL);
347
348   return gst_structure_get_string ((GstStructure *) klass->metadata, key);
349 }
350
351 /**
352  * gst_device_provider_get_devices:
353  * @provider: A #GstDeviceProvider
354  *
355  * Gets a list of devices that this provider understands. This may actually
356  * probe the hardware if the provider is not currently started.
357  *
358  * Returns: (transfer full) (element-type GstDevice): a #GList of
359  *   #GstDevice
360  *
361  * Since: 1.4
362  */
363
364 GList *
365 gst_device_provider_get_devices (GstDeviceProvider * provider)
366 {
367   GstDeviceProviderClass *klass;
368   GList *devices = NULL;
369   gboolean started;
370   GList *item;
371
372   g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), NULL);
373   klass = GST_DEVICE_PROVIDER_GET_CLASS (provider);
374
375   g_mutex_lock (&provider->priv->start_lock);
376   started = (provider->priv->started_count > 0);
377
378   if (started) {
379     GST_OBJECT_LOCK (provider);
380     for (item = provider->devices; item; item = item->next)
381       devices = g_list_prepend (devices, gst_object_ref (item->data));
382     GST_OBJECT_UNLOCK (provider);
383   } else if (klass->probe)
384     devices = klass->probe (provider);
385
386   g_mutex_unlock (&provider->priv->start_lock);
387
388   return devices;
389 }
390
391 /**
392  * gst_device_provider_start:
393  * @provider: A #GstDeviceProvider
394  *
395  * Starts providering the devices. This will cause #GST_MESSAGE_DEVICE_ADDED
396  * and #GST_MESSAGE_DEVICE_REMOVED messages to be posted on the provider's bus
397  * when devices are added or removed from the system.
398  *
399  * Since the #GstDeviceProvider is a singleton,
400  * gst_device_provider_start() may already have been called by another
401  * user of the object, gst_device_provider_stop() needs to be called the same
402  * number of times.
403  *
404  * Returns: %TRUE if the device providering could be started
405  *
406  * Since: 1.4
407  */
408
409 gboolean
410 gst_device_provider_start (GstDeviceProvider * provider)
411 {
412   GstDeviceProviderClass *klass;
413   gboolean ret = FALSE;
414
415   g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), FALSE);
416   klass = GST_DEVICE_PROVIDER_GET_CLASS (provider);
417
418   g_mutex_lock (&provider->priv->start_lock);
419
420   if (provider->priv->started_count > 0) {
421     ret = TRUE;
422     goto started;
423   }
424
425   if (klass->start)
426     ret = klass->start (provider);
427
428   if (ret) {
429     provider->priv->started_count++;
430     gst_bus_set_flushing (provider->priv->bus, FALSE);
431   }
432
433 started:
434
435   g_mutex_unlock (&provider->priv->start_lock);
436
437   return ret;
438 }
439
440 /**
441  * gst_device_provider_stop:
442  * @provider: A #GstDeviceProvider
443  *
444  * Decreases the use-count by one. If the use count reaches zero, this
445  * #GstDeviceProvider will stop providering the devices. This needs to be
446  * called the same number of times that gst_device_provider_start() was called.
447  *
448  * Since: 1.4
449  */
450
451 void
452 gst_device_provider_stop (GstDeviceProvider * provider)
453 {
454   GstDeviceProviderClass *klass;
455
456   g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider));
457   klass = GST_DEVICE_PROVIDER_GET_CLASS (provider);
458
459   g_mutex_lock (&provider->priv->start_lock);
460
461   if (provider->priv->started_count == 1) {
462     gst_bus_set_flushing (provider->priv->bus, TRUE);
463     if (klass->stop)
464       klass->stop (provider);
465     GST_OBJECT_LOCK (provider);
466     g_list_free_full (provider->devices, (GDestroyNotify) gst_object_unparent);
467     provider->devices = NULL;
468     GST_OBJECT_UNLOCK (provider);
469   } else if (provider->priv->started_count < 1) {
470     g_critical
471         ("Trying to stop a GstDeviceProvider %s which is already stopped",
472         GST_OBJECT_NAME (provider));
473   }
474
475   provider->priv->started_count--;
476   g_mutex_unlock (&provider->priv->start_lock);
477 }
478
479
480 /**
481  * gst_device_provider_get_factory:
482  * @provider: a #GstDeviceProvider to request the device provider factory of.
483  *
484  * Retrieves the factory that was used to create this device provider.
485  *
486  * Returns: (transfer none): the #GstDeviceProviderFactory used for
487  *     creating this device provider. no refcounting is needed.
488  *
489  * Since: 1.4
490  */
491 GstDeviceProviderFactory *
492 gst_device_provider_get_factory (GstDeviceProvider * provider)
493 {
494   g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), NULL);
495
496   return GST_DEVICE_PROVIDER_GET_CLASS (provider)->factory;
497 }
498
499 /**
500  * gst_device_provider_can_provider:
501  * @provider: a #GstDeviceProvider
502  *
503  * If this function returns %TRUE, then the device provider can provider if
504  * devices are added or removed. Otherwise, it can only do static probing.
505  *
506  * Returns: %TRUE if the #GstDeviceProvider support providering, %FALSE otherwise
507  */
508 gboolean
509 gst_device_provider_can_monitor (GstDeviceProvider * provider)
510 {
511   GstDeviceProviderClass *klass;
512
513   g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), FALSE);
514   klass = GST_DEVICE_PROVIDER_GET_CLASS (provider);
515
516   if (klass->start)
517     return TRUE;
518   else
519     return FALSE;
520 }
521
522 /**
523  * gst_device_provider_get_bus:
524  * @provider: a #GstDeviceProvider
525  *
526  * Gets the #GstBus of this #GstDeviceProvider
527  *
528  * Returns: (transfer full): a #GstBus
529  *
530  * Since: 1.4
531  */
532 GstBus *
533 gst_device_provider_get_bus (GstDeviceProvider * provider)
534 {
535   g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), NULL);
536
537   return gst_object_ref (provider->priv->bus);
538 }
539
540 /**
541  * gst_device_provider_device_add:
542  * @provider: a #GstDeviceProvider
543  * @device: (transfer full): a #GstDevice that has been added
544  *
545  * Posts a message on the provider's #GstBus to inform applications that
546  * a new device has been added.
547  *
548  * This is for use by subclasses.
549  *
550  * Since: 1.4
551  */
552 void
553 gst_device_provider_device_add (GstDeviceProvider * provider,
554     GstDevice * device)
555 {
556   GstMessage *message;
557
558   g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider));
559   g_return_if_fail (GST_IS_DEVICE (device));
560
561   if (!gst_object_set_parent (GST_OBJECT (device), GST_OBJECT (provider))) {
562     GST_WARNING_OBJECT (provider, "Could not parent device %p to provider,"
563         " it already has a parent", device);
564     return;
565   }
566
567   GST_OBJECT_LOCK (provider);
568   provider->devices = g_list_prepend (provider->devices,
569       gst_object_ref (device));
570   GST_OBJECT_UNLOCK (provider);
571
572   message = gst_message_new_device_added (GST_OBJECT (provider), device);
573   gst_bus_post (provider->priv->bus, message);
574   gst_object_unref (device);
575 }
576
577
578 /**
579  * gst_device_provider_device_remove:
580  * @provider: a #GstDeviceProvider
581  * @device: a #GstDevice that has been removed
582  *
583  * Posts a message on the provider's #GstBus to inform applications that
584  * a device has been removed.
585  *
586  * This is for use by subclasses.
587  *
588  * Since: 1.4
589  */
590 void
591 gst_device_provider_device_remove (GstDeviceProvider * provider,
592     GstDevice * device)
593 {
594   GstMessage *message;
595   GList *item;
596
597   g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider));
598   g_return_if_fail (GST_IS_DEVICE (device));
599
600   GST_OBJECT_LOCK (provider);
601   item = g_list_find (provider->devices, device);
602   if (item) {
603     provider->devices = g_list_delete_link (provider->devices, item);
604   }
605   GST_OBJECT_UNLOCK (provider);
606
607   message = gst_message_new_device_removed (GST_OBJECT (provider), device);
608   g_signal_emit_by_name (device, "removed");
609   gst_bus_post (provider->priv->bus, message);
610   if (item)
611     gst_object_unparent (GST_OBJECT (device));
612 }
613
614 /**
615  * gst_device_provider_get_hidden_providers:
616  * @provider: a #GstDeviceProvider
617  *
618  * Get the provider factory names of the #GstDeviceProvider instances that
619  * are hidden by @provider.
620  *
621  * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*):
622  *   a list of hidden providers factory names or %NULL when
623  *   nothing is hidden by @provider. Free with g_strfreev.
624  *
625  * Since: 1.6
626  */
627 gchar **
628 gst_device_provider_get_hidden_providers (GstDeviceProvider * provider)
629 {
630   GList *walk;
631   guint i, len;
632   gchar **res = NULL;
633
634   g_return_val_if_fail (GST_IS_DEVICE_PROVIDER (provider), NULL);
635
636   GST_OBJECT_LOCK (provider);
637   len = g_list_length (provider->priv->hidden_providers);
638   if (len == 0)
639     goto done;
640
641   res = g_new (gchar *, len + 1);
642   for (i = 0, walk = provider->priv->hidden_providers; walk;
643       walk = g_list_next (walk), i++)
644     res[i] = g_strdup (walk->data);
645   res[i] = NULL;
646
647 done:
648   GST_OBJECT_UNLOCK (provider);
649
650   return res;
651 }
652
653 /**
654  * gst_device_provider_hide_provider:
655  * @provider: a #GstDeviceProvider
656  * @name: a provider factory name
657  *
658  * Make @provider hide the devices from the factory with @name.
659  *
660  * This function is used when @provider will also provide the devices reported
661  * by provider factory @name. A monitor should stop monitoring the
662  * device provider with @name to avoid duplicate devices.
663  *
664  * Since: 1.6
665  */
666 void
667 gst_device_provider_hide_provider (GstDeviceProvider * provider,
668     const gchar * name)
669 {
670   GList *find;
671   const gchar *hidden_name = NULL;
672
673   g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider));
674   g_return_if_fail (name != NULL);
675
676   GST_OBJECT_LOCK (provider);
677   find =
678       g_list_find_custom (provider->priv->hidden_providers, name,
679       (GCompareFunc) g_strcmp0);
680   if (find == NULL) {
681     hidden_name = name;
682     provider->priv->hidden_providers =
683         g_list_prepend (provider->priv->hidden_providers, g_strdup (name));
684   }
685   GST_OBJECT_UNLOCK (provider);
686
687   if (hidden_name)
688     g_signal_emit (provider, gst_device_provider_signals[PROVIDER_HIDDEN],
689         0, hidden_name);
690 }
691
692 /**
693  * gst_device_provider_unhide_provider:
694  * @provider: a #GstDeviceProvider
695  * @name: a provider factory name
696  *
697  * Make @provider unhide the devices from factory @name.
698  *
699  * This function is used when @provider will no longer provide the devices
700  * reported by provider factory @name. A monitor should start
701  * monitoring the devices from provider factory @name in order to see
702  * all devices again.
703  *
704  * Since: 1.6
705  */
706 void
707 gst_device_provider_unhide_provider (GstDeviceProvider * provider,
708     const gchar * name)
709 {
710   GList *find;
711   gchar *unhidden_name = NULL;
712
713   g_return_if_fail (GST_IS_DEVICE_PROVIDER (provider));
714   g_return_if_fail (unhidden_name != NULL);
715
716   GST_OBJECT_LOCK (provider);
717   find =
718       g_list_find_custom (provider->priv->hidden_providers, name,
719       (GCompareFunc) g_strcmp0);
720   if (find) {
721     unhidden_name = find->data;
722     provider->priv->hidden_providers =
723         g_list_delete_link (provider->priv->hidden_providers, find);
724   }
725   GST_OBJECT_UNLOCK (provider);
726
727   if (unhidden_name) {
728     g_signal_emit (provider,
729         gst_device_provider_signals[PROVIDER_UNHIDDEN], 0, unhidden_name);
730     g_free (unhidden_name);
731   }
732 }