<chapter id="gstreamer-device-probing">
<title>GStreamer Device Discovery and Device Probing</title>
- <xi:include href="xml/gstglobaldevicemonitor.xml" />
+ <xi:include href="xml/gstdevicemonitor.xml" />
<xi:include href="xml/gstdevice.xml" />
<xi:include href="xml/gstdeviceprovider.xml" />
<xi:include href="xml/gstdeviceproviderfactory.xml" />
</SECTION>
<SECTION>
-<FILE>gstglobaldevicemonitor</FILE>
-<TITLE>GstGlobalDeviceMonitor</TITLE>
-GstGlobalDeviceMonitor
-GstGlobalDeviceMonitorClass
-gst_global_device_monitor_get_bus
-gst_global_device_monitor_get_caps_filter
-gst_global_device_monitor_get_classes_filter
-gst_global_device_monitor_get_devices
-gst_global_device_monitor_new
-gst_global_device_monitor_set_caps_filter
-gst_global_device_monitor_set_classes_filter
-gst_global_device_monitor_start
-gst_global_device_monitor_stop
+<FILE>gstdevicemonitor</FILE>
+<TITLE>GstDeviceMonitor</TITLE>
+GstDeviceMonitor
+GstDeviceMonitorClass
+gst_device_monitor_get_bus
+gst_device_monitor_get_caps_filter
+gst_device_monitor_get_classes_filter
+gst_device_monitor_get_devices
+gst_device_monitor_new
+gst_device_monitor_set_caps_filter
+gst_device_monitor_set_classes_filter
+gst_device_monitor_start
+gst_device_monitor_stop
<SUBSECTION Standard>
-GstGlobalDeviceMonitorPrivate
-GST_GLOBAL_DEVICE_MONITOR
-GST_GLOBAL_DEVICE_MONITOR_CAST
-GST_GLOBAL_DEVICE_MONITOR_CLASS
-GST_GLOBAL_DEVICE_MONITOR_GET_CLASS
-GST_IS_GLOBAL_DEVICE_MONITOR
-GST_IS_GLOBAL_DEVICE_MONITOR_CLASS
-GST_TYPE_GLOBAL_DEVICE_MONITOR
-gst_global_device_monitor_get_type
+GstDeviceMonitorPrivate
+GST_DEVICE_MONITOR
+GST_DEVICE_MONITOR_CAST
+GST_DEVICE_MONITOR_CLASS
+GST_DEVICE_MONITOR_GET_CLASS
+GST_IS_DEVICE_MONITOR
+GST_IS_DEVICE_MONITOR_CLASS
+GST_TYPE_DEVICE_MONITOR
+gst_device_monitor_get_type
</SECTION>
gstevent.c \
gstformat.c \
gstghostpad.c \
- gstglobaldevicemonitor.c \
+ gstdevicemonitor.c \
gstinfo.c \
gstiterator.c \
gstatomicqueue.c \
gstevent.h \
gstformat.h \
gstghostpad.h \
- gstglobaldevicemonitor.h \
+ gstdevicemonitor.h \
gstinfo.h \
gstiterator.h \
gstatomicqueue.h \
#include <gst/gsterror.h>
#include <gst/gstevent.h>
#include <gst/gstghostpad.h>
-#include <gst/gstglobaldevicemonitor.h>
+#include <gst/gstdevicemonitor.h>
#include <gst/gstinfo.h>
#include <gst/gstiterator.h>
#include <gst/gstmessage.h>
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2013 Olivier Crete <olivier.crete@collabora.com>
+ *
+ * gstdevicemonitor.c: device monitor
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gstdevicemonitor
+ * @short_description: A device monitor and prober
+ * @see_also: #GstDevice, #GstDeviceProvider
+ *
+ * Applications should create a #GstDeviceMonitor when they want
+ * to probe, list and monitor devices of a specific type. The
+ * #GstDeviceMonitor will create the appropriate
+ * #GstDeviceProvider objects and manage them. It will then post
+ * messages on its #GstBus for devices that have been added and
+ * removed.
+ *
+ * Since: 1.4
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gst_private.h"
+#include "gstdevicemonitor.h"
+
+struct _GstDeviceMonitorPrivate
+{
+ gboolean started;
+
+ GstBus *bus;
+
+ GPtrArray *providers;
+ guint cookie;
+
+ GstCaps *caps;
+ gchar *classes;
+};
+
+
+G_DEFINE_TYPE (GstDeviceMonitor, gst_device_monitor, GST_TYPE_OBJECT);
+
+static void gst_device_monitor_dispose (GObject * object);
+
+static void
+gst_device_monitor_class_init (GstDeviceMonitorClass * klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GstDeviceMonitorPrivate));
+
+ object_class->dispose = gst_device_monitor_dispose;
+}
+
+static void
+bus_sync_message (GstBus * bus, GstMessage * message,
+ GstDeviceMonitor * monitor)
+{
+ GstMessageType type = GST_MESSAGE_TYPE (message);
+
+ if (type == GST_MESSAGE_DEVICE_ADDED || type == GST_MESSAGE_DEVICE_REMOVED) {
+ gboolean matches;
+ GstCaps *caps;
+ GstDevice *device;
+
+ if (type == GST_MESSAGE_DEVICE_ADDED)
+ gst_message_parse_device_added (message, &device);
+ else
+ gst_message_parse_device_removed (message, &device);
+
+ GST_OBJECT_LOCK (monitor);
+ caps = gst_device_get_caps (device);
+ matches = gst_caps_can_intersect (monitor->priv->caps, caps) &&
+ gst_device_has_classes (device, monitor->priv->classes);
+ gst_caps_unref (caps);
+ GST_OBJECT_UNLOCK (monitor);
+
+ if (matches)
+ gst_bus_post (monitor->priv->bus, gst_message_ref (message));
+ }
+}
+
+
+static void
+gst_device_monitor_init (GstDeviceMonitor * self)
+{
+ GList *factories;
+
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ GST_TYPE_DEVICE_MONITOR, GstDeviceMonitorPrivate);
+
+ self->priv->bus = gst_bus_new ();
+ gst_bus_set_flushing (self->priv->bus, TRUE);
+
+ self->priv->providers = g_ptr_array_new ();
+ self->priv->caps = gst_caps_new_any ();
+ self->priv->classes = g_strdup ("");
+
+ factories =
+ gst_device_provider_factory_list_get_device_providers (self->
+ priv->classes, 1);
+
+ while (factories) {
+ GstDeviceProviderFactory *factory = factories->data;
+ GstDeviceProvider *provider;
+
+ factories = g_list_remove (factories, factory);
+
+ provider = gst_device_provider_factory_get (factory);
+ if (provider) {
+ GstBus *bus = gst_device_provider_get_bus (provider);
+
+ gst_bus_enable_sync_message_emission (bus);
+ g_signal_connect (bus, "sync-message",
+ G_CALLBACK (bus_sync_message), self);
+ g_ptr_array_add (self->priv->providers, provider);
+ }
+
+ gst_object_unref (factory);
+ }
+}
+
+
+static void
+gst_device_monitor_remove (GstDeviceMonitor * self, guint i)
+{
+ GstDeviceProvider *provider = g_ptr_array_index (self->priv->providers, i);
+ GstBus *bus;
+
+ g_ptr_array_remove_index_fast (self->priv->providers, i);
+
+ bus = gst_device_provider_get_bus (provider);
+ g_signal_handlers_disconnect_by_func (bus, bus_sync_message, self);
+ gst_object_unref (bus);
+
+ gst_object_unref (provider);
+}
+
+static void
+gst_device_monitor_dispose (GObject * object)
+{
+ GstDeviceMonitor *self = GST_DEVICE_MONITOR (object);
+
+ g_return_if_fail (self->priv->started == FALSE);
+
+ if (self->priv->providers) {
+ while (self->priv->providers->len)
+ gst_device_monitor_remove (self, self->priv->providers->len - 1);
+ g_ptr_array_unref (self->priv->providers);
+ self->priv->providers = NULL;
+ }
+
+ gst_caps_replace (&self->priv->caps, NULL);
+ g_free (self->priv->classes);
+ gst_object_replace ((GstObject **) & self->priv->bus, NULL);
+
+ G_OBJECT_CLASS (gst_device_monitor_parent_class)->dispose (object);
+}
+
+/**
+ * gst_device_monitor_get_devices:
+ * @monitor: A #GstDeviceProvider
+ *
+ * Gets a list of devices from all of the relevant monitors. This may actually
+ * probe the hardware if the monitor is not currently started.
+ *
+ * Returns: (transfer full) (element-type GstDevice): a #GList of
+ * #GstDevice
+ *
+ * Since: 1.4
+ */
+
+GList *
+gst_device_monitor_get_devices (GstDeviceMonitor * monitor)
+{
+ GList *devices = NULL;
+ guint i;
+ guint cookie;
+
+ g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL);
+
+ GST_OBJECT_LOCK (monitor);
+
+again:
+
+ g_list_free_full (devices, gst_object_unref);
+ devices = NULL;
+
+ cookie = monitor->priv->cookie;
+
+ for (i = 0; i < monitor->priv->providers->len; i++) {
+ GList *tmpdev;
+ GstDeviceProvider *provider =
+ gst_object_ref (g_ptr_array_index (monitor->priv->providers, i));
+ GList *item;
+
+ GST_OBJECT_UNLOCK (monitor);
+
+ tmpdev = gst_device_provider_get_devices (provider);
+
+ for (item = tmpdev; item; item = item->next) {
+ GstDevice *dev = GST_DEVICE (item->data);
+ GstCaps *caps = gst_device_get_caps (dev);
+
+ if (gst_caps_can_intersect (monitor->priv->caps, caps) &&
+ gst_device_has_classes (dev, monitor->priv->classes))
+ devices = g_list_prepend (devices, gst_object_ref (dev));
+ gst_caps_unref (caps);
+ }
+
+ g_list_free_full (tmpdev, gst_object_unref);
+ gst_object_unref (provider);
+
+ GST_OBJECT_LOCK (monitor);
+
+ if (monitor->priv->cookie != cookie)
+ goto again;
+ }
+
+ GST_OBJECT_UNLOCK (monitor);
+
+ return devices;
+}
+
+/**
+ * gst_device_monitor_start:
+ * @monitor: A #GstDeviceMonitor
+ *
+ * Starts monitoring the devices, one this has succeeded, the
+ * %GST_MESSAGE_DEVICE_ADDED and %GST_MESSAGE_DEVICE_REMOVED messages
+ * will be emitted on the bus when the list of devices changes.
+ *
+ * Returns: %TRUE if the device monitoring could be started
+ *
+ * Since: 1.4
+ */
+
+gboolean
+gst_device_monitor_start (GstDeviceMonitor * monitor)
+{
+ guint i;
+
+ g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), FALSE);
+
+ GST_OBJECT_LOCK (monitor);
+
+ if (monitor->priv->providers->len == 0) {
+ GST_OBJECT_UNLOCK (monitor);
+ return FALSE;
+ }
+
+ gst_bus_set_flushing (monitor->priv->bus, FALSE);
+
+ for (i = 0; i < monitor->priv->providers->len; i++) {
+ if (!gst_device_provider_start (g_ptr_array_index (monitor->priv->providers,
+ i))) {
+ gst_bus_set_flushing (monitor->priv->bus, TRUE);
+
+ for (; i != 0; i--)
+ gst_device_provider_stop (g_ptr_array_index (monitor->priv->providers,
+ i - 1));
+
+ GST_OBJECT_UNLOCK (monitor);
+ return FALSE;
+ }
+ }
+
+ monitor->priv->started = TRUE;
+ GST_OBJECT_UNLOCK (monitor);
+
+ return TRUE;
+}
+
+/**
+ * gst_device_monitor_stop:
+ * @monitor: A #GstDeviceProvider
+ *
+ * Stops monitoring the devices.
+ *
+ * Since: 1.4
+ */
+void
+gst_device_monitor_stop (GstDeviceMonitor * monitor)
+{
+ guint i;
+
+ g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor));
+
+ gst_bus_set_flushing (monitor->priv->bus, TRUE);
+
+ GST_OBJECT_LOCK (monitor);
+ for (i = 0; i < monitor->priv->providers->len; i++)
+ gst_device_provider_stop (g_ptr_array_index (monitor->priv->providers, i));
+ monitor->priv->started = FALSE;
+ GST_OBJECT_UNLOCK (monitor);
+
+}
+
+/**
+ * gst_device_monitor_set_classes_filter:
+ * @monitor: the device monitor
+ * @classes: device classes to use as filter
+ *
+ * Filter devices monitored by device class, e.g. in case you are only
+ * interested in a certain type of device like audio devices or
+ * video sources.
+ *
+ * Since: 1.4
+ */
+void
+gst_device_monitor_set_classes_filter (GstDeviceMonitor * monitor,
+ const gchar * classes)
+{
+ GList *factories = NULL;
+ guint i;
+
+ g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor));
+ g_return_if_fail (!monitor->priv->started);
+
+ GST_OBJECT_LOCK (monitor);
+ if (!strcmp (monitor->priv->classes, classes)) {
+ GST_OBJECT_UNLOCK (monitor);
+ return;
+ }
+
+ g_free (monitor->priv->classes);
+ monitor->priv->classes = g_strdup (classes);
+
+ factories = gst_device_provider_factory_list_get_device_providers (classes,
+ 1);
+
+ for (i = 0; i < monitor->priv->providers->len; i++) {
+ GstDeviceProvider *provider;
+ GstDeviceProviderFactory *f;
+ GList *item;
+
+ provider = g_ptr_array_index (monitor->priv->providers, i);
+ f = gst_device_provider_get_factory (provider);
+
+ item = g_list_find (factories, f);
+
+ if (item) {
+ /* If the item is in our list, then remove it from the list of factories,
+ * we don't have it to re-create it later
+ */
+ factories = g_list_remove_link (factories, item);
+ gst_object_unref (f);
+ } else {
+ /* If it's not in our list, them remove it from the list of providers.
+ */
+
+ monitor->priv->cookie++;
+ gst_device_monitor_remove (monitor, i);
+ i--;
+ }
+ }
+
+ while (factories) {
+ GstDeviceProviderFactory *factory = factories->data;
+ GstDeviceProvider *provider;
+
+ factories = g_list_remove (factories, factory);
+
+ provider = gst_device_provider_factory_get (factory);
+ if (provider) {
+ GstBus *bus = gst_device_provider_get_bus (provider);
+
+ gst_bus_enable_sync_message_emission (bus);
+ g_signal_connect (bus, "sync-message",
+ G_CALLBACK (bus_sync_message), monitor);
+ gst_object_unref (bus);
+ g_ptr_array_add (monitor->priv->providers, provider);
+ monitor->priv->cookie++;
+ }
+
+ gst_object_unref (factory);
+ }
+
+ GST_OBJECT_UNLOCK (monitor);
+}
+
+/**
+ * gst_device_monitor_get_classes_filter:
+ * @monitor: the device monitor
+ *
+ * Return the type (device classes) filter active for device filtering.
+ *
+ * Returns: string of device classes that are being filtered.
+ *
+ * Since: 1.4
+ */
+gchar *
+gst_device_monitor_get_classes_filter (GstDeviceMonitor * monitor)
+{
+ gchar *res;
+
+ g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), 0);
+
+ GST_OBJECT_LOCK (monitor);
+ res = g_strdup (monitor->priv->classes);
+ GST_OBJECT_UNLOCK (monitor);
+
+ return res;
+}
+
+/**
+ * gst_device_monitor_set_caps_filter:
+ * @monitor: the device monitor
+ * @caps: caps to filter
+ *
+ * Set caps to use as filter for devices. By default ANY caps are used,
+ * meaning no caps filter is active.
+ *
+ * Since: 1.4
+ */
+void
+gst_device_monitor_set_caps_filter (GstDeviceMonitor * monitor, GstCaps * caps)
+{
+ g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor));
+ g_return_if_fail (GST_IS_CAPS (caps));
+
+ GST_OBJECT_LOCK (monitor);
+ gst_caps_replace (&monitor->priv->caps, caps);
+ GST_OBJECT_UNLOCK (monitor);
+}
+
+/**
+ * gst_device_monitor_get_caps_filter:
+ * @monitor: a device monitor
+ *
+ * Get the #GstCaps filter set by gst_device_monitor_set_caps_filter().
+ *
+ * Returns: (transfer full): the filter caps that are active (or ANY caps)
+ *
+ * Since: 1.4
+ */
+GstCaps *
+gst_device_monitor_get_caps_filter (GstDeviceMonitor * monitor)
+{
+ GstCaps *res;
+
+ g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL);
+
+ GST_OBJECT_LOCK (monitor);
+ res = gst_caps_ref (monitor->priv->caps);
+ GST_OBJECT_UNLOCK (monitor);
+
+ return res;
+}
+
+/**
+ * gst_device_monitor_new:
+ *
+ * Create a new #GstDeviceMonitor
+ *
+ * Returns: (transfer full): a new device monitor.
+ *
+ * Since: 1.4
+ */
+GstDeviceMonitor *
+gst_device_monitor_new (void)
+{
+ return g_object_new (GST_TYPE_DEVICE_MONITOR, NULL);
+}
+
+/**
+ * gst_device_monitor_get_bus:
+ * @monitor: a #GstDeviceProvider
+ *
+ * Gets the #GstBus of this #GstDeviceMonitor
+ *
+ * Returns: (transfer full): a #GstBus
+ *
+ * Since: 1.4
+ */
+GstBus *
+gst_device_monitor_get_bus (GstDeviceMonitor * monitor)
+{
+ g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL);
+
+ return gst_object_ref (monitor->priv->bus);
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2013 Olivier Crete <olivier.crete@collabora.com>
+ *
+ * gstdevicemonitor.c: Device monitor
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_DEVICE_MONITOR_H__
+#define __GST_DEVICE_MONITOR_H__
+
+#include <gst/gstobject.h>
+#include <gst/gstdevice.h>
+#include <gst/gstdeviceprovider.h>
+#include <gst/gstdeviceproviderfactory.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstDeviceMonitor GstDeviceMonitor;
+typedef struct _GstDeviceMonitorPrivate GstDeviceMonitorPrivate;
+typedef struct _GstDeviceMonitorClass GstDeviceMonitorClass;
+
+#define GST_TYPE_DEVICE_MONITOR (gst_device_monitor_get_type())
+#define GST_IS_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEVICE_MONITOR))
+#define GST_IS_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEVICE_MONITOR))
+#define GST_DEVICE_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEVICE_MONITOR, GstDeviceMonitorClass))
+#define GST_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEVICE_MONITOR, GstDeviceMonitor))
+#define GST_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE_MONITOR, GstDeviceMonitorClass))
+#define GST_DEVICE_MONITOR_CAST(obj) ((GstDeviceMonitor *)(obj))
+
+/**
+ * GstDeviceMonitor:
+ * @parent: the parent #GstObject structure
+ *
+ * Opaque device monitor object structure.
+ *
+ * Since: 1.4
+ */
+struct _GstDeviceMonitor {
+ GstObject parent;
+
+ /*< private >*/
+
+ GstDeviceMonitorPrivate *priv;
+
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+/**
+ * GstDeviceMonitorClass:
+ * @parent_class: the parent #GstObjectClass structure
+ *
+ * Opaque device monitor class structure.
+ *
+ * Since: 1.4
+ */
+struct _GstDeviceMonitorClass {
+ GstObjectClass parent_class;
+
+ /*< private >*/
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+GType gst_device_monitor_get_type (void);
+
+GstDeviceMonitor * gst_device_monitor_new (void);
+
+GstBus * gst_device_monitor_get_bus (GstDeviceMonitor * monitor);
+
+GList * gst_device_monitor_get_devices (GstDeviceMonitor * monitor);
+
+
+gboolean gst_device_monitor_start (GstDeviceMonitor * monitor);
+
+void gst_device_monitor_stop (GstDeviceMonitor * monitor);
+
+
+void gst_device_monitor_set_classes_filter (GstDeviceMonitor * monitor,
+ const gchar * classes);
+
+gchar * gst_device_monitor_get_classes_filter (GstDeviceMonitor * monitor);
+
+
+void gst_device_monitor_set_caps_filter (GstDeviceMonitor * monitor,
+ GstCaps * caps);
+
+GstCaps * gst_device_monitor_get_caps_filter (GstDeviceMonitor * monitor);
+
+G_END_DECLS
+
+#endif /* __GST_DEVICE_MONITOR_H__ */
+++ /dev/null
-/* GStreamer
- * Copyright (C) 2013 Olivier Crete <olivier.crete@collabora.com>
- *
- * gstglobaldevicemonitor.c: Global device monitor
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:gstglobaldevicemonitor
- * @short_description: A global device monitor and prober
- * @see_also: #GstDevice, #GstDeviceProvider
- *
- * Applications should create a #GstGlobalDeviceMonitor when they want
- * to probe, list and monitor devices of a specific type. The
- * #GstGlobalDeviceMonitor will create the appropriate
- * #GstDeviceProvider objects and manage them. It will then post
- * messages on its #GstBus for devices that have been added and
- * removed.
- *
- * Since: 1.4
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gst_private.h"
-#include "gstglobaldevicemonitor.h"
-
-struct _GstGlobalDeviceMonitorPrivate
-{
- gboolean started;
-
- GstBus *bus;
-
- GPtrArray *providers;
- guint cookie;
-
- GstCaps *caps;
- gchar *classes;
-};
-
-
-G_DEFINE_TYPE (GstGlobalDeviceMonitor, gst_global_device_monitor,
- GST_TYPE_OBJECT);
-
-static void gst_global_device_monitor_dispose (GObject * object);
-
-static void
-gst_global_device_monitor_class_init (GstGlobalDeviceMonitorClass * klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (GstGlobalDeviceMonitorPrivate));
-
- object_class->dispose = gst_global_device_monitor_dispose;
-}
-
-static void
-bus_sync_message (GstBus * bus, GstMessage * message,
- GstGlobalDeviceMonitor * monitor)
-{
- GstMessageType type = GST_MESSAGE_TYPE (message);
-
- if (type == GST_MESSAGE_DEVICE_ADDED || type == GST_MESSAGE_DEVICE_REMOVED) {
- gboolean matches;
- GstCaps *caps;
- GstDevice *device;
-
- if (type == GST_MESSAGE_DEVICE_ADDED)
- gst_message_parse_device_added (message, &device);
- else
- gst_message_parse_device_removed (message, &device);
-
- GST_OBJECT_LOCK (monitor);
- caps = gst_device_get_caps (device);
- matches = gst_caps_can_intersect (monitor->priv->caps, caps) &&
- gst_device_has_classes (device, monitor->priv->classes);
- gst_caps_unref (caps);
- GST_OBJECT_UNLOCK (monitor);
-
- if (matches)
- gst_bus_post (monitor->priv->bus, gst_message_ref (message));
- }
-}
-
-
-static void
-gst_global_device_monitor_init (GstGlobalDeviceMonitor * self)
-{
- GList *factories;
-
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GST_TYPE_GLOBAL_DEVICE_MONITOR, GstGlobalDeviceMonitorPrivate);
-
- self->priv->bus = gst_bus_new ();
- gst_bus_set_flushing (self->priv->bus, TRUE);
-
- self->priv->providers = g_ptr_array_new ();
- self->priv->caps = gst_caps_new_any ();
- self->priv->classes = g_strdup ("");
-
- factories =
- gst_device_provider_factory_list_get_device_providers (self->priv->
- classes, 1);
-
- while (factories) {
- GstDeviceProviderFactory *factory = factories->data;
- GstDeviceProvider *provider;
-
- factories = g_list_remove (factories, factory);
-
- provider = gst_device_provider_factory_get (factory);
- if (provider) {
- GstBus *bus = gst_device_provider_get_bus (provider);
-
- gst_bus_enable_sync_message_emission (bus);
- g_signal_connect (bus, "sync-message",
- G_CALLBACK (bus_sync_message), self);
- g_ptr_array_add (self->priv->providers, provider);
- }
-
- gst_object_unref (factory);
- }
-}
-
-
-static void
-gst_global_device_monitor_remove (GstGlobalDeviceMonitor * self, guint i)
-{
- GstDeviceProvider *provider = g_ptr_array_index (self->priv->providers, i);
- GstBus *bus;
-
- g_ptr_array_remove_index_fast (self->priv->providers, i);
-
- bus = gst_device_provider_get_bus (provider);
- g_signal_handlers_disconnect_by_func (bus, bus_sync_message, self);
- gst_object_unref (bus);
-
- gst_object_unref (provider);
-}
-
-static void
-gst_global_device_monitor_dispose (GObject * object)
-{
- GstGlobalDeviceMonitor *self = GST_GLOBAL_DEVICE_MONITOR (object);
-
- g_return_if_fail (self->priv->started == FALSE);
-
- if (self->priv->providers) {
- while (self->priv->providers->len)
- gst_global_device_monitor_remove (self, self->priv->providers->len - 1);
- g_ptr_array_unref (self->priv->providers);
- self->priv->providers = NULL;
- }
-
- gst_caps_replace (&self->priv->caps, NULL);
- g_free (self->priv->classes);
- gst_object_replace ((GstObject **) & self->priv->bus, NULL);
-
- G_OBJECT_CLASS (gst_global_device_monitor_parent_class)->dispose (object);
-}
-
-/**
- * gst_global_device_monitor_get_devices:
- * @monitor: A #GstDeviceProvider
- *
- * Gets a list of devices from all of the relevant monitors. This may actually
- * probe the hardware if the global monitor is not currently started.
- *
- * Returns: (transfer full) (element-type GstDevice): a #GList of
- * #GstDevice
- *
- * Since: 1.4
- */
-
-GList *
-gst_global_device_monitor_get_devices (GstGlobalDeviceMonitor * monitor)
-{
- GList *devices = NULL;
- guint i;
- guint cookie;
-
- g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor), NULL);
-
- GST_OBJECT_LOCK (monitor);
-
-again:
-
- g_list_free_full (devices, gst_object_unref);
- devices = NULL;
-
- cookie = monitor->priv->cookie;
-
- for (i = 0; i < monitor->priv->providers->len; i++) {
- GList *tmpdev;
- GstDeviceProvider *provider =
- gst_object_ref (g_ptr_array_index (monitor->priv->providers, i));
- GList *item;
-
- GST_OBJECT_UNLOCK (monitor);
-
- tmpdev = gst_device_provider_get_devices (provider);
-
- for (item = tmpdev; item; item = item->next) {
- GstDevice *dev = GST_DEVICE (item->data);
- GstCaps *caps = gst_device_get_caps (dev);
-
- if (gst_caps_can_intersect (monitor->priv->caps, caps) &&
- gst_device_has_classes (dev, monitor->priv->classes))
- devices = g_list_prepend (devices, gst_object_ref (dev));
- gst_caps_unref (caps);
- }
-
- g_list_free_full (tmpdev, gst_object_unref);
- gst_object_unref (provider);
-
- GST_OBJECT_LOCK (monitor);
-
- if (monitor->priv->cookie != cookie)
- goto again;
- }
-
- GST_OBJECT_UNLOCK (monitor);
-
- return devices;
-}
-
-/**
- * gst_global_device_monitor_start:
- * @monitor: A #GstGlobalDeviceMonitor
- *
- * Starts monitoring the devices, one this has succeeded, the
- * %GST_MESSAGE_DEVICE_ADDED and %GST_MESSAGE_DEVICE_REMOVED messages
- * will be emitted on the bus when the list of devices changes.
- *
- * Returns: %TRUE if the device monitoring could be started
- *
- * Since: 1.4
- */
-
-gboolean
-gst_global_device_monitor_start (GstGlobalDeviceMonitor * monitor)
-{
- guint i;
-
- g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor), FALSE);
-
- GST_OBJECT_LOCK (monitor);
-
- if (monitor->priv->providers->len == 0) {
- GST_OBJECT_UNLOCK (monitor);
- return FALSE;
- }
-
- gst_bus_set_flushing (monitor->priv->bus, FALSE);
-
- for (i = 0; i < monitor->priv->providers->len; i++) {
- if (!gst_device_provider_start (g_ptr_array_index (monitor->priv->providers,
- i))) {
- gst_bus_set_flushing (monitor->priv->bus, TRUE);
-
- for (; i != 0; i--)
- gst_device_provider_stop (g_ptr_array_index (monitor->priv->providers,
- i - 1));
-
- GST_OBJECT_UNLOCK (monitor);
- return FALSE;
- }
- }
-
- monitor->priv->started = TRUE;
- GST_OBJECT_UNLOCK (monitor);
-
- return TRUE;
-}
-
-/**
- * gst_global_device_monitor_stop:
- * @monitor: A #GstDeviceProvider
- *
- * Stops monitoring the devices.
- *
- * Since: 1.4
- */
-void
-gst_global_device_monitor_stop (GstGlobalDeviceMonitor * monitor)
-{
- guint i;
-
- g_return_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor));
-
- gst_bus_set_flushing (monitor->priv->bus, TRUE);
-
- GST_OBJECT_LOCK (monitor);
- for (i = 0; i < monitor->priv->providers->len; i++)
- gst_device_provider_stop (g_ptr_array_index (monitor->priv->providers, i));
- monitor->priv->started = FALSE;
- GST_OBJECT_UNLOCK (monitor);
-
-}
-
-/**
- * gst_global_device_monitor_set_classes_filter:
- * @monitor: the global device monitor
- * @classes: device classes to use as filter
- *
- * Filter devices monitored by device class, e.g. in case you are only
- * interested in a certain type of device like audio devices or
- * video sources.
- *
- * Since: 1.4
- */
-void
-gst_global_device_monitor_set_classes_filter (GstGlobalDeviceMonitor * monitor,
- const gchar * classes)
-{
- GList *factories = NULL;
- guint i;
-
- g_return_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor));
- g_return_if_fail (!monitor->priv->started);
-
- GST_OBJECT_LOCK (monitor);
- if (!strcmp (monitor->priv->classes, classes)) {
- GST_OBJECT_UNLOCK (monitor);
- return;
- }
-
- g_free (monitor->priv->classes);
- monitor->priv->classes = g_strdup (classes);
-
- factories = gst_device_provider_factory_list_get_device_providers (classes,
- 1);
-
- for (i = 0; i < monitor->priv->providers->len; i++) {
- GstDeviceProvider *provider;
- GstDeviceProviderFactory *f;
- GList *item;
-
- provider = g_ptr_array_index (monitor->priv->providers, i);
- f = gst_device_provider_get_factory (provider);
-
- item = g_list_find (factories, f);
-
- if (item) {
- /* If the item is in our list, then remove it from the list of factories,
- * we don't have it to re-create it later
- */
- factories = g_list_remove_link (factories, item);
- gst_object_unref (f);
- } else {
- /* If it's not in our list, them remove it from the list of providers.
- */
-
- monitor->priv->cookie++;
- gst_global_device_monitor_remove (monitor, i);
- i--;
- }
- }
-
- while (factories) {
- GstDeviceProviderFactory *factory = factories->data;
- GstDeviceProvider *provider;
-
- factories = g_list_remove (factories, factory);
-
- provider = gst_device_provider_factory_get (factory);
- if (provider) {
- GstBus *bus = gst_device_provider_get_bus (provider);
-
- gst_bus_enable_sync_message_emission (bus);
- g_signal_connect (bus, "sync-message",
- G_CALLBACK (bus_sync_message), monitor);
- gst_object_unref (bus);
- g_ptr_array_add (monitor->priv->providers, provider);
- monitor->priv->cookie++;
- }
-
- gst_object_unref (factory);
- }
-
- GST_OBJECT_UNLOCK (monitor);
-}
-
-/**
- * gst_global_device_monitor_get_classes_filter:
- * @monitor: the global device monitor
- *
- * Return the type (device classes) filter active for device filtering.
- *
- * Returns: string of device classes that are being filtered.
- *
- * Since: 1.4
- */
-gchar *
-gst_global_device_monitor_get_classes_filter (GstGlobalDeviceMonitor * monitor)
-{
- gchar *res;
-
- g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor), 0);
-
- GST_OBJECT_LOCK (monitor);
- res = g_strdup (monitor->priv->classes);
- GST_OBJECT_UNLOCK (monitor);
-
- return res;
-}
-
-/**
- * gst_global_device_monitor_set_caps_filter:
- * @monitor: the global device monitor
- * @caps: caps to filter
- *
- * Set caps to use as filter for devices. By default ANY caps are used,
- * meaning no caps filter is active.
- *
- * Since: 1.4
- */
-void
-gst_global_device_monitor_set_caps_filter (GstGlobalDeviceMonitor * monitor,
- GstCaps * caps)
-{
- g_return_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor));
- g_return_if_fail (GST_IS_CAPS (caps));
-
- GST_OBJECT_LOCK (monitor);
- gst_caps_replace (&monitor->priv->caps, caps);
- GST_OBJECT_UNLOCK (monitor);
-}
-
-/**
- * gst_global_device_monitor_get_caps_filter:
- * @monitor: a global device monitor
- *
- * Get the #GstCaps filter set by gst_global_device_monitor_set_caps_filter().
- *
- * Returns: (transfer full): the filter caps that are active (or ANY caps)
- *
- * Since: 1.4
- */
-GstCaps *
-gst_global_device_monitor_get_caps_filter (GstGlobalDeviceMonitor * monitor)
-{
- GstCaps *res;
-
- g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor), NULL);
-
- GST_OBJECT_LOCK (monitor);
- res = gst_caps_ref (monitor->priv->caps);
- GST_OBJECT_UNLOCK (monitor);
-
- return res;
-}
-
-/**
- * gst_global_device_monitor_new:
- *
- * Create a new #GstGlobalDeviceMonitor
- *
- * Returns: (transfer full): a new global device monitor.
- *
- * Since: 1.4
- */
-GstGlobalDeviceMonitor *
-gst_global_device_monitor_new (void)
-{
- return g_object_new (GST_TYPE_GLOBAL_DEVICE_MONITOR, NULL);
-}
-
-/**
- * gst_global_device_monitor_get_bus:
- * @monitor: a #GstDeviceProvider
- *
- * Gets the #GstBus of this #GstGlobalDeviceMonitor
- *
- * Returns: (transfer full): a #GstBus
- *
- * Since: 1.4
- */
-GstBus *
-gst_global_device_monitor_get_bus (GstGlobalDeviceMonitor * monitor)
-{
- g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor), NULL);
-
- return gst_object_ref (monitor->priv->bus);
-}
+++ /dev/null
-/* GStreamer
- * Copyright (C) 2013 Olivier Crete <olivier.crete@collabora.com>
- *
- * gstglobaldevicemonitor.c: Global device monitor
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-
-#ifndef __GST_GLOBAL_DEVICE_MONITOR_H__
-#define __GST_GLOBAL_DEVICE_MONITOR_H__
-
-#include <gst/gstobject.h>
-#include <gst/gstdevice.h>
-#include <gst/gstdeviceprovider.h>
-#include <gst/gstdeviceproviderfactory.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GstGlobalDeviceMonitor GstGlobalDeviceMonitor;
-typedef struct _GstGlobalDeviceMonitorPrivate GstGlobalDeviceMonitorPrivate;
-typedef struct _GstGlobalDeviceMonitorClass GstGlobalDeviceMonitorClass;
-
-#define GST_TYPE_GLOBAL_DEVICE_MONITOR (gst_global_device_monitor_get_type())
-#define GST_IS_GLOBAL_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GLOBAL_DEVICE_MONITOR))
-#define GST_IS_GLOBAL_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GLOBAL_DEVICE_MONITOR))
-#define GST_GLOBAL_DEVICE_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GLOBAL_DEVICE_MONITOR, GstGlobalDeviceMonitorClass))
-#define GST_GLOBAL_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GLOBAL_DEVICE_MONITOR, GstGlobalDeviceMonitor))
-#define GST_GLOBAL_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GLOBAL_DEVICE_MONITOR, GstGlobalDeviceMonitorClass))
-#define GST_GLOBAL_DEVICE_MONITOR_CAST(obj) ((GstGlobalDeviceMonitor *)(obj))
-
-/**
- * GstGlobalDeviceMonitor:
- * @parent: the parent #GstObject structure
- *
- * Opaque global device monitor object structure.
- *
- * Since: 1.4
- */
-struct _GstGlobalDeviceMonitor {
- GstObject parent;
-
- /*< private >*/
-
- GstGlobalDeviceMonitorPrivate *priv;
-
- gpointer _gst_reserved[GST_PADDING];
-};
-
-/**
- * GstGlobalDeviceMonitorClass:
- * @parent_class: the parent #GstObjectClass structure
- *
- * Opaque global device monitor class structure.
- *
- * Since: 1.4
- */
-struct _GstGlobalDeviceMonitorClass {
- GstObjectClass parent_class;
-
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
-};
-
-GType gst_global_device_monitor_get_type (void);
-
-GstGlobalDeviceMonitor * gst_global_device_monitor_new (void);
-
-GstBus * gst_global_device_monitor_get_bus (GstGlobalDeviceMonitor * monitor);
-
-GList * gst_global_device_monitor_get_devices (GstGlobalDeviceMonitor * monitor);
-
-
-gboolean gst_global_device_monitor_start (GstGlobalDeviceMonitor * monitor);
-
-void gst_global_device_monitor_stop (GstGlobalDeviceMonitor * monitor);
-
-
-void gst_global_device_monitor_set_classes_filter (GstGlobalDeviceMonitor * monitor,
- const gchar * classes);
-
-gchar * gst_global_device_monitor_get_classes_filter (GstGlobalDeviceMonitor * monitor);
-
-
-void gst_global_device_monitor_set_caps_filter (GstGlobalDeviceMonitor * monitor,
- GstCaps * caps);
-
-GstCaps * gst_global_device_monitor_get_caps_filter (GstGlobalDeviceMonitor * monitor);
-
-G_END_DECLS
-
-#endif /* __GST_GLOBAL_DEVICE_MONITOR_H__ */
gst_device_get_type
gst_device_has_classes
gst_device_has_classesv
+ gst_device_monitor_get_bus
+ gst_device_monitor_get_caps_filter
+ gst_device_monitor_get_classes_filter
+ gst_device_monitor_get_devices
+ gst_device_monitor_get_type
+ gst_device_monitor_new
+ gst_device_monitor_set_caps_filter
+ gst_device_monitor_set_classes_filter
+ gst_device_monitor_start
+ gst_device_monitor_stop
gst_device_provider_can_monitor
gst_device_provider_class_add_metadata
gst_device_provider_class_add_static_metadata
gst_ghost_pad_new_no_target
gst_ghost_pad_new_no_target_from_template
gst_ghost_pad_set_target
- gst_global_device_monitor_get_bus
- gst_global_device_monitor_get_caps_filter
- gst_global_device_monitor_get_classes_filter
- gst_global_device_monitor_get_devices
- gst_global_device_monitor_get_type
- gst_global_device_monitor_new
- gst_global_device_monitor_set_caps_filter
- gst_global_device_monitor_set_classes_filter
- gst_global_device_monitor_start
- gst_global_device_monitor_stop
gst_init
gst_init_check
gst_init_get_option_group