From 1a02a59e42b71a65263ca998262001559dac4f5f Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Mon, 29 Sep 2014 21:10:14 +0200 Subject: [PATCH] timedvaluecontrolsource: Add some signals about values changes In order for user to be able to track changes in the value set in GstTimedValueControlSource the following signals have been added: * value-added * value-removed * value-changed To be able to use a GstControlPoint to be marshalled into the signals, the GstControlPoint structure is now registerd as a GBoxed type. New API: ~~~~~~~ * GstTimedValueControlSource::value-added * GstTimedValueControlSource::value-removed * GstTimedValueControlSource::value-added https://bugzilla.gnome.org/show_bug.cgi?id=737616 --- libs/gst/controller/gsttimedvaluecontrolsource.c | 114 +++++++++++++++++++++-- libs/gst/controller/gsttimedvaluecontrolsource.h | 2 + 2 files changed, 108 insertions(+), 8 deletions(-) diff --git a/libs/gst/controller/gsttimedvaluecontrolsource.c b/libs/gst/controller/gsttimedvaluecontrolsource.c index 0d0b8be..42fa976 100644 --- a/libs/gst/controller/gsttimedvaluecontrolsource.c +++ b/libs/gst/controller/gsttimedvaluecontrolsource.c @@ -52,6 +52,17 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstTimedValueControlSource, gst_timed_value_control_source, GST_TYPE_CONTROL_SOURCE, _do_init); + +enum +{ + VALUE_CHANGED_SIGNAL, + VALUE_ADDED_SIGNAL, + VALUE_REMOVED_SIGNAL, + LAST_SIGNAL +}; + +static guint gst_timed_value_control_source_signals[LAST_SIGNAL] = { 0 }; + /* * gst_control_point_free: * @prop: the object to free @@ -67,6 +78,29 @@ gst_control_point_free (GstControlPoint * cp) g_slice_free (GstControlPoint, cp); } +static gpointer +gst_control_point_copy (GstControlPoint * boxed) +{ + return g_slice_dup (GstControlPoint, boxed); +} + +GType +gst_control_point_get_type (void) +{ + static volatile gsize type_id = 0; + + if (g_once_init_enter (&type_id)) { + GType tmp = + g_boxed_type_register_static (g_intern_static_string + ("GstControlPoint"), + (GBoxedCopyFunc) gst_control_point_copy, + (GBoxedFreeFunc) gst_control_point_free); + g_once_init_leave (&type_id, tmp); + } + + return type_id; +} + static void gst_timed_value_control_source_reset (GstTimedValueControlSource * self) { @@ -138,9 +172,11 @@ gst_timed_value_control_source_set_internal (GstTimedValueControlSource * self, GstClockTime timestamp, const gdouble value) { GSequenceIter *iter; + GstControlPoint *cp; - /* check if a control point for the timestamp already exists */ + g_mutex_lock (&self->lock); + /* check if a control point for the timestamp already exists */ /* iter contains the iter right *after* timestamp */ if (G_LIKELY (self->values)) { iter = @@ -152,8 +188,14 @@ gst_timed_value_control_source_set_internal (GstTimedValueControlSource * /* If the timestamp is the same just update the control point value */ if (cp->timestamp == timestamp) { + /* update control point */ cp->value = value; + g_mutex_unlock (&self->lock); + + g_signal_emit (self, + gst_timed_value_control_source_signals[VALUE_CHANGED_SIGNAL], 0, + cp); goto done; } } @@ -163,9 +205,14 @@ gst_timed_value_control_source_set_internal (GstTimedValueControlSource * } /* 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); + cp = _make_new_cp (self, timestamp, value); + g_sequence_insert_sorted (self->values, cp, + (GCompareDataFunc) gst_control_point_compare, NULL); self->nvalues++; + g_mutex_unlock (&self->lock); + + g_signal_emit (self, + gst_timed_value_control_source_signals[VALUE_ADDED_SIGNAL], 0, cp); done: self->valid_cache = FALSE; @@ -224,9 +271,7 @@ gst_timed_value_control_source_set (GstTimedValueControlSource * self, 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); gst_timed_value_control_source_set_internal (self, timestamp, value); - g_mutex_unlock (&self->lock); return TRUE; } @@ -257,10 +302,8 @@ gst_timed_value_control_source_set_from_list (GstTimedValueControlSource * GST_WARNING ("GstTimedValued with invalid timestamp passed to %s", GST_FUNCTION); } 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; } } @@ -283,6 +326,7 @@ gst_timed_value_control_source_unset (GstTimedValueControlSource * self, { GSequenceIter *iter; gboolean res = FALSE; + GstControlPoint *cp = NULL; 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); @@ -292,7 +336,6 @@ gst_timed_value_control_source_unset (GstTimedValueControlSource * self, if (G_LIKELY (self->values) && (iter = g_sequence_search (self->values, ×tamp, (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 @@ -300,6 +343,7 @@ gst_timed_value_control_source_unset (GstTimedValueControlSource * self, iter = g_sequence_iter_prev (iter); cp = g_sequence_get (iter); if (cp->timestamp == timestamp) { + cp = g_slice_dup (GstControlPoint, cp); g_sequence_remove (iter); self->nvalues--; self->valid_cache = FALSE; @@ -308,6 +352,12 @@ gst_timed_value_control_source_unset (GstTimedValueControlSource * self, } g_mutex_unlock (&self->lock); + if (cp) { + g_signal_emit (self, + gst_timed_value_control_source_signals[VALUE_REMOVED_SIGNAL], 0, cp); + g_slice_free (GstControlPoint, cp); + } + return res; } @@ -420,5 +470,53 @@ gst_timed_value_control_source_class_init (GstTimedValueControlSourceClass GObjectClass *gobject_class = G_OBJECT_CLASS (klass); //GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass); + /** + * GstTimedValueControlSource::value-changed + * @self: The #GstTimedValueControlSource on which a #GstTimedValue has changed + * @timed_value: The #GstTimedValue where the value changed + * + * Emited right after the new value has been set on @timed_signals + * + * Since 1.6 + */ + gst_timed_value_control_source_signals[VALUE_CHANGED_SIGNAL] = + g_signal_new ("value-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + gst_control_point_get_type ()); + + /** + * GstTimedValueControlSource::value-added + * @self: The #GstTimedValueControlSource into which a #GstTimedValue has been + * added + * @timed_value: The newly added #GstTimedValue + * + * Emited right after the new value has been added to @self + * + * Since 1.6 + */ + gst_timed_value_control_source_signals[VALUE_ADDED_SIGNAL] = + g_signal_new ("value-added", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + gst_control_point_get_type ()); + + /** + * GstTimedValueControlSource::value-removed + * @self: The #GstTimedValueControlSource from which a #GstTimedValue has been + * removed + * @timed_value: The removed #GstTimedValue + * + * Emited when @timed_value is removed from @self + * + * Since 1.6 + */ + gst_timed_value_control_source_signals[VALUE_REMOVED_SIGNAL] = + g_signal_new ("value-removed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + gst_control_point_get_type ()); + + gobject_class->finalize = gst_timed_value_control_source_finalize; } diff --git a/libs/gst/controller/gsttimedvaluecontrolsource.h b/libs/gst/controller/gsttimedvaluecontrolsource.h index aea2a44..cb92cd9 100644 --- a/libs/gst/controller/gsttimedvaluecontrolsource.h +++ b/libs/gst/controller/gsttimedvaluecontrolsource.h @@ -76,6 +76,8 @@ struct _GstControlPoint }; +GType gst_control_point_get_type (void); + /** * GstTimedValueControlSource: * -- 2.7.4