summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/libs/gstreamer-libs-docs.sgml2
-rw-r--r--docs/libs/gstreamer-libs-sections.txt64
-rw-r--r--docs/libs/gstreamer-libs.types4
-rw-r--r--docs/random/porting-to-0.11.txt6
-rw-r--r--gst/gstobject.c4
-rw-r--r--libs/gst/controller/Makefile.am4
-rw-r--r--libs/gst/controller/gstinterpolation.c328
-rw-r--r--libs/gst/controller/gstinterpolationcontrolsource.c551
-rw-r--r--libs/gst/controller/gstinterpolationcontrolsource.h27
-rw-r--r--libs/gst/controller/gstinterpolationcontrolsourceprivate.h15
-rw-r--r--libs/gst/controller/gsttimedvaluecontrolsource.c603
-rw-r--r--libs/gst/controller/gsttimedvaluecontrolsource.h114
-rw-r--r--libs/gst/controller/gsttriggercontrolsource.c404
-rw-r--r--libs/gst/controller/gsttriggercontrolsource.h83
-rw-r--r--tests/benchmarks/controller.c6
-rw-r--r--tests/check/libs/controller.c499
-rw-r--r--tests/examples/controller/audio-example.c15
17 files changed, 1649 insertions, 1080 deletions
diff --git a/docs/libs/gstreamer-libs-docs.sgml b/docs/libs/gstreamer-libs-docs.sgml
index 8f12e655a..788c3d836 100644
--- a/docs/libs/gstreamer-libs-docs.sgml
+++ b/docs/libs/gstreamer-libs-docs.sgml
@@ -55,8 +55,10 @@
element properties over time.
</para>
+ <xi:include href="xml/gsttimedvaluecontrolsource.xml" />
<xi:include href="xml/gstinterpolationcontrolsource.xml" />
<xi:include href="xml/gstlfocontrolsource.xml" />
+ <xi:include href="xml/gsttriggercontrolsource.xml" />
</chapter>
<chapter id="gstreamer-dataprotocol">
diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt
index 2491b29dd..c61a1838d 100644
--- a/docs/libs/gstreamer-libs-sections.txt
+++ b/docs/libs/gstreamer-libs-sections.txt
@@ -53,28 +53,49 @@ gst_dp_version_get_type
# control source classes
<SECTION>
+<FILE>gsttimedvaluecontrolsource</FILE>
+<TITLE>GstTimedValueControlSource</TITLE>
+<INCLUDE>libs/controller/gsttimedvaluecontrolsource.h</INCLUDE>
+GstTimedValueControlSource
+gst_timed_value_control_source_find_control_point_iter
+gst_timed_value_control_source_set
+gst_timed_value_control_source_set_from_list
+gst_timed_value_control_source_get_all
+gst_timed_value_control_source_unset
+gst_timed_value_control_source_unset_all
+gst_timed_value_control_source_get_count
+gst_timed_value_control_source_get_base_value_type
+gst_timed_value_control_invalidate_cache
+<SUBSECTION Standard>
+GstTimedValueControlSourceClass
+GstTimedValueControlSourcePrivate
+GST_INTERPOLATION_CONTROL_SOURCE
+GST_IS_INTERPOLATION_CONTROL_SOURCE
+GST_INTERPOLATION_CONTROL_SOURCE_CLASS
+GST_IS_INTERPOLATION_CONTROL_SOURCE_CLASS
+GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS
+GST_TYPE_INTERPOLATION_CONTROL_SOURCE
+<SUBSECTION Private>
+gst_timed_value_control_source_get_type
+</SECTION>
+
+<SECTION>
<FILE>gstinterpolationcontrolsource</FILE>
<TITLE>GstInterpolationControlSource</TITLE>
<INCLUDE>libs/controller/gstinterpolationcontrolsource.h</INCLUDE>
GstInterpolationControlSource
GstInterpolateMode
gst_interpolation_control_source_new
-gst_interpolation_control_source_set
-gst_interpolation_control_source_set_from_list
gst_interpolation_control_source_set_interpolation_mode
-gst_interpolation_control_source_get_all
-gst_interpolation_control_source_unset
-gst_interpolation_control_source_unset_all
-gst_interpolation_control_source_get_count
<SUBSECTION Standard>
GstInterpolationControlSourceClass
GstInterpolationControlSourcePrivate
-GST_INTERPOLATION_CONTROL_SOURCE
-GST_IS_INTERPOLATION_CONTROL_SOURCE
-GST_INTERPOLATION_CONTROL_SOURCE_CLASS
-GST_IS_INTERPOLATION_CONTROL_SOURCE_CLASS
-GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS
-GST_TYPE_INTERPOLATION_CONTROL_SOURCE
+GST_TIMED_VALUE_CONTROL_SOURCE
+GST_IS_TIMED_VALUE_CONTROL_SOURCE
+GST_TIMED_VALUE_CONTROL_SOURCE_CLASS
+GST_IS_TIMED_VALUE_CONTROL_SOURCE_CLASS
+GST_TIMED_VALUE_CONTROL_SOURCE_GET_CLASS
+GST_TYPE_TIMED_VALUE_CONTROL_SOURCE
<SUBSECTION Private>
gst_interpolation_control_source_get_type
</SECTION>
@@ -101,6 +122,25 @@ gst_lfo_control_source_get_type
gst_lfo_waveform_get_type
</SECTION>
+<SECTION>
+<FILE>gsttriggercontrolsource</FILE>
+<TITLE>GstTriggerControlSource</TITLE>
+<INCLUDE>libs/controller/gsttriggercontrolsource.h</INCLUDE>
+GstTriggerControlSource
+gst_trigger_control_source_new
+<SUBSECTION Standard>
+GstTriggerControlSourceClass
+GstTriggerControlSourcePrivate
+GST_TRIGGER_CONTROL_SOURCE
+GST_IS_TRIGGER_CONTROL_SOURCE
+GST_TRIGGER_CONTROL_SOURCE_CLASS
+GST_IS_TRIGGER_CONTROL_SOURCE_CLASS
+GST_TRIGGER_CONTROL_SOURCE_GET_CLASS
+GST_TYPE_TRIGGER_CONTROL_SOURCE
+<SUBSECTION Private>
+gst_trigger_control_source_get_type
+</SECTION>
+
# base classes
<SECTION>
diff --git a/docs/libs/gstreamer-libs.types b/docs/libs/gstreamer-libs.types
index 62594a4f4..a75d55b4f 100644
--- a/docs/libs/gstreamer-libs.types
+++ b/docs/libs/gstreamer-libs.types
@@ -18,11 +18,15 @@ gst_push_src_get_type
% controller
+#include <gst/controller/gsttimedvaluecontrolsource.h>
#include <gst/controller/gstinterpolationcontrolsource.h>
#include <gst/controller/gstlfocontrolsource.h>
+#include <gst/controller/gsttriggercontrolsource.h>
+gst_timed_value_control_source_get_type
gst_interpolation_control_source_get_type
gst_lfo_control_source_get_type
+gst_trigger_control_source_get_type
% net
diff --git a/docs/random/porting-to-0.11.txt b/docs/random/porting-to-0.11.txt
index 33dddaf00..57eba376e 100644
--- a/docs/random/porting-to-0.11.txt
+++ b/docs/random/porting-to-0.11.txt
@@ -447,4 +447,8 @@ The 0.11 porting guide
properties fetch the value array. Also GstValueArray is gone. The fields of
GstValueArray are now passed directly to gst_object_get_value_array as
arguments.
-
+
+ GstInterpolationControlSource has been split. There is a new
+ GstTimedValueControlSource baseclass and 2 sub classes:
+ GstInterpolationControlSource and GstTriggerControlSource. The API for setting
+ and getting the timestamps is in GstTimedValueControlSource.
diff --git a/gst/gstobject.c b/gst/gstobject.c
index 21c3126f0..c3b8db7d4 100644
--- a/gst/gstobject.c
+++ b/gst/gstobject.c
@@ -121,8 +121,8 @@
* </para></listitem>
* <listitem><para>
* Set the control values
- * gst_interpolation_control_source_set (csource,0 * GST_SECOND, value1);
- * gst_interpolation_control_source_set (csource,1 * GST_SECOND, value2);
+ * gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,0 * GST_SECOND, value1);
+ * gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,1 * GST_SECOND, value2);
* </para></listitem>
* <listitem><para>
* start your pipeline
diff --git a/libs/gst/controller/Makefile.am b/libs/gst/controller/Makefile.am
index c5e61b211..793caadfa 100644
--- a/libs/gst/controller/Makefile.am
+++ b/libs/gst/controller/Makefile.am
@@ -2,7 +2,9 @@ lib_LTLIBRARIES = libgstcontroller-@GST_MAJORMINOR@.la
libgstcontroller_@GST_MAJORMINOR@_includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/controller
libgstcontroller_@GST_MAJORMINOR@_include_HEADERS = \
+ gsttimedvaluecontrolsource.h \
gstinterpolationcontrolsource.h \
+ gsttriggercontrolsource.h \
gstlfocontrolsource.h
noinst_HEADERS = \
@@ -10,8 +12,10 @@ noinst_HEADERS = \
gstlfocontrolsourceprivate.h
libgstcontroller_@GST_MAJORMINOR@_la_SOURCES = \
+ gsttimedvaluecontrolsource.c \
gstinterpolation.c \
gstinterpolationcontrolsource.c \
+ gsttriggercontrolsource.c \
gstlfocontrolsource.c
libgstcontroller_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
diff --git a/libs/gst/controller/gstinterpolation.c b/libs/gst/controller/gstinterpolation.c
index 40bdb6a4f..7098f3a1b 100644
--- a/libs/gst/controller/gstinterpolation.c
+++ b/libs/gst/controller/gstinterpolation.c
@@ -33,55 +33,10 @@ GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
#define EMPTY(x) (x)
-/* common helper */
-
-static gint
-gst_control_point_find (gconstpointer p1, gconstpointer p2)
-{
- GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
- GstClockTime ct2 = *(GstClockTime *) p2;
-
- return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
-}
-
-/*
- * gst_interpolation_control_source_find_control_point_iter:
- * @self: the interpolation control source to search in
- * @timestamp: the search key
- *
- * Find last value before given timestamp in control point list.
- * If all values in the control point list come after the given
- * timestamp or no values exist, %NULL is returned.
- *
- * Returns: the found #GSequenceIter or %NULL
- */
-static GSequenceIter *gst_interpolation_control_source_find_control_point_iter
- (GstInterpolationControlSource * self, GstClockTime timestamp)
-{
- GSequenceIter *iter;
-
- if (!self->priv->values)
- return NULL;
-
- iter =
- g_sequence_search (self->priv->values, &timestamp,
- (GCompareDataFunc) gst_control_point_find, NULL);
-
- /* g_sequence_search() returns the iter where timestamp
- * would be inserted, i.e. the iter > timestamp, so
- * we need to get the previous one. And of course, if
- * there is no previous one, we return NULL. */
- if (g_sequence_iter_is_begin (iter))
- return NULL;
-
- return g_sequence_iter_prev (iter);
-}
-
/* steps-like (no-)interpolation, default */
/* just returns the value for the most recent key-frame */
static inline const GValue *
-_interpolate_none_get (GstInterpolationControlSource * self,
- GSequenceIter * iter)
+_interpolate_none_get (GstTimedValueControlSource * self, GSequenceIter * iter)
{
const GValue *ret;
@@ -90,14 +45,14 @@ _interpolate_none_get (GstInterpolationControlSource * self,
ret = &cp->value;
} else {
- ret = &self->priv->default_value;
+ ret = &self->default_value;
}
return ret;
}
#define DEFINE_NONE_GET_FUNC_COMPARABLE(type) \
static inline const GValue * \
-_interpolate_none_get_##type (GstInterpolationControlSource *self, GSequenceIter *iter) \
+_interpolate_none_get_##type (GstTimedValueControlSource *self, GSequenceIter *iter) \
{ \
const GValue *ret; \
\
@@ -105,28 +60,28 @@ _interpolate_none_get_##type (GstInterpolationControlSource *self, GSequenceIter
GstControlPoint *cp = g_sequence_get (iter); \
g##type ret_val = g_value_get_##type (&cp->value); \
\
- if (g_value_get_##type (&self->priv->minimum_value) > ret_val) \
- ret = &self->priv->minimum_value; \
- else if (g_value_get_##type (&self->priv->maximum_value) < ret_val) \
- ret = &self->priv->maximum_value; \
+ if (g_value_get_##type (&self->minimum_value) > ret_val) \
+ ret = &self->minimum_value; \
+ else if (g_value_get_##type (&self->maximum_value) < ret_val) \
+ ret = &self->maximum_value; \
else \
ret = &cp->value; \
} else { \
- ret = &self->priv->default_value; \
+ ret = &self->default_value; \
} \
return ret; \
}
#define DEFINE_NONE_GET(type,ctype,get_func) \
static gboolean \
-interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
+interpolate_none_get_##type (GstTimedValueControlSource *self, GstClockTime timestamp, GValue *value) \
{ \
const GValue *ret; \
GSequenceIter *iter; \
\
g_mutex_lock (self->lock); \
\
- iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
+ iter = gst_timed_value_control_source_find_control_point_iter (self, timestamp); \
ret = get_func (self, iter); \
g_value_copy (ret, value); \
g_mutex_unlock (self->lock); \
@@ -134,7 +89,7 @@ interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime t
} \
\
static gboolean \
-interpolate_none_get_##type##_value_array (GstInterpolationControlSource *self, \
+interpolate_none_get_##type##_value_array (GstTimedValueControlSource *self, \
GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
{ \
guint i; \
@@ -148,10 +103,10 @@ interpolate_none_get_##type##_value_array (GstInterpolationControlSource *self,
g_mutex_lock (self->lock); \
for(i = 0; i < n_values; i++) { \
if (!ret_val || ts >= next_ts) { \
- iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
+ iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts); \
if (!iter1) { \
- if (G_LIKELY (self->priv->values)) \
- iter2 = g_sequence_get_begin_iter (self->priv->values); \
+ if (G_LIKELY (self->values)) \
+ iter2 = g_sequence_get_begin_iter (self->values); \
else \
iter2 = NULL; \
} else { \
@@ -224,178 +179,6 @@ static GstInterpolateMethod interpolate_none = {
(GstControlSourceGetValueArray) interpolate_none_get_string_value_array
};
-/* returns the default value of the property, except for times with specific values */
-/* needed for one-shot events, such as notes and triggers */
-static inline const GValue *
-_interpolate_trigger_get (GstInterpolationControlSource * self,
- GSequenceIter * iter, GstClockTime timestamp)
-{
- GstControlPoint *cp;
-
- /* check if there is a value at the registered timestamp */
- if (iter) {
- cp = g_sequence_get (iter);
- if (timestamp == cp->timestamp) {
- return &cp->value;
- }
- }
- if (self->priv->nvalues > 0)
- return &self->priv->default_value;
- else
- return NULL;
-}
-
-#define DEFINE_TRIGGER_GET_FUNC_COMPARABLE(type) \
-static inline const GValue * \
-_interpolate_trigger_get_##type (GstInterpolationControlSource *self, GSequenceIter *iter, GstClockTime timestamp) \
-{ \
- GstControlPoint *cp; \
- \
- /* check if there is a value at the registered timestamp */ \
- if (iter) { \
- cp = g_sequence_get (iter); \
- if (timestamp == cp->timestamp) { \
- g##type ret = g_value_get_##type (&cp->value); \
- if (g_value_get_##type (&self->priv->minimum_value) > ret) \
- return &self->priv->minimum_value; \
- else if (g_value_get_##type (&self->priv->maximum_value) < ret) \
- return &self->priv->maximum_value; \
- else \
- return &cp->value; \
- } \
- } \
- \
- if (self->priv->nvalues > 0) \
- return &self->priv->default_value; \
- else \
- return NULL; \
-}
-
-#define DEFINE_TRIGGER_GET(type, ctype, get_func) \
-static gboolean \
-interpolate_trigger_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
-{ \
- const GValue *ret; \
- GSequenceIter *iter; \
- \
- g_mutex_lock (self->lock); \
- \
- iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
- ret = get_func (self, iter, timestamp); \
- if (!ret) { \
- g_mutex_unlock (self->lock); \
- return FALSE; \
- } \
- \
- g_value_copy (ret, value); \
- g_mutex_unlock (self->lock); \
- return TRUE; \
-} \
-\
-static gboolean \
-interpolate_trigger_get_##type##_value_array (GstInterpolationControlSource *self, \
- GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
-{ \
- guint i; \
- GstClockTime ts = timestamp; \
- GstClockTime next_ts = 0; \
- ctype *values = (ctype *) _values; \
- const GValue *ret_val = NULL; \
- ctype ret = 0; \
- GSequenceIter *iter1 = NULL, *iter2 = NULL; \
- gboolean triggered = FALSE; \
- \
- g_mutex_lock (self->lock); \
- for(i = 0; i < n_values; i++) { \
- if (!ret_val || ts >= next_ts) { \
- iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
- if (!iter1) { \
- if (G_LIKELY (self->priv->values)) \
- iter2 = g_sequence_get_begin_iter (self->priv->values); \
- else \
- iter2 = NULL; \
- } else { \
- iter2 = g_sequence_iter_next (iter1); \
- } \
- \
- if (iter2 && !g_sequence_iter_is_end (iter2)) { \
- GstControlPoint *cp; \
- \
- cp = g_sequence_get (iter2); \
- next_ts = cp->timestamp; \
- } else { \
- next_ts = GST_CLOCK_TIME_NONE; \
- } \
- \
- ret_val = get_func (self, iter1, ts); \
- if (!ret_val) { \
- g_mutex_unlock (self->lock); \
- return FALSE; \
- } \
- ret = g_value_get_##type (ret_val); \
- triggered = TRUE; \
- } else if (triggered) { \
- ret_val = get_func (self, iter1, ts); \
- if (!ret_val) { \
- g_mutex_unlock (self->lock); \
- return FALSE; \
- } \
- ret = g_value_get_##type (ret_val); \
- triggered = FALSE; \
- } \
- *values = ret; \
- ts += interval; \
- values++; \
- } \
- g_mutex_unlock (self->lock); \
- return TRUE; \
-}
-
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int);
-DEFINE_TRIGGER_GET (int, gint, _interpolate_trigger_get_int);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint);
-DEFINE_TRIGGER_GET (uint, guint, _interpolate_trigger_get_uint);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (long);
-DEFINE_TRIGGER_GET (long, glong, _interpolate_trigger_get_long);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (ulong);
-DEFINE_TRIGGER_GET (ulong, gulong, _interpolate_trigger_get_ulong);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int64);
-DEFINE_TRIGGER_GET (int64, gint64, _interpolate_trigger_get_int64);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint64);
-DEFINE_TRIGGER_GET (uint64, guint64, _interpolate_trigger_get_uint64);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (float);
-DEFINE_TRIGGER_GET (float, gfloat, _interpolate_trigger_get_float);
-DEFINE_TRIGGER_GET_FUNC_COMPARABLE (double);
-DEFINE_TRIGGER_GET (double, gdouble, _interpolate_trigger_get_double);
-
-DEFINE_TRIGGER_GET (boolean, gboolean, _interpolate_trigger_get);
-DEFINE_TRIGGER_GET (enum, gint, _interpolate_trigger_get);
-DEFINE_TRIGGER_GET (string, const gchar *, _interpolate_trigger_get);
-
-static GstInterpolateMethod interpolate_trigger = {
- (GstControlSourceGetValue) interpolate_trigger_get_int,
- (GstControlSourceGetValueArray) interpolate_trigger_get_int_value_array,
- (GstControlSourceGetValue) interpolate_trigger_get_uint,
- (GstControlSourceGetValueArray) interpolate_trigger_get_uint_value_array,
- (GstControlSourceGetValue) interpolate_trigger_get_long,
- (GstControlSourceGetValueArray) interpolate_trigger_get_long_value_array,
- (GstControlSourceGetValue) interpolate_trigger_get_ulong,
- (GstControlSourceGetValueArray) interpolate_trigger_get_ulong_value_array,
- (GstControlSourceGetValue) interpolate_trigger_get_int64,
- (GstControlSourceGetValueArray) interpolate_trigger_get_int64_value_array,
- (GstControlSourceGetValue) interpolate_trigger_get_uint64,
- (GstControlSourceGetValueArray) interpolate_trigger_get_uint64_value_array,
- (GstControlSourceGetValue) interpolate_trigger_get_float,
- (GstControlSourceGetValueArray) interpolate_trigger_get_float_value_array,
- (GstControlSourceGetValue) interpolate_trigger_get_double,
- (GstControlSourceGetValueArray) interpolate_trigger_get_double_value_array,
- (GstControlSourceGetValue) interpolate_trigger_get_boolean,
- (GstControlSourceGetValueArray) interpolate_trigger_get_boolean_value_array,
- (GstControlSourceGetValue) interpolate_trigger_get_enum,
- (GstControlSourceGetValueArray) interpolate_trigger_get_enum_value_array,
- (GstControlSourceGetValue) interpolate_trigger_get_string,
- (GstControlSourceGetValueArray) interpolate_trigger_get_string_value_array
-};
/* linear interpolation */
/* smoothes inbetween values */
@@ -419,7 +202,7 @@ _interpolate_linear_internal_##vtype (GstClockTime timestamp1, g##vtype value1,
} \
\
static gboolean \
-interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
+interpolate_linear_get_##vtype (GstTimedValueControlSource *self, GstClockTime timestamp, GValue *value) \
{ \
g##vtype ret, min, max; \
GSequenceIter *iter; \
@@ -427,20 +210,20 @@ interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTim
\
g_mutex_lock (self->lock); \
\
- min = g_value_get_##vtype (&self->priv->minimum_value); \
- max = g_value_get_##vtype (&self->priv->maximum_value); \
+ min = g_value_get_##vtype (&self->minimum_value); \
+ max = g_value_get_##vtype (&self->maximum_value); \
\
- iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
+ iter = gst_timed_value_control_source_find_control_point_iter (self, timestamp); \
if (iter) { \
cp1 = g_sequence_get (iter); \
iter = g_sequence_iter_next (iter); \
} else { \
cp.timestamp = G_GUINT64_CONSTANT(0); \
- g_value_init (&cp.value, self->priv->type); \
- g_value_copy (&self->priv->default_value, &cp.value); \
+ g_value_init (&cp.value, self->type); \
+ g_value_copy (&self->default_value, &cp.value); \
cp1 = &cp; \
- if (G_LIKELY (self->priv->values)) \
- iter = g_sequence_get_begin_iter (self->priv->values); \
+ if (G_LIKELY (self->values)) \
+ iter = g_sequence_get_begin_iter (self->values); \
} \
if (iter && !g_sequence_iter_is_end (iter)) \
cp2 = g_sequence_get (iter); \
@@ -454,7 +237,7 @@ interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTim
} \
\
static gboolean \
-interpolate_linear_get_##vtype##_value_array (GstInterpolationControlSource *self, \
+interpolate_linear_get_##vtype##_value_array (GstTimedValueControlSource *self, \
GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
{ \
guint i; \
@@ -468,19 +251,19 @@ interpolate_linear_get_##vtype##_value_array (GstInterpolationControlSource *sel
g_mutex_lock (self->lock); \
\
cp.timestamp = G_GUINT64_CONSTANT(0); \
- g_value_init (&cp.value, self->priv->type); \
- g_value_copy (&self->priv->default_value, &cp.value); \
+ g_value_init (&cp.value, self->type); \
+ g_value_copy (&self->default_value, &cp.value); \
\
- min = g_value_get_##vtype (&self->priv->minimum_value); \
- max = g_value_get_##vtype (&self->priv->maximum_value); \
+ min = g_value_get_##vtype (&self->minimum_value); \
+ max = g_value_get_##vtype (&self->maximum_value); \
\
for(i = 0; i < n_values; i++) { \
if (timestamp >= next_ts) { \
- iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
+ iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts); \
if (!iter1) { \
cp1 = &cp; \
- if (G_LIKELY (self->priv->values)) \
- iter2 = g_sequence_get_begin_iter (self->priv->values); \
+ if (G_LIKELY (self->values)) \
+ iter2 = g_sequence_get_begin_iter (self->values); \
else \
iter2 = NULL; \
} else { \
@@ -560,9 +343,9 @@ static GstInterpolateMethod interpolate_linear = {
#define DEFINE_CUBIC_GET(vtype,round, convert) \
static void \
-_interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
+_interpolate_cubic_update_cache_##vtype (GstTimedValueControlSource *self) \
{ \
- gint i, n = self->priv->nvalues; \
+ gint i, n = self->nvalues; \
gdouble *o = g_new0 (gdouble, n); \
gdouble *p = g_new0 (gdouble, n); \
gdouble *q = g_new0 (gdouble, n); \
@@ -577,7 +360,7 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
g##vtype y_prev, y, y_next; \
\
/* Fill linear system of equations */ \
- iter = g_sequence_get_begin_iter (self->priv->values); \
+ iter = g_sequence_get_begin_iter (self->values); \
cp = g_sequence_get (iter); \
x = cp->timestamp; \
y = g_value_get_##vtype (&cp->value); \
@@ -622,7 +405,7 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
\
/* Save cache next in the GstControlPoint */ \
\
- iter = g_sequence_get_begin_iter (self->priv->values); \
+ iter = g_sequence_get_begin_iter (self->values); \
for (i = 0; i < n; i++) { \
cp = g_sequence_get (iter); \
cp->cache.cubic.h = h[i]; \
@@ -640,11 +423,11 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
} \
\
static inline void \
-_interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstControlPoint *cp1, g##vtype value1, GstControlPoint *cp2, g##vtype value2, GstClockTime timestamp, g##vtype min, g##vtype max, g##vtype *ret) \
+_interpolate_cubic_get_##vtype (GstTimedValueControlSource *self, GstControlPoint *cp1, g##vtype value1, GstControlPoint *cp2, g##vtype value2, GstClockTime timestamp, g##vtype min, g##vtype max, g##vtype *ret) \
{ \
- if (!self->priv->valid_cache) { \
+ if (!self->valid_cache) { \
_interpolate_cubic_update_cache_##vtype (self); \
- self->priv->valid_cache = TRUE; \
+ self->valid_cache = TRUE; \
} \
\
if (cp2) { \
@@ -670,31 +453,31 @@ _interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstControlP
} \
\
static gboolean \
-interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
+interpolate_cubic_get_##vtype (GstTimedValueControlSource *self, GstClockTime timestamp, GValue *value) \
{ \
g##vtype ret, min, max; \
GSequenceIter *iter; \
GstControlPoint *cp1, *cp2 = NULL, cp = {0, }; \
\
- if (self->priv->nvalues <= 2) \
+ if (self->nvalues <= 2) \
return interpolate_linear_get_##vtype (self, timestamp, value); \
\
g_mutex_lock (self->lock); \
\
- min = g_value_get_##vtype (&self->priv->minimum_value); \
- max = g_value_get_##vtype (&self->priv->maximum_value); \
+ min = g_value_get_##vtype (&self->minimum_value); \
+ max = g_value_get_##vtype (&self->maximum_value); \
\
- iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
+ iter = gst_timed_value_control_source_find_control_point_iter (self, timestamp); \
if (iter) { \
cp1 = g_sequence_get (iter); \
iter = g_sequence_iter_next (iter); \
} else { \
cp.timestamp = G_GUINT64_CONSTANT(0); \
- g_value_init (&cp.value, self->priv->type); \
- g_value_copy (&self->priv->default_value, &cp.value); \
+ g_value_init (&cp.value, self->type); \
+ g_value_copy (&self->default_value, &cp.value); \
cp1 = &cp; \
- if (G_LIKELY (self->priv->values)) \
- iter = g_sequence_get_begin_iter (self->priv->values); \
+ if (G_LIKELY (self->values)) \
+ iter = g_sequence_get_begin_iter (self->values); \
} \
if (iter && !g_sequence_iter_is_end (iter)) \
cp2 = g_sequence_get (iter); \
@@ -708,7 +491,7 @@ interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime
} \
\
static gboolean \
-interpolate_cubic_get_##vtype##_value_array (GstInterpolationControlSource *self, \
+interpolate_cubic_get_##vtype##_value_array (GstTimedValueControlSource *self, \
GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
{ \
guint i; \
@@ -719,25 +502,25 @@ interpolate_cubic_get_##vtype##_value_array (GstInterpolationControlSource *self
GstControlPoint *cp1 = NULL, *cp2 = NULL, cp = {0, }; \
g##vtype val1 = 0, val2 = 0, min, max; \
\
- if (self->priv->nvalues <= 2) \
+ if (self->nvalues <= 2) \
return interpolate_linear_get_##vtype##_value_array (self, timestamp, interval, n_values, values); \
\
g_mutex_lock (self->lock); \
\
cp.timestamp = G_GUINT64_CONSTANT(0); \
- g_value_init (&cp.value, self->priv->type); \
- g_value_copy (&self->priv->default_value, &cp.value); \
+ g_value_init (&cp.value, self->type); \
+ g_value_copy (&self->default_value, &cp.value); \
\
- min = g_value_get_##vtype (&self->priv->minimum_value); \
- max = g_value_get_##vtype (&self->priv->maximum_value); \
+ min = g_value_get_##vtype (&self->minimum_value); \
+ max = g_value_get_##vtype (&self->maximum_value); \
\
for(i = 0; i < n_values; i++) { \
if (timestamp >= next_ts) { \
- iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
+ iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts); \
if (!iter1) { \
cp1 = &cp; \
- if (G_LIKELY (self->priv->values)) \
- iter2 = g_sequence_get_begin_iter (self->priv->values); \
+ if (G_LIKELY (self->values)) \
+ iter2 = g_sequence_get_begin_iter (self->values); \
else \
iter2 = NULL; \
} else { \
@@ -801,7 +584,6 @@ static GstInterpolateMethod interpolate_cubic = {
/* register all interpolation methods */
GstInterpolateMethod *priv_gst_interpolation_methods[] = {
&interpolate_none,
- &interpolate_trigger,
&interpolate_linear,
&interpolate_cubic,
&interpolate_cubic
diff --git a/libs/gst/controller/gstinterpolationcontrolsource.c b/libs/gst/controller/gstinterpolationcontrolsource.c
index 4a81cadd2..037bc7528 100644
--- a/libs/gst/controller/gstinterpolationcontrolsource.c
+++ b/libs/gst/controller/gstinterpolationcontrolsource.c
@@ -31,7 +31,7 @@
* To use #GstInterpolationControlSource get a new instance by calling
* gst_interpolation_control_source_new(), bind it to a #GParamSpec, select a interpolation mode with
* gst_interpolation_control_source_set_interpolation_mode() and set some control points by calling
- * gst_interpolation_control_source_set().
+ * gst_timed_value_control_source_set().
*
* All functions are MT-safe.
*
@@ -48,54 +48,17 @@
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define _do_init \
- GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "interpolation control source", 0, "timeline value interpolating control source")
+ GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "interpolation control source", 0, \
+ "timeline value interpolating control source")
G_DEFINE_TYPE_WITH_CODE (GstInterpolationControlSource,
- gst_interpolation_control_source, GST_TYPE_CONTROL_SOURCE, _do_init);
+ gst_interpolation_control_source, GST_TYPE_TIMED_VALUE_CONTROL_SOURCE,
+ _do_init);
-static GObjectClass *parent_class = NULL;
-
-/*
- * gst_control_point_free:
- * @prop: the object to free
- *
- * Private method which frees all data allocated by a #GstControlPoint
- * instance.
- */
-static void
-gst_control_point_free (GstControlPoint * cp)
+struct _GstInterpolationControlSourcePrivate
{
- g_return_if_fail (cp);
-
- g_value_unset (&cp->value);
- g_slice_free (GstControlPoint, cp);
-}
-
-static void
-gst_interpolation_control_source_reset (GstInterpolationControlSource * self)
-{
- GstControlSource *csource = (GstControlSource *) self;
-
- csource->get_value = NULL;
- csource->get_value_array = NULL;
-
- self->priv->type = self->priv->base = G_TYPE_INVALID;
-
- if (G_IS_VALUE (&self->priv->default_value))
- g_value_unset (&self->priv->default_value);
- if (G_IS_VALUE (&self->priv->minimum_value))
- g_value_unset (&self->priv->minimum_value);
- if (G_IS_VALUE (&self->priv->maximum_value))
- g_value_unset (&self->priv->maximum_value);
-
- if (self->priv->values) {
- g_sequence_free (self->priv->values);
- self->priv->values = NULL;
- }
-
- self->priv->nvalues = 0;
- self->priv->valid_cache = FALSE;
-}
+ GstInterpolateMode interpolation_mode;
+};
/**
* gst_interpolation_control_source_new:
@@ -142,525 +105,101 @@ gst_interpolation_control_source_set_interpolation_mode (
"interpolation mode");
}
- if (mode == GST_INTERPOLATE_USER) {
- GST_WARNING ("User interpolation mode is not implemented yet");
- return FALSE;
- }
-
- g_mutex_lock (self->lock);
- switch (self->priv->base) {
+ GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (self);
+ switch (gst_timed_value_control_source_get_base_value_type (
+ (GstTimedValueControlSource *) self)) {
case G_TYPE_INT:
csource->get_value = priv_gst_interpolation_methods[mode]->get_int;
csource->get_value_array =
priv_gst_interpolation_methods[mode]->get_int_value_array;
break;
- case G_TYPE_UINT:{
+ case G_TYPE_UINT:
csource->get_value = priv_gst_interpolation_methods[mode]->get_uint;
csource->get_value_array =
priv_gst_interpolation_methods[mode]->get_uint_value_array;
break;
- }
- case G_TYPE_LONG:{
+ case G_TYPE_LONG:
csource->get_value = priv_gst_interpolation_methods[mode]->get_long;
csource->get_value_array =
priv_gst_interpolation_methods[mode]->get_long_value_array;
break;
- }
- case G_TYPE_ULONG:{
+ case G_TYPE_ULONG:
csource->get_value = priv_gst_interpolation_methods[mode]->get_ulong;
csource->get_value_array =
priv_gst_interpolation_methods[mode]->get_ulong_value_array;
break;
- }
- case G_TYPE_INT64:{
+ case G_TYPE_INT64:
csource->get_value = priv_gst_interpolation_methods[mode]->get_int64;
csource->get_value_array =
priv_gst_interpolation_methods[mode]->get_int64_value_array;
break;
- }
- case G_TYPE_UINT64:{
+ case G_TYPE_UINT64:
csource->get_value = priv_gst_interpolation_methods[mode]->get_uint64;
csource->get_value_array =
priv_gst_interpolation_methods[mode]->get_uint64_value_array;
break;
- }
- case G_TYPE_FLOAT:{
+ case G_TYPE_FLOAT:
csource->get_value = priv_gst_interpolation_methods[mode]->get_float;
csource->get_value_array =
priv_gst_interpolation_methods[mode]->get_float_value_array;
break;
- }
- case G_TYPE_DOUBLE:{
+ case G_TYPE_DOUBLE:
csource->get_value = priv_gst_interpolation_methods[mode]->get_double;
csource->get_value_array =
priv_gst_interpolation_methods[mode]->get_double_value_array;
break;
- }
- case G_TYPE_BOOLEAN:{
+ case G_TYPE_BOOLEAN:
csource->get_value = priv_gst_interpolation_methods[mode]->get_boolean;
csource->get_value_array =
priv_gst_interpolation_methods[mode]->get_boolean_value_array;
break;
- }
- case G_TYPE_ENUM:{
+ case G_TYPE_ENUM:
csource->get_value = priv_gst_interpolation_methods[mode]->get_enum;
csource->get_value_array =
priv_gst_interpolation_methods[mode]->get_enum_value_array;
break;
- }
- case G_TYPE_STRING:{
+ case G_TYPE_STRING:
csource->get_value = priv_gst_interpolation_methods[mode]->get_string;
csource->get_value_array =
priv_gst_interpolation_methods[mode]->get_string_value_array;
break;
- }
default:
ret = FALSE;
break;
}
/* Incomplete implementation */
- if (!ret || !csource->get_value || !csource->get_value_array) {
- gst_interpolation_control_source_reset (self);
+ if (!csource->get_value || !csource->get_value_array) {
ret = FALSE;
}
-
- self->priv->valid_cache = FALSE;
+ gst_timed_value_control_invalidate_cache ((GstTimedValueControlSource *)
+ csource);
self->priv->interpolation_mode = mode;
- g_mutex_unlock (self->lock);
+ GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (self);
return ret;
}
static gboolean
-gst_interpolation_control_source_bind (GstControlSource * source,
+gst_interpolation_control_source_bind (GstControlSource * csource,
GParamSpec * pspec)
{
- GType type, base;
- GstInterpolationControlSource *self =
- (GstInterpolationControlSource *) source;
- gboolean ret = TRUE;
-
- /* get the fundamental base type */
- self->priv->type = base = type = G_PARAM_SPEC_VALUE_TYPE (pspec);
- while ((type = g_type_parent (type)))
- base = type;
-
- self->priv->base = base;
- /* restore type */
- type = self->priv->type;
-
- if (!gst_interpolation_control_source_set_interpolation_mode (self,
- self->priv->interpolation_mode))
- return FALSE;
-
- switch (base) {
- case G_TYPE_INT:{
- GParamSpecInt *tpspec = G_PARAM_SPEC_INT (pspec);
-
- g_value_init (&self->priv->default_value, type);
- g_value_set_int (&self->priv->default_value, tpspec->default_value);
- g_value_init (&self->priv->minimum_value, type);
- g_value_set_int (&self->priv->minimum_value, tpspec->minimum);
- g_value_init (&self->priv->maximum_value, type);
- g_value_set_int (&self->priv->maximum_value, tpspec->maximum);
- break;
- }
- case G_TYPE_UINT:{
- GParamSpecUInt *tpspec = G_PARAM_SPEC_UINT (pspec);
-
- g_value_init (&self->priv->default_value, type);
- g_value_set_uint (&self->priv->default_value, tpspec->default_value);
- g_value_init (&self->priv->minimum_value, type);
- g_value_set_uint (&self->priv->minimum_value, tpspec->minimum);
- g_value_init (&self->priv->maximum_value, type);
- g_value_set_uint (&self->priv->maximum_value, tpspec->maximum);
- break;
- }
- case G_TYPE_LONG:{
- GParamSpecLong *tpspec = G_PARAM_SPEC_LONG (pspec);
-
- g_value_init (&self->priv->default_value, type);
- g_value_set_long (&self->priv->default_value, tpspec->default_value);
- g_value_init (&self->priv->minimum_value, type);
- g_value_set_long (&self->priv->minimum_value, tpspec->minimum);
- g_value_init (&self->priv->maximum_value, type);
- g_value_set_long (&self->priv->maximum_value, tpspec->maximum);
- break;
- }
- case G_TYPE_ULONG:{
- GParamSpecULong *tpspec = G_PARAM_SPEC_ULONG (pspec);
-
- g_value_init (&self->priv->default_value, type);
- g_value_set_ulong (&self->priv->default_value, tpspec->default_value);
- g_value_init (&self->priv->minimum_value, type);
- g_value_set_ulong (&self->priv->minimum_value, tpspec->minimum);
- g_value_init (&self->priv->maximum_value, type);
- g_value_set_ulong (&self->priv->maximum_value, tpspec->maximum);
- break;
- }
- case G_TYPE_INT64:{
- GParamSpecInt64 *tpspec = G_PARAM_SPEC_INT64 (pspec);
-
- g_value_init (&self->priv->default_value, type);
- g_value_set_int64 (&self->priv->default_value, tpspec->default_value);
- g_value_init (&self->priv->minimum_value, type);
- g_value_set_int64 (&self->priv->minimum_value, tpspec->minimum);
- g_value_init (&self->priv->maximum_value, type);
- g_value_set_int64 (&self->priv->maximum_value, tpspec->maximum);
- break;
- }
- case G_TYPE_UINT64:{
- GParamSpecUInt64 *tpspec = G_PARAM_SPEC_UINT64 (pspec);
-
- g_value_init (&self->priv->default_value, type);
- g_value_set_uint64 (&self->priv->default_value, tpspec->default_value);
- g_value_init (&self->priv->minimum_value, type);
- g_value_set_uint64 (&self->priv->minimum_value, tpspec->minimum);
- g_value_init (&self->priv->maximum_value, type);
- g_value_set_uint64 (&self->priv->maximum_value, tpspec->maximum);
- break;
- }
- case G_TYPE_FLOAT:{
- GParamSpecFloat *tpspec = G_PARAM_SPEC_FLOAT (pspec);
-
- g_value_init (&self->priv->default_value, type);
- g_value_set_float (&self->priv->default_value, tpspec->default_value);
- g_value_init (&self->priv->minimum_value, type);
- g_value_set_float (&self->priv->minimum_value, tpspec->minimum);
- g_value_init (&self->priv->maximum_value, type);
- g_value_set_float (&self->priv->maximum_value, tpspec->maximum);
- break;
- }
- case G_TYPE_DOUBLE:{
- GParamSpecDouble *tpspec = G_PARAM_SPEC_DOUBLE (pspec);
-
- g_value_init (&self->priv->default_value, type);
- g_value_set_double (&self->priv->default_value, tpspec->default_value);
- g_value_init (&self->priv->minimum_value, type);
- g_value_set_double (&self->priv->minimum_value, tpspec->minimum);
- g_value_init (&self->priv->maximum_value, type);
- g_value_set_double (&self->priv->maximum_value, tpspec->maximum);
- break;
- }
- case G_TYPE_BOOLEAN:{
- GParamSpecBoolean *tpspec = G_PARAM_SPEC_BOOLEAN (pspec);
-
- g_value_init (&self->priv->default_value, type);
- g_value_set_boolean (&self->priv->default_value, tpspec->default_value);
- break;
- }
- case G_TYPE_ENUM:{
- GParamSpecEnum *tpspec = G_PARAM_SPEC_ENUM (pspec);
-
- g_value_init (&self->priv->default_value, type);
- g_value_set_enum (&self->priv->default_value, tpspec->default_value);
- break;
- }
- case G_TYPE_STRING:{
- GParamSpecString *tpspec = G_PARAM_SPEC_STRING (pspec);
-
- g_value_init (&self->priv->default_value, type);
- g_value_set_string (&self->priv->default_value, tpspec->default_value);
- break;
- }
- default:
- GST_WARNING ("incomplete implementation for paramspec type '%s'",
- G_PARAM_SPEC_TYPE_NAME (pspec));
- ret = FALSE;
- break;
- }
-
- if (ret) {
- self->priv->valid_cache = FALSE;
- self->priv->nvalues = 0;
- } else {
- gst_interpolation_control_source_reset (self);
- }
-
- return ret;
-}
-
-/*
- * gst_control_point_compare:
- * @p1: a pointer to a #GstControlPoint
- * @p2: a pointer to a #GstControlPoint
- *
- * Compare function for g_list operations that operates on two #GstControlPoint
- * parameters.
- */
-static gint
-gst_control_point_compare (gconstpointer p1, gconstpointer p2)
-{
- GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
- GstClockTime ct2 = ((GstControlPoint *) p2)->timestamp;
-
- return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
-}
-
-/*
- * gst_control_point_find:
- * @p1: a pointer to a #GstControlPoint
- * @p2: a pointer to a #GstClockTime
- *
- * Compare function for g_list operations that operates on a #GstControlPoint and
- * a #GstClockTime.
- */
-static gint
-gst_control_point_find (gconstpointer p1, gconstpointer p2)
-{
- GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
- GstClockTime ct2 = *(GstClockTime *) p2;
-
- return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
-}
-
-static GstControlPoint *
-_make_new_cp (GstInterpolationControlSource * self, GstClockTime timestamp,
- const GValue * value)
-{
- GstControlPoint *cp;
-
- /* create a new GstControlPoint */
- cp = g_slice_new0 (GstControlPoint);
- cp->timestamp = timestamp;
- g_value_init (&cp->value, self->priv->type);
- g_value_copy (value, &cp->value);
-
- return cp;
-}
-
-static void
-gst_interpolation_control_source_set_internal (GstInterpolationControlSource *
- self, GstClockTime timestamp, const GValue * value)
-{
- GSequenceIter *iter;
-
- /* check if a control point for the timestamp already exists */
-
- /* iter contains the iter right *after* timestamp */
- if (G_LIKELY (self->priv->values)) {
- iter =
- g_sequence_search (self->priv->values, &timestamp,
- (GCompareDataFunc) gst_control_point_find, NULL);
- if (iter) {
- GSequenceIter *prev = g_sequence_iter_prev (iter);
- GstControlPoint *cp = g_sequence_get (prev);
-
- /* If the timestamp is the same just update the control point value */
- if (cp->timestamp == timestamp) {
- /* update control point */
- g_value_reset (&cp->value);
- g_value_copy (value, &cp->value);
- goto done;
- }
- }
- } else {
- self->priv->values =
- g_sequence_new ((GDestroyNotify) gst_control_point_free);
- }
-
- /* sort new cp into the prop->values list */
- g_sequence_insert_sorted (self->priv->values, _make_new_cp (self, timestamp,
- value), (GCompareDataFunc) gst_control_point_compare, NULL);
- self->priv->nvalues++;
-
-done:
- self->priv->valid_cache = FALSE;
-}
-
-
-/**
- * gst_interpolation_control_source_set:
- * @self: the #GstInterpolationControlSource object
- * @timestamp: the time the control-change is scheduled for
- * @value: the control-value
- *
- * Set the value of given controller-handled property at a certain time.
- *
- * Returns: FALSE if the values couldn't be set, TRUE otherwise.
- */
-gboolean
-gst_interpolation_control_source_set (GstInterpolationControlSource * self,
- GstClockTime timestamp, const GValue * value)
-{
- g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
- g_return_val_if_fail (G_IS_VALUE (value), FALSE);
- g_return_val_if_fail (G_VALUE_TYPE (value) == self->priv->type, FALSE);
-
- g_mutex_lock (self->lock);
- gst_interpolation_control_source_set_internal (self, timestamp, value);
- g_mutex_unlock (self->lock);
+ if (GST_CONTROL_SOURCE_CLASS
+ (gst_interpolation_control_source_parent_class)->bind (csource, pspec)) {
+ GstInterpolationControlSource *self =
+ GST_INTERPOLATION_CONTROL_SOURCE (csource);
- return TRUE;
-}
-
-/**
- * gst_interpolation_control_source_set_from_list:
- * @self: the #GstInterpolationControlSource object
- * @timedvalues: (transfer none) (element-type GstController.TimedValue): a list
- * with #GstTimedValue items
- *
- * Sets multiple timed values at once.
- *
- * Returns: FALSE if the values couldn't be set, TRUE otherwise.
- */
-gboolean
-gst_interpolation_control_source_set_from_list (GstInterpolationControlSource *
- self, const GSList * timedvalues)
-{
- const GSList *node;
- GstTimedValue *tv;
- gboolean res = FALSE;
-
- g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
-
- for (node = timedvalues; node; node = g_slist_next (node)) {
- tv = node->data;
- if (!GST_CLOCK_TIME_IS_VALID (tv->timestamp)) {
- GST_WARNING ("GstTimedValued with invalid timestamp passed to %s",
- GST_FUNCTION);
- } else if (!G_IS_VALUE (&tv->value)) {
- GST_WARNING ("GstTimedValued with invalid value passed to %s",
- GST_FUNCTION);
- } else if (G_VALUE_TYPE (&tv->value) != self->priv->type) {
- GST_WARNING ("incompatible value type for property");
- } else {
- g_mutex_lock (self->lock);
- gst_interpolation_control_source_set_internal (self, tv->timestamp,
- &tv->value);
- g_mutex_unlock (self->lock);
- res = TRUE;
- }
- }
- return res;
-}
-
-/**
- * gst_interpolation_control_source_unset:
- * @self: the #GstInterpolationControlSource object
- * @timestamp: the time the control-change should be removed from
- *
- * Used to remove the value of given controller-handled property at a certain
- * time.
- *
- * Returns: FALSE if the value couldn't be unset (i.e. not found, TRUE otherwise.
- */
-gboolean
-gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
- GstClockTime timestamp)
-{
- GSequenceIter *iter;
- gboolean res = FALSE;
-
- g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
- g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
-
- g_mutex_lock (self->lock);
- /* check if a control point for the timestamp exists */
- if (G_LIKELY (self->priv->values) && (iter =
- g_sequence_search (self->priv->values, &timestamp,
- (GCompareDataFunc) gst_control_point_find, NULL))) {
- GstControlPoint *cp;
-
- /* Iter contains the iter right after timestamp, i.e.
- * we need to get the previous one and check the timestamp
- */
- iter = g_sequence_iter_prev (iter);
- cp = g_sequence_get (iter);
- if (cp->timestamp == timestamp) {
- g_sequence_remove (iter);
- self->priv->nvalues--;
- self->priv->valid_cache = FALSE;
- res = TRUE;
- }
+ if (gst_interpolation_control_source_set_interpolation_mode (self,
+ self->priv->interpolation_mode))
+ return TRUE;
}
- g_mutex_unlock (self->lock);
-
- return res;
+ return FALSE;
}
-/**
- * gst_interpolation_control_source_unset_all:
- * @self: the #GstInterpolationControlSource object
- *
- * Used to remove all time-stamped values of given controller-handled property
- *
- */
-void
-gst_interpolation_control_source_unset_all (GstInterpolationControlSource *
- self)
-{
- g_return_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self));
-
- g_mutex_lock (self->lock);
- /* free GstControlPoint structures */
- if (self->priv->values) {
- g_sequence_free (self->priv->values);
- self->priv->values = NULL;
- }
- self->priv->nvalues = 0;
- self->priv->valid_cache = FALSE;
-
- g_mutex_unlock (self->lock);
-}
-
-static void
-_append_control_point (GstControlPoint * cp, GQueue * res)
-{
- g_queue_push_tail (res, cp);
-}
-
-/**
- * gst_interpolation_control_source_get_all:
- * @self: the #GstInterpolationControlSource to get the list from
- *
- * Returns a read-only copy of the list of #GstTimedValue for the given property.
- * Free the list after done with it.
- *
- * Returns: (transfer container) (element-type GstController.TimedValue): a copy
- * of the list, or %NULL if the property isn't handled by the controller
- */
-GList *
-gst_interpolation_control_source_get_all (GstInterpolationControlSource * self)
-{
- GQueue res = G_QUEUE_INIT;
-
- g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), NULL);
-
- g_mutex_lock (self->lock);
- if (G_LIKELY (self->priv->values))
- g_sequence_foreach (self->priv->values, (GFunc) _append_control_point,
- &res);
- g_mutex_unlock (self->lock);
-
- return res.head;
-}
-
-/**
- * gst_interpolation_control_source_get_count:
- * @self: the #GstInterpolationControlSource to get the number of values from
- *
- * Returns the number of control points that are set.
- *
- * Returns: the number of control points that are set.
- *
- */
-gint
-gst_interpolation_control_source_get_count (GstInterpolationControlSource *
- self)
-{
- g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), 0);
- return self->priv->nvalues;
-}
-
-
static void
gst_interpolation_control_source_init (GstInterpolationControlSource * self)
{
- self->lock = g_mutex_new ();
self->priv =
G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_INTERPOLATION_CONTROL_SOURCE,
GstInterpolationControlSourcePrivate);
@@ -668,35 +207,13 @@ gst_interpolation_control_source_init (GstInterpolationControlSource * self)
}
static void
-gst_interpolation_control_source_finalize (GObject * obj)
-{
- GstInterpolationControlSource *self = GST_INTERPOLATION_CONTROL_SOURCE (obj);
-
- g_mutex_lock (self->lock);
- gst_interpolation_control_source_reset (self);
- g_mutex_unlock (self->lock);
- g_mutex_free (self->lock);
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-static void
-gst_interpolation_control_source_dispose (GObject * obj)
-{
- G_OBJECT_CLASS (parent_class)->dispose (obj);
-}
-
-static void
gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass
* klass)
{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
- parent_class = g_type_class_peek_parent (klass);
g_type_class_add_private (klass,
sizeof (GstInterpolationControlSourcePrivate));
- gobject_class->finalize = gst_interpolation_control_source_finalize;
- gobject_class->dispose = gst_interpolation_control_source_dispose;
csource_class->bind = gst_interpolation_control_source_bind;
}
diff --git a/libs/gst/controller/gstinterpolationcontrolsource.h b/libs/gst/controller/gstinterpolationcontrolsource.h
index 82cd479b9..7b810cfef 100644
--- a/libs/gst/controller/gstinterpolationcontrolsource.h
+++ b/libs/gst/controller/gstinterpolationcontrolsource.h
@@ -27,7 +27,7 @@
#include <glib-object.h>
#include <gst/gst.h>
-#include <gst/gstcontrolsource.h>
+#include <gst/controller/gsttimedvaluecontrolsource.h>
G_BEGIN_DECLS
@@ -51,23 +51,18 @@ typedef struct _GstInterpolationControlSourcePrivate GstInterpolationControlSour
/**
* GstInterpolateMode:
* @GST_INTERPOLATE_NONE: steps-like interpolation, default
- * @GST_INTERPOLATE_TRIGGER: returns the default value of the property,
- * except for times with specific values
* @GST_INTERPOLATE_LINEAR: linear interpolation
* @GST_INTERPOLATE_QUADRATIC: square interpolation (deprecated, maps to cubic)
* @GST_INTERPOLATE_CUBIC: cubic interpolation
- * @GST_INTERPOLATE_USER: user-provided interpolation (not yet available)
*
* The various interpolation modes available.
*/
typedef enum
{
GST_INTERPOLATE_NONE,
- GST_INTERPOLATE_TRIGGER,
GST_INTERPOLATE_LINEAR,
GST_INTERPOLATE_QUADRATIC,
- GST_INTERPOLATE_CUBIC,
- GST_INTERPOLATE_USER
+ GST_INTERPOLATE_CUBIC
} GstInterpolateMode;
/**
@@ -76,17 +71,15 @@ typedef enum
* The instance structure of #GstControlSource.
*/
struct _GstInterpolationControlSource {
- GstControlSource parent;
+ GstTimedValueControlSource parent;
- /* <private> */
- GMutex *lock;
+ /*< private >*/
GstInterpolationControlSourcePrivate *priv;
-
gpointer _gst_reserved[GST_PADDING];
};
struct _GstInterpolationControlSourceClass {
- GstControlSourceClass parent_class;
+ GstTimedValueControlSourceClass parent_class;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
@@ -101,16 +94,6 @@ GstInterpolationControlSource *
gboolean gst_interpolation_control_source_set_interpolation_mode
(GstInterpolationControlSource *self,
GstInterpolateMode mode);
-gboolean gst_interpolation_control_source_set (GstInterpolationControlSource * self,
- GstClockTime timestamp,
- const GValue * value);
-gboolean gst_interpolation_control_source_set_from_list (GstInterpolationControlSource * self,
- const GSList * timedvalues);
-gboolean gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
- GstClockTime timestamp);
-void gst_interpolation_control_source_unset_all (GstInterpolationControlSource *self);
-GList * gst_interpolation_control_source_get_all (GstInterpolationControlSource * self);
-gint gst_interpolation_control_source_get_count (GstInterpolationControlSource * self);
G_END_DECLS
diff --git a/libs/gst/controller/gstinterpolationcontrolsourceprivate.h b/libs/gst/controller/gstinterpolationcontrolsourceprivate.h
index 516effda1..5447121f1 100644
--- a/libs/gst/controller/gstinterpolationcontrolsourceprivate.h
+++ b/libs/gst/controller/gstinterpolationcontrolsourceprivate.h
@@ -80,21 +80,6 @@ typedef struct _GstControlPoint
} GstControlPoint;
-struct _GstInterpolationControlSourcePrivate
-{
- GType type; /* type of the handled property */
- GType base; /* base-type of the handled property */
-
- GValue default_value; /* default value for the handled property */
- GValue minimum_value; /* min value for the handled property */
- GValue maximum_value; /* max value for the handled property */
- GstInterpolateMode interpolation_mode;
-
- GSequence *values; /* List of GstControlPoint */
- gint nvalues; /* Number of control points */
- gboolean valid_cache;
-};
-
extern GstInterpolateMethod *priv_gst_interpolation_methods[];
extern guint priv_gst_num_interpolation_methods;
diff --git a/libs/gst/controller/gsttimedvaluecontrolsource.c b/libs/gst/controller/gsttimedvaluecontrolsource.c
new file mode 100644
index 000000000..46fc61a52
--- /dev/null
+++ b/libs/gst/controller/gsttimedvaluecontrolsource.c
@@ -0,0 +1,603 @@
+/* GStreamer
+ *
+ * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * 2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gsttimedvaluecontrolsource.c: Base class for timeed value based control
+ * sources
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gsttimedvaluecontrolsource
+ * @short_description: timed value control source base class
+ *
+ * Base class for #GstContrlSources that use time-stamped values.
+ *
+ * When overriding bind, chain up first to give this bind implementation a
+ * chance to setup things.
+ *
+ * All functions are MT-safe.
+ *
+ */
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include "gstinterpolationcontrolsource.h"
+#include "gstinterpolationcontrolsourceprivate.h"
+#include "gst/glib-compat-private.h"
+
+#define GST_CAT_DEFAULT controller_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+#define _do_init \
+ GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "timed value control source", 0, \
+ "timed value control source base class")
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstTimedValueControlSource,
+ gst_timed_value_control_source, GST_TYPE_CONTROL_SOURCE, _do_init);
+
+/*
+ * gst_control_point_free:
+ * @prop: the object to free
+ *
+ * Private method which frees all data allocated by a #GstControlPoint
+ * instance.
+ */
+static void
+gst_control_point_free (GstControlPoint * cp)
+{
+ g_return_if_fail (cp);
+
+ g_value_unset (&cp->value);
+ g_slice_free (GstControlPoint, cp);
+}
+
+static void
+gst_timed_value_control_source_reset (GstTimedValueControlSource * self)
+{
+ GstControlSource *csource = (GstControlSource *) self;
+
+ csource->get_value = NULL;
+ csource->get_value_array = NULL;
+
+ self->type = self->base = G_TYPE_INVALID;
+
+ if (G_IS_VALUE (&self->default_value))
+ g_value_unset (&self->default_value);
+ if (G_IS_VALUE (&self->minimum_value))
+ g_value_unset (&self->minimum_value);
+ if (G_IS_VALUE (&self->maximum_value))
+ g_value_unset (&self->maximum_value);
+
+ if (self->values) {
+ g_sequence_free (self->values);
+ self->values = NULL;
+ }
+
+ self->nvalues = 0;
+ self->valid_cache = FALSE;
+}
+
+static gboolean
+gst_timed_value_control_source_bind (GstControlSource * source,
+ GParamSpec * pspec)
+{
+ GType type, base;
+ GstTimedValueControlSource *self = (GstTimedValueControlSource *) source;
+ gboolean ret = TRUE;
+
+ /* get the fundamental base type */
+ self->type = base = type = G_PARAM_SPEC_VALUE_TYPE (pspec);
+ while ((type = g_type_parent (type)))
+ base = type;
+
+ self->base = base;
+ /* restore type */
+ type = self->type;
+
+ switch (base) {
+ case G_TYPE_INT:{
+ GParamSpecInt *tpspec = G_PARAM_SPEC_INT (pspec);
+
+ g_value_init (&self->default_value, type);
+ g_value_set_int (&self->default_value, tpspec->default_value);
+ g_value_init (&self->minimum_value, type);
+ g_value_set_int (&self->minimum_value, tpspec->minimum);
+ g_value_init (&self->maximum_value, type);
+ g_value_set_int (&self->maximum_value, tpspec->maximum);
+ break;
+ }
+ case G_TYPE_UINT:{
+ GParamSpecUInt *tpspec = G_PARAM_SPEC_UINT (pspec);
+
+ g_value_init (&self->default_value, type);
+ g_value_set_uint (&self->default_value, tpspec->default_value);
+ g_value_init (&self->minimum_value, type);
+ g_value_set_uint (&self->minimum_value, tpspec->minimum);
+ g_value_init (&self->maximum_value, type);
+ g_value_set_uint (&self->maximum_value, tpspec->maximum);
+ break;
+ }
+ case G_TYPE_LONG:{
+ GParamSpecLong *tpspec = G_PARAM_SPEC_LONG (pspec);
+
+ g_value_init (&self->default_value, type);
+ g_value_set_long (&self->default_value, tpspec->default_value);
+ g_value_init (&self->minimum_value, type);
+ g_value_set_long (&self->minimum_value, tpspec->minimum);
+ g_value_init (&self->maximum_value, type);
+ g_value_set_long (&self->maximum_value, tpspec->maximum);
+ break;
+ }
+ case G_TYPE_ULONG:{
+ GParamSpecULong *tpspec = G_PARAM_SPEC_ULONG (pspec);
+
+ g_value_init (&self->default_value, type);
+ g_value_set_ulong (&self->default_value, tpspec->default_value);
+ g_value_init (&self->minimum_value, type);
+ g_value_set_ulong (&self->minimum_value, tpspec->minimum);
+ g_value_init (&self->maximum_value, type);
+ g_value_set_ulong (&self->maximum_value, tpspec->maximum);
+ break;
+ }
+ case G_TYPE_INT64:{
+ GParamSpecInt64 *tpspec = G_PARAM_SPEC_INT64 (pspec);
+
+ g_value_init (&self->default_value, type);
+ g_value_set_int64 (&self->default_value, tpspec->default_value);
+ g_value_init (&self->minimum_value, type);
+ g_value_set_int64 (&self->minimum_value, tpspec->minimum);
+ g_value_init (&self->maximum_value, type);
+ g_value_set_int64 (&self->maximum_value, tpspec->maximum);
+ break;
+ }
+ case G_TYPE_UINT64:{
+ GParamSpecUInt64 *tpspec = G_PARAM_SPEC_UINT64 (pspec);
+
+ g_value_init (&self->default_value, type);
+ g_value_set_uint64 (&self->default_value, tpspec->default_value);
+ g_value_init (&self->minimum_value, type);
+ g_value_set_uint64 (&self->minimum_value, tpspec->minimum);
+ g_value_init (&self->maximum_value, type);
+ g_value_set_uint64 (&self->maximum_value, tpspec->maximum);
+ break;
+ }
+ case G_TYPE_FLOAT:{
+ GParamSpecFloat *tpspec = G_PARAM_SPEC_FLOAT (pspec);
+
+ g_value_init (&self->default_value, type);
+ g_value_set_float (&self->default_value, tpspec->default_value);
+ g_value_init (&self->minimum_value, type);
+ g_value_set_float (&self->minimum_value, tpspec->minimum);
+ g_value_init (&self->maximum_value, type);
+ g_value_set_float (&self->maximum_value, tpspec->maximum);
+ break;
+ }
+ case G_TYPE_DOUBLE:{
+ GParamSpecDouble *tpspec = G_PARAM_SPEC_DOUBLE (pspec);
+
+ g_value_init (&self->default_value, type);
+ g_value_set_double (&self->default_value, tpspec->default_value);
+ g_value_init (&self->minimum_value, type);
+ g_value_set_double (&self->minimum_value, tpspec->minimum);
+ g_value_init (&self->maximum_value, type);
+ g_value_set_double (&self->maximum_value, tpspec->maximum);
+ break;
+ }
+ case G_TYPE_BOOLEAN:{
+ GParamSpecBoolean *tpspec = G_PARAM_SPEC_BOOLEAN (pspec);
+
+ g_value_init (&self->default_value, type);
+ g_value_set_boolean (&self->default_value, tpspec->default_value);
+ break;
+ }
+ case G_TYPE_ENUM:{
+ GParamSpecEnum *tpspec = G_PARAM_SPEC_ENUM (pspec);
+
+ g_value_init (&self->default_value, type);
+ g_value_set_enum (&self->default_value, tpspec->default_value);
+ break;
+ }
+ case G_TYPE_STRING:{
+ GParamSpecString *tpspec = G_PARAM_SPEC_STRING (pspec);
+
+ g_value_init (&self->default_value, type);
+ g_value_set_string (&self->default_value, tpspec->default_value);
+ break;
+ }
+ default:
+ GST_WARNING ("incomplete implementation for paramspec type '%s'",
+ G_PARAM_SPEC_TYPE_NAME (pspec));
+ ret = FALSE;
+ break;
+ }
+
+ if (ret) {
+ self->valid_cache = FALSE;
+ self->nvalues = 0;
+ } else {
+ gst_timed_value_control_source_reset (self);
+ }
+
+ return ret;
+}
+
+/*
+ * gst_control_point_compare:
+ * @p1: a pointer to a #GstControlPoint
+ * @p2: a pointer to a #GstControlPoint
+ *
+ * Compare function for g_list operations that operates on two #GstControlPoint
+ * parameters.
+ */
+static gint
+gst_control_point_compare (gconstpointer p1, gconstpointer p2)
+{
+ GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
+ GstClockTime ct2 = ((GstControlPoint *) p2)->timestamp;
+
+ return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
+}
+
+/*
+ * gst_control_point_find:
+ * @p1: a pointer to a #GstControlPoint
+ * @p2: a pointer to a #GstClockTime
+ *
+ * Compare function for g_list operations that operates on a #GstControlPoint and
+ * a #GstClockTime.
+ */
+static gint
+gst_control_point_find (gconstpointer p1, gconstpointer p2)
+{
+ GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
+ GstClockTime ct2 = *(GstClockTime *) p2;
+
+ return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
+}
+
+static GstControlPoint *
+_make_new_cp (GstTimedValueControlSource * self, GstClockTime timestamp,
+ const GValue * value)
+{
+ GstControlPoint *cp;
+
+ /* create a new GstControlPoint */
+ cp = g_slice_new0 (GstControlPoint);
+ cp->timestamp = timestamp;
+ g_value_init (&cp->value, self->type);
+ g_value_copy (value, &cp->value);
+
+ return cp;
+}
+
+static void
+gst_timed_value_control_source_set_internal (GstTimedValueControlSource *
+ self, GstClockTime timestamp, const GValue * value)
+{
+ GSequenceIter *iter;
+
+ /* check if a control point for the timestamp already exists */
+
+ /* iter contains the iter right *after* timestamp */
+ if (G_LIKELY (self->values)) {
+ iter =
+ g_sequence_search (self->values, &timestamp,
+ (GCompareDataFunc) gst_control_point_find, NULL);
+ if (iter) {
+ GSequenceIter *prev = g_sequence_iter_prev (iter);
+ GstControlPoint *cp = g_sequence_get (prev);
+
+ /* If the timestamp is the same just update the control point value */
+ if (cp->timestamp == timestamp) {
+ /* update control point */
+ g_value_reset (&cp->value);
+ g_value_copy (value, &cp->value);
+ goto done;
+ }
+ }
+ } else {
+ self->values = g_sequence_new ((GDestroyNotify) gst_control_point_free);
+ }
+
+ /* sort new cp into the prop->values list */
+ g_sequence_insert_sorted (self->values, _make_new_cp (self, timestamp,
+ value), (GCompareDataFunc) gst_control_point_compare, NULL);
+ self->nvalues++;
+
+done:
+ self->valid_cache = FALSE;
+}
+
+/**
+ * gst_timed_value_control_source_find_control_point_iter:
+ * @self: the control source to search in
+ * @timestamp: the search key
+ *
+ * Find last value before given timestamp in control point list.
+ * If all values in the control point list come after the given
+ * timestamp or no values exist, %NULL is returned.
+ *
+ * For use in control source implementations.
+ *
+ * Returns: the found #GSequenceIter or %NULL
+ */
+GSequenceIter *gst_timed_value_control_source_find_control_point_iter
+ (GstTimedValueControlSource * self, GstClockTime timestamp)
+{
+ GSequenceIter *iter;
+
+ if (!self->values)
+ return NULL;
+
+ iter =
+ g_sequence_search (self->values, &timestamp,
+ (GCompareDataFunc) gst_control_point_find, NULL);
+
+ /* g_sequence_search() returns the iter where timestamp
+ * would be inserted, i.e. the iter > timestamp, so
+ * we need to get the previous one. And of course, if
+ * there is no previous one, we return NULL. */
+ if (g_sequence_iter_is_begin (iter))
+ return NULL;
+
+ return g_sequence_iter_prev (iter);
+}
+
+
+/**
+ * gst_timed_value_control_source_set:
+ * @self: the #GstTimedValueControlSource object
+ * @timestamp: the time the control-change is scheduled for
+ * @value: the control-value
+ *
+ * Set the value of given controller-handled property at a certain time.
+ *
+ * Returns: FALSE if the values couldn't be set, TRUE otherwise.
+ */
+gboolean
+gst_timed_value_control_source_set (GstTimedValueControlSource * self,
+ GstClockTime timestamp, const GValue * value)
+{
+ g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
+ g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+ g_return_val_if_fail (G_IS_VALUE (value), FALSE);
+ g_return_val_if_fail (G_VALUE_TYPE (value) == self->type, FALSE);
+
+ g_mutex_lock (self->lock);
+ gst_timed_value_control_source_set_internal (self, timestamp, value);
+ g_mutex_unlock (self->lock);
+
+ return TRUE;
+}
+
+/**
+ * gst_timed_value_control_source_set_from_list:
+ * @self: the #GstTimedValueControlSource object
+ * @timedvalues: (transfer none) (element-type GstController.TimedValue): a list
+ * with #GstTimedValue items
+ *
+ * Sets multiple timed values at once.
+ *
+ * Returns: FALSE if the values couldn't be set, TRUE otherwise.
+ */
+gboolean
+gst_timed_value_control_source_set_from_list (GstTimedValueControlSource *
+ self, const GSList * timedvalues)
+{
+ const GSList *node;
+ GstTimedValue *tv;
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
+
+ for (node = timedvalues; node; node = g_slist_next (node)) {
+ tv = node->data;
+ if (!GST_CLOCK_TIME_IS_VALID (tv->timestamp)) {
+ GST_WARNING ("GstTimedValued with invalid timestamp passed to %s",
+ GST_FUNCTION);
+ } else if (!G_IS_VALUE (&tv->value)) {
+ GST_WARNING ("GstTimedValued with invalid value passed to %s",
+ GST_FUNCTION);
+ } else if (G_VALUE_TYPE (&tv->value) != self->type) {
+ GST_WARNING ("incompatible value type for property");
+ } else {
+ g_mutex_lock (self->lock);
+ gst_timed_value_control_source_set_internal (self, tv->timestamp,
+ &tv->value);
+ g_mutex_unlock (self->lock);
+ res = TRUE;
+ }
+ }
+ return res;
+}
+
+/**
+ * gst_timed_value_control_source_unset:
+ * @self: the #GstTimedValueControlSource object
+ * @timestamp: the time the control-change should be removed from
+ *
+ * Used to remove the value of given controller-handled property at a certain
+ * time.
+ *
+ * Returns: FALSE if the value couldn't be unset (i.e. not found, TRUE otherwise.
+ */
+gboolean
+gst_timed_value_control_source_unset (GstTimedValueControlSource * self,
+ GstClockTime timestamp)
+{
+ GSequenceIter *iter;
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
+ g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
+
+ g_mutex_lock (self->lock);
+ /* check if a control point for the timestamp exists */
+ if (G_LIKELY (self->values) && (iter =
+ g_sequence_search (self->values, &timestamp,
+ (GCompareDataFunc) gst_control_point_find, NULL))) {
+ GstControlPoint *cp;
+
+ /* Iter contains the iter right after timestamp, i.e.
+ * we need to get the previous one and check the timestamp
+ */
+ iter = g_sequence_iter_prev (iter);
+ cp = g_sequence_get (iter);
+ if (cp->timestamp == timestamp) {
+ g_sequence_remove (iter);
+ self->nvalues--;
+ self->valid_cache = FALSE;
+ res = TRUE;
+ }
+ }
+ g_mutex_unlock (self->lock);
+
+ return res;
+}
+
+/**
+ * gst_timed_value_control_source_unset_all:
+ * @self: the #GstTimedValueControlSource object
+ *
+ * Used to remove all time-stamped values of given controller-handled property
+ *
+ */
+void
+gst_timed_value_control_source_unset_all (GstTimedValueControlSource * self)
+{
+ g_return_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self));
+
+ g_mutex_lock (self->lock);
+ /* free GstControlPoint structures */
+ if (self->values) {
+ g_sequence_free (self->values);
+ self->values = NULL;
+ }
+ self->nvalues = 0;
+ self->valid_cache = FALSE;
+
+ g_mutex_unlock (self->lock);
+}
+
+static void
+_append_control_point (GstControlPoint * cp, GQueue * res)
+{
+ g_queue_push_tail (res, cp);
+}
+
+/**
+ * gst_timed_value_control_source_get_all:
+ * @self: the #GstTimedValueControlSource to get the list from
+ *
+ * Returns a read-only copy of the list of #GstTimedValue for the given property.
+ * Free the list after done with it.
+ *
+ * Returns: (transfer container) (element-type GstController.TimedValue): a copy
+ * of the list, or %NULL if the property isn't handled by the controller
+ */
+GList *
+gst_timed_value_control_source_get_all (GstTimedValueControlSource * self)
+{
+ GQueue res = G_QUEUE_INIT;
+
+ g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), NULL);
+
+ g_mutex_lock (self->lock);
+ if (G_LIKELY (self->values))
+ g_sequence_foreach (self->values, (GFunc) _append_control_point, &res);
+ g_mutex_unlock (self->lock);
+
+ return res.head;
+}
+
+/**
+ * gst_timed_value_control_source_get_count:
+ * @self: the #GstTimedValueControlSource to get the number of values from
+ *
+ * Get the number of control points that are set.
+ *
+ * Returns: the number of control points that are set.
+ */
+gint
+gst_timed_value_control_source_get_count (GstTimedValueControlSource * self)
+{
+ g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), 0);
+ return self->nvalues;
+}
+
+/**
+ * gst_timed_value_control_source_get_base_value_type:
+ * @self: the #GstTimedValueControlSource
+ *
+ * Get the base #GType of the property value.
+ *
+ * Returns: the #GType, %G_TYPE_INVALID if not yet known.
+ */
+GType
+gst_timed_value_control_source_get_base_value_type (GstTimedValueControlSource *
+ self)
+{
+ g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self),
+ G_TYPE_INVALID);
+ return self->base;
+}
+
+/**
+ * gst_timed_value_control_invalidate_cache:
+ * @self: the #GstTimedValueControlSource
+ *
+ * Reset the controlled value cache.
+ */
+void
+gst_timed_value_control_invalidate_cache (GstTimedValueControlSource * self)
+{
+ g_return_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self));
+ self->valid_cache = FALSE;
+}
+
+static void
+gst_timed_value_control_source_init (GstTimedValueControlSource * self)
+{
+ self->lock = g_mutex_new ();
+}
+
+static void
+gst_timed_value_control_source_finalize (GObject * obj)
+{
+ GstTimedValueControlSource *self = GST_TIMED_VALUE_CONTROL_SOURCE (obj);
+
+ g_mutex_lock (self->lock);
+ gst_timed_value_control_source_reset (self);
+ g_mutex_unlock (self->lock);
+ g_mutex_free (self->lock);
+
+ G_OBJECT_CLASS (gst_timed_value_control_source_parent_class)->finalize (obj);
+}
+
+static void
+gst_timed_value_control_source_class_init (GstTimedValueControlSourceClass
+ * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
+
+ gobject_class->finalize = gst_timed_value_control_source_finalize;
+ csource_class->bind = gst_timed_value_control_source_bind;
+}
diff --git a/libs/gst/controller/gsttimedvaluecontrolsource.h b/libs/gst/controller/gsttimedvaluecontrolsource.h
new file mode 100644
index 000000000..b8645e6d1
--- /dev/null
+++ b/libs/gst/controller/gsttimedvaluecontrolsource.h
@@ -0,0 +1,114 @@
+/* GStreamer
+ *
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ * 2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gsttimedvaluecontrolsource.h: Base class for timeed value based control
+ * sources
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_TIMED_VALUE_CONTROL_SOURCE_H__
+#define __GST_TIMED_VALUE_CONTROL_SOURCE_H__
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include <gst/gstcontrolsource.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_TIMED_VALUE_CONTROL_SOURCE \
+ (gst_timed_value_control_source_get_type ())
+#define GST_TIMED_VALUE_CONTROL_SOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSource))
+#define GST_TIMED_VALUE_CONTROL_SOURCE_CLASS(vtable) \
+ (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSourceClass))
+#define GST_IS_TIMED_VALUE_CONTROL_SOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE))
+#define GST_IS_TIMED_VALUE_CONTROL_SOURCE_CLASS(vtable) \
+ (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE))
+#define GST_TIMED_VALUE_CONTROL_SOURCE_GET_CLASS(inst) \
+ (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSourceClass))
+
+typedef struct _GstTimedValueControlSource GstTimedValueControlSource;
+typedef struct _GstTimedValueControlSourceClass GstTimedValueControlSourceClass;
+typedef struct _GstTimedValueControlSourcePrivate GstTimedValueControlSourcePrivate;
+
+/**
+ * GstTimedValueControlSource:
+ *
+ * The instance structure of #GstControlSource.
+ */
+struct _GstTimedValueControlSource {
+ GstControlSource parent;
+
+ /*< protected >*/
+ GMutex *lock;
+
+ GType type; /* type of the handled property */
+ GType base; /* base-type of the handled property */
+
+ GValue default_value; /* default value for the handled property */
+ GValue minimum_value; /* min value for the handled property */
+ GValue maximum_value; /* max value for the handled property */
+
+ GSequence *values; /* List of GstControlPoint */
+ gint nvalues; /* Number of control points */
+ gboolean valid_cache;
+
+ GstTimedValueControlSourcePrivate *priv;
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+struct _GstTimedValueControlSourceClass {
+ GstControlSourceClass parent_class;
+
+ /*< private >*/
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+#define GST_TIMED_VALUE_CONTROL_SOURCE_LOCK(o) \
+ g_mutex_lock(((GstTimedValueControlSource *)o)->lock)
+#define GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK(o) \
+ g_mutex_unlock(((GstTimedValueControlSource *)o)->lock)
+
+GType gst_timed_value_control_source_get_type (void);
+
+/* Functions */
+
+GSequenceIter * gst_timed_value_control_source_find_control_point_iter (
+ GstTimedValueControlSource * self,
+ GstClockTime timestamp);
+
+gboolean gst_timed_value_control_source_set (GstTimedValueControlSource * self,
+ GstClockTime timestamp,
+ const GValue * value);
+gboolean gst_timed_value_control_source_set_from_list (GstTimedValueControlSource * self,
+ const GSList * timedvalues);
+gboolean gst_timed_value_control_source_unset (GstTimedValueControlSource * self,
+ GstClockTime timestamp);
+void gst_timed_value_control_source_unset_all (GstTimedValueControlSource *self);
+GList * gst_timed_value_control_source_get_all (GstTimedValueControlSource * self);
+gint gst_timed_value_control_source_get_count (GstTimedValueControlSource * self);
+GType gst_timed_value_control_source_get_base_value_type (
+ GstTimedValueControlSource * self);
+void gst_timed_value_control_invalidate_cache (GstTimedValueControlSource * self);
+
+G_END_DECLS
+
+#endif /* __GST_TIMED_VALUE_CONTROL_SOURCE_H__ */
diff --git a/libs/gst/controller/gsttriggercontrolsource.c b/libs/gst/controller/gsttriggercontrolsource.c
new file mode 100644
index 000000000..f6ca81519
--- /dev/null
+++ b/libs/gst/controller/gsttriggercontrolsource.c
@@ -0,0 +1,404 @@
+/* GStreamer
+ *
+ * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * 2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gsttriggercontrolsource.c: Control source that provides some values at time-
+ * stamps
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+ /**
+ * SECTION:gsttriggercontrolsource
+ * @short_description: interpolation control source
+ *
+ * #GstTriggerControlSource is a #GstControlSource, that returns values from user-given
+ * control points. It allows for a tolerance on the time-stamps.
+ *
+ * To use #GstTriggerControlSource get a new instance by calling
+ * gst_trigger_control_source_new(), bind it to a #GParamSpec and set some
+ * control points by calling gst_timed_value_control_source_set().
+ *
+ * All functions are MT-safe.
+ */
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include "gsttriggercontrolsource.h"
+#include "gstinterpolationcontrolsourceprivate.h"
+#include "gst/glib-compat-private.h"
+
+#define GST_CAT_DEFAULT controller_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+enum
+{
+ PROP_TOLERANCE = 1,
+};
+
+#define _do_init \
+ GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "trigger control source", 0, \
+ "timeline value trigger control source")
+
+G_DEFINE_TYPE_WITH_CODE (GstTriggerControlSource, gst_trigger_control_source,
+ GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, _do_init);
+
+struct _GstTriggerControlSourcePrivate
+{
+ gint64 tolerance;
+};
+
+/* control point accessors */
+
+/* returns the default value of the property, except for times with specific values */
+/* needed for one-shot events, such as notes and triggers */
+static inline const GValue *
+_interpolate_trigger_get (GstTimedValueControlSource * self,
+ GSequenceIter * iter, GstClockTime timestamp)
+{
+ GstControlPoint *cp;
+
+ /* check if there is a value at the registered timestamp */
+ if (iter) {
+ gint64 tolerance = ((GstTriggerControlSource *) self)->priv->tolerance;
+ cp = g_sequence_get (iter);
+ if (GST_CLOCK_DIFF (cp->timestamp, timestamp) <= tolerance) {
+ return &cp->value;
+ } else {
+ if ((iter = g_sequence_iter_next (iter))) {
+ cp = g_sequence_get (iter);
+ if (GST_CLOCK_DIFF (timestamp, cp->timestamp) <= tolerance) {
+ return &cp->value;
+ }
+ }
+ }
+ }
+ if (self->nvalues > 0)
+ return &self->default_value;
+ else
+ return NULL;
+}
+
+#define DEFINE_TRIGGER_GET_FUNC_COMPARABLE(type) \
+static inline const GValue * \
+_interpolate_trigger_get_##type (GstTimedValueControlSource *self, GSequenceIter *iter, GstClockTime timestamp) \
+{ \
+ GstControlPoint *cp; \
+ \
+ /* check if there is a value at the registered timestamp */ \
+ if (iter) { \
+ gint64 tolerance = ((GstTriggerControlSource *)self)->priv->tolerance; \
+ gboolean found = FALSE; \
+ cp = g_sequence_get (iter); \
+ if (GST_CLOCK_DIFF (cp->timestamp,timestamp) <= tolerance ) { \
+ found = TRUE; \
+ } else { \
+ if ((iter = g_sequence_iter_next (iter))) { \
+ cp = g_sequence_get (iter); \
+ if (GST_CLOCK_DIFF (timestamp, cp->timestamp) <= tolerance) { \
+ found = TRUE; \
+ } \
+ } \
+ } \
+ if (found) { \
+ g##type ret = g_value_get_##type (&cp->value); \
+ if (g_value_get_##type (&self->minimum_value) > ret) \
+ return &self->minimum_value; \
+ else if (g_value_get_##type (&self->maximum_value) < ret) \
+ return &self->maximum_value; \
+ else \
+ return &cp->value; \
+ } \
+ } \
+ \
+ if (self->nvalues > 0) \
+ return &self->default_value; \
+ else \
+ return NULL; \
+}
+
+#define DEFINE_TRIGGER_GET(type, ctype, get_func) \
+static gboolean \
+interpolate_trigger_get_##type (GstTimedValueControlSource *self, GstClockTime timestamp, GValue *value) \
+{ \
+ const GValue *ret; \
+ GSequenceIter *iter; \
+ \
+ g_mutex_lock (self->lock); \
+ \
+ iter = gst_timed_value_control_source_find_control_point_iter (self, timestamp); \
+ ret = get_func (self, iter, timestamp); \
+ if (!ret) { \
+ g_mutex_unlock (self->lock); \
+ return FALSE; \
+ } \
+ \
+ g_value_copy (ret, value); \
+ g_mutex_unlock (self->lock); \
+ return TRUE; \
+} \
+\
+static gboolean \
+interpolate_trigger_get_##type##_value_array (GstTimedValueControlSource *self, \
+ GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
+{ \
+ guint i; \
+ GstClockTime ts = timestamp; \
+ GstClockTime next_ts = 0; \
+ ctype *values = (ctype *) _values; \
+ const GValue *ret_val = NULL; \
+ ctype ret = 0; \
+ GSequenceIter *iter1 = NULL, *iter2 = NULL; \
+ gboolean triggered = FALSE; \
+ \
+ g_mutex_lock (self->lock); \
+ for(i = 0; i < n_values; i++) { \
+ if (!ret_val || ts >= next_ts) { \
+ iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts); \
+ if (!iter1) { \
+ if (G_LIKELY (self->values)) \
+ iter2 = g_sequence_get_begin_iter (self->values); \
+ else \
+ iter2 = NULL; \
+ } else { \
+ iter2 = g_sequence_iter_next (iter1); \
+ } \
+ \
+ if (iter2 && !g_sequence_iter_is_end (iter2)) { \
+ GstControlPoint *cp; \
+ \
+ cp = g_sequence_get (iter2); \
+ next_ts = cp->timestamp; \
+ } else { \
+ next_ts = GST_CLOCK_TIME_NONE; \
+ } \
+ \
+ ret_val = get_func (self, iter1, ts); \
+ if (!ret_val) { \
+ g_mutex_unlock (self->lock); \
+ return FALSE; \
+ } \
+ ret = g_value_get_##type (ret_val); \
+ triggered = TRUE; \
+ } else if (triggered) { \
+ ret_val = get_func (self, iter1, ts); \
+ if (!ret_val) { \
+ g_mutex_unlock (self->lock); \
+ return FALSE; \
+ } \
+ ret = g_value_get_##type (ret_val); \
+ triggered = FALSE; \
+ } \
+ *values = ret; \
+ ts += interval; \
+ values++; \
+ } \
+ g_mutex_unlock (self->lock); \
+ return TRUE; \
+}
+
+DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int);
+DEFINE_TRIGGER_GET (int, gint, _interpolate_trigger_get_int);
+DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint);
+DEFINE_TRIGGER_GET (uint, guint, _interpolate_trigger_get_uint);
+DEFINE_TRIGGER_GET_FUNC_COMPARABLE (long);
+DEFINE_TRIGGER_GET (long, glong, _interpolate_trigger_get_long);
+DEFINE_TRIGGER_GET_FUNC_COMPARABLE (ulong);
+DEFINE_TRIGGER_GET (ulong, gulong, _interpolate_trigger_get_ulong);
+DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int64);
+DEFINE_TRIGGER_GET (int64, gint64, _interpolate_trigger_get_int64);
+DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint64);
+DEFINE_TRIGGER_GET (uint64, guint64, _interpolate_trigger_get_uint64);
+DEFINE_TRIGGER_GET_FUNC_COMPARABLE (float);
+DEFINE_TRIGGER_GET (float, gfloat, _interpolate_trigger_get_float);
+DEFINE_TRIGGER_GET_FUNC_COMPARABLE (double);
+DEFINE_TRIGGER_GET (double, gdouble, _interpolate_trigger_get_double);
+
+DEFINE_TRIGGER_GET (boolean, gboolean, _interpolate_trigger_get);
+DEFINE_TRIGGER_GET (enum, gint, _interpolate_trigger_get);
+DEFINE_TRIGGER_GET (string, const gchar *, _interpolate_trigger_get);
+
+/**
+ * gst_trigger_control_source_new:
+ *
+ * This returns a new, unbound #GstTriggerControlSource.
+ *
+ * Returns: a new, unbound #GstTriggerControlSource.
+ */
+GstTriggerControlSource *
+gst_trigger_control_source_new (void)
+{
+ return g_object_newv (GST_TYPE_TRIGGER_CONTROL_SOURCE, 0, NULL);
+}
+
+static gboolean
+gst_trigger_control_source_bind (GstControlSource * csource, GParamSpec * pspec)
+{
+ if (GST_CONTROL_SOURCE_CLASS
+ (gst_trigger_control_source_parent_class)->bind (csource, pspec)) {
+ gboolean ret = TRUE;
+
+ GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (csource);
+ switch (gst_timed_value_control_source_get_base_value_type (
+ (GstTimedValueControlSource *) csource)) {
+ case G_TYPE_INT:
+ csource->get_value =
+ (GstControlSourceGetValue) interpolate_trigger_get_int;
+ csource->get_value_array = (GstControlSourceGetValueArray)
+ interpolate_trigger_get_int_value_array;
+ break;
+ case G_TYPE_UINT:
+ csource->get_value =
+ (GstControlSourceGetValue) interpolate_trigger_get_uint;
+ csource->get_value_array = (GstControlSourceGetValueArray)
+ interpolate_trigger_get_uint_value_array;
+ break;
+ case G_TYPE_LONG:
+ csource->get_value =
+ (GstControlSourceGetValue) interpolate_trigger_get_long;
+ csource->get_value_array = (GstControlSourceGetValueArray)
+ interpolate_trigger_get_long_value_array;
+ break;
+ case G_TYPE_ULONG:
+ csource->get_value =
+ (GstControlSourceGetValue) interpolate_trigger_get_ulong;
+ csource->get_value_array = (GstControlSourceGetValueArray)
+ interpolate_trigger_get_ulong_value_array;
+ break;
+ case G_TYPE_INT64:
+ csource->get_value =
+ (GstControlSourceGetValue) interpolate_trigger_get_int64;
+ csource->get_value_array = (GstControlSourceGetValueArray)
+ interpolate_trigger_get_int64_value_array;
+ break;
+ case G_TYPE_UINT64:
+ csource->get_value =
+ (GstControlSourceGetValue) interpolate_trigger_get_uint64;
+ csource->get_value_array = (GstControlSourceGetValueArray)
+ interpolate_trigger_get_uint64_value_array;
+ break;
+ case G_TYPE_FLOAT:
+ csource->get_value =
+ (GstControlSourceGetValue) interpolate_trigger_get_float;
+ csource->get_value_array = (GstControlSourceGetValueArray)
+ interpolate_trigger_get_float_value_array;
+ break;
+ case G_TYPE_DOUBLE:
+ csource->get_value =
+ (GstControlSourceGetValue) interpolate_trigger_get_double;
+ csource->get_value_array = (GstControlSourceGetValueArray)
+ interpolate_trigger_get_double_value_array;
+ break;
+ case G_TYPE_BOOLEAN:
+ csource->get_value =
+ (GstControlSourceGetValue) interpolate_trigger_get_boolean;
+ csource->get_value_array = (GstControlSourceGetValueArray)
+ interpolate_trigger_get_boolean_value_array;
+ break;
+ case G_TYPE_ENUM:
+ csource->get_value =
+ (GstControlSourceGetValue) interpolate_trigger_get_enum;
+ csource->get_value_array = (GstControlSourceGetValueArray)
+ interpolate_trigger_get_enum_value_array;
+ break;
+ case G_TYPE_STRING:
+ csource->get_value =
+ (GstControlSourceGetValue) interpolate_trigger_get_string;
+ csource->get_value_array = (GstControlSourceGetValueArray)
+ interpolate_trigger_get_string_value_array;
+ break;
+ default:
+ ret = FALSE;
+ break;
+ }
+
+ /* Incomplete implementation */
+ if (!csource->get_value || !csource->get_value_array) {
+ ret = FALSE;
+ }
+ gst_timed_value_control_invalidate_cache ((GstTimedValueControlSource *)
+ csource);
+
+ GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (csource);
+
+ return ret;
+ }
+ return FALSE;
+}
+
+static void
+gst_trigger_control_source_init (GstTriggerControlSource * self)
+{
+ self->priv =
+ G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_TRIGGER_CONTROL_SOURCE,
+ GstTriggerControlSourcePrivate);
+}
+
+static void
+gst_trigger_control_source_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstTriggerControlSource *self = GST_TRIGGER_CONTROL_SOURCE (object);
+
+ switch (prop_id) {
+ case PROP_TOLERANCE:
+ GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (self);
+ self->priv->tolerance = g_value_get_int64 (value);
+ GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (self);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_trigger_control_source_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstTriggerControlSource *self = GST_TRIGGER_CONTROL_SOURCE (object);
+
+ switch (prop_id) {
+ case PROP_TOLERANCE:
+ g_value_set_int64 (value, self->priv->tolerance);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_trigger_control_source_class_init (GstTriggerControlSourceClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GstTriggerControlSourcePrivate));
+
+ gobject_class->set_property = gst_trigger_control_source_set_property;
+ gobject_class->get_property = gst_trigger_control_source_get_property;
+
+ csource_class->bind = gst_trigger_control_source_bind;
+
+ g_object_class_install_property (gobject_class, PROP_TOLERANCE,
+ g_param_spec_int64 ("tolerance", "Tolerance",
+ "Amount of ns a control time can be off to still trigger",
+ 0, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+}
diff --git a/libs/gst/controller/gsttriggercontrolsource.h b/libs/gst/controller/gsttriggercontrolsource.h
new file mode 100644
index 000000000..f3d993935
--- /dev/null
+++ b/libs/gst/controller/gsttriggercontrolsource.h
@@ -0,0 +1,83 @@
+/* GStreamer
+ *
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ * 2011 Stefan Sauer <ensonic@users.sf.net>
+ *
+ * gsttriggercontrolsource.h: Control source that provides some values at time-
+ * stamps
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_TRIGGER_CONTROL_SOURCE_H__
+#define __GST_TRIGGER_CONTROL_SOURCE_H__
+
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include <gst/controller/gsttimedvaluecontrolsource.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_TRIGGER_CONTROL_SOURCE \
+ (gst_trigger_control_source_get_type ())
+#define GST_TRIGGER_CONTROL_SOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSource))
+#define GST_TRIGGER_CONTROL_SOURCE_CLASS(vtable) \
+ (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSourceClass))
+#define GST_IS_TRIGGER_CONTROL_SOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TRIGGER_CONTROL_SOURCE))
+#define GST_IS_TRIGGER_CONTROL_SOURCE_CLASS(vtable) \
+ (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_TRIGGER_CONTROL_SOURCE))
+#define GST_TRIGGER_CONTROL_SOURCE_GET_CLASS(inst) \
+ (G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSourceClass))
+
+#define GST_TYPE_TRIGGER_WAVEFORM (gst_trigger_waveform_get_type ())
+
+typedef struct _GstTriggerControlSource GstTriggerControlSource;
+typedef struct _GstTriggerControlSourceClass GstTriggerControlSourceClass;
+typedef struct _GstTriggerControlSourcePrivate GstTriggerControlSourcePrivate;
+
+/**
+ * GstTriggerControlSource:
+ *
+ * The instance structure of #GstControlSource.
+ */
+struct _GstTriggerControlSource {
+ GstTimedValueControlSource parent;
+
+ /*< private >*/
+ GstTriggerControlSourcePrivate *priv;
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+struct _GstTriggerControlSourceClass {
+ GstTimedValueControlSourceClass parent_class;
+
+ /*< private >*/
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+GType gst_trigger_control_source_get_type (void);
+
+/* Functions */
+
+GstTriggerControlSource *gst_trigger_control_source_new (void);
+
+G_END_DECLS
+
+#endif /* __GST_TRIGGER_CONTROL_SOURCE_H__ */
diff --git a/tests/benchmarks/controller.c b/tests/benchmarks/controller.c
index ff95e44f1..f196bd92e 100644
--- a/tests/benchmarks/controller.c
+++ b/tests/benchmarks/controller.c
@@ -126,7 +126,8 @@ main (gint argc, gchar * argv[])
for (i = 0; i < NUM_CP; i++) {
g_value_set_double (&freq, g_random_double_range (50.0, 3000.0));
- gst_interpolation_control_source_set (csource, i * tick, &freq);
+ gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource,
+ i * tick, &freq);
}
ct = gst_util_get_timestamp ();
@@ -143,7 +144,8 @@ main (gint argc, gchar * argv[])
for (i = 0; i < 100; i++) {
j = g_random_int_range (0, NUM_CP - 1);
g_value_set_double (&freq, g_random_double_range (50.0, 3000.0));
- gst_interpolation_control_source_set (csource, j * tick, &freq);
+ gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource,
+ j * tick, &freq);
}
ct = gst_util_get_timestamp ();
diff --git a/tests/check/libs/controller.c b/tests/check/libs/controller.c
index f326c04a1..3fc51174b 100644
--- a/tests/check/libs/controller.c
+++ b/tests/check/libs/controller.c
@@ -28,6 +28,7 @@
#include <gst/check/gstcheck.h>
#include <gst/controller/gstinterpolationcontrolsource.h>
#include <gst/controller/gstlfocontrolsource.h>
+#include <gst/controller/gsttriggercontrolsource.h>
/* LOCAL TEST ELEMENT */
@@ -396,6 +397,24 @@ GST_START_TEST (controller_param_twice)
GST_END_TEST;
+/* tests if we can run controller methods against any GObject */
+GST_START_TEST (controller_any_gobject)
+{
+ GstElement *elem;
+ gboolean res;
+
+ elem = gst_element_factory_make ("bin", "test_elem");
+
+ /* that element is not controllable */
+ res = gst_object_sync_values (GST_OBJECT (elem), 0LL);
+ /* Syncing should still succeed as there's nothing to sync */
+ fail_unless (res == TRUE, NULL);
+
+ gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
/* tests if we cleanup properly */
GST_START_TEST (controller_controlsource_refcounts)
{
@@ -466,10 +485,12 @@ GST_START_TEST (controller_controlsource_empty2)
/* set control values */
g_value_init (&val, G_TYPE_ULONG);
g_value_set_ulong (&val, 0);
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND, &val);
+ gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource,
+ 0 * GST_SECOND, &val);
/* ... and unset the value */
- gst_interpolation_control_source_unset (csource, 0 * GST_SECOND);
+ gst_timed_value_control_source_unset ((GstTimedValueControlSource *) csource,
+ 0 * GST_SECOND);
/* don't fail on empty control point lists */
gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
@@ -502,22 +523,23 @@ GST_START_TEST (controller_interpolate_none)
fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
GST_INTERPOLATE_NONE));
- fail_unless (gst_interpolation_control_source_get_count (csource) == 0);
+ fail_unless (gst_timed_value_control_source_get_count (
+ (GstTimedValueControlSource *) csource) == 0);
/* set control values */
g_value_init (&val_ulong, G_TYPE_ULONG);
g_value_set_ulong (&val_ulong, 0);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
- fail_unless (gst_interpolation_control_source_get_count (csource) == 1);
+ fail_unless (gst_timed_value_control_source_get_count (
+ (GstTimedValueControlSource *) csource) == 1);
g_value_set_ulong (&val_ulong, 100);
- res =
- gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
- fail_unless (gst_interpolation_control_source_get_count (csource) == 2);
+ fail_unless (gst_timed_value_control_source_get_count (
+ (GstTimedValueControlSource *) csource) == 2);
g_object_unref (csource);
@@ -534,64 +556,6 @@ GST_START_TEST (controller_interpolate_none)
GST_END_TEST;
-/* test timed value handling in trigger mode */
-GST_START_TEST (controller_interpolate_trigger)
-{
- GstInterpolationControlSource *csource;
- GstElement *elem;
- gboolean res;
- GValue val_ulong = { 0, };
-
- elem = gst_element_factory_make ("testmonosource", "test_source");
-
- /* Get interpolation control source */
- csource = gst_interpolation_control_source_new ();
-
- fail_unless (csource != NULL);
- fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
- GST_CONTROL_SOURCE (csource)));
-
- /* set interpolation mode */
- fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
- GST_INTERPOLATE_TRIGGER));
-
- g_value_init (&val_ulong, G_TYPE_ULONG);
- fail_if (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
- 0 * GST_SECOND, &val_ulong));
-
- /* set control values */
- g_value_set_ulong (&val_ulong, 50);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_ulong);
- fail_unless (res, NULL);
- g_value_set_ulong (&val_ulong, 100);
- res =
- gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
- &val_ulong);
- fail_unless (res, NULL);
-
-
- /* now pull in values for some timestamps */
- fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
- 0 * GST_SECOND, &val_ulong));
- gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
- fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
- fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
- 1 * GST_SECOND, &val_ulong));
- gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
- fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
- fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
- 2 * GST_SECOND, &val_ulong));
- gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
- fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
-
- g_object_unref (csource);
- gst_object_unref (elem);
-}
-
-GST_END_TEST;
-
/* test timed value handling with linear interpolation */
GST_START_TEST (controller_interpolate_linear)
{
@@ -616,14 +580,12 @@ GST_START_TEST (controller_interpolate_linear)
/* set control values */
g_value_init (&val_ulong, G_TYPE_ULONG);
g_value_set_ulong (&val_ulong, 0);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
g_value_set_ulong (&val_ulong, 100);
- res =
- gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
g_object_unref (csource);
@@ -665,24 +627,20 @@ GST_START_TEST (controller_interpolate_cubic)
/* set control values */
g_value_init (&val_double, G_TYPE_DOUBLE);
g_value_set_double (&val_double, 0.0);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_double);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_double);
fail_unless (res, NULL);
g_value_set_double (&val_double, 5.0);
- res =
- gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
- &val_double);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 1 * GST_SECOND, &val_double);
fail_unless (res, NULL);
g_value_set_double (&val_double, 2.0);
- res =
- gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
- &val_double);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_double);
fail_unless (res, NULL);
g_value_set_double (&val_double, 8.0);
- res =
- gst_interpolation_control_source_set (csource, 4 * GST_SECOND,
- &val_double);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 4 * GST_SECOND, &val_double);
fail_unless (res, NULL);
g_object_unref (csource);
@@ -731,14 +689,12 @@ GST_START_TEST (controller_interpolate_cubic_too_few_cp)
/* set 2 control values */
g_value_init (&val_double, G_TYPE_DOUBLE);
g_value_set_double (&val_double, 0.0);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_double);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_double);
fail_unless (res, NULL);
g_value_set_double (&val_double, 4.0);
- res =
- gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
- &val_double);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_double);
fail_unless (res, NULL);
g_object_unref (csource);
@@ -809,19 +765,16 @@ GST_START_TEST (controller_interpolation_unset)
/* set control values */
g_value_init (&val_ulong, G_TYPE_ULONG);
g_value_set_ulong (&val_ulong, 0);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
g_value_set_ulong (&val_ulong, 100);
- res =
- gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 1 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
g_value_set_ulong (&val_ulong, 50);
- res =
- gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
/* verify values */
@@ -833,7 +786,8 @@ GST_START_TEST (controller_interpolation_unset)
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
/* unset second */
- res = gst_interpolation_control_source_unset (csource, 1 * GST_SECOND);
+ res = gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
+ csource, 1 * GST_SECOND);
fail_unless (res, NULL);
/* verify value again */
@@ -843,12 +797,14 @@ GST_START_TEST (controller_interpolation_unset)
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
/* unset all values, reset and try to unset again */
- fail_unless (gst_interpolation_control_source_unset (csource,
- 0 * GST_SECOND));
- fail_unless (gst_interpolation_control_source_unset (csource,
- 2 * GST_SECOND));
- gst_interpolation_control_source_unset_all (csource);
- fail_if (gst_interpolation_control_source_unset (csource, 2 * GST_SECOND));
+ fail_unless (gst_timed_value_control_source_unset ((GstTimedValueControlSource
+ *) csource, 0 * GST_SECOND));
+ fail_unless (gst_timed_value_control_source_unset ((GstTimedValueControlSource
+ *) csource, 2 * GST_SECOND));
+ gst_timed_value_control_source_unset_all ((GstTimedValueControlSource *)
+ csource);
+ fail_if (gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND));
g_object_unref (csource);
@@ -881,14 +837,12 @@ GST_START_TEST (controller_interpolation_unset_all)
/* set control values */
g_value_init (&val_ulong, G_TYPE_ULONG);
g_value_set_ulong (&val_ulong, 0);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
g_value_set_ulong (&val_ulong, 100);
- res =
- gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 1 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
/* verify values */
@@ -898,7 +852,8 @@ GST_START_TEST (controller_interpolation_unset_all)
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
/* unset all */
- gst_interpolation_control_source_unset_all (csource);
+ gst_timed_value_control_source_unset_all ((GstTimedValueControlSource *)
+ csource);
g_object_unref (csource);
@@ -936,14 +891,12 @@ GST_START_TEST (controller_interpolation_linear_value_array)
/* set control values */
g_value_init (&val_ulong, G_TYPE_ULONG);
g_value_set_ulong (&val_ulong, 0);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
g_value_set_ulong (&val_ulong, 100);
- res =
- gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
/* now pull in values for some timestamps */
@@ -987,14 +940,12 @@ GST_START_TEST (controller_interpolation_linear_invalid_values)
/* set control values */
g_value_init (&val_float, G_TYPE_FLOAT);
g_value_set_float (&val_float, 200.0);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_float);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_float);
fail_unless (res, NULL);
g_value_set_float (&val_float, -200.0);
- res =
- gst_interpolation_control_source_set (csource, 4 * GST_SECOND,
- &val_float);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 4 * GST_SECOND, &val_float);
fail_unless (res, NULL);
g_object_unref (csource);
@@ -1056,14 +1007,12 @@ GST_START_TEST (controller_interpolation_linear_default_values)
/* set control values */
g_value_set_ulong (&val_ulong, 0);
- res =
- gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 1 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
g_value_set_ulong (&val_ulong, 100);
- res =
- gst_interpolation_control_source_set (csource, 3 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 3 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
/* now pull in values for some timestamps */
@@ -1079,20 +1028,20 @@ GST_START_TEST (controller_interpolation_linear_default_values)
/* set control values */
g_value_set_ulong (&val_ulong, 0);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
g_value_set_ulong (&val_ulong, 100);
- res =
- gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
/* unset the old ones */
- res = gst_interpolation_control_source_unset (csource, 1 * GST_SECOND);
+ res = gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
+ csource, 1 * GST_SECOND);
fail_unless (res, NULL);
- res = gst_interpolation_control_source_unset (csource, 3 * GST_SECOND);
+ res = gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
+ csource, 3 * GST_SECOND);
fail_unless (res, NULL);
/* now pull in values for some timestamps */
@@ -1143,14 +1092,12 @@ GST_START_TEST (controller_interpolate_linear_disabled)
/* set control values */
g_value_init (&val_ulong, G_TYPE_ULONG);
g_value_set_ulong (&val_ulong, 0);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
g_value_set_ulong (&val_ulong, 100);
- res =
- gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
g_object_unref (csource);
@@ -1158,14 +1105,12 @@ GST_START_TEST (controller_interpolate_linear_disabled)
/* set control values */
g_value_init (&val_double, G_TYPE_DOUBLE);
g_value_set_double (&val_double, 2.0);
- res =
- gst_interpolation_control_source_set (csource2, 0 * GST_SECOND,
- &val_double);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource2, 0 * GST_SECOND, &val_double);
fail_unless (res, NULL);
g_value_set_double (&val_double, 4.0);
- res =
- gst_interpolation_control_source_set (csource2, 2 * GST_SECOND,
- &val_double);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource2, 2 * GST_SECOND, &val_double);
fail_unless (res, NULL);
g_object_unref (G_OBJECT (csource2));
@@ -1289,11 +1234,13 @@ GST_START_TEST (controller_interpolation_set_from_list)
list = g_slist_append (list, tval);
- fail_if (gst_interpolation_control_source_set_from_list (csource, list));
+ fail_if (gst_timed_value_control_source_set_from_list (
+ (GstTimedValueControlSource *) csource, list));
/* try again with a valid stamp, should work now */
tval->timestamp = 0;
- fail_unless (gst_interpolation_control_source_set_from_list (csource, list));
+ fail_unless (gst_timed_value_control_source_set_from_list (
+ (GstTimedValueControlSource *) csource, list));
g_object_unref (csource);
@@ -1306,6 +1253,119 @@ GST_START_TEST (controller_interpolation_set_from_list)
GST_END_TEST;
+
+/* test linear interpolation for ts < first control point */
+GST_START_TEST (controller_interpolate_linear_before_ts0)
+{
+ GstInterpolationControlSource *csource;
+ GstElement *elem;
+ gboolean res;
+ GValue val_ulong = { 0, };
+
+ elem = gst_element_factory_make ("testmonosource", "test_source");
+
+ /* Get interpolation control source */
+ csource = gst_interpolation_control_source_new ();
+
+ fail_unless (csource != NULL);
+ fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
+ GST_CONTROL_SOURCE (csource)));
+
+ /* set interpolation mode */
+ fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
+ GST_INTERPOLATE_LINEAR));
+
+ /* set control values */
+ g_value_init (&val_ulong, G_TYPE_ULONG);
+ g_value_set_ulong (&val_ulong, 100);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_ulong);
+ fail_unless (res, NULL);
+ g_value_set_ulong (&val_ulong, 0);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 4 * GST_SECOND, &val_ulong);
+ fail_unless (res, NULL);
+
+ g_object_unref (csource);
+
+ /* now pull in values for some timestamps after first control point */
+ gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+ fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
+ gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND);
+ fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
+ gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND);
+ fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
+
+ /* now pull in values for some timestamps before first control point */
+ gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+ fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
+ gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+ fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
+
+ gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
+/* test control-point handling in interpolation control source */
+GST_START_TEST (controller_interpolation_cp_count)
+{
+ GstInterpolationControlSource *csource;
+ GstElement *elem;
+ gboolean res;
+ GValue val_ulong = { 0, };
+
+ elem = gst_element_factory_make ("testmonosource", "test_source");
+
+ /* Get interpolation control source */
+ csource = gst_interpolation_control_source_new ();
+
+ fail_unless (csource != NULL);
+ fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
+ GST_CONTROL_SOURCE (csource)));
+
+ /* set interpolation mode */
+ fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
+ GST_INTERPOLATE_NONE));
+
+ fail_unless (gst_timed_value_control_source_get_count (
+ (GstTimedValueControlSource *) csource) == 0);
+
+ /* set control values */
+ g_value_init (&val_ulong, G_TYPE_ULONG);
+ g_value_set_ulong (&val_ulong, 0);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_ulong);
+ fail_unless (res, NULL);
+ fail_unless (gst_timed_value_control_source_get_count (
+ (GstTimedValueControlSource *) csource) == 1);
+ g_value_set_ulong (&val_ulong, 100);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_ulong);
+ fail_unless (res, NULL);
+ fail_unless (gst_timed_value_control_source_get_count (
+ (GstTimedValueControlSource *) csource) == 2);
+
+ /* now unset control values */
+ res = gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND);
+ fail_unless (res, NULL);
+ fail_unless (gst_timed_value_control_source_get_count (
+ (GstTimedValueControlSource *) csource) == 1);
+
+ res = gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND);
+ fail_unless (res, NULL);
+ fail_unless (gst_timed_value_control_source_get_count (
+ (GstTimedValueControlSource *) csource) == 0);
+
+ g_object_unref (csource);
+
+ gst_object_unref (elem);
+}
+
+GST_END_TEST;
+
/* test lfo control source with sine waveform */
GST_START_TEST (controller_lfo_sine)
{
@@ -1720,28 +1780,10 @@ GST_START_TEST (controller_lfo_none)
GST_END_TEST;
-/* tests if we can run helper methods against any GObject */
-GST_START_TEST (controller_helper_any_gobject)
-{
- GstElement *elem;
- gboolean res;
-
- elem = gst_element_factory_make ("bin", "test_elem");
-
- /* that element is not controllable */
- res = gst_object_sync_values (GST_OBJECT (elem), 0LL);
- /* Syncing should still succeed as there's nothing to sync */
- fail_unless (res == TRUE, NULL);
-
- gst_object_unref (elem);
-}
-
-GST_END_TEST;
-
-/* test linear interpolation for ts < first control point */
-GST_START_TEST (controller_interpolate_linear_before_ts0)
+/* test timed value handling in trigger mode */
+GST_START_TEST (controller_trigger_exact)
{
- GstInterpolationControlSource *csource;
+ GstTriggerControlSource *csource;
GstElement *elem;
gboolean res;
GValue val_ulong = { 0, };
@@ -1749,54 +1791,50 @@ GST_START_TEST (controller_interpolate_linear_before_ts0)
elem = gst_element_factory_make ("testmonosource", "test_source");
/* Get interpolation control source */
- csource = gst_interpolation_control_source_new ();
+ csource = gst_trigger_control_source_new ();
fail_unless (csource != NULL);
fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
GST_CONTROL_SOURCE (csource)));
- /* set interpolation mode */
- fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
- GST_INTERPOLATE_LINEAR));
+ g_value_init (&val_ulong, G_TYPE_ULONG);
+ fail_if (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
+ 0 * GST_SECOND, &val_ulong));
/* set control values */
- g_value_init (&val_ulong, G_TYPE_ULONG);
- g_value_set_ulong (&val_ulong, 100);
- res =
- gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
- &val_ulong);
+ g_value_set_ulong (&val_ulong, 50);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
- g_value_set_ulong (&val_ulong, 0);
- res =
- gst_interpolation_control_source_set (csource, 4 * GST_SECOND,
- &val_ulong);
+ g_value_set_ulong (&val_ulong, 100);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
- g_object_unref (csource);
- /* now pull in values for some timestamps after first control point */
- gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
- fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
- gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND);
+ /* now pull in values for some timestamps */
+ fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
+ 0 * GST_SECOND, &val_ulong));
+ gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
- gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND);
- fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
-
- /* now pull in values for some timestamps before first control point */
+ fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
+ 1 * GST_SECOND, &val_ulong));
gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
- fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
- gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
+ fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
+ 2 * GST_SECOND, &val_ulong));
+ gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+ fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
+ g_object_unref (csource);
gst_object_unref (elem);
}
GST_END_TEST;
-/* test control-point handling in interpolation control source */
-GST_START_TEST (controller_interpolation_cp_count)
+GST_START_TEST (controller_trigger_tolerance)
{
- GstInterpolationControlSource *csource;
+ GstTriggerControlSource *csource;
GstElement *elem;
gboolean res;
GValue val_ulong = { 0, };
@@ -1804,44 +1842,42 @@ GST_START_TEST (controller_interpolation_cp_count)
elem = gst_element_factory_make ("testmonosource", "test_source");
/* Get interpolation control source */
- csource = gst_interpolation_control_source_new ();
+ csource = gst_trigger_control_source_new ();
fail_unless (csource != NULL);
fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
GST_CONTROL_SOURCE (csource)));
- /* set interpolation mode */
- fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
- GST_INTERPOLATE_NONE));
+ g_object_set (csource, "tolerance", G_GINT64_CONSTANT (10), NULL);
- fail_unless (gst_interpolation_control_source_get_count (csource) == 0);
+ g_value_init (&val_ulong, G_TYPE_ULONG);
+ fail_if (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
+ 0 * GST_SECOND, &val_ulong));
/* set control values */
- g_value_init (&val_ulong, G_TYPE_ULONG);
- g_value_set_ulong (&val_ulong, 0);
- res =
- gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
- &val_ulong);
+ g_value_set_ulong (&val_ulong, 50);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 0 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
- fail_unless (gst_interpolation_control_source_get_count (csource) == 1);
g_value_set_ulong (&val_ulong, 100);
- res =
- gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
- &val_ulong);
+ res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
+ csource, 2 * GST_SECOND, &val_ulong);
fail_unless (res, NULL);
- fail_unless (gst_interpolation_control_source_get_count (csource) == 2);
- /* now unset control values */
- res = gst_interpolation_control_source_unset (csource, 2 * GST_SECOND);
- fail_unless (res, NULL);
- fail_unless (gst_interpolation_control_source_get_count (csource) == 1);
- res = gst_interpolation_control_source_unset (csource, 0 * GST_SECOND);
- fail_unless (res, NULL);
- fail_unless (gst_interpolation_control_source_get_count (csource) == 0);
+ /* now pull in values for some timestamps */
+ gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
+ fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
+ gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND + 5);
+ fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
+ gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
+ fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
+ gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND - 5);
+ fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
+ gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
+ fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
g_object_unref (csource);
-
gst_object_unref (elem);
}
@@ -1863,11 +1899,11 @@ gst_controller_suite (void)
tcase_add_test (tc, controller_new_okay1);
tcase_add_test (tc, controller_new_okay2);
tcase_add_test (tc, controller_param_twice);
+ tcase_add_test (tc, controller_any_gobject);
tcase_add_test (tc, controller_controlsource_refcounts);
tcase_add_test (tc, controller_controlsource_empty1);
tcase_add_test (tc, controller_controlsource_empty2);
tcase_add_test (tc, controller_interpolate_none);
- tcase_add_test (tc, controller_interpolate_trigger);
tcase_add_test (tc, controller_interpolate_linear);
tcase_add_test (tc, controller_interpolate_cubic);
tcase_add_test (tc, controller_interpolate_cubic_too_few_cp);
@@ -1879,6 +1915,8 @@ gst_controller_suite (void)
tcase_add_test (tc, controller_interpolation_linear_default_values);
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_interpolation_cp_count);
tcase_add_test (tc, controller_lfo_sine);
tcase_add_test (tc, controller_lfo_sine_timeshift);
tcase_add_test (tc, controller_lfo_square);
@@ -1886,9 +1924,8 @@ gst_controller_suite (void)
tcase_add_test (tc, controller_lfo_rsaw);
tcase_add_test (tc, controller_lfo_triangle);
tcase_add_test (tc, controller_lfo_none);
- tcase_add_test (tc, controller_helper_any_gobject);
- tcase_add_test (tc, controller_interpolate_linear_before_ts0);
- tcase_add_test (tc, controller_interpolation_cp_count);
+ tcase_add_test (tc, controller_trigger_exact);
+ tcase_add_test (tc, controller_trigger_tolerance);
return s;
}
diff --git a/tests/examples/controller/audio-example.c b/tests/examples/controller/audio-example.c
index 76805b186..c0acba6f5 100644
--- a/tests/examples/controller/audio-example.c
+++ b/tests/examples/controller/audio-example.c
@@ -66,18 +66,23 @@ main (gint argc, gchar ** argv)
/* set control values */
g_value_init (&vol, G_TYPE_DOUBLE);
g_value_set_double (&vol, 0.0);
- gst_interpolation_control_source_set (csource1, 0 * GST_SECOND, &vol);
+ gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource1,
+ 0 * GST_SECOND, &vol);
g_value_set_double (&vol, 1.0);
- gst_interpolation_control_source_set (csource1, 5 * GST_SECOND, &vol);
+ gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource1,
+ 5 * GST_SECOND, &vol);
g_object_unref (csource1);
g_value_set_double (&vol, 220.0);
- gst_interpolation_control_source_set (csource2, 0 * GST_SECOND, &vol);
+ gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource2,
+ 0 * GST_SECOND, &vol);
g_value_set_double (&vol, 3520.0);
- gst_interpolation_control_source_set (csource2, 3 * GST_SECOND, &vol);
+ gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource2,
+ 3 * GST_SECOND, &vol);
g_value_set_double (&vol, 440.0);
- gst_interpolation_control_source_set (csource2, 6 * GST_SECOND, &vol);
+ gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource2,
+ 6 * GST_SECOND, &vol);
g_object_unref (csource2);