From e743fac26bd5f36268bf1035f33ab900d956b1e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Sun, 16 Mar 2014 15:56:59 -0400 Subject: [PATCH] device: Add "klass" to GstDevices --- gst/gstdevice.c | 103 ++++++++++++++++++++++++++++++++++- gst/gstdevice.h | 8 +++ gst/gstglobaldevicemonitor.c | 10 ++-- 3 files changed, 115 insertions(+), 6 deletions(-) diff --git a/gst/gstdevice.c b/gst/gstdevice.c index 64f39253e2..6a7b506447 100644 --- a/gst/gstdevice.c +++ b/gst/gstdevice.c @@ -31,7 +31,8 @@ enum { PROP_DISPLAY_NAME = 1, - PROP_CAPS + PROP_CAPS, + PROP_KLASS }; enum @@ -43,6 +44,7 @@ enum struct _GstDevicePrivate { GstCaps *caps; + gchar *klass; gchar *display_name; }; @@ -77,6 +79,10 @@ gst_device_class_init (GstDeviceClass * klass) g_param_spec_boxed ("caps", "Device Caps", "The possible caps of a device", GST_TYPE_CAPS, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_KLASS, + g_param_spec_string ("klass", "Device Class", + "The Class of the device", "", + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); signals[REMOVED] = g_signal_new ("removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); @@ -97,6 +103,7 @@ gst_device_finalize (GObject * object) gst_caps_replace (&device->priv->caps, NULL); g_free (device->priv->display_name); + g_free (device->priv->klass); G_OBJECT_CLASS (gst_device_parent_class)->finalize (object); } @@ -117,6 +124,9 @@ gst_device_get_property (GObject * object, guint prop_id, if (gstdevice->priv->caps) g_value_take_boxed (value, gst_device_get_caps (gstdevice)); break; + case PROP_KLASS: + g_value_take_string (value, gst_device_get_klass (gstdevice)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -139,6 +149,9 @@ gst_device_set_property (GObject * object, guint prop_id, case PROP_CAPS: gst_caps_replace (&gstdevice->priv->caps, g_value_get_boxed (value)); break; + case PROP_KLASS: + gstdevice->priv->klass = g_value_dup_string (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -199,7 +212,26 @@ gst_device_get_caps (GstDevice * device) gchar * gst_device_get_display_name (GstDevice * device) { - return g_strdup (device->priv->display_name); + return + g_strdup (device->priv->display_name ? device->priv->display_name : ""); +} + +/** + * gst_device_get_klass: + * @device: a #GstDevice + * + * Gets the "class" of a device. This is a "/" separated list of + * classes that represent this device. They are a subset of the + * classes of the #GstDeviceMonitor that produced this device. + * + * Returns: The device class. Free with g_free() after use. + * + * Since: 1.4 + */ +gchar * +gst_device_get_klass (GstDevice * device) +{ + return g_strdup (device->priv->klass ? device->priv->klass : ""); } /** @@ -229,3 +261,70 @@ gst_device_reconfigure_element (GstDevice * device, GstElement * element) else return FALSE; } + +/** + * gst_device_has_classesv: + * @device: a #GstDevice + * @classes: a %NULL terminated array of klasses to match, only match if all + * classes are matched + * + * Check if @factory matches all of the given classes + * + * Returns: %TRUE if @device matches. + * + * Since: 1.4 + */ +gboolean +gst_device_has_classesv (GstDevice * device, gchar ** classes) +{ + g_return_val_if_fail (GST_IS_DEVICE (device), FALSE); + + + for (; classes[0]; classes++) { + const gchar *found; + guint len; + + if (classes[0] == '\0') + continue; + + found = strstr (device->priv->klass, classes[0]); + + if (!found) + return FALSE; + if (found != device->priv->klass && *(found - 1) != '/') + return FALSE; + + len = strlen (classes[0]); + if (found[len] != 0 && found[len] != '/') + return FALSE; + } + + return TRUE; +} + +/** + * gst_device_has_classes: + * @device: a #GstDevice + * @classes: a "/" separate list of klasses to match, only match if all classes + * are matched + * + * Check if @device matches all of the given classes + * + * Returns: %TRUE if @device matches. + * + * Since: 1.4 + */ +gboolean +gst_device_has_classes (GstDevice * device, const gchar * classes) +{ + gchar **classesv; + gboolean res; + + classesv = g_strsplit (classes, "/", 0); + + res = gst_device_has_classesv (device, classesv); + + g_strfreev (classesv); + + return res; +} diff --git a/gst/gstdevice.h b/gst/gstdevice.h index dc71eeb803..9a5d9b3fc0 100644 --- a/gst/gstdevice.h +++ b/gst/gstdevice.h @@ -68,9 +68,17 @@ GstElement * gst_device_create_element (GstDevice * device, const gchar * name); GstCaps * gst_device_get_caps (GstDevice * device); gchar * gst_device_get_display_name (GstDevice * device); +gchar * gst_device_get_klass (GstDevice * device); gboolean gst_device_reconfigure_element (GstDevice * device, GstElement * element); +gboolean gst_device_has_classesv (GstDevice * device, + gchar ** classes); + +gboolean gst_device_has_classes (GstDevice * device, + const gchar * classes); + + G_END_DECLS #endif /* __GST_DEVICE_H__ */ diff --git a/gst/gstglobaldevicemonitor.c b/gst/gstglobaldevicemonitor.c index 974dc7f4c6..cf537131b7 100644 --- a/gst/gstglobaldevicemonitor.c +++ b/gst/gstglobaldevicemonitor.c @@ -64,7 +64,7 @@ bus_sync_message (GstBus * bus, GstMessage * message, GstMessageType type = GST_MESSAGE_TYPE (message); if (type == GST_MESSAGE_DEVICE_ADDED || type == GST_MESSAGE_DEVICE_REMOVED) { - gboolean intersects; + gboolean matches; GstCaps *caps; GstDevice *device; @@ -75,11 +75,12 @@ bus_sync_message (GstBus * bus, GstMessage * message, GST_OBJECT_LOCK (monitor); caps = gst_device_get_caps (device); - intersects = gst_caps_can_intersect (monitor->priv->caps, caps); + 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 (intersects) + if (matches) gst_bus_post (monitor->priv->bus, gst_message_ref (message)); } } @@ -204,7 +205,8 @@ again: GstDevice *dev = GST_DEVICE (item->data); GstCaps *caps = gst_device_get_caps (dev); - if (gst_caps_can_intersect (self->priv->caps, caps)) + if (gst_caps_can_intersect (self->priv->caps, caps) && + gst_device_has_classes (dev, self->priv->classes)) devices = g_list_prepend (devices, gst_object_ref (dev)); gst_caps_unref (caps); }