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;
        GstDevice *device;
        GstDeviceProvider *provider;

        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);
        provider =
            GST_DEVICE_PROVIDER (gst_object_get_parent (GST_OBJECT (device)));
        if (is_provider_hidden (monitor, monitor->priv->hidden, provider)) {
            matches = FALSE;
        } else if (monitor->priv->filters->len) {
            guint i;

            for (i = 0; i < monitor->priv->filters->len; i++) {
                struct DeviceFilter *filter =
                    g_ptr_array_index (monitor->priv->filters, i);
                GstCaps *caps;

                caps = gst_device_get_caps (device);
                matches = gst_caps_can_intersect (filter->caps, caps) &&
                          gst_device_has_classesv (device, filter->classesv);
                gst_caps_unref (caps);
                if (matches)
                    break;
            }
        } else {
            matches = TRUE;
        }
        GST_OBJECT_UNLOCK (monitor);

        gst_object_unref (provider);
        gst_object_unref (device);

        if (matches)
            gst_bus_post (monitor->priv->bus, gst_message_ref (message));
    }
}
static void
gst_device_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstDevice *gstdevice;

  gstdevice = GST_DEVICE_CAST (object);

  switch (prop_id) {
    case PROP_DISPLAY_NAME:
      g_value_take_string (value, gst_device_get_display_name (gstdevice));
      break;
    case PROP_CAPS:
      if (gstdevice->priv->caps)
        g_value_take_boxed (value, gst_device_get_caps (gstdevice));
      break;
    case PROP_DEVICE_CLASS:
      g_value_take_string (value, gst_device_get_device_class (gstdevice));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
GList *
gst_device_monitor_get_devices (GstDeviceMonitor * monitor)
{
    GList *devices = NULL, *hidden = NULL;
    guint i;
    guint cookie;

    g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL);

    GST_OBJECT_LOCK (monitor);

    if (monitor->priv->filters->len == 0) {
        GST_OBJECT_UNLOCK (monitor);
        GST_WARNING_OBJECT (monitor, "No filters have been set");
        return FALSE;
    }

    if (monitor->priv->providers->len == 0) {
        GST_OBJECT_UNLOCK (monitor);
        GST_WARNING_OBJECT (monitor, "No providers match the current filters");
        return FALSE;
    }

again:

    g_list_free_full (devices, gst_object_unref);
    g_list_free_full (hidden, g_free);
    devices = NULL;
    hidden = 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;

        if (!is_provider_hidden (monitor, hidden, provider)) {
            GST_OBJECT_UNLOCK (monitor);

            tmpdev = gst_device_provider_get_devices (provider);

            GST_OBJECT_LOCK (monitor);
            update_hidden_providers_list (&hidden, provider);
        } else {
            tmpdev = NULL;
        }


        for (item = tmpdev; item; item = item->next) {
            GstDevice *dev = GST_DEVICE (item->data);
            GstCaps *caps = gst_device_get_caps (dev);
            guint j;

            for (j = 0; j < monitor->priv->filters->len; j++) {
                struct DeviceFilter *filter =
                    g_ptr_array_index (monitor->priv->filters, j);

                if (gst_caps_can_intersect (filter->caps, caps) &&
                        gst_device_has_classesv (dev, filter->classesv)) {
                    devices = g_list_prepend (devices, gst_object_ref (dev));
                    break;
                }
            }
            gst_caps_unref (caps);
        }

        g_list_free_full (tmpdev, gst_object_unref);
        gst_object_unref (provider);

        if (monitor->priv->cookie != cookie)
            goto again;
    }
    g_list_free_full (hidden, g_free);

    GST_OBJECT_UNLOCK (monitor);

    return g_list_reverse (devices);
}