2 * Copyright (C) 2013 Olivier Crete <olivier.crete@collabora.com>
4 * gstglobaldevicemonitor.c: Global 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.
26 #include <gst/gstglobaldevicemonitor.h>
28 #include "gst/gst_private.h"
31 struct _GstGlobalDeviceMonitorPrivate
41 GstDeviceMonitorFactoryListType type;
45 G_DEFINE_TYPE (GstGlobalDeviceMonitor, gst_global_device_monitor,
48 static void gst_global_device_monitor_dispose (GObject * object);
51 gst_global_device_monitor_class_init (GstGlobalDeviceMonitorClass * klass)
53 GObjectClass *object_class = G_OBJECT_CLASS (klass);
55 g_type_class_add_private (klass, sizeof (GstGlobalDeviceMonitorPrivate));
57 object_class->dispose = gst_global_device_monitor_dispose;
61 bus_sync_message (GstBus * bus, GstMessage * message,
62 GstGlobalDeviceMonitor * monitor)
64 GstMessageType type = GST_MESSAGE_TYPE (message);
66 if (type == GST_MESSAGE_DEVICE_ADDED || type == GST_MESSAGE_DEVICE_REMOVED) {
71 if (type == GST_MESSAGE_DEVICE_ADDED)
72 gst_message_parse_device_added (message, &device);
74 gst_message_parse_device_removed (message, &device);
76 GST_OBJECT_LOCK (monitor);
77 caps = gst_device_get_caps (device);
78 intersects = gst_caps_can_intersect (monitor->priv->caps, caps);
79 gst_caps_unref (caps);
80 GST_OBJECT_UNLOCK (monitor);
83 gst_bus_post (monitor->priv->bus, gst_message_ref (message));
89 gst_global_device_monitor_init (GstGlobalDeviceMonitor * self)
93 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
94 GST_TYPE_GLOBAL_DEVICE_MONITOR, GstGlobalDeviceMonitorPrivate);
96 self->priv->bus = gst_bus_new ();
97 gst_bus_set_flushing (self->priv->bus, TRUE);
99 self->priv->monitors = g_ptr_array_new ();
100 self->priv->caps = gst_caps_new_any ();
101 self->priv->type = GST_DEVICE_MONITOR_FACTORY_TYPE_SINK |
102 GST_DEVICE_MONITOR_FACTORY_TYPE_SRC;
105 gst_device_monitor_factory_list_get_device_monitors (self->priv->type, 1);
108 GstDeviceMonitorFactory *factory = factories->data;
109 GstDeviceMonitor *monitor;
111 factories = g_list_remove (factories, factory);
113 monitor = gst_device_monitor_factory_get (factory);
115 GstBus *bus = gst_device_monitor_get_bus (monitor);
117 gst_bus_enable_sync_message_emission (bus);
118 g_signal_connect (monitor, "sync-message",
119 G_CALLBACK (bus_sync_message), self);
120 g_ptr_array_add (self->priv->monitors, monitor);
123 gst_object_unref (factory);
129 gst_global_device_monitor_remove (GstGlobalDeviceMonitor * self, guint i)
131 GstDeviceMonitor *monitor = g_ptr_array_index (self->priv->monitors, i);
134 g_ptr_array_remove_index_fast (self->priv->monitors, i);
136 bus = gst_device_monitor_get_bus (monitor);
137 g_signal_handlers_disconnect_by_func (bus, bus_sync_message, self);
138 gst_object_unref (bus);
140 gst_object_unref (monitor);
144 gst_global_device_monitor_dispose (GObject * object)
146 GstGlobalDeviceMonitor *self = GST_GLOBAL_DEVICE_MONITOR (object);
148 g_return_if_fail (self->priv->started == FALSE);
150 if (self->priv->monitors) {
151 while (self->priv->monitors->len)
152 gst_global_device_monitor_remove (self, self->priv->monitors->len - 1);
153 g_ptr_array_unref (self->priv->monitors);
154 self->priv->monitors = NULL;
157 gst_caps_replace (&self->priv->caps, NULL);
158 gst_object_replace ((GstObject **) & self->priv->bus, NULL);
160 G_OBJECT_CLASS (gst_global_device_monitor_parent_class)->dispose (object);
164 * gst_global_device_monitor_get_devices:
165 * @monitor: A #GstDeviceMonitor
167 * Gets a list of devices from all of the relevant monitors. This may actually
168 * probe the hardware if the global monitor is not currently started.
170 * Returns: (transfer full) (element-type GstDevice): a #GList of
175 gst_global_device_monitor_get_devices (GstGlobalDeviceMonitor * self)
177 GList *devices = NULL;
181 g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (self), NULL);
183 GST_OBJECT_LOCK (self);
187 g_list_free_full (devices, gst_object_unref);
190 cookie = self->priv->cookie;
192 for (i = 0; i < self->priv->monitors->len; i++) {
194 GstDeviceMonitor *monitor =
195 gst_object_ref (g_ptr_array_index (self->priv->monitors, i));
198 GST_OBJECT_UNLOCK (self);
200 tmpdev = gst_device_monitor_get_devices (monitor);
202 for (item = tmpdev; item; item = item->next) {
203 GstDevice *dev = GST_DEVICE (item->data);
204 GstCaps *caps = gst_device_get_caps (dev);
206 if (gst_caps_can_intersect (self->priv->caps, caps))
207 devices = g_list_prepend (devices, gst_object_ref (dev));
208 gst_caps_unref (caps);
211 g_list_free_full (tmpdev, gst_object_unref);
212 gst_object_unref (monitor);
214 GST_OBJECT_LOCK (self);
216 if (self->priv->cookie != cookie)
220 GST_OBJECT_UNLOCK (self);
226 * gst_global_device_monitor_start:
227 * @monitor: A #GstGlobalDeviceMonitor
229 * Starts monitoring the devices, one this has succeeded, the
230 * #GstGlobalDeviceMonitor:added and #GstGlobalDeviceMonitor:removed
231 * signals will be emitted when the list of devices changes.
233 * Returns: %TRUE if the device monitoring could be started
237 gst_global_device_monitor_start (GstGlobalDeviceMonitor * self)
241 g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (self), FALSE);
243 GST_OBJECT_LOCK (self);
245 if (self->priv->monitors->len == 0) {
246 GST_OBJECT_UNLOCK (self);
250 gst_bus_set_flushing (self->priv->bus, FALSE);
252 for (i = 0; i < self->priv->monitors->len; i++) {
253 if (!gst_device_monitor_start (g_ptr_array_index (self->priv->monitors, i))) {
254 gst_bus_set_flushing (self->priv->bus, TRUE);
257 gst_device_monitor_stop (g_ptr_array_index (self->priv->monitors,
260 GST_OBJECT_UNLOCK (self);
265 self->priv->started = TRUE;
266 GST_OBJECT_UNLOCK (self);
272 * gst_global_device_monitor_stop:
273 * @monitor: A #GstDeviceMonitor
275 * Stops monitoring the devices.
279 gst_global_device_monitor_stop (GstGlobalDeviceMonitor * self)
283 g_return_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (self));
285 gst_bus_set_flushing (self->priv->bus, TRUE);
287 GST_OBJECT_LOCK (self);
288 for (i = 0; i < self->priv->monitors->len; i++)
289 gst_device_monitor_stop (g_ptr_array_index (self->priv->monitors, i));
290 self->priv->started = FALSE;
291 GST_OBJECT_UNLOCK (self);
296 gst_global_device_monitor_set_type_filter (GstGlobalDeviceMonitor * self,
297 GstDeviceMonitorFactoryListType type)
299 GList *factories = NULL;
302 g_return_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (self));
303 g_return_if_fail (!self->priv->started);
304 g_return_if_fail (type &
305 (GST_DEVICE_MONITOR_FACTORY_TYPE_SINK |
306 GST_DEVICE_MONITOR_FACTORY_TYPE_SRC));
308 GST_OBJECT_LOCK (self);
309 if (self->priv->type == type) {
310 GST_OBJECT_UNLOCK (self);
314 self->priv->type = type;
317 gst_device_monitor_factory_list_get_device_monitors (self->priv->type, 1);
319 for (i = 0; i < self->priv->monitors->len; i++) {
320 GstDeviceMonitor *monitor = g_ptr_array_index (self->priv->monitors, i);
321 GstDeviceMonitorFactory *f = gst_device_monitor_get_factory (monitor);
324 item = g_list_find (factories, f);
327 /* If the item is in our list, then remove it from the list of factories,
328 * we don't have it to re-create it later
330 factories = g_list_remove_link (factories, item);
331 gst_object_unref (f);
333 /* If it's not in our list, them remove it from the list of monitors.
336 self->priv->cookie++;
337 gst_global_device_monitor_remove (self, i);
343 GstDeviceMonitorFactory *factory = factories->data;
344 GstDeviceMonitor *monitor;
346 factories = g_list_remove (factories, factory);
348 monitor = gst_device_monitor_factory_get (factory);
350 GstBus *bus = gst_device_monitor_get_bus (monitor);
352 gst_bus_enable_sync_message_emission (bus);
353 g_signal_connect (bus, "sync-message",
354 G_CALLBACK (bus_sync_message), self);
355 gst_object_unref (bus);
356 g_ptr_array_add (self->priv->monitors, monitor);
357 self->priv->cookie++;
360 gst_object_unref (factory);
363 GST_OBJECT_UNLOCK (self);
366 GstDeviceMonitorFactoryListType
367 gst_global_device_monitor_get_type_filter (GstGlobalDeviceMonitor * self)
369 GstDeviceMonitorFactoryListType res;
371 g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (self), 0);
373 GST_OBJECT_LOCK (self);
374 res = self->priv->type;
375 GST_OBJECT_UNLOCK (self);
381 gst_global_device_monitor_set_caps_filter (GstGlobalDeviceMonitor * self,
384 g_return_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (self));
385 g_return_if_fail (GST_IS_CAPS (caps));
387 GST_OBJECT_LOCK (self);
388 gst_caps_replace (&self->priv->caps, caps);
389 GST_OBJECT_UNLOCK (self);
393 gst_global_device_monitor_get_caps_filter (GstGlobalDeviceMonitor * self)
397 g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (self), NULL);
399 GST_OBJECT_LOCK (self);
400 res = gst_caps_ref (self->priv->caps);
401 GST_OBJECT_UNLOCK (self);
406 GstGlobalDeviceMonitor *
407 gst_global_device_monitor_new (void)
409 return g_object_new (GST_TYPE_GLOBAL_DEVICE_MONITOR, NULL);
413 * gst_global_device_monitor_get_bus:
414 * @monitor: a #GstDeviceMonitor
416 * Gets the #GstBus of this #GstGlobalDeviceMonitor
418 * Returns: (transfer full): a #GstBus
421 gst_global_device_monitor_get_bus (GstGlobalDeviceMonitor * monitor)
423 g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor), NULL);
425 return gst_object_ref (monitor->priv->bus);