2 * Copyright (C) 2013 Olivier Crete <olivier.crete@collabora.com>
4 * gstdevicemonitor.c: device monitor
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.
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.
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.
23 * SECTION:gstdevicemonitor
24 * @short_description: A device monitor and prober
25 * @see_also: #GstDevice, #GstDeviceProvider
27 * Applications should create a #GstDeviceMonitor when they want
28 * to probe, list and monitor devices of a specific type. The
29 * #GstDeviceMonitor will create the appropriate
30 * #GstDeviceProvider objects and manage them. It will then post
31 * messages on its #GstBus for devices that have been added and
42 #include "gst_private.h"
43 #include "gstdevicemonitor.h"
45 struct _GstDeviceMonitorPrivate
59 G_DEFINE_TYPE (GstDeviceMonitor, gst_device_monitor, GST_TYPE_OBJECT);
61 static void gst_device_monitor_dispose (GObject * object);
64 gst_device_monitor_class_init (GstDeviceMonitorClass * klass)
66 GObjectClass *object_class = G_OBJECT_CLASS (klass);
68 g_type_class_add_private (klass, sizeof (GstDeviceMonitorPrivate));
70 object_class->dispose = gst_device_monitor_dispose;
74 bus_sync_message (GstBus * bus, GstMessage * message,
75 GstDeviceMonitor * monitor)
77 GstMessageType type = GST_MESSAGE_TYPE (message);
79 if (type == GST_MESSAGE_DEVICE_ADDED || type == GST_MESSAGE_DEVICE_REMOVED) {
84 if (type == GST_MESSAGE_DEVICE_ADDED)
85 gst_message_parse_device_added (message, &device);
87 gst_message_parse_device_removed (message, &device);
89 GST_OBJECT_LOCK (monitor);
90 caps = gst_device_get_caps (device);
91 matches = gst_caps_can_intersect (monitor->priv->caps, caps) &&
92 gst_device_has_classes (device, monitor->priv->classes);
93 gst_caps_unref (caps);
94 GST_OBJECT_UNLOCK (monitor);
97 gst_bus_post (monitor->priv->bus, gst_message_ref (message));
103 gst_device_monitor_init (GstDeviceMonitor * self)
107 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
108 GST_TYPE_DEVICE_MONITOR, GstDeviceMonitorPrivate);
110 self->priv->bus = gst_bus_new ();
111 gst_bus_set_flushing (self->priv->bus, TRUE);
113 self->priv->providers = g_ptr_array_new ();
114 self->priv->caps = gst_caps_new_any ();
115 self->priv->classes = g_strdup ("");
118 gst_device_provider_factory_list_get_device_providers (self->
122 GstDeviceProviderFactory *factory = factories->data;
123 GstDeviceProvider *provider;
125 factories = g_list_remove (factories, factory);
127 provider = gst_device_provider_factory_get (factory);
129 GstBus *bus = gst_device_provider_get_bus (provider);
131 gst_bus_enable_sync_message_emission (bus);
132 g_signal_connect (bus, "sync-message",
133 G_CALLBACK (bus_sync_message), self);
134 g_ptr_array_add (self->priv->providers, provider);
137 gst_object_unref (factory);
143 gst_device_monitor_remove (GstDeviceMonitor * self, guint i)
145 GstDeviceProvider *provider = g_ptr_array_index (self->priv->providers, i);
148 g_ptr_array_remove_index_fast (self->priv->providers, i);
150 bus = gst_device_provider_get_bus (provider);
151 g_signal_handlers_disconnect_by_func (bus, bus_sync_message, self);
152 gst_object_unref (bus);
154 gst_object_unref (provider);
158 gst_device_monitor_dispose (GObject * object)
160 GstDeviceMonitor *self = GST_DEVICE_MONITOR (object);
162 g_return_if_fail (self->priv->started == FALSE);
164 if (self->priv->providers) {
165 while (self->priv->providers->len)
166 gst_device_monitor_remove (self, self->priv->providers->len - 1);
167 g_ptr_array_unref (self->priv->providers);
168 self->priv->providers = NULL;
171 gst_caps_replace (&self->priv->caps, NULL);
172 g_free (self->priv->classes);
173 gst_object_replace ((GstObject **) & self->priv->bus, NULL);
175 G_OBJECT_CLASS (gst_device_monitor_parent_class)->dispose (object);
179 * gst_device_monitor_get_devices:
180 * @monitor: A #GstDeviceProvider
182 * Gets a list of devices from all of the relevant monitors. This may actually
183 * probe the hardware if the monitor is not currently started.
185 * Returns: (transfer full) (element-type GstDevice): a #GList of
192 gst_device_monitor_get_devices (GstDeviceMonitor * monitor)
194 GList *devices = NULL;
198 g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL);
200 GST_OBJECT_LOCK (monitor);
204 g_list_free_full (devices, gst_object_unref);
207 cookie = monitor->priv->cookie;
209 for (i = 0; i < monitor->priv->providers->len; i++) {
211 GstDeviceProvider *provider =
212 gst_object_ref (g_ptr_array_index (monitor->priv->providers, i));
215 GST_OBJECT_UNLOCK (monitor);
217 tmpdev = gst_device_provider_get_devices (provider);
219 for (item = tmpdev; item; item = item->next) {
220 GstDevice *dev = GST_DEVICE (item->data);
221 GstCaps *caps = gst_device_get_caps (dev);
223 if (gst_caps_can_intersect (monitor->priv->caps, caps) &&
224 gst_device_has_classes (dev, monitor->priv->classes))
225 devices = g_list_prepend (devices, gst_object_ref (dev));
226 gst_caps_unref (caps);
229 g_list_free_full (tmpdev, gst_object_unref);
230 gst_object_unref (provider);
232 GST_OBJECT_LOCK (monitor);
234 if (monitor->priv->cookie != cookie)
238 GST_OBJECT_UNLOCK (monitor);
244 * gst_device_monitor_start:
245 * @monitor: A #GstDeviceMonitor
247 * Starts monitoring the devices, one this has succeeded, the
248 * %GST_MESSAGE_DEVICE_ADDED and %GST_MESSAGE_DEVICE_REMOVED messages
249 * will be emitted on the bus when the list of devices changes.
251 * Returns: %TRUE if the device monitoring could be started
257 gst_device_monitor_start (GstDeviceMonitor * monitor)
261 g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), FALSE);
263 GST_OBJECT_LOCK (monitor);
265 if (monitor->priv->providers->len == 0) {
266 GST_OBJECT_UNLOCK (monitor);
270 gst_bus_set_flushing (monitor->priv->bus, FALSE);
272 for (i = 0; i < monitor->priv->providers->len; i++) {
273 if (!gst_device_provider_start (g_ptr_array_index (monitor->priv->providers,
275 gst_bus_set_flushing (monitor->priv->bus, TRUE);
278 gst_device_provider_stop (g_ptr_array_index (monitor->priv->providers,
281 GST_OBJECT_UNLOCK (monitor);
286 monitor->priv->started = TRUE;
287 GST_OBJECT_UNLOCK (monitor);
293 * gst_device_monitor_stop:
294 * @monitor: A #GstDeviceProvider
296 * Stops monitoring the devices.
301 gst_device_monitor_stop (GstDeviceMonitor * monitor)
305 g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor));
307 gst_bus_set_flushing (monitor->priv->bus, TRUE);
309 GST_OBJECT_LOCK (monitor);
310 for (i = 0; i < monitor->priv->providers->len; i++)
311 gst_device_provider_stop (g_ptr_array_index (monitor->priv->providers, i));
312 monitor->priv->started = FALSE;
313 GST_OBJECT_UNLOCK (monitor);
318 * gst_device_monitor_set_classes_filter:
319 * @monitor: the device monitor
320 * @classes: device classes to use as filter
322 * Filter devices monitored by device class, e.g. in case you are only
323 * interested in a certain type of device like audio devices or
329 gst_device_monitor_set_classes_filter (GstDeviceMonitor * monitor,
330 const gchar * classes)
332 GList *factories = NULL;
335 g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor));
336 g_return_if_fail (!monitor->priv->started);
338 GST_OBJECT_LOCK (monitor);
339 if (!strcmp (monitor->priv->classes, classes)) {
340 GST_OBJECT_UNLOCK (monitor);
344 g_free (monitor->priv->classes);
345 monitor->priv->classes = g_strdup (classes);
347 factories = gst_device_provider_factory_list_get_device_providers (classes,
350 for (i = 0; i < monitor->priv->providers->len; i++) {
351 GstDeviceProvider *provider;
352 GstDeviceProviderFactory *f;
355 provider = g_ptr_array_index (monitor->priv->providers, i);
356 f = gst_device_provider_get_factory (provider);
358 item = g_list_find (factories, f);
361 /* If the item is in our list, then remove it from the list of factories,
362 * we don't have it to re-create it later
364 factories = g_list_remove_link (factories, item);
365 gst_object_unref (f);
367 /* If it's not in our list, them remove it from the list of providers.
370 monitor->priv->cookie++;
371 gst_device_monitor_remove (monitor, i);
377 GstDeviceProviderFactory *factory = factories->data;
378 GstDeviceProvider *provider;
380 factories = g_list_remove (factories, factory);
382 provider = gst_device_provider_factory_get (factory);
384 GstBus *bus = gst_device_provider_get_bus (provider);
386 gst_bus_enable_sync_message_emission (bus);
387 g_signal_connect (bus, "sync-message",
388 G_CALLBACK (bus_sync_message), monitor);
389 gst_object_unref (bus);
390 g_ptr_array_add (monitor->priv->providers, provider);
391 monitor->priv->cookie++;
394 gst_object_unref (factory);
397 GST_OBJECT_UNLOCK (monitor);
401 * gst_device_monitor_get_classes_filter:
402 * @monitor: the device monitor
404 * Return the type (device classes) filter active for device filtering.
406 * Returns: string of device classes that are being filtered.
411 gst_device_monitor_get_classes_filter (GstDeviceMonitor * monitor)
415 g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), 0);
417 GST_OBJECT_LOCK (monitor);
418 res = g_strdup (monitor->priv->classes);
419 GST_OBJECT_UNLOCK (monitor);
425 * gst_device_monitor_set_caps_filter:
426 * @monitor: the device monitor
427 * @caps: caps to filter
429 * Set caps to use as filter for devices. By default ANY caps are used,
430 * meaning no caps filter is active.
435 gst_device_monitor_set_caps_filter (GstDeviceMonitor * monitor, GstCaps * caps)
437 g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor));
438 g_return_if_fail (GST_IS_CAPS (caps));
440 GST_OBJECT_LOCK (monitor);
441 gst_caps_replace (&monitor->priv->caps, caps);
442 GST_OBJECT_UNLOCK (monitor);
446 * gst_device_monitor_get_caps_filter:
447 * @monitor: a device monitor
449 * Get the #GstCaps filter set by gst_device_monitor_set_caps_filter().
451 * Returns: (transfer full): the filter caps that are active (or ANY caps)
456 gst_device_monitor_get_caps_filter (GstDeviceMonitor * monitor)
460 g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL);
462 GST_OBJECT_LOCK (monitor);
463 res = gst_caps_ref (monitor->priv->caps);
464 GST_OBJECT_UNLOCK (monitor);
470 * gst_device_monitor_new:
472 * Create a new #GstDeviceMonitor
474 * Returns: (transfer full): a new device monitor.
479 gst_device_monitor_new (void)
481 return g_object_new (GST_TYPE_DEVICE_MONITOR, NULL);
485 * gst_device_monitor_get_bus:
486 * @monitor: a #GstDeviceProvider
488 * Gets the #GstBus of this #GstDeviceMonitor
490 * Returns: (transfer full): a #GstBus
495 gst_device_monitor_get_bus (GstDeviceMonitor * monitor)
497 g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL);
499 return gst_object_ref (monitor->priv->bus);