Revert "gst/parse: define pure-parser depending on bison version"
[platform/upstream/gstreamer.git] / gst / gstdevice.c
index 269dd53..64f5ba5 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+/**
+ * SECTION:gstdevice
+ * @title: GstDevice
+ * @short_description: Object representing a device
+ * @see_also: #GstDeviceProvider
+ *
+ * #GstDevice are objects representing a device, they contain
+ * relevant metadata about the device, such as its class and the #GstCaps
+ * representing the media types it can produce or handle.
+ *
+ * #GstDevice are created by #GstDeviceProvider objects which can be
+ * aggregated by #GstDeviceMonitor objects.
+ *
+ * Since: 1.4
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -31,7 +47,8 @@ enum
 {
   PROP_DISPLAY_NAME = 1,
   PROP_CAPS,
-  PROP_KLASS
+  PROP_DEVICE_CLASS,
+  PROP_PROPERTIES
 };
 
 enum
@@ -43,14 +60,15 @@ enum
 struct _GstDevicePrivate
 {
   GstCaps *caps;
-  gchar *klass;
+  gchar *device_class;
   gchar *display_name;
+  GstStructure *properties;
 };
 
 
 static guint signals[LAST_SIGNAL];
 
-G_DEFINE_ABSTRACT_TYPE (GstDevice, gst_device, GST_TYPE_OBJECT);
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstDevice, gst_device, GST_TYPE_OBJECT);
 
 static void gst_device_get_property (GObject * object, guint property_id,
     GValue * value, GParamSpec * pspec);
@@ -64,8 +82,6 @@ gst_device_class_init (GstDeviceClass * klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  g_type_class_add_private (klass, sizeof (GstDevicePrivate));
-
   object_class->get_property = gst_device_get_property;
   object_class->set_property = gst_device_set_property;
   object_class->finalize = gst_device_finalize;
@@ -78,10 +94,14 @@ 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",
+  g_object_class_install_property (object_class, PROP_DEVICE_CLASS,
+      g_param_spec_string ("device-class", "Device Class",
           "The Class of the device", "",
           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_PROPERTIES,
+      g_param_spec_boxed ("properties", "Properties",
+          "The extra properties of the device", GST_TYPE_STRUCTURE,
+          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);
@@ -90,8 +110,7 @@ gst_device_class_init (GstDeviceClass * klass)
 static void
 gst_device_init (GstDevice * device)
 {
-  device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device, GST_TYPE_DEVICE,
-      GstDevicePrivate);
+  device->priv = gst_device_get_instance_private (device);
 }
 
 static void
@@ -101,8 +120,10 @@ gst_device_finalize (GObject * object)
 
   gst_caps_replace (&device->priv->caps, NULL);
 
+  if (device->priv->properties)
+    gst_structure_free (device->priv->properties);
   g_free (device->priv->display_name);
-  g_free (device->priv->klass);
+  g_free (device->priv->device_class);
 
   G_OBJECT_CLASS (gst_device_parent_class)->finalize (object);
 }
@@ -123,8 +144,12 @@ 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));
+    case PROP_DEVICE_CLASS:
+      g_value_take_string (value, gst_device_get_device_class (gstdevice));
+      break;
+    case PROP_PROPERTIES:
+      if (gstdevice->priv->properties)
+        g_value_take_boxed (value, gst_device_get_properties (gstdevice));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -148,8 +173,13 @@ 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);
+    case PROP_DEVICE_CLASS:
+      gstdevice->priv->device_class = g_value_dup_string (value);
+      break;
+    case PROP_PROPERTIES:
+      if (gstdevice->priv->properties)
+        gst_structure_free (gstdevice->priv->properties);
+      gstdevice->priv->properties = g_value_dup_boxed (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -160,10 +190,14 @@ gst_device_set_property (GObject * object, guint prop_id,
 /**
  * gst_device_create_element:
  * @device: a #GstDevice
- * @name: (allow-none): name of new element, or NULL to automatically
+ * @name: (allow-none): name of new element, or %NULL to automatically
  * create a unique name.
  *
- * Returns: (transfer full): a new #GstElement configured to use this device
+ * Creates the element with all of the required parameters set to use
+ * this device.
+ *
+ * Returns: (transfer floating) (nullable): a new #GstElement configured to use
+ * this device
  *
  * Since: 1.4
  */
