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