static void
ges_track_video_transition_duration_changed (GESTrackObject * object,
    guint64 duration)
{
  GstElement *gnlobj = ges_track_object_get_gnlobject (object);
  GESTrackVideoTransition *self = GES_TRACK_VIDEO_TRANSITION (object);
  GESTrackVideoTransitionPrivate *priv = self->priv;
  GstTimedValueControlSource *ts;

  GST_LOG ("updating controller");

  if (G_UNLIKELY (!gnlobj || !priv->control_source))
    return;

  ts = GST_TIMED_VALUE_CONTROL_SOURCE (priv->control_source);

  GST_INFO ("duration: %" G_GUINT64_FORMAT, duration);
  GST_LOG ("setting values on controller");

  gst_timed_value_control_source_unset_all (ts);
  gst_timed_value_control_source_set (ts, 0, priv->start_value);
  gst_timed_value_control_source_set (ts, duration, priv->end_value);

  priv->dur = duration;
  GST_LOG ("done updating controller");
}
static void
set_interpolation (GstObject * element, GESTrackVideoTransitionPrivate * priv,
    const gchar * propname)
{
  GstTimedValueControlSource *ts;

  if (priv->control_source) {
    ts = GST_TIMED_VALUE_CONTROL_SOURCE (priv->control_source);

    gst_timed_value_control_source_unset_all (ts);
    gst_object_unref (priv->control_source);
  }

  g_object_set (element, propname, (gfloat) 0.0, NULL);

  priv->control_source = gst_interpolation_control_source_new ();
  gst_object_add_control_binding (GST_OBJECT (element),
      gst_direct_control_binding_new (GST_OBJECT (element), propname,
          priv->control_source));
  g_object_set (priv->control_source, "mode", GST_INTERPOLATION_MODE_LINEAR,
      NULL);


}
static void
_update_control_bindings (GESTimelineElement * element, GstClockTime inpoint,
    GstClockTime duration)
{
  GParamSpec **specs;
  guint n, n_specs;
  GstControlBinding *binding;
  GstTimedValueControlSource *source;
  GESTrackElement *self = GES_TRACK_ELEMENT (element);

  specs = ges_track_element_list_children_properties (self, &n_specs);

  for (n = 0; n < n_specs; ++n) {
    GList *values, *tmp;
    GstTimedValue *last, *first, *prev = NULL, *next = NULL;
    gfloat value_at_pos;

    binding = ges_track_element_get_control_binding (self, specs[n]->name);

    if (!binding)
      continue;

    g_object_get (binding, "control_source", &source, NULL);

    if (duration == 0) {
      gst_timed_value_control_source_unset_all (GST_TIMED_VALUE_CONTROL_SOURCE
          (source));
      continue;
    }

    values =
        gst_timed_value_control_source_get_all (GST_TIMED_VALUE_CONTROL_SOURCE
        (source));

    if (g_list_length (values) == 0)
      continue;

    first = values->data;

    for (tmp = values->next; tmp; tmp = tmp->next) {
      next = tmp->data;

      if (next->timestamp > inpoint)
        break;
    }

    value_at_pos = interpolate_values_for_position (first, next, inpoint);
    gst_timed_value_control_source_unset (source, first->timestamp);
    gst_timed_value_control_source_set (source, inpoint, value_at_pos);

    values =
        gst_timed_value_control_source_get_all (GST_TIMED_VALUE_CONTROL_SOURCE
        (source));

    if (duration != GST_CLOCK_TIME_NONE) {
      last = g_list_last (values)->data;

      for (tmp = g_list_last (values)->prev; tmp; tmp = tmp->prev) {
        prev = tmp->data;

        if (prev->timestamp < duration + inpoint)
          break;
      }

      value_at_pos =
          interpolate_values_for_position (prev, last, duration + inpoint);

      gst_timed_value_control_source_unset (source, last->timestamp);
      gst_timed_value_control_source_set (source, duration + inpoint,
          value_at_pos);
      values =
          gst_timed_value_control_source_get_all (GST_TIMED_VALUE_CONTROL_SOURCE
          (source));
    }

    for (tmp = values; tmp; tmp = tmp->next) {
      GstTimedValue *value = tmp->data;
      if (value->timestamp < inpoint)
        gst_timed_value_control_source_unset (source, value->timestamp);
      else if (duration != GST_CLOCK_TIME_NONE
          && value->timestamp > duration + inpoint)
        gst_timed_value_control_source_unset (source, value->timestamp);
    }
  }

  g_free (specs);
}