@@ -171,11 +205,20 @@ GstElement *
 gst_device_create_element (GstDevice * device, const gchar * name)
 {
   GstDeviceClass *klass = GST_DEVICE_GET_CLASS (device);
+  GstElement *element = NULL;
+
+  g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
 
   if (klass->create_element)
-    return klass->create_element (device, name);
-  else
-    return NULL;
+    element = klass->create_element (device, name);
+
+  /* Ensure that the reference is floating. Bindings might have a hard time
+   * making sure that the reference is indeed still floating after returning
+   * here */
+  if (element)
+    g_object_force_floating ((GObject *) element);
+
+  return element;
 }
 
 /**
@@ -184,7 +227,7 @@ gst_device_create_element (GstDevice * device, const gchar * name)
  *
  * Getter for the #GstCaps that this device supports.
  *
- * Returns: The #GstCaps supported by this device. Unref with
+ * Returns: (nullable): The #GstCaps supported by this device. Unref with
  * gst_caps_unref() when done.
  *
  * Since: 1.4
@@ -192,6 +235,8 @@ gst_device_create_element (GstDevice * device, const gchar * name)
 GstCaps *
 gst_device_get_caps (GstDevice * device)
 {
+  g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
+
   if (device->priv->caps)
     return gst_caps_ref (device->priv->caps);
   else
@@ -211,26 +256,55 @@ gst_device_get_caps (GstDevice * device)
 gchar *
 gst_device_get_display_name (GstDevice * device)
 {
+  g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
+
   return
       g_strdup (device->priv->display_name ? device->priv->display_name : "");
 }
 
 /**
- * gst_device_get_klass:
+ * gst_device_get_device_class:
  * @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.
+ * classes of the #GstDeviceProvider that produced this device.
  *
  * Returns: The device class. Free with g_free() after use.
  *
  * Since: 1.4
  */
 gchar *
-gst_device_get_klass (GstDevice * device)
+gst_device_get_device_class (GstDevice * device)
 {
-  return g_strdup (device->priv->klass ? device->priv->klass : "");
+  g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
+
+  if (device->priv->device_class != NULL)
+    return g_strdup (device->priv->device_class);
+  else
+    return g_strdup ("");
+}
+
+/**
+ * gst_device_get_properties:
+ * @device: a #GstDevice
+ *
+ * Gets the extra properties of a device.
+ *
+ * Returns: (nullable): The extra properties or %NULL when there are none.
+ *          Free with gst_structure_free() after use.
+ *
+ * Since: 1.6
+ */
+GstStructure *
+gst_device_get_properties (GstDevice * device)
+{
+  g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
+
+  if (device->priv->properties != NULL)
+    return gst_structure_copy (device->priv->properties);
+  else
+    return NULL;
 }
 
 /**
@@ -255,6 +329,8 @@ gst_device_reconfigure_element (GstDevice * device, GstElement * element)
 {
   GstDeviceClass *klass = GST_DEVICE_GET_CLASS (device);
 
+  g_return_val_if_fail (GST_IS_DEVICE (device), FALSE);
+
   if (klass->reconfigure_element)
     return klass->reconfigure_element (device, element);
   else
@@ -264,8 +340,8 @@ gst_device_reconfigure_element (GstDevice * device, GstElement * element)
 /**
  * gst_device_has_classesv:
  * @device: a #GstDevice
- * @classes: a %NULL terminated array of klasses to match, only match if all
- *  classes are matched
+ * @classes: (array zero-terminated=1): a %NULL terminated array of classes
+ *   to match, only match if all classes are matched
  *
  * Check if @factory matches all of the given classes
  *
@@ -278,22 +354,25 @@ gst_device_has_classesv (GstDevice * device, gchar ** classes)
 {
   g_return_val_if_fail (GST_IS_DEVICE (device), FALSE);
 
+  if (!classes)
+    return TRUE;
 
   for (; classes[0]; classes++) {
+    const gchar *klass = classes[0];
     const gchar *found;
     guint len;
 
-    if (classes[0] == '\0')
+    if (*klass == '\0')
       continue;
 
-    found = strstr (device->priv->klass, classes[0]);
+    found = strstr (device->priv->device_class, klass);
 
     if (!found)
       return FALSE;
-    if (found != device->priv->klass && *(found - 1) != '/')
+    if (found != device->priv->device_class && *(found - 1) != '/')
       return FALSE;
 
-    len = strlen (classes[0]);
+    len = strlen (klass);
     if (found[len] != 0 && found[len] != '/')
       return FALSE;
   }
@@ -304,8 +383,8 @@ gst_device_has_classesv (GstDevice * device, gchar ** classes)
 /**
  * gst_device_has_classes:
  * @device: a #GstDevice
- * @classes: a "/" separate list of klasses to match, only match if all classes
- *  are matched
+ * @classes: a "/"-separated list of device classes to match, only match if
+ *  all classes are matched
  *
  * Check if @device matches all of the given classes
  *
@@ -319,6 +398,11 @@ gst_device_has_classes (GstDevice * device, const gchar * classes)
   gchar **classesv;
   gboolean res;
 
+  g_return_val_if_fail (GST_IS_DEVICE (device), FALSE);
+
+  if (!classes)
+    return TRUE;
+
   classesv = g_strsplit (classes, "/", 0);
 
   res = gst_device_has_classesv (device, classesv);