diff --git a/gst/gstcontrolbinding.c b/gst/gstcontrolbinding.c index e0def7aeb3..1bdfcb2af5 100644 --- a/gst/gstcontrolbinding.c +++ b/gst/gstcontrolbinding.c @@ -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'", diff --git a/tests/check/libs/controller.c b/tests/check/libs/controller.c index d07f1229ad..155c863029 100644 --- a/tests/check/libs/controller.c +++ b/tests/check/libs/controller.c @@ -30,6 +30,40 @@ #include #include +/* 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 (>ype)) { + GType tmp = g_enum_register_static ("GstTestEnum", values); + g_once_init_leave (>ype, 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);