controller: expand the api to offer functions for plain and GValue arrays
authorStefan Sauer <ensonic@users.sf.net>
Wed, 25 Apr 2012 07:47:10 +0000 (09:47 +0200)
committerStefan Sauer <ensonic@users.sf.net>
Wed, 25 Apr 2012 18:19:23 +0000 (20:19 +0200)
Rename the _get_value_array() functions to _get_g_value_array() and reintroduce
the former to operate on plain unboxed c datatypes (like in 0.10). The _g_value
variants are for bindings while the _value ones are more suited to processing
in elements.

12 files changed:
docs/gst/gstreamer-sections.txt
gst/gstcontrolbinding.c
gst/gstcontrolbinding.h
gst/gstcontrolsource.c
gst/gstobject.c
gst/gstobject.h
libs/gst/controller/gstargbcontrolbinding.c
libs/gst/controller/gstdirectcontrolbinding.c
libs/gst/controller/gstdirectcontrolbinding.h
tests/check/libs/controller.c
tests/examples/controller/control-sources.c
win32/common/libgstreamer.def

index c66ccc1..1904a6b 100644 (file)
@@ -615,6 +615,7 @@ GstControlBindingConvert
 gst_control_binding_sync_values
 gst_control_binding_get_value
 gst_control_binding_get_value_array
+gst_control_binding_get_g_value_array
 gst_control_binding_set_disabled
 gst_control_binding_is_disabled
 <SUBSECTION Standard>
@@ -1560,6 +1561,7 @@ gst_object_get_control_binding
 gst_object_remove_control_binding
 gst_object_get_value
 gst_object_get_value_array
+gst_object_get_g_value_array
 gst_object_get_control_rate
 gst_object_set_control_rate
 
index b9b7bd8..8394dd2 100644 (file)
  *   gst_control_binding_constructor()
  * - the weak-ref on object is not nice, as is the same as gst_object_parent()
  *   once the object is added to the parent
+ *
+ * - another option would be do defer what I am doing in _constructor to when
+ *   the parent is set (need to listen to the signal then)
+ *   then basically I could
+ *   a) remove the obj arg and wait the binding to be added or
+ *   b) add the binding from constructor, unref object there and make obj
+ *      writeonly
  */
 
 #include "gst_private.h"
@@ -273,19 +280,23 @@ gst_control_binding_get_value (GstControlBinding * self, GstClockTime timestamp)
  * @n_values: the number of values
  * @values: array to put control-values in
  *
- * Gets a number of values for the given controllered property starting at the
+ * Gets a number of values for the given controlled property starting at the
  * requested time. The array @values need to hold enough space for @n_values of
  * the same type as the objects property's type.
  *
  * This function is useful if one wants to e.g. draw a graph of the control
  * curve or apply a control curve sample by sample.
  *
