GESSimpleTimelineLayer: Implement add()/move() and parent class changes
authorEdward Hervey <edward.hervey@collabora.co.uk>
Tue, 29 Sep 2009 13:27:55 +0000 (15:27 +0200)
committerEdward Hervey <edward.hervey@collabora.co.uk>
Tue, 29 Sep 2009 13:27:55 +0000 (15:27 +0200)
If changes happen when accessing the GESTimelineLayer API, they will be taken
into account.

ges/ges-simple-timeline-layer.c
ges/ges-simple-timeline-layer.h

index a3e48e4..27faa45 100644 (file)
 
 #include "ges-internal.h"
 #include "ges-simple-timeline-layer.h"
+#include "ges-timeline-object.h"
+
+static void
+ges_simple_timeline_layer_object_removed (GESTimelineLayer * layer,
+    GESTimelineObject * object);
+
+static void
+ges_simple_timeline_layer_object_added (GESTimelineLayer * layer,
+    GESTimelineObject * object);
 
 G_DEFINE_TYPE (GESSimpleTimelineLayer, ges_simple_timeline_layer,
     GES_TYPE_TIMELINE_LAYER);
@@ -67,16 +76,40 @@ static void
 ges_simple_timeline_layer_class_init (GESSimpleTimelineLayerClass * klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GESTimelineLayerClass *layer_class = GES_TIMELINE_LAYER_CLASS (klass);
 
   object_class->get_property = ges_simple_timeline_layer_get_property;
   object_class->set_property = ges_simple_timeline_layer_set_property;
   object_class->dispose = ges_simple_timeline_layer_dispose;
   object_class->finalize = ges_simple_timeline_layer_finalize;
+
+  /* Be informed when objects are being added/removed from elsewhere */
+  layer_class->object_removed = ges_simple_timeline_layer_object_removed;
+  layer_class->object_added = ges_simple_timeline_layer_object_added;
 }
 
 static void
 ges_simple_timeline_layer_init (GESSimpleTimelineLayer * self)
 {
+  self->objects = NULL;
+}
+
+static void
+gstl_recalculate (GESSimpleTimelineLayer * self)
+{
+  GList *tmp;
+  GstClockTime pos = 0;
+
+  GST_DEBUG ("recalculating values");
+
+  for (tmp = self->objects; tmp; tmp = tmp->next) {
+    GESTimelineObject *obj = (GESTimelineObject *) tmp->data;
+
+    if (G_UNLIKELY (GES_TIMELINE_OBJECT_START (obj) != pos)) {
+      ges_timeline_object_set_start (obj, pos);
+    }
+    pos += GES_TIMELINE_OBJECT_DURATION (obj);
+  }
 }
 
 /**
@@ -91,17 +124,35 @@ ges_simple_timeline_layer_init (GESSimpleTimelineLayer * self)
  *
  * The layer will steal a reference to the provided object.
  *
- * NOT IMPLEMENTED !
- *
  * Returns: TRUE if the object was successfuly added, else FALSE.
  */
 gboolean
 ges_simple_timeline_layer_add_object (GESSimpleTimelineLayer * layer,
     GESTimelineObject * object, gint position)
 {
-  /* NOT IMPLEMENTED */
+  gboolean res;
+
+  GST_DEBUG ("layer:%p, object:%p, position:%d", layer, object, position);
+
+  layer->adding_object = TRUE;
+
+  res = ges_timeline_layer_add_object ((GESTimelineLayer *) layer, object);
+
+  /* Add to layer */
+  if (G_UNLIKELY (!res)) {
+    layer->adding_object = FALSE;
+    return FALSE;
+  }
+
+  layer->adding_object = FALSE;
+
+  GST_DEBUG ("Adding object %p to the list", object);
+  layer->objects = g_list_insert (layer->objects, object, position);
+
+  /* recalculate positions */
+  gstl_recalculate (layer);
 
-  return FALSE;
+  return TRUE;
 }
 
 /**
@@ -114,8 +165,6 @@ ges_simple_timeline_layer_add_object (GESSimpleTimelineLayer * layer,
  * all other objects, use position 0. To put the objects after all objects, use
  * position -1.
  *
- * NOT IMPLEMENTED !
- *
  * Returns: TRUE if the object was successfuly moved, else FALSE.
  */
 
@@ -123,9 +172,39 @@ gboolean
 ges_simple_timeline_layer_move_object (GESSimpleTimelineLayer * layer,
     GESTimelineObject * object, gint newposition)
 {
-  /* NOT IMPLEMENTED */
+  gint idx;
+
+  GST_DEBUG ("layer:%p, object:%p, newposition:%d", layer, object, newposition);
+
+  if (G_UNLIKELY (object->layer != (GESTimelineLayer *) layer)) {
+    GST_WARNING ("TimelineObject doesn't belong to this layer");
+    return FALSE;
+  }
+
+  /* Find it's current position */
+  idx = g_list_index (layer->objects, object);
+  if (G_UNLIKELY (idx == -1)) {
+    GST_WARNING ("TimelineObject not controlled by this layer");
+    return FALSE;
+  }
+
+  GST_DEBUG ("Object was previously at position %d", idx);
+
+  /* If we don't have to change its position, don't */
+  if (idx == newposition)
+    return TRUE;
+
+  /* pop it off the list */
+  layer->objects = g_list_remove (layer->objects, object);
+
+  /* re-add it at the proper position */
+  layer->objects = g_list_insert (layer->objects, object, (newposition >= 0
+          && newposition < idx) ? newposition : newposition - 1);
+
+  /* recalculate positions */
+  gstl_recalculate (layer);
 
-  return FALSE;
+  return TRUE;
 }
 
 /**
@@ -140,3 +219,27 @@ ges_simple_timeline_layer_new (void)
 {
   return g_object_new (GES_TYPE_SIMPLE_TIMELINE_LAYER, NULL);
 }
+
+static void
+ges_simple_timeline_layer_object_removed (GESTimelineLayer * layer,
+    GESTimelineObject * object)
+{
+  GESSimpleTimelineLayer *sl = (GESSimpleTimelineLayer *) layer;
+
+  /* remove object from our list */
+  sl->objects = g_list_remove (sl->objects, object);
+  gstl_recalculate (sl);
+}
+
+static void
+ges_simple_timeline_layer_object_added (GESTimelineLayer * layer,
+    GESTimelineObject * object)
+{
+  GESSimpleTimelineLayer *sl = (GESSimpleTimelineLayer *) layer;
+
+  if (sl->adding_object == FALSE) {
+    /* remove object from our list */
+    sl->objects = g_list_append (sl->objects, object);
+    gstl_recalculate (sl);
+  }
+}
index a246d26..baf31f0 100644 (file)
@@ -45,6 +45,12 @@ G_BEGIN_DECLS
 
 struct _GESSimpleTimelineLayer {
   GESTimelineLayer parent;
+
+  /*< private >*/
+  /* Sorted list of objects */
+  GList *objects;
+
+  gboolean adding_object;
 };
 
 struct _GESSimpleTimelineLayerClass {