timedvaluecontrolsource: Add some signals about values changes
authorThibault Saunier <tsaunier@gnome.org>
Mon, 29 Sep 2014 19:10:14 +0000 (21:10 +0200)
committerThibault Saunier <tsaunier@gnome.org>
Wed, 22 Oct 2014 16:08:30 +0000 (18:08 +0200)
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
libs/gst/controller/gsttimedvaluecontrolsource.h

index 0d0b8be..42fa976 100644 (file)
@@ -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, &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
@@ -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;
 }
index aea2a44..cb92cd9 100644 (file)
@@ -76,6 +76,8 @@ struct _GstControlPoint
 
 };
 
+GType gst_control_point_get_type (void);
+
 /**
  * GstTimedValueControlSource:
  *