+ * The values are unboxed and ready to be used. The similar function 
+ * gst_control_binding_get_g_value_array() returns the array as #GValues and is
+ * better suites for bindings.
+ *
  * Returns: %TRUE if the given array could be filled, %FALSE otherwise
  */
 gboolean
 gst_control_binding_get_value_array (GstControlBinding * self,
     GstClockTime timestamp, GstClockTime interval, guint n_values,
-    GValue * values)
+    gpointer values)
 {
   GstControlBindingClass *klass;
   gboolean ret = FALSE;
@@ -306,6 +317,48 @@ gst_control_binding_get_value_array (GstControlBinding * self,
 }
 
 /**
+ * gst_control_binding_get_g_value_array:
+ * @self: the control binding
+ * @timestamp: the time that should be processed
+ * @interval: the time spacing between subsequent values
+ * @n_values: the number of values
+ * @values: array to put control-values in
+ *
+ * Gets a number of #GValues for the given controlled property starting at the
+ * requested time. The array @values need to hold enough space for @n_values of
+ * #GValue.
+ *
+ * This function is useful if one wants to e.g. draw a graph of the control
+ * curve or apply a control curve sample by sample.
+ *
+ * Returns: %TRUE if the given array could be filled, %FALSE otherwise
+ */
+gboolean
+gst_control_binding_get_g_value_array (GstControlBinding * self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    GValue * values)
+{
+  GstControlBindingClass *klass;
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (GST_IS_CONTROL_BINDING (self), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
+  g_return_val_if_fail (values, FALSE);
+
+  klass = GST_CONTROL_BINDING_GET_CLASS (self);
+
+  if (G_LIKELY (klass->get_g_value_array != NULL)) {
+    ret =
+        klass->get_g_value_array (self, timestamp, interval, n_values, values);
+  } else {
+    GST_WARNING_OBJECT (self, "missing get_g_value_array implementation");
+    // FIXME(ensonic): emulate
+  }
+  return ret;
+}
+
+/**
  * gst_control_binding_set_disabled:
  * @self: the control binding
  * @disabled: boolean that specifies whether to disable the controller
index 96652fa..7f83d3d 100644 (file)
@@ -93,7 +93,8 @@ struct _GstControlBindingClass
   /* virtual methods */
   gboolean (* sync_values) (GstControlBinding *self, GstObject *object, GstClockTime timestamp, GstClockTime last_sync);
   GValue * (* get_value) (GstControlBinding *self, GstClockTime timestamp);
-  gboolean (* get_value_array) (GstControlBinding *self, GstClockTime timestamp,GstClockTime interval, guint n_values, GValue *values);
+  gboolean (* get_value_array) (GstControlBinding *self, GstClockTime timestamp,GstClockTime interval, guint n_values, gpointer values);
+  gboolean (* get_g_value_array) (GstControlBinding *self, GstClockTime timestamp,GstClockTime interval, guint n_values, GValue *values);
 
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
@@ -110,6 +111,8 @@ gboolean            gst_control_binding_sync_values        (GstControlBinding *
 GValue *            gst_control_binding_get_value          (GstControlBinding *binding,
                                                             GstClockTime timestamp);
 gboolean            gst_control_binding_get_value_array    (GstControlBinding *binding, GstClockTime timestamp,
+                                                            GstClockTime interval, guint n_values, gpointer values);
+gboolean            gst_control_binding_get_g_value_array  (GstControlBinding *binding, GstClockTime timestamp,
                                                             GstClockTime interval, guint n_values, GValue *values);
 
 void                gst_control_binding_set_disabled       (GstControlBinding * self, gboolean disabled);
index b75c2ee..611784f 100644 (file)
@@ -122,7 +122,8 @@ gst_control_source_get_value (GstControlSource * self, GstClockTime timestamp,
  * @n_values: the number of values to fetch
  * @value_array: array to put control-values in
  *
- * Gets an array of values for for this #GstControlSource.
+ * Gets an array of values for for this #GstControlSource. Values that are
+ * undefined contain NANs.
  *
  * Returns: %TRUE if the given array could be filled, %FALSE otherwise
  */
index 18dbbeb..6f58e3d 100644 (file)
@@ -1300,19 +1300,23 @@ gst_object_get_value (GstObject * object, const gchar * property_name,
  * @n_values: the number of values
  * @values: array to put control-values in
  *
- * Gets a number of values for the given controllered property starting at the
+ * Gets a number of values for the given controlled property starting at the
  * requested time. The array @values need to hold enough space for @n_values of
  * the same type as the objects property's type.
  *
  * This function is useful if one wants to e.g. draw a graph of the control
  * curve or apply a control curve sample by sample.
  *
+ * The values are unboxed and ready to be used. The similar function 
+ * gst_object_get_g_value_array() returns the array as #GValues and is
+ * better suites for bindings.
+ *
  * Returns: %TRUE if the given array could be filled, %FALSE otherwise
  */
 gboolean
 gst_object_get_value_array (GstObject * object, const gchar * property_name,
     GstClockTime timestamp, GstClockTime interval, guint n_values,
-    GValue * values)
+    gpointer values)
 {
   gboolean res = FALSE;
   GstControlBinding *binding;
@@ -1332,6 +1336,47 @@ gst_object_get_value_array (GstObject * object, const gchar * property_name,
   return res;
 }
 
+/**
+ * gst_object_get_g_value_array:
+ * @object: the object that has controlled properties
+ * @property_name: the name of the property to get
+ * @timestamp: the time that should be processed
+ * @interval: the time spacing between subsequent values
+ * @n_values: the number of values
+ * @values: array to put control-values in
+ *
+ * Gets a number of #GValues for the given controlled property starting at the
+ * requested time. The array @values need to hold enough space for @n_values of
+ * #GValue.
+ *
+ * This function is useful if one wants to e.g. draw a graph of the control
+ * curve or apply a control curve sample by sample.
+ *
+ * Returns: %TRUE if the given array could be filled, %FALSE otherwise
+ */
+gboolean
+gst_object_get_g_value_array (GstObject * object, const gchar * property_name,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
+    GValue * values)
+{
+  gboolean res = FALSE;
+  GstControlBinding *binding;
+
+  g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
+  g_return_val_if_fail (property_name, FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
+  g_return_val_if_fail (values, FALSE);
+
+  GST_OBJECT_LOCK (object);
+  if ((binding = gst_object_find_control_binding (object, property_name))) {
+    res = gst_control_binding_get_g_value_array (binding, timestamp, interval,
+        n_values, values);
+  }
+  GST_OBJECT_UNLOCK (object);
+  return res;
+}
+
 
 /**
  * gst_object_get_control_rate:
index e753516..6c9f9f5 100644 (file)
@@ -253,6 +253,9 @@ GValue *        gst_object_get_value              (GstObject * object, const gch
                                                    GstClockTime timestamp);
 gboolean        gst_object_get_value_array        (GstObject * object, const gchar * property_name,
                                                    GstClockTime timestamp, GstClockTime interval,
+                                                   guint n_values, gpointer values);
+gboolean        gst_object_get_g_value_array      (GstObject * object, const gchar * property_name,
+                                                   GstClockTime timestamp, GstClockTime interval,
                                                    guint n_values, GValue *values);
 
 GstClockTime    gst_object_get_control_rate       (GstObject * object);
index 400dbbb..9e4728a 100644 (file)
@@ -53,6 +53,9 @@ static GValue *gst_argb_control_binding_get_value (GstControlBinding * _self,
     GstClockTime timestamp);
 static gboolean gst_argb_control_binding_get_value_array (GstControlBinding *
     _self, GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gpointer values);
+static gboolean gst_argb_control_binding_get_g_value_array (GstControlBinding *
+    _self, GstClockTime timestamp, GstClockTime interval, guint n_values,
     GValue * values);
 
 #define _do_init \
@@ -94,6 +97,8 @@ gst_argb_control_binding_class_init (GstARGBControlBindingClass * klass)
   control_binding_class->get_value = gst_argb_control_binding_get_value;
   control_binding_class->get_value_array =
       gst_argb_control_binding_get_value_array;
+  control_binding_class->get_g_value_array =
+      gst_argb_control_binding_get_g_value_array;
 
   properties[PROP_CS_A] =
       g_param_spec_object ("control-source-a", "ControlSource A",
@@ -316,6 +321,71 @@ gst_argb_control_binding_get_value (GstControlBinding * _self,
 static gboolean
 gst_argb_control_binding_get_value_array (GstControlBinding * _self,
     GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gpointer values_)
+{
+  GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (_self);
+  gint i;
+  gdouble *src_val_a = NULL, *src_val_r = NULL, *src_val_g = NULL, *src_val_b =
+      NULL;
+  guint *values = (guint *) values_;
+  gboolean ret = TRUE;
+
+  g_return_val_if_fail (GST_IS_ARGB_CONTROL_BINDING (self), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
+  g_return_val_if_fail (values, FALSE);
+  g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
+
+  if (self->cs_a) {
+    src_val_a = g_new0 (gdouble, n_values);
+    ret &= gst_control_source_get_value_array (self->cs_a, timestamp,
+        interval, n_values, src_val_a);
+  }
+  if (self->cs_r) {
+    src_val_r = g_new0 (gdouble, n_values);
+    ret &= gst_control_source_get_value_array (self->cs_r, timestamp,
+        interval, n_values, src_val_r);
+  }
+  if (self->cs_g) {
+    src_val_g = g_new0 (gdouble, n_values);
+    ret &= gst_control_source_get_value_array (self->cs_g, timestamp,
+        interval, n_values, src_val_g);
+  }
+  if (self->cs_b) {
+    src_val_b = g_new0 (gdouble, n_values);
+    ret &= gst_control_source_get_value_array (self->cs_b, timestamp,
+        interval, n_values, src_val_b);
+  }
+  if (G_LIKELY (ret)) {
+    for (i = 0; i < n_values; i++) {
+      gdouble a = 1.0, r = 0.0, g = 0.0, b = 0.0;
+      if (src_val_a && !isnan (src_val_a[i]))
+        a = src_val_a[i];
+      if (src_val_r && !isnan (src_val_r[i]))
+        r = src_val_r[i];
+      if (src_val_g && !isnan (src_val_g[i]))
+        g = src_val_g[i];
+      if (src_val_b && !isnan (src_val_b[i]))
+        b = src_val_b[i];
+      values[i] = (((guint) (CLAMP (a, 0.0, 1.0) * 255)) << 24) |
+          (((guint) (CLAMP (r, 0.0, 1.0) * 255)) << 16) |
+          (((guint) (CLAMP (g, 0.0, 1.0) * 255)) << 8) |
+          ((guint) (CLAMP (b, 0.0, 1.0) * 255));
+    }
+  } else {
+    GST_LOG ("failed to get control value for property %s at ts %"
+        GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp));
+  }
+  g_free (src_val_a);
+  g_free (src_val_r);
+  g_free (src_val_g);
+  g_free (src_val_b);
+  return ret;
+}
+
+static gboolean
+gst_argb_control_binding_get_g_value_array (GstControlBinding * _self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
     GValue * values)
 {
   GstARGBControlBinding *self = GST_ARGB_CONTROL_BINDING (_self);
index 6a8ef63..8d102c4 100644 (file)
@@ -52,6 +52,9 @@ static GValue *gst_direct_control_binding_get_value (GstControlBinding * _self,
     GstClockTime timestamp);
 static gboolean gst_direct_control_binding_get_value_array (GstControlBinding *
     _self, GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gpointer values);
+static gboolean gst_direct_control_binding_get_g_value_array (GstControlBinding
+    * _self, GstClockTime timestamp, GstClockTime interval, guint n_values,
     GValue * values);
 
 #define _do_init \
@@ -75,7 +78,7 @@ static GParamSpec *properties[PROP_LAST];
 
 #define DEFINE_CONVERT(type,Type,TYPE) \
 static void \
-convert_to_##type (GstDirectControlBinding *self, gdouble s, GValue *d) \
+convert_g_value_to_##type (GstDirectControlBinding *self, gdouble s, GValue *d) \
 { \
   GParamSpec##Type *pspec = G_PARAM_SPEC_##TYPE (((GstControlBinding *)self)->pspec); \
   g##type v; \
@@ -83,8 +86,19 @@ convert_to_##type (GstDirectControlBinding *self, gdouble s, GValue *d) \
   s = CLAMP (s, 0.0, 1.0); \
   v = pspec->minimum + (g##type) ((pspec->maximum - pspec->minimum) * s); \
   g_value_set_##type (d, v); \
+} \
+\
+static void \
+convert_value_to_##type (GstDirectControlBinding *self, gdouble s, gpointer d_) \
+{ \
+  GParamSpec##Type *pspec = G_PARAM_SPEC_##TYPE (((GstControlBinding *)self)->pspec); \
+  g##type *d = (g##type *)d_; \
+  \
+  s = CLAMP (s, 0.0, 1.0); \
+  *d = pspec->minimum + (g##type) ((pspec->maximum - pspec->minimum) * s); \
 }
 
+
 DEFINE_CONVERT (int, Int, INT);
 DEFINE_CONVERT (uint, UInt, UINT);
 DEFINE_CONVERT (long, Long, LONG);
@@ -95,14 +109,25 @@ DEFINE_CONVERT (float, Float, FLOAT);
 DEFINE_CONVERT (double, Double, DOUBLE);
 
 static void
-convert_to_boolean (GstDirectControlBinding * self, gdouble s, GValue * d)
+convert_g_value_to_boolean (GstDirectControlBinding * self, gdouble s,
+    GValue * d)
 {
   s = CLAMP (s, 0.0, 1.0);
   g_value_set_boolean (d, (gboolean) (s + 0.5));
 }
 
 static void
-convert_to_enum (GstDirectControlBinding * self, gdouble s, GValue * d)
+convert_value_to_boolean (GstDirectControlBinding * self, gdouble s,
+    gpointer d_)
+{
+  gboolean *d = (gboolean *) d_;
+
+  s = CLAMP (s, 0.0, 1.0);
+  *d = (gboolean) (s + 0.5);
+}
+
+static void
+convert_g_value_to_enum (GstDirectControlBinding * self, gdouble s, GValue * d)
 {
   GParamSpecEnum *pspec =
       G_PARAM_SPEC_ENUM (((GstControlBinding *) self)->pspec);
@@ -114,6 +139,18 @@ convert_to_enum (GstDirectControlBinding * self, gdouble s, GValue * d)
   g_value_set_enum (d, e->values[v].value);
 }
 
+static void
+convert_value_to_enum (GstDirectControlBinding * self, gdouble s, gpointer d_)
+{
+  GParamSpecEnum *pspec =
+      G_PARAM_SPEC_ENUM (((GstControlBinding *) self)->pspec);
+  GEnumClass *e = pspec->enum_class;
+  gint *d = (gint *) d_;
+
+  s = CLAMP (s, 0.0, 1.0);
+  *d = e->values[(gint) (s * (e->n_values - 1))].value;
+}
+
 /* vmethods */
 
 static void
@@ -133,6 +170,8 @@ gst_direct_control_binding_class_init (GstDirectControlBindingClass * klass)
   control_binding_class->get_value = gst_direct_control_binding_get_value;
   control_binding_class->get_value_array =
       gst_direct_control_binding_get_value_array;
+  control_binding_class->get_g_value_array =
+      gst_direct_control_binding_get_g_value_array;
 
   properties[PROP_CS] =
       g_param_spec_object ("control-source", "ControlSource",
@@ -171,34 +210,54 @@ gst_direct_control_binding_constructor (GType type, guint n_construct_params,
     // select mapping function
     switch (base) {
       case G_TYPE_INT:
-        self->convert = convert_to_int;
+        self->convert_g_value = convert_g_value_to_int;
+        self->convert_value = convert_value_to_int;
+        self->byte_size = sizeof (gint);
         break;
       case G_TYPE_UINT:
-        self->convert = convert_to_uint;
+        self->convert_g_value = convert_g_value_to_uint;
+        self->convert_value = convert_value_to_uint;
+        self->byte_size = sizeof (guint);
         break;
       case G_TYPE_LONG:
-        self->convert = convert_to_long;
+        self->convert_g_value = convert_g_value_to_long;
+        self->convert_value = convert_value_to_long;
+        self->byte_size = sizeof (glong);
         break;
       case G_TYPE_ULONG:
-        self->convert = convert_to_ulong;
+        self->convert_g_value = convert_g_value_to_ulong;
+        self->convert_value = convert_value_to_ulong;
+        self->byte_size = sizeof (gulong);
         break;
       case G_TYPE_INT64:
-        self->convert = convert_to_int64;
+        self->convert_g_value = convert_g_value_to_int64;
+        self->convert_value = convert_value_to_int64;
+        self->byte_size = sizeof (gint64);
         break;
       case G_TYPE_UINT64:
-        self->convert = convert_to_uint64;
+        self->convert_g_value = convert_g_value_to_uint64;
+        self->convert_value = convert_value_to_uint64;
+        self->byte_size = sizeof (guint64);
         break;
       case G_TYPE_FLOAT:
-        self->convert = convert_to_float;
+        self->convert_g_value = convert_g_value_to_float;
+        self->convert_value = convert_value_to_float;
+        self->byte_size = sizeof (gfloat);
         break;
       case G_TYPE_DOUBLE:
-        self->convert = convert_to_double;
+        self->convert_g_value = convert_g_value_to_double;
+        self->convert_value = convert_value_to_double;
+        self->byte_size = sizeof (gdouble);
         break;
       case G_TYPE_BOOLEAN:
-        self->convert = convert_to_boolean;
+        self->convert_g_value = convert_g_value_to_boolean;
+        self->convert_value = convert_value_to_boolean;
+        self->byte_size = sizeof (gboolean);
         break;
       case G_TYPE_ENUM:
-        self->convert = convert_to_enum;
+        self->convert_g_value = convert_g_value_to_enum;
+        self->convert_value = convert_value_to_enum;
+        self->byte_size = sizeof (gint);
         break;
       default:
         GST_WARNING ("incomplete implementation for paramspec type '%s'",
@@ -290,7 +349,7 @@ gst_direct_control_binding_sync_values (GstControlBinding * _self,
       GST_LOG_OBJECT (object, "  mapping %s to value of type %s", _self->name,
           G_VALUE_TYPE_NAME (dst_val));
       /* run mapping function to convert gdouble to GValue */
-      self->convert (self, src_val, dst_val);
+      self->convert_g_value (self, src_val, dst_val);
       /* we can make this faster
        * http://bugzilla.gnome.org/show_bug.cgi?id=536939
        */
@@ -319,7 +378,7 @@ gst_direct_control_binding_get_value (GstControlBinding * _self,
   if (gst_control_source_get_value (self->cs, timestamp, &src_val)) {
     dst_val = g_new0 (GValue, 1);
     g_value_init (dst_val, G_PARAM_SPEC_VALUE_TYPE (_self->pspec));
-    self->convert (self, src_val, dst_val);
+    self->convert_g_value (self, src_val, dst_val);
   } else {
     GST_LOG ("no control value for property %s at ts %" GST_TIME_FORMAT,
         _self->name, GST_TIME_ARGS (timestamp));
@@ -331,6 +390,48 @@ gst_direct_control_binding_get_value (GstControlBinding * _self,
 static gboolean
 gst_direct_control_binding_get_value_array (GstControlBinding * _self,
     GstClockTime timestamp, GstClockTime interval, guint n_values,
+    gpointer values_)
+{
+  GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self);
+  gint i;
+  gdouble *src_val;
+  gboolean res = FALSE;
+  GstDirectControlBindingConvertValue convert;
+  gint byte_size;
+  guint8 *values = (guint8 *) values_;
+
+  g_return_val_if_fail (GST_IS_DIRECT_CONTROL_BINDING (self), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
+  g_return_val_if_fail (values, FALSE);
+  g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
+
+  convert = self->convert_value;
+  byte_size = self->byte_size;
+
+  src_val = g_new0 (gdouble, n_values);
+  if ((res = gst_control_source_get_value_array (self->cs, timestamp,
+              interval, n_values, src_val))) {
+    for (i = 0; i < n_values; i++) {
+      if (!isnan (src_val[i])) {
+        convert (self, src_val[i], (gpointer) values);
+      } else {
+        GST_LOG ("no control value for property %s at index %d", _self->name,
+            i);
+      }
+      values += byte_size;
+    }
+  } else {
+    GST_LOG ("failed to get control value for property %s at ts %"
+        GST_TIME_FORMAT, _self->name, GST_TIME_ARGS (timestamp));
+  }
+  g_free (src_val);
+  return res;
+}
+
+static gboolean
+gst_direct_control_binding_get_g_value_array (GstControlBinding * _self,
+    GstClockTime timestamp, GstClockTime interval, guint n_values,
     GValue * values)
 {
   GstDirectControlBinding *self = GST_DIRECT_CONTROL_BINDING (_self);
@@ -338,7 +439,7 @@ gst_direct_control_binding_get_value_array (GstControlBinding * _self,
   gdouble *src_val;
   gboolean res = FALSE;
   GType type;
-  GstDirectControlBindingConvert convert;
+  GstDirectControlBindingConvertGValue convert;
 
   g_return_val_if_fail (GST_IS_DIRECT_CONTROL_BINDING (self), FALSE);
   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
@@ -346,7 +447,7 @@ gst_direct_control_binding_get_value_array (GstControlBinding * _self,
   g_return_val_if_fail (values, FALSE);
   g_return_val_if_fail (GST_CONTROL_BINDING_PSPEC (self), FALSE);
 
-  convert = self->convert;
+  convert = self->convert_g_value;
   type = G_PARAM_SPEC_VALUE_TYPE (_self->pspec);
 
   src_val = g_new0 (gdouble, n_values);
index 729d117..24ece6d 100644 (file)
@@ -48,14 +48,24 @@ typedef struct _GstDirectControlBinding GstDirectControlBinding;
 typedef struct _GstDirectControlBindingClass GstDirectControlBindingClass;
 
 /**
- * GstDirectControlBindingConvert:
+ * GstDirectControlBindingConvertValue:
+ * @self: the #GstDirectControlBinding instance
+ * @src_value: the value returned by the cotnrol source
+ * @dest_value: the target location
+ *
+ * Function to map a control-value to the target plain data type.
+ */
+typedef void (* GstDirectControlBindingConvertValue) (GstDirectControlBinding *self, gdouble src_value, gpointer dest_value);
+
+/**
+ * GstDirectControlBindingConvertGValue:
  * @self: the #GstDirectControlBinding instance
  * @src_value: the value returned by the cotnrol source
  * @dest_value: the target GValue
  *
  * Function to map a control-value to the target GValue.
  */
-typedef void (* GstDirectControlBindingConvert) (GstDirectControlBinding *self, gdouble src_value, GValue *dest_value);
+typedef void (* GstDirectControlBindingConvertGValue) (GstDirectControlBinding *self, gdouble src_value, GValue *dest_value);
 
 /**
  * GstDirectControlBinding:
@@ -70,8 +80,10 @@ struct _GstDirectControlBinding {
   GstControlSource *cs;    /* GstControlSource for this property */
   GValue cur_value;
   gdouble last_value;
+  gint byte_size;
 
-  GstDirectControlBindingConvert convert;
+  GstDirectControlBindingConvertValue convert_value;
+  GstDirectControlBindingConvertGValue convert_g_value;
 
   gpointer _gst_reserved[GST_PADDING];
 };
index 68388c7..c8d9528 100644 (file)
@@ -605,6 +605,7 @@ GST_START_TEST (controller_interpolation_linear_value_array)
   GstElement *elem;
   gdouble *raw_values;
   GValue *g_values;
+  gint *values;
 
   elem = gst_element_factory_make ("testobj", NULL);
 
@@ -633,10 +634,10 @@ GST_START_TEST (controller_interpolation_linear_value_array)
 
   g_free (raw_values);
 
-  /* now pull in mapped values for some timestamps */
+  /* now pull in mapped GValues for some timestamps */
   g_values = g_new0 (GValue, 3);
 
-  fail_unless (gst_object_get_value_array (GST_OBJECT (elem), "int",
+  fail_unless (gst_object_get_g_value_array (GST_OBJECT (elem), "int",
           0, GST_SECOND / 2, 3, g_values));
   fail_unless_equals_int (g_value_get_int (&g_values[0]), 0);
   fail_unless_equals_int (g_value_get_int (&g_values[1]), 50);
@@ -644,6 +645,17 @@ GST_START_TEST (controller_interpolation_linear_value_array)
 
   g_free (g_values);
 
+  /* now pull in mapped values for some timestamps */
+  values = g_new0 (gint, 3);
+
+  fail_unless (gst_object_get_value_array (GST_OBJECT (elem), "int",
+          0, GST_SECOND / 2, 3, values));
+  fail_unless_equals_int (values[0], 0);
+  fail_unless_equals_int (values[1], 50);
+  fail_unless_equals_int (values[2], 100);
+
+  g_free (values);
+
   gst_object_unref (cs);
   gst_object_unref (elem);
 }
index 950cee2..7d74a87 100644 (file)
@@ -230,15 +230,15 @@ test_interpolation (void)
 
   g_object_set (cs, "mode", GST_INTERPOLATION_MODE_NONE, NULL);
   v1 = g_new0 (GValue, n_values);
-  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
+  gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
 
   g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
   v2 = g_new0 (GValue, n_values);
-  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v2);
+  gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v2);
 
   g_object_set (cs, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL);
   v3 = g_new0 (GValue, n_values);
-  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v3);
+  gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v3);
 
   for (t = 0; t < n_values; t++) {
     i1 = g_value_get_int (&v1[t]);
@@ -320,23 +320,23 @@ test_lfo (void)
 
   g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SINE, NULL);
   v1 = g_new0 (GValue, n_values);
-  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
+  gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
 
   g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SQUARE, NULL);
   v2 = g_new0 (GValue, n_values);
-  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v2);
+  gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v2);
 
   g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SAW, NULL);
   v3 = g_new0 (GValue, n_values);
-  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v3);
+  gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v3);
 
   g_object_set (cs, "waveform", GST_LFO_WAVEFORM_REVERSE_SAW, NULL);
   v4 = g_new0 (GValue, n_values);
-  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v4);
+  gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v4);
 
   g_object_set (cs, "waveform", GST_LFO_WAVEFORM_TRIANGLE, NULL);
   v5 = g_new0 (GValue, n_values);
-  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v5);
+  gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v5);
 
   for (t = 0; t < n_values; t++) {
     i1 = g_value_get_int (&v1[t]);
@@ -418,7 +418,7 @@ test_chained_lfo (void)
   n_values = 40 * 10;
 
   v1 = g_new0 (GValue, n_values);
-  gst_object_get_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
+  gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
 
   for (t = 0; t < n_values; t++) {
     i1 = g_value_get_int (&v1[t]);
index f7fba34..bfddc37 100644 (file)
@@ -254,6 +254,7 @@ EXPORTS
        gst_clock_single_shot_id_reinit
        gst_clock_type_get_type
        gst_clock_unadjust_unlocked
+       gst_control_binding_get_g_value_array
        gst_control_binding_get_type
        gst_control_binding_get_value
        gst_control_binding_get_value_array
@@ -605,6 +606,7 @@ EXPORTS
        gst_object_flags_get_type
        gst_object_get_control_binding
        gst_object_get_control_rate
+       gst_object_get_g_value_array
        gst_object_get_name
        gst_object_get_parent
        gst_object_get_path_string