Blame gst/gstdevicemonitor.c

Packit Service 963350
/* GStreamer
Packit Service 963350
 * Copyright (C) 2013 Olivier Crete <olivier.crete@collabora.com>
Packit Service 963350
 *
Packit Service 963350
 * gstdevicemonitor.c: device monitor
Packit Service 963350
 *
Packit Service 963350
 * This library is free software; you can redistribute it and/or
Packit Service 963350
 * modify it under the terms of the GNU Library General Public
Packit Service 963350
 * License as published by the Free Software Foundation; either
Packit Service 963350
 * version 2 of the License, or (at your option) any later version.
Packit Service 963350
 *
Packit Service 963350
 * This library is distributed in the hope that it will be useful,
Packit Service 963350
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 963350
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 963350
 * Library General Public License for more details.
Packit Service 963350
 *
Packit Service 963350
 * You should have received a copy of the GNU Library General Public
Packit Service 963350
 * License along with this library; if not, write to the
Packit Service 963350
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit Service 963350
 * Boston, MA 02111-1307, USA.
Packit Service 963350
 */
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * SECTION:gstdevicemonitor
Packit Service 963350
 * @title: GstDeviceMonitor
Packit Service 963350
 * @short_description: A device monitor and prober
Packit Service 963350
 * @see_also: #GstDevice, #GstDeviceProvider
Packit Service 963350
 *
Packit Service 963350
 * Applications should create a #GstDeviceMonitor when they want
Packit Service 963350
 * to probe, list and monitor devices of a specific type. The
Packit Service 963350
 * #GstDeviceMonitor will create the appropriate
Packit Service 963350
 * #GstDeviceProvider objects and manage them. It will then post
Packit Service 963350
 * messages on its #GstBus for devices that have been added and
Packit Service 963350
 * removed.
Packit Service 963350
 *
Packit Service 963350
 * The device monitor will monitor all devices matching the filters that
Packit Service 963350
 * the application has set.
Packit Service 963350
 *
Packit Service 963350
 * The basic use pattern of a device monitor is as follows:
Packit Service 963350
 * |[
Packit Service 963350
 *   static gboolean
Packit Service 963350
 *   my_bus_func (GstBus * bus, GstMessage * message, gpointer user_data)
Packit Service 963350
 *   {
Packit Service 963350
 *      GstDevice *device;
Packit Service 963350
 *      gchar *name;
Packit Service 963350
 *
Packit Service 963350
 *      switch (GST_MESSAGE_TYPE (message)) {
Packit Service 963350
 *        case GST_MESSAGE_DEVICE_ADDED:
Packit Service 963350
 *          gst_message_parse_device_added (message, &device);
Packit Service 963350
 *          name = gst_device_get_display_name (device);
Packit Service 963350
 *          g_print("Device added: %s\n", name);
Packit Service 963350
 *          g_free (name);
Packit Service 963350
 *          gst_object_unref (device);
Packit Service 963350
 *          break;
Packit Service 963350
 *        case GST_MESSAGE_DEVICE_REMOVED:
Packit Service 963350
 *          gst_message_parse_device_removed (message, &device);
Packit Service 963350
 *          name = gst_device_get_display_name (device);
Packit Service 963350
 *          g_print("Device removed: %s\n", name);
Packit Service 963350
 *          g_free (name);
Packit Service 963350
 *          gst_object_unref (device);
Packit Service 963350
 *          break;
Packit Service 963350
 *        default:
Packit Service 963350
 *          break;
Packit Service 963350
 *      }
Packit Service 963350
 *
Packit Service 963350
 *      return G_SOURCE_CONTINUE;
Packit Service 963350
 *   }
Packit Service 963350
 *
Packit Service 963350
 *   GstDeviceMonitor *
Packit Service 963350
 *   setup_raw_video_source_device_monitor (void) {
Packit Service 963350
 *      GstDeviceMonitor *monitor;
Packit Service 963350
 *      GstBus *bus;
Packit Service 963350
 *      GstCaps *caps;
Packit Service 963350
 *
Packit Service 963350
 *      monitor = gst_device_monitor_new ();
Packit Service 963350
 *
Packit Service 963350
 *      bus = gst_device_monitor_get_bus (monitor);
Packit Service 963350
 *      gst_bus_add_watch (bus, my_bus_func, NULL);
Packit Service 963350
 *      gst_object_unref (bus);
Packit Service 963350
 *
Packit Service 963350
 *      caps = gst_caps_new_empty_simple ("video/x-raw");
Packit Service 963350
 *      gst_device_monitor_add_filter (monitor, "Video/Source", caps);
Packit Service 963350
 *      gst_caps_unref (caps);
Packit Service 963350
 *
Packit Service 963350
 *      gst_device_monitor_start (monitor);
Packit Service 963350
 *
Packit Service 963350
 *      return monitor;
Packit Service 963350
 *   }
Packit Service 963350
 * ]|
Packit Service 963350
 *
Packit Service 963350
 * Since: 1.4
Packit Service 963350
 */
