add vaid property and unit tests
authorBrandon Lewis <brandon@collabora.co.uk>
Thu, 5 Aug 2010 13:21:57 +0000 (15:21 +0200)
committerEdward Hervey <edward.hervey@collabora.co.uk>
Thu, 2 Sep 2010 16:08:43 +0000 (18:08 +0200)
ges/ges-simple-timeline-layer.c
ges/ges-simple-timeline-layer.h
tests/check/ges/simplelayer.c

index f89cfa7..19a8a29 100644 (file)
@@ -61,13 +61,26 @@ enum
   LAST_SIGNAL,
 };
 
+enum
+{
+  PROP_0,
+  PROP_VALID,
+  LAST_PROP,
+};
+
 static guint gstl_signals[LAST_SIGNAL] = { 0 };
 
 static void
 ges_simple_timeline_layer_get_property (GObject * object,
     guint property_id, GValue * value, GParamSpec * pspec)
 {
+  GESSimpleTimelineLayer *self;
+  self = GES_SIMPLE_TIMELINE_LAYER (object);
+
   switch (property_id) {
+    case PROP_VALID:
+      g_value_set_boolean (value, self->valid);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
   }
@@ -111,6 +124,17 @@ ges_simple_timeline_layer_class_init (GESSimpleTimelineLayerClass * klass)
   layer_class->object_added = ges_simple_timeline_layer_object_added;
 
   /**
+   * GESSimpleTimelineLayer:valid:
+   *
+   * FALSE when the arrangement of objects in the layer would cause errors or
+   * unexpected output during playback. Do not set the containing pipeline
+   * state to PLAYING when this property is FALSE.
+   */
+  g_object_class_install_property (object_class, PROP_VALID,
+      g_param_spec_boolean ("valid", "Valid",
+          "Layer is in a valid configuration", FALSE, G_PARAM_READABLE));
+
+  /**
    * GESSimpleTimelineLayer::object-moved
    * @layer: the #GESSimpleTimelineLayer
    * @object: the #GESTimelineObject that was added
@@ -145,6 +169,7 @@ gstl_recalculate (GESSimpleTimelineLayer * self)
   gint height;
   GESTimelineObject *prev_object = NULL;
   GESTimelineObject *prev_transition = NULL;
+  gboolean valid = TRUE;
 
   priority = GES_TIMELINE_LAYER (self)->min_gnl_priority + 2;
 
@@ -199,14 +224,17 @@ gstl_recalculate (GESSimpleTimelineLayer * self)
 
       if (GES_IS_TIMELINE_TRANSITION (prev_object)) {
         GST_ERROR ("two transitions in sequence!");
+        valid = FALSE;
       }
 
       if (prev_object && (GES_TIMELINE_OBJECT_DURATION (prev_object) < dur)) {
         GST_ERROR ("transition duration exceeds that of previous neighbor!");
+        valid = FALSE;
       }
 
       if (l_next && (GES_TIMELINE_OBJECT_DURATION (l_next->data) < dur)) {
         GST_ERROR ("transition duration exceeds that of next neighbor!");
+        valid = FALSE;
       }
 
       if (prev_transition) {
@@ -216,8 +244,10 @@ gstl_recalculate (GESSimpleTimelineLayer * self)
 
         start = pos;
 
-        if (end > start)
+        if (end > start) {
           GST_ERROR ("%d, %d: overlapping transitions!", start, end);
+          valid = FALSE;
+        }
       }
       prev_transition = obj;
     }
@@ -230,6 +260,11 @@ gstl_recalculate (GESSimpleTimelineLayer * self)
       GST_TIME_ARGS (pos));
 
   GES_TIMELINE_LAYER (self)->max_gnl_priority = priority;
+
+  if (valid != self->valid) {
+    self->valid = valid;
+    g_object_notify (G_OBJECT (self), "valid");
+  }
 }
 
 /**
index cbde229..d8271f1 100644 (file)
@@ -57,6 +57,7 @@ struct _GESSimpleTimelineLayer {
   GList *objects;
 
   gboolean adding_object;
+  gboolean valid;
 };
 
 /**
index 76e1faf..59afaf1 100644 (file)
@@ -162,7 +162,8 @@ GST_START_TEST (test_gsl_move_simple)
           (layer), GES_TIMELINE_OBJECT (source2), -1));
   fail_unless_equals_uint64 (GES_TIMELINE_OBJECT_START (source1), 0);
   fail_unless_equals_uint64 (GES_TIMELINE_OBJECT_START (source2), GST_SECOND);
-  fail_unless_equals_int (info.new, -1);
+  /* position will be decremented, this is expected */
+  fail_unless_equals_int (info.new, -2);
   fail_unless_equals_int (info.old, 0);
 
   /* remove source1, source2 should be moved to the beginning */
@@ -194,6 +195,12 @@ GST_START_TEST (test_gsl_move_simple)
 
 GST_END_TEST;
 
+static void
+valid_notify_cb (GObject * obj, GParamSpec * unused G_GNUC_UNUSED, gint * count)
+{
+  (*count)++;
+}
+
 GST_START_TEST (test_gsl_with_transitions)
 {
   GESTimeline *timeline;
@@ -202,12 +209,18 @@ GST_START_TEST (test_gsl_with_transitions)
   GESCustomTimelineSource *source1, *source2, *source3, *source4;
   GESTimelineTransition *tr1, *tr2, *tr3, *tr4, *tr5;
   GESSimpleTimelineLayer *gstl;
+  gboolean valid;
+  gint count = 0;
 
   ges_init ();
 
   /* Timeline and 1 Layer */
   timeline = ges_timeline_new ();
   layer = (GESTimelineLayer *) ges_simple_timeline_layer_new ();
+
+  g_signal_connect (G_OBJECT (layer), "notify::valid",
+      G_CALLBACK (valid_notify_cb), &count);
+
   fail_unless (ges_timeline_add_layer (timeline, layer));
   ges_timeline_layer_set_priority (layer, 0);
 
@@ -420,22 +433,36 @@ GST_START_TEST (test_gsl_with_transitions)
   fail_unless (ges_simple_timeline_layer_add_object (gstl,
           GES_TIMELINE_OBJECT (tr5), 0));
 
-  /* check that removals which result in two or more adjacent transitions at
-   * least print a warning. */
+  /* at this point the layer should still be valid */
+  g_object_get (G_OBJECT (layer), "valid", &valid, NULL);
+  fail_unless (valid);
+  fail_unless_equals_int (count, 1);
 
-  /* FIXME: this needs to be checked manually in the console output */
+  /* removals which result in two or more adjacent transitions will also
+   * print a warning on the console. This is expected */
 
   GST_DEBUG ("Removing sources");
 
   fail_unless (ges_timeline_layer_remove_object (layer,
           GES_TIMELINE_OBJECT (source1)));
-  fail_unless (ges_timeline_layer_remove_object (layer,
+
+  /* transition should now be invalid */
+
+  g_object_get (G_OBJECT (layer), "valid", &valid, NULL);
+  fail_unless (!valid);
+  fail_unless_equals_int (count, 2)
+
+      fail_unless (ges_timeline_layer_remove_object (layer,
           GES_TIMELINE_OBJECT (source2)));
   fail_unless (ges_timeline_layer_remove_object (layer,
           GES_TIMELINE_OBJECT (source3)));
   fail_unless (ges_timeline_layer_remove_object (layer,
           GES_TIMELINE_OBJECT (source4)));
 
+  g_object_get (G_OBJECT (layer), "valid", &valid, NULL);
+  fail_unless (!valid);
+  fail_unless_equals_int (count, 2);
+
   GST_DEBUG ("Removing transitions");
 
   fail_unless (ges_timeline_layer_remove_object (layer,