controller: support control mapping for enums
authorStefan Sauer <ensonic@users.sf.net>
Sun, 1 Jan 2012 19:55:20 +0000 (20:55 +0100)
committerStefan Sauer <ensonic@users.sf.net>
Sun, 1 Jan 2012 19:55:20 +0000 (20:55 +0100)
Add a mapping for enum types (supporting sparse enums). Add a test.

gst/gstcontrolbinding.c
tests/check/libs/controller.c

index e0def7a..1bdfcb2 100644 (file)
@@ -110,6 +110,18 @@ convert_to_boolean (GstControlBinding * self, gdouble s, GValue * d)
   g_value_set_boolean (d, (gboolean) (s + 0.5));
 }
 
+static void
+convert_to_enum (GstControlBinding * self, gdouble s, GValue * d)
+{
+  GParamSpecEnum *pspec = G_PARAM_SPEC_ENUM (self->pspec);
+  GEnumClass *e = pspec->enum_class;
+  gint v;
+
+  s = CLAMP (s, 0.0, 1.0);
+  v = s * (e->n_values - 1);
+  g_value_set_enum (d, e->values[v].value);
+}
+
 /**
  * gst_control_binding_new:
  * @object: the object of the property
@@ -189,6 +201,9 @@ gst_control_binding_new (GstObject * object, const gchar * property_name,
         case G_TYPE_BOOLEAN:
           self->convert = convert_to_boolean;
           break;
+        case G_TYPE_ENUM:
+          self->convert = convert_to_enum;
+          break;
         default:
           // FIXME: return NULL?
           GST_WARNING ("incomplete implementation for paramspec type '%s'",
index d07f122..155c863 100644 (file)
 #include <gst/controller/gstlfocontrolsource.h>
 #include <gst/controller/gsttriggercontrolsource.h>
 
+/* enum for text element */
+
+#define GST_TYPE_TEST_ENUM (gst_test_enum_get_type ())
+
+typedef enum
+{
+  ENUM_V0 = 0,
+  ENUM_V10 = 10,
+  ENUM_V11,
+  ENUM_V12,
+  ENUM_V255 = 255
+} GstTestEnum;
+
+static GType
+gst_test_enum_get_type (void)
+{
+  static gsize gtype = 0;
+  static const GEnumValue values[] = {
+    {ENUM_V0, "ENUM_V0", "0"},
+    {ENUM_V10, "ENUM_V10", "10"},
+    {ENUM_V11, "ENUM_V11", "11"},
+    {ENUM_V12, "ENUM_V12", "12"},
+    {ENUM_V255, "ENUM_V255", "255"},
+    {0, NULL, NULL}
+  };
+
+  if (g_once_init_enter (&gtype)) {
+    GType tmp = g_enum_register_static ("GstTestEnum", values);
+    g_once_init_leave (&gtype, tmp);
+  }
+
+  return (GType) gtype;
+}
+
 /* local test element */
 
 enum
@@ -38,6 +72,7 @@ enum
   PROP_FLOAT,
   PROP_DOUBLE,
   PROP_BOOLEAN,
+  PROP_ENUM,
   PROP_READONLY,
   PROP_STATIC,
   PROP_CONSTRUCTONLY,
@@ -61,6 +96,7 @@ struct _GstTestObj
   gfloat val_float;
   gdouble val_double;
   gboolean val_boolean;
+  GstTestEnum val_enum;
 };
 struct _GstTestObjClass
 {
@@ -88,6 +124,9 @@ gst_test_obj_get_property (GObject * object,
     case PROP_BOOLEAN:
       g_value_set_boolean (value, self->val_boolean);
       break;
+    case PROP_ENUM:
+      g_value_set_enum (value, self->val_enum);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -117,6 +156,10 @@ gst_test_obj_set_property (GObject * object,
       self->val_boolean = g_value_get_boolean (value);
       GST_DEBUG ("test value boolean=%d", self->val_boolean);
       break;
+    case PROP_ENUM:
+      self->val_enum = g_value_get_enum (value);
+      GST_DEBUG ("test value enum=%d", self->val_enum);
+      break;
     case PROP_CONSTRUCTONLY:
       break;
     default:
@@ -157,6 +200,13 @@ gst_test_obj_class_init (GstTestObjClass * klass)
           "boolean parameter",
           FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
+  g_object_class_install_property (gobject_class, PROP_ENUM,
+      g_param_spec_enum ("enum",
+          "enum prop",
+          "enum parameter",
+          GST_TYPE_TEST_ENUM, ENUM_V0,
+          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+
   g_object_class_install_property (gobject_class, PROP_READONLY,
       g_param_spec_int ("readonly",
           "readonly prop",
@@ -950,6 +1000,49 @@ GST_START_TEST (controller_interpolate_linear_before_ts0)
 
 GST_END_TEST;
 
+/* test linear interpolation of enums */
+GST_START_TEST (controller_interpolate_linear_enums)
+{
+  GstInterpolationControlSource *csource;
+  GstTimedValueControlSource *tvcs;
+  GstControlSource *cs;
+  GstElement *elem;
+
+  elem = gst_element_factory_make ("testobj", NULL);
+
+  /* new interpolation control source */
+  csource = gst_interpolation_control_source_new ();
+  tvcs = (GstTimedValueControlSource *) csource;
+  cs = (GstControlSource *) csource;
+
+  fail_unless (csource != NULL);
+  fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "enum", cs));
+
+  /* set interpolation mode */
+  g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
+
+  /* set control values */
+  fail_unless (gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0));
+  fail_unless (gst_timed_value_control_source_set (tvcs, 4 * GST_SECOND, 1.0));
+
+  /* now pull in values going over the enum values */
+  gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V0);
+  gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V10);
+  gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V11);
+  gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V12);
+  gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND);
+  fail_unless_equals_int (GST_TEST_OBJ (elem)->val_enum, ENUM_V255);
+
+  gst_object_unref (csource);
+  gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
 /* test timed value counts */
 GST_START_TEST (controller_timed_value_count)
 {
@@ -1475,6 +1568,7 @@ gst_controller_suite (void)
   tcase_add_test (tc, controller_interpolate_linear_disabled);
   tcase_add_test (tc, controller_interpolation_set_from_list);
   tcase_add_test (tc, controller_interpolate_linear_before_ts0);
+  tcase_add_test (tc, controller_interpolate_linear_enums);
   tcase_add_test (tc, controller_timed_value_count);
   tcase_add_test (tc, controller_lfo_sine);
   tcase_add_test (tc, controller_lfo_sine_timeshift);