Packit Service 963350
Packit Service 963350
Packit Service 963350
#ifdef HAVE_CONFIG_H
Packit Service 963350
#include "config.h"
Packit Service 963350
#endif
Packit Service 963350
Packit Service 963350
#include "gst_private.h"
Packit Service 963350
#include "gstdevicemonitor.h"
Packit Service 963350
Packit Service 963350
struct _GstDeviceMonitorPrivate
Packit Service 963350
{
Packit Service 963350
  gboolean started;
Packit Service 963350
Packit Service 963350
  GstBus *bus;
Packit Service 963350
Packit Service 963350
  GPtrArray *providers;
Packit Service 963350
  guint cookie;
Packit Service 963350
Packit Service 963350
  GPtrArray *filters;
Packit Service 963350
Packit Service 963350
  guint last_id;
Packit Service 963350
  GList *hidden;
Packit Service 963350
  gboolean show_all;
Packit Service 963350
};
Packit Service 963350
Packit Service 963350
#define DEFAULT_SHOW_ALL        FALSE
Packit Service 963350
Packit Service 963350
enum
Packit Service 963350
{
Packit Service 963350
  PROP_SHOW_ALL = 1,
Packit Service 963350
};
Packit Service 963350
Packit Service 963350
G_DEFINE_TYPE (GstDeviceMonitor, gst_device_monitor, GST_TYPE_OBJECT);
Packit Service 963350
Packit Service 963350
static void gst_device_monitor_dispose (GObject * object);
Packit Service 963350
Packit Service 963350
struct DeviceFilter
Packit Service 963350
{
Packit Service 963350
  guint id;
Packit Service 963350
Packit Service 963350
  gchar **classesv;
Packit Service 963350
  GstCaps *caps;
Packit Service 963350
};
Packit Service 963350
Packit Service 963350
static void
Packit Service 963350
device_filter_free (struct DeviceFilter *filter)
Packit Service 963350
{
Packit Service 963350
  g_strfreev (filter->classesv);
Packit Service 963350
  gst_caps_unref (filter->caps);
Packit Service 963350
Packit Service 963350
  g_slice_free (struct DeviceFilter, filter);
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
static void
Packit Service 963350
gst_device_monitor_get_property (GObject * object, guint prop_id,
Packit Service 963350
    GValue * value, GParamSpec * pspec)
Packit Service 963350
{
Packit Service 963350
  GstDeviceMonitor *monitor = GST_DEVICE_MONITOR (object);
Packit Service 963350
Packit Service 963350
  switch (prop_id) {
Packit Service 963350
    case PROP_SHOW_ALL:
Packit Service 963350
      g_value_set_boolean (value,
Packit Service 963350
          gst_device_monitor_get_show_all_devices (monitor));
Packit Service 963350
      break;
Packit Service 963350
    default:
Packit Service 963350
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit Service 963350
      break;
Packit Service 963350
  }
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
static void
Packit Service 963350
gst_device_monitor_set_property (GObject * object, guint prop_id,
Packit Service 963350
    const GValue * value, GParamSpec * pspec)
Packit Service 963350
{
Packit Service 963350
  GstDeviceMonitor *monitor = GST_DEVICE_MONITOR (object);
Packit Service 963350
Packit Service 963350
  switch (prop_id) {
Packit Service 963350
    case PROP_SHOW_ALL:
Packit Service 963350
      gst_device_monitor_set_show_all_devices (monitor,
Packit Service 963350
          g_value_get_boolean (value));
Packit Service 963350
      break;
Packit Service 963350
    default:
Packit Service 963350
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit Service 963350
      break;
Packit Service 963350
  }
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
Packit Service 963350
static void
Packit Service 963350
gst_device_monitor_class_init (GstDeviceMonitorClass * klass)
Packit Service 963350
{
Packit Service 963350
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
Packit Service 963350
Packit Service 963350
  g_type_class_add_private (klass, sizeof (GstDeviceMonitorPrivate));
Packit Service 963350
Packit Service 963350
  object_class->get_property = gst_device_monitor_get_property;
Packit Service 963350
  object_class->set_property = gst_device_monitor_set_property;
Packit Service 963350
  object_class->dispose = gst_device_monitor_dispose;
Packit Service 963350
Packit Service 963350
  g_object_class_install_property (object_class, PROP_SHOW_ALL,
Packit Service 963350
      g_param_spec_boolean ("show-all", "Show All",
Packit Service 963350
          "Show all devices, even those from hidden providers",
Packit Service 963350
          DEFAULT_SHOW_ALL, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/* must be called with monitor lock */
Packit Service 963350
static gboolean
Packit Service 963350
is_provider_hidden (GstDeviceMonitor * monitor, GList * hidden,
Packit Service 963350
    GstDeviceProvider * provider)
Packit Service 963350
{
Packit Service 963350
  GstDeviceProviderFactory *factory;
Packit Service 963350
Packit Service 963350
  if (monitor->priv->show_all)
Packit Service 963350
    return FALSE;
Packit Service 963350
Packit Service 963350
  factory = gst_device_provider_get_factory (provider);
Packit Service 963350
  if (g_list_find_custom (hidden, GST_OBJECT_NAME (factory),
Packit Service 963350
          (GCompareFunc) g_strcmp0))
Packit Service 963350
    return TRUE;
Packit Service 963350
Packit Service 963350
  return FALSE;
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/* must be called with monitor lock */
Packit Service 963350
static void
Packit Service 963350
update_hidden_providers_list (GList ** hidden, GstDeviceProvider * provider)
Packit Service 963350
{
Packit Service 963350
  gchar **obs;
Packit Service 963350
Packit Service 963350
  obs = gst_device_provider_get_hidden_providers (provider);
Packit Service 963350
  if (obs) {
Packit Service 963350
    gint i;
Packit Service 963350
Packit Service 963350
    for (i = 0; obs[i]; i++)
Packit Service 963350
      *hidden = g_list_prepend (*hidden, obs[i]);
Packit Service 963350
Packit Service 963350
    g_free (obs);
Packit Service 963350
  }
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
static void
Packit Service 963350
bus_sync_message (GstBus * bus, GstMessage * message,
Packit Service 963350
    GstDeviceMonitor * monitor)
Packit Service 963350
{
Packit Service 963350
  GstMessageType type = GST_MESSAGE_TYPE (message);
Packit Service 963350
Packit Service 963350
  if (type == GST_MESSAGE_DEVICE_ADDED || type == GST_MESSAGE_DEVICE_REMOVED) {
Packit Service 963350
    gboolean matches = TRUE;
Packit Service 963350
    GstDevice *device;
Packit Service 963350
    GstDeviceProvider *provider;
Packit Service 963350
Packit Service 963350
    if (type == GST_MESSAGE_DEVICE_ADDED)
Packit Service 963350
      gst_message_parse_device_added (message, &device);
Packit Service 963350
    else
Packit Service 963350
      gst_message_parse_device_removed (message, &device);
Packit Service 963350
Packit Service 963350
    GST_OBJECT_LOCK (monitor);
Packit Service 963350
    provider =
Packit Service 963350
        GST_DEVICE_PROVIDER (gst_object_get_parent (GST_OBJECT (device)));
Packit Service 963350
    if (is_provider_hidden (monitor, monitor->priv->hidden, provider)) {
Packit Service 963350
      matches = FALSE;
Packit Service 963350
    } else {
Packit Service 963350
      guint i;
Packit Service 963350
Packit Service 963350
      for (i = 0; i < monitor->priv->filters->len; i++) {
Packit Service 963350
        struct DeviceFilter *filter =
Packit Service 963350
            g_ptr_array_index (monitor->priv->filters, i);
Packit Service 963350
        GstCaps *caps;
Packit Service 963350
Packit Service 963350
        caps = gst_device_get_caps (device);
Packit Service 963350
        matches = gst_caps_can_intersect (filter->caps, caps) &&
Packit Service 963350
            gst_device_has_classesv (device, filter->classesv);
Packit Service 963350
        gst_caps_unref (caps);
Packit Service 963350
        if (matches)
Packit Service 963350
          break;
Packit Service 963350
      }
Packit Service 963350
    }
Packit Service 963350
    GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
    gst_object_unref (provider);
Packit Service 963350
    gst_object_unref (device);
Packit Service 963350
Packit Service 963350
    if (matches)
Packit Service 963350
      gst_bus_post (monitor->priv->bus, gst_message_ref (message));
Packit Service 963350
  }
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
Packit Service 963350
static void
Packit Service 963350
gst_device_monitor_init (GstDeviceMonitor * self)
Packit Service 963350
{
Packit Service 963350
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
Packit Service 963350
      GST_TYPE_DEVICE_MONITOR, GstDeviceMonitorPrivate);
Packit Service 963350
Packit Service 963350
  self->priv->show_all = DEFAULT_SHOW_ALL;
Packit Service 963350
Packit Service 963350
  self->priv->bus = gst_bus_new ();
Packit Service 963350
  gst_bus_set_flushing (self->priv->bus, TRUE);
Packit Service 963350
Packit Service 963350
  self->priv->providers = g_ptr_array_new ();
Packit Service 963350
  self->priv->filters = g_ptr_array_new_with_free_func (
Packit Service 963350
      (GDestroyNotify) device_filter_free);
Packit Service 963350
Packit Service 963350
  self->priv->last_id = 1;
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
Packit Service 963350
static void
Packit Service 963350
gst_device_monitor_remove (GstDeviceMonitor * self, guint i)
Packit Service 963350
{
Packit Service 963350
  GstDeviceProvider *provider = g_ptr_array_index (self->priv->providers, i);
Packit Service 963350
  GstBus *bus;
Packit Service 963350
Packit Service 963350
  g_ptr_array_remove_index (self->priv->providers, i);
Packit Service 963350
Packit Service 963350
  bus = gst_device_provider_get_bus (provider);
Packit Service 963350
  g_signal_handlers_disconnect_by_func (bus, bus_sync_message, self);
Packit Service 963350
  gst_object_unref (bus);
Packit Service 963350
Packit Service 963350
  gst_object_unref (provider);
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
static void
Packit Service 963350
gst_device_monitor_dispose (GObject * object)
Packit Service 963350
{
Packit Service 963350
  GstDeviceMonitor *self = GST_DEVICE_MONITOR (object);
Packit Service 963350
Packit Service 963350
  g_return_if_fail (!self->priv->started);
Packit Service 963350
Packit Service 963350
  if (self->priv->providers) {
Packit Service 963350
    while (self->priv->providers->len)
Packit Service 963350
      gst_device_monitor_remove (self, self->priv->providers->len - 1);
Packit Service 963350
    g_ptr_array_unref (self->priv->providers);
Packit Service 963350
    self->priv->providers = NULL;
Packit Service 963350
  }
Packit Service 963350
Packit Service 963350
  if (self->priv->filters) {
Packit Service 963350
    g_ptr_array_unref (self->priv->filters);
Packit Service 963350
    self->priv->filters = NULL;
Packit Service 963350
  }
Packit Service 963350
Packit Service 963350
  gst_object_replace ((GstObject **) & self->priv->bus, NULL);
Packit Service 963350
Packit Service 963350
  G_OBJECT_CLASS (gst_device_monitor_parent_class)->dispose (object);
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * gst_device_monitor_get_devices:
Packit Service 963350
 * @monitor: A #GstDeviceProvider
Packit Service 963350
 *
Packit Service 963350
 * Gets a list of devices from all of the relevant monitors. This may actually
Packit Service 963350
 * probe the hardware if the monitor is not currently started.
Packit Service 963350
 *
Packit Service 963350
 * Returns: (transfer full) (element-type GstDevice) (nullable): a #GList of
Packit Service 963350
 *   #GstDevice
Packit Service 963350
 *
Packit Service 963350
 * Since: 1.4
Packit Service 963350
 */
Packit Service 963350
Packit Service 963350
GList *
Packit Service 963350
gst_device_monitor_get_devices (GstDeviceMonitor * monitor)
Packit Service 963350
{
Packit Service 963350
  GList *devices = NULL, *hidden = NULL;
Packit Service 963350
  guint i;
Packit Service 963350
  guint cookie;
Packit Service 963350
Packit Service 963350
  g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL);
Packit Service 963350
Packit Service 963350
  GST_OBJECT_LOCK (monitor);
Packit Service 963350
Packit Service 963350
  if (monitor->priv->filters->len == 0) {
Packit Service 963350
    GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
    GST_WARNING_OBJECT (monitor, "No filters have been set");
Packit Service 963350
    return NULL;
Packit Service 963350
  }
Packit Service 963350
Packit Service 963350
  if (monitor->priv->providers->len == 0) {
Packit Service 963350
    GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
    GST_WARNING_OBJECT (monitor, "No providers match the current filters");
Packit Service 963350
    return NULL;
Packit Service 963350
  }
Packit Service 963350
Packit Service 963350
again:
Packit Service 963350
Packit Service 963350
  g_list_free_full (devices, gst_object_unref);
Packit Service 963350
  g_list_free_full (hidden, g_free);
Packit Service 963350
  devices = NULL;
Packit Service 963350
  hidden = NULL;
Packit Service 963350
Packit Service 963350
  cookie = monitor->priv->cookie;
Packit Service 963350
Packit Service 963350
  for (i = 0; i < monitor->priv->providers->len; i++) {
Packit Service 963350
    GList *tmpdev;
Packit Service 963350
    GstDeviceProvider *provider =
Packit Service 963350
        gst_object_ref (g_ptr_array_index (monitor->priv->providers, i));
Packit Service 963350
    GList *item;
Packit Service 963350
Packit Service 963350
    if (!is_provider_hidden (monitor, hidden, provider)) {
Packit Service 963350
      GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
      tmpdev = gst_device_provider_get_devices (provider);
Packit Service 963350
Packit Service 963350
      GST_OBJECT_LOCK (monitor);
Packit Service 963350
      update_hidden_providers_list (&hidden, provider);
Packit Service 963350
    } else {
Packit Service 963350
      tmpdev = NULL;
Packit Service 963350
    }
Packit Service 963350
Packit Service 963350
Packit Service 963350
    for (item = tmpdev; item; item = item->next) {
Packit Service 963350
      GstDevice *dev = GST_DEVICE (item->data);
Packit Service 963350
      GstCaps *caps = gst_device_get_caps (dev);
Packit Service 963350
      guint j;
Packit Service 963350
Packit Service 963350
      for (j = 0; j < monitor->priv->filters->len; j++) {
Packit Service 963350
        struct DeviceFilter *filter =
Packit Service 963350
            g_ptr_array_index (monitor->priv->filters, j);
Packit Service 963350
Packit Service 963350
        if (gst_caps_can_intersect (filter->caps, caps) &&
Packit Service 963350
            gst_device_has_classesv (dev, filter->classesv)) {
Packit Service 963350
          devices = g_list_prepend (devices, gst_object_ref (dev));
Packit Service 963350
          break;
Packit Service 963350
        }
Packit Service 963350
      }
Packit Service 963350
      gst_caps_unref (caps);
Packit Service 963350
    }
Packit Service 963350
Packit Service 963350
    g_list_free_full (tmpdev, gst_object_unref);
Packit Service 963350
    gst_object_unref (provider);
Packit Service 963350
Packit Service 963350
    if (monitor->priv->cookie != cookie)
Packit Service 963350
      goto again;
Packit Service 963350
  }
Packit Service 963350
  g_list_free_full (hidden, g_free);
Packit Service 963350
Packit Service 963350
  GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
  return g_list_reverse (devices);
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * gst_device_monitor_start:
Packit Service 963350
 * @monitor: A #GstDeviceMonitor
Packit Service 963350
 *
Packit Service 963350
 * Starts monitoring the devices, one this has succeeded, the
Packit Service 963350
 * %GST_MESSAGE_DEVICE_ADDED and %GST_MESSAGE_DEVICE_REMOVED messages
Packit Service 963350
 * will be emitted on the bus when the list of devices changes.
Packit Service 963350
 *
Packit Service 963350
 * Returns: %TRUE if the device monitoring could be started
Packit Service 963350
 *
Packit Service 963350
 * Since: 1.4
Packit Service 963350
 */
Packit Service 963350
Packit Service 963350
gboolean
Packit Service 963350
gst_device_monitor_start (GstDeviceMonitor * monitor)
Packit Service 963350
{
Packit Service 963350
  guint cookie, i;
Packit Service 963350
  GList *pending = NULL, *started = NULL, *removed = NULL;
Packit Service 963350
Packit Service 963350
  g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), FALSE);
Packit Service 963350
Packit Service 963350
  GST_OBJECT_LOCK (monitor);
Packit Service 963350
Packit Service 963350
  if (monitor->priv->filters->len == 0) {
Packit Service 963350
    GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
    GST_WARNING_OBJECT (monitor, "No filters have been set, will expose all "
Packit Service 963350
        "devices found");
Packit Service 963350
    gst_device_monitor_add_filter (monitor, NULL, NULL);
Packit Service 963350
    GST_OBJECT_LOCK (monitor);
Packit Service 963350
  }
Packit Service 963350
Packit Service 963350
  if (monitor->priv->providers->len == 0) {
Packit Service 963350
    GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
    GST_WARNING_OBJECT (monitor, "No providers match the current filters");
Packit Service 963350
    return FALSE;
Packit Service 963350
  }
Packit Service 963350
Packit Service 963350
  gst_bus_set_flushing (monitor->priv->bus, FALSE);
Packit Service 963350
Packit Service 963350
again:
Packit Service 963350
  cookie = monitor->priv->cookie;
Packit Service 963350
Packit Service 963350
  g_list_free_full (pending, gst_object_unref);
Packit Service 963350
  pending = NULL;
Packit Service 963350
  removed = started;
Packit Service 963350
  started = NULL;
Packit Service 963350
Packit Service 963350
  for (i = 0; i < monitor->priv->providers->len; i++) {
Packit Service 963350
    GstDeviceProvider *provider;
Packit Service 963350
    GList *find;
Packit Service 963350
Packit Service 963350
    provider = g_ptr_array_index (monitor->priv->providers, i);
Packit Service 963350
Packit Service 963350
    find = g_list_find (removed, provider);
Packit Service 963350
    if (find) {
Packit Service 963350
      /* this was already started, move to started list */
Packit Service 963350
      removed = g_list_remove_link (removed, find);
Packit Service 963350
      started = g_list_concat (started, find);
Packit Service 963350
    } else {
Packit Service 963350
      /* not started, add to pending list */
Packit Service 963350
      pending = g_list_append (pending, gst_object_ref (provider));
Packit Service 963350
    }
Packit Service 963350
  }
Packit Service 963350
  g_list_free_full (removed, gst_object_unref);
Packit Service 963350
  removed = NULL;
Packit Service 963350
Packit Service 963350
  while (pending) {
Packit Service 963350
    GstDeviceProvider *provider = pending->data;
Packit Service 963350
Packit Service 963350
    if (gst_device_provider_can_monitor (provider)) {
Packit Service 963350
      GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
      if (!gst_device_provider_start (provider))
Packit Service 963350
        goto start_failed;
Packit Service 963350
Packit Service 963350
      GST_OBJECT_LOCK (monitor);
Packit Service 963350
    }
Packit Service 963350
    started = g_list_prepend (started, provider);
Packit Service 963350
    pending = g_list_delete_link (pending, pending);
Packit Service 963350
Packit Service 963350
    if (monitor->priv->cookie != cookie)
Packit Service 963350
      goto again;
Packit Service 963350
  }
Packit Service 963350
  monitor->priv->started = TRUE;
Packit Service 963350
  GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
  g_list_free_full (started, gst_object_unref);
Packit Service 963350
Packit Service 963350
  return TRUE;
Packit Service 963350
Packit Service 963350
start_failed:
Packit Service 963350
  {
Packit Service 963350
    GST_OBJECT_LOCK (monitor);
Packit Service 963350
    gst_bus_set_flushing (monitor->priv->bus, TRUE);
Packit Service 963350
    GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
    while (started) {
Packit Service 963350
      GstDeviceProvider *provider = started->data;
Packit Service 963350
Packit Service 963350
      gst_device_provider_stop (provider);
Packit Service 963350
      gst_object_unref (provider);
Packit Service 963350
Packit Service 963350
      started = g_list_delete_link (started, started);
Packit Service 963350
    }
Packit Service 963350
    return FALSE;
Packit Service 963350
  }
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * gst_device_monitor_stop:
Packit Service 963350
 * @monitor: A #GstDeviceProvider
Packit Service 963350
 *
Packit Service 963350
 * Stops monitoring the devices.
Packit Service 963350
 *
Packit Service 963350
 * Since: 1.4
Packit Service 963350
 */
Packit Service 963350
void
Packit Service 963350
gst_device_monitor_stop (GstDeviceMonitor * monitor)
Packit Service 963350
{
Packit Service 963350
  guint i;
Packit Service 963350
  GList *started = NULL;
Packit Service 963350
Packit Service 963350
  g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor));
Packit Service 963350
Packit Service 963350
  gst_bus_set_flushing (monitor->priv->bus, TRUE);
Packit Service 963350
Packit Service 963350
  GST_OBJECT_LOCK (monitor);
Packit Service 963350
  for (i = 0; i < monitor->priv->providers->len; i++) {
Packit Service 963350
    GstDeviceProvider *provider =
Packit Service 963350
        g_ptr_array_index (monitor->priv->providers, i);
Packit Service 963350
Packit Service 963350
    started = g_list_prepend (started, gst_object_ref (provider));
Packit Service 963350
  }
Packit Service 963350
  GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
  while (started) {
Packit Service 963350
    GstDeviceProvider *provider = started->data;
Packit Service 963350
Packit Service 963350
    if (gst_device_provider_can_monitor (provider))
Packit Service 963350
      gst_device_provider_stop (provider);
Packit Service 963350
Packit Service 963350
    started = g_list_delete_link (started, started);
Packit Service 963350
    gst_object_unref (provider);
Packit Service 963350
  }
Packit Service 963350
Packit Service 963350
  GST_OBJECT_LOCK (monitor);
Packit Service 963350
  monitor->priv->started = FALSE;
Packit Service 963350
  GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
static void
Packit Service 963350
provider_hidden (GstDeviceProvider * provider, const gchar * hidden,
Packit Service 963350
    GstDeviceMonitor * monitor)
Packit Service 963350
{
Packit Service 963350
  GST_OBJECT_LOCK (monitor);
Packit Service 963350
  monitor->priv->hidden =
Packit Service 963350
      g_list_prepend (monitor->priv->hidden, g_strdup (hidden));
Packit Service 963350
  GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
static void
Packit Service 963350
provider_unhidden (GstDeviceProvider * provider, const gchar * hidden,
Packit Service 963350
    GstDeviceMonitor * monitor)
Packit Service 963350
{
Packit Service 963350
  GList *find;
Packit Service 963350
Packit Service 963350
  GST_OBJECT_LOCK (monitor);
Packit Service 963350
  find =
Packit Service 963350
      g_list_find_custom (monitor->priv->hidden, hidden,
Packit Service 963350
      (GCompareFunc) g_strcmp0);
Packit Service 963350
  if (find) {
Packit Service 963350
    g_free (find->data);
Packit Service 963350
    monitor->priv->hidden = g_list_delete_link (monitor->priv->hidden, find);
Packit Service 963350
  }
Packit Service 963350
  GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * gst_device_monitor_add_filter:
Packit Service 963350
 * @monitor: a device monitor
Packit Service 963350
 * @classes: (allow-none): device classes to use as filter or %NULL for any class
Packit Service 963350
 * @caps: (allow-none): the #GstCaps to filter or %NULL for ANY
Packit Service 963350
 *
Packit Service 963350
 * Adds a filter for which #GstDevice will be monitored, any device that matches
Packit Service 963350
 * all these classes and the #GstCaps will be returned.
Packit Service 963350
 *
Packit Service 963350
 * If this function is called multiple times to add more filters, each will be
Packit Service 963350
 * matched independently. That is, adding more filters will not further restrict
Packit Service 963350
 * what devices are matched.
Packit Service 963350
 *
Packit Service 963350
 * The #GstCaps supported by the device as returned by gst_device_get_caps() are
Packit Service 963350
 * not intersected with caps filters added using this function.
Packit Service 963350
 *
Packit Service 963350
 * Filters must be added before the #GstDeviceMonitor is started.
Packit Service 963350
 *
Packit Service 963350
 * Returns: The id of the new filter or 0 if no provider matched the filter's
Packit Service 963350
 *  classes.
Packit Service 963350
 *
Packit Service 963350
 * Since: 1.4
Packit Service 963350
 */
Packit Service 963350
guint
Packit Service 963350
gst_device_monitor_add_filter (GstDeviceMonitor * monitor,
Packit Service 963350
    const gchar * classes, GstCaps * caps)
Packit Service 963350
{
Packit Service 963350
  GList *factories = NULL;
Packit Service 963350
  struct DeviceFilter *filter;
Packit Service 963350
  guint id = 0;
Packit Service 963350
  gboolean matched = FALSE;
Packit Service 963350
Packit Service 963350
  g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), 0);
Packit Service 963350
  g_return_val_if_fail (!monitor->priv->started, 0);
Packit Service 963350
Packit Service 963350
  GST_OBJECT_LOCK (monitor);
Packit Service 963350
Packit Service 963350
  filter = g_slice_new0 (struct DeviceFilter);
Packit Service 963350
  filter->id = monitor->priv->last_id++;
Packit Service 963350
  if (caps)
Packit Service 963350
    filter->caps = gst_caps_ref (caps);
Packit Service 963350
  else
Packit Service 963350
    filter->caps = gst_caps_new_any ();
Packit Service 963350
  if (classes)
Packit Service 963350
    filter->classesv = g_strsplit (classes, "/", 0);
Packit Service 963350
Packit Service 963350
  factories = gst_device_provider_factory_list_get_device_providers (1);
Packit Service 963350
Packit Service 963350
  while (factories) {
Packit Service 963350
    GstDeviceProviderFactory *factory = factories->data;
Packit Service 963350
Packit Service 963350
    if (gst_device_provider_factory_has_classesv (factory, filter->classesv)) {
Packit Service 963350
      GstDeviceProvider *provider;
Packit Service 963350
Packit Service 963350
      provider = gst_device_provider_factory_get (factory);
Packit Service 963350
Packit Service 963350
      if (provider) {
Packit Service 963350
        guint i;
Packit Service 963350
Packit Service 963350
        for (i = 0; i < monitor->priv->providers->len; i++) {
Packit Service 963350
          if (g_ptr_array_index (monitor->priv->providers, i) == provider) {
Packit Service 963350
            gst_object_unref (provider);
Packit Service 963350
            provider = NULL;
Packit Service 963350
            matched = TRUE;
Packit Service 963350
            break;
Packit Service 963350
          }
Packit Service 963350
        }
Packit Service 963350
      }
Packit Service 963350
Packit Service 963350
      if (provider) {
Packit Service 963350
        GstBus *bus = gst_device_provider_get_bus (provider);
Packit Service 963350
Packit Service 963350
        update_hidden_providers_list (&monitor->priv->hidden, provider);
Packit Service 963350
        g_signal_connect (provider, "provider-hidden",
Packit Service 963350
            (GCallback) provider_hidden, monitor);
Packit Service 963350
        g_signal_connect (provider, "provider-unhidden",
Packit Service 963350
            (GCallback) provider_unhidden, monitor);
Packit Service 963350
Packit Service 963350
        matched = TRUE;
Packit Service 963350
        gst_bus_enable_sync_message_emission (bus);
Packit Service 963350
        g_signal_connect (bus, "sync-message",
Packit Service 963350
            G_CALLBACK (bus_sync_message), monitor);
Packit Service 963350
        gst_object_unref (bus);
Packit Service 963350
        g_ptr_array_add (monitor->priv->providers, provider);
Packit Service 963350
        monitor->priv->cookie++;
Packit Service 963350
      }
Packit Service 963350
    }
Packit Service 963350
Packit Service 963350
    factories = g_list_remove (factories, factory);
Packit Service 963350
    gst_object_unref (factory);
Packit Service 963350
  }
Packit Service 963350
Packit Service 963350
  /* Ensure there is no leak here */
Packit Service 963350
  g_assert (factories == NULL);
Packit Service 963350
Packit Service 963350
  if (matched)
Packit Service 963350
    id = filter->id;
Packit Service 963350
  g_ptr_array_add (monitor->priv->filters, filter);
Packit Service 963350
Packit Service 963350
  GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
  return id;
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * gst_device_monitor_remove_filter:
Packit Service 963350
 * @monitor: a device monitor
Packit Service 963350
 * @filter_id: the id of the filter
Packit Service 963350
 *
Packit Service 963350
 * Removes a filter from the #GstDeviceMonitor using the id that was returned
Packit Service 963350
 * by gst_device_monitor_add_filter().
Packit Service 963350
 *
Packit Service 963350
 * Returns: %TRUE of the filter id was valid, %FALSE otherwise
Packit Service 963350
 *
Packit Service 963350
 * Since: 1.4
Packit Service 963350
 */
Packit Service 963350
gboolean
Packit Service 963350
gst_device_monitor_remove_filter (GstDeviceMonitor * monitor, guint filter_id)
Packit Service 963350
{
Packit Service 963350
  guint i, j;
Packit Service 963350
  gboolean removed = FALSE;
Packit Service 963350
Packit Service 963350
  g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), FALSE);
Packit Service 963350
  g_return_val_if_fail (!monitor->priv->started, FALSE);
Packit Service 963350
  g_return_val_if_fail (filter_id > 0, FALSE);
Packit Service 963350
Packit Service 963350
  GST_OBJECT_LOCK (monitor);
Packit Service 963350
  for (i = 0; i < monitor->priv->filters->len; i++) {
Packit Service 963350
    struct DeviceFilter *filter = g_ptr_array_index (monitor->priv->filters, i);
Packit Service 963350
Packit Service 963350
    if (filter->id == filter_id) {
Packit Service 963350
      g_ptr_array_remove_index (monitor->priv->filters, i);
Packit Service 963350
      removed = TRUE;
Packit Service 963350
      break;
Packit Service 963350
    }
Packit Service 963350
  }
Packit Service 963350
Packit Service 963350
  if (removed) {
Packit Service 963350
    for (i = 0; i < monitor->priv->providers->len; i++) {
Packit Service 963350
      GstDeviceProvider *provider =
Packit Service 963350
          g_ptr_array_index (monitor->priv->providers, i);
Packit Service 963350
      GstDeviceProviderFactory *factory =
Packit Service 963350
          gst_device_provider_get_factory (provider);
Packit Service 963350
      gboolean valid = FALSE;
Packit Service 963350
Packit Service 963350
      for (j = 0; j < monitor->priv->filters->len; j++) {
Packit Service 963350
        struct DeviceFilter *filter =
Packit Service 963350
            g_ptr_array_index (monitor->priv->filters, j);
Packit Service 963350
Packit Service 963350
        if (gst_device_provider_factory_has_classesv (factory,
Packit Service 963350
                filter->classesv)) {
Packit Service 963350
          valid = TRUE;
Packit Service 963350
          break;
Packit Service 963350
        }
Packit Service 963350
      }
Packit Service 963350
Packit Service 963350
      if (!valid) {
Packit Service 963350
        monitor->priv->cookie++;
Packit Service 963350
        gst_device_monitor_remove (monitor, i);
Packit Service 963350
        i--;
Packit Service 963350
      }
Packit Service 963350
    }
Packit Service 963350
  }
Packit Service 963350
Packit Service 963350
  GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
  return removed;
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * gst_device_monitor_new:
Packit Service 963350
 *
Packit Service 963350
 * Create a new #GstDeviceMonitor
Packit Service 963350
 *
Packit Service 963350
 * Returns: (transfer full): a new device monitor.
Packit Service 963350
 *
Packit Service 963350
 * Since: 1.4
Packit Service 963350
 */
Packit Service 963350
GstDeviceMonitor *
Packit Service 963350
gst_device_monitor_new (void)
Packit Service 963350
{
Packit Service 963350
  GstDeviceMonitor *monitor;
Packit Service 963350
Packit Service 963350
  monitor = g_object_new (GST_TYPE_DEVICE_MONITOR, NULL);
Packit Service 963350
Packit Service 963350
  /* Clear floating flag */
Packit Service 963350
  gst_object_ref_sink (monitor);
Packit Service 963350
Packit Service 963350
  return monitor;
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * gst_device_monitor_get_bus:
Packit Service 963350
 * @monitor: a #GstDeviceProvider
Packit Service 963350
 *
Packit Service 963350
 * Gets the #GstBus of this #GstDeviceMonitor
Packit Service 963350
 *
Packit Service 963350
 * Returns: (transfer full): a #GstBus
Packit Service 963350
 *
Packit Service 963350
 * Since: 1.4
Packit Service 963350
 */
Packit Service 963350
GstBus *
Packit Service 963350
gst_device_monitor_get_bus (GstDeviceMonitor * monitor)
Packit Service 963350
{
Packit Service 963350
  g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL);
Packit Service 963350
Packit Service 963350
  return gst_object_ref (monitor->priv->bus);
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * gst_device_monitor_get_providers:
Packit Service 963350
 * @monitor: a #GstDeviceMonitor
Packit Service 963350
 *
Packit Service 963350
 * Get a list of the currently selected device provider factories.
Packit Service 963350
 *
Packit Service 963350
 * This
Packit Service 963350
 *
Packit Service 963350
 * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*):
Packit Service 963350
 *     A list of device provider factory names that are currently being
Packit Service 963350
 *     monitored by @monitor or %NULL when nothing is being monitored.
Packit Service 963350
 *
Packit Service 963350
 * Since: 1.6
Packit Service 963350
 */
Packit Service 963350
gchar **
Packit Service 963350
gst_device_monitor_get_providers (GstDeviceMonitor * monitor)
Packit Service 963350
{
Packit Service 963350
  guint i, len;
Packit Service 963350
  gchar **res = NULL;
Packit Service 963350
Packit Service 963350
  g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL);
Packit Service 963350
Packit Service 963350
  GST_OBJECT_LOCK (monitor);
Packit Service 963350
  len = monitor->priv->providers->len;
Packit Service 963350
  if (len == 0)
Packit Service 963350
    goto done;
Packit Service 963350
Packit Service 963350
  res = g_new (gchar *, len + 1);
Packit Service 963350
Packit Service 963350
  for (i = 0; i < len; i++) {
Packit Service 963350
    GstDeviceProvider *provider =
Packit Service 963350
        g_ptr_array_index (monitor->priv->providers, i);
Packit Service 963350
    GstDeviceProviderFactory *factory =
Packit Service 963350
        gst_device_provider_get_factory (provider);
Packit Service 963350
Packit Service 963350
    res[i] = g_strdup (GST_OBJECT_NAME (factory));
Packit Service 963350
  }
Packit Service 963350
  res[i] = NULL;
Packit Service 963350
Packit Service 963350
done:
Packit Service 963350
  GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
  return res;
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * gst_device_monitor_set_show_all_devices:
Packit Service 963350
 * @monitor: a #GstDeviceMonitor
Packit Service 963350
 * @show_all: show all devices
Packit Service 963350
 *
Packit Service 963350
 * Set if all devices should be visible, even those devices from hidden
Packit Service 963350
 * providers. Setting @show_all to true might show some devices multiple times.
Packit Service 963350
 *
Packit Service 963350
 * Since: 1.6
Packit Service 963350
 */
Packit Service 963350
void
Packit Service 963350
gst_device_monitor_set_show_all_devices (GstDeviceMonitor * monitor,
Packit Service 963350
    gboolean show_all)
Packit Service 963350
{
Packit Service 963350
  g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor));
Packit Service 963350
Packit Service 963350
  GST_OBJECT_LOCK (monitor);
Packit Service 963350
  monitor->priv->show_all = show_all;
Packit Service 963350
  GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * gst_device_monitor_get_show_all_devices:
Packit Service 963350
 * @monitor: a #GstDeviceMonitor
Packit Service 963350
 *
Packit Service 963350
 * Get if @monitor is curretly showing all devices, even those from hidden
Packit Service 963350
 * providers.
Packit Service 963350
 *
Packit Service 963350
 * Returns: %TRUE when all devices will be shown.
Packit Service 963350
 *
Packit Service 963350
 * Since: 1.6
Packit Service 963350
 */
Packit Service 963350
gboolean
Packit Service 963350
gst_device_monitor_get_show_all_devices (GstDeviceMonitor * monitor)
Packit Service 963350
{
Packit Service 963350
  gboolean res;
Packit Service 963350
Packit Service 963350
  g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), FALSE);
Packit Service 963350
Packit Service 963350
  GST_OBJECT_LOCK (monitor);
Packit Service 963350
  res = monitor->priv->show_all;
Packit Service 963350
  GST_OBJECT_UNLOCK (monitor);
Packit Service 963350
Packit Service 963350
  return res;
Packit Service 963350
}