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);
}
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
gint height;
GESTimelineObject *prev_object = NULL;
GESTimelineObject *prev_transition = NULL;
+ gboolean valid = TRUE;
priority = GES_TIMELINE_LAYER (self)->min_gnl_priority + 2;
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) {
start = pos;
- if (end > start)
+ if (end > start) {
GST_ERROR ("%d, %d: overlapping transitions!", start, end);
+ valid = FALSE;
+ }
}
prev_transition = obj;
}
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");
+ }
}
/**
(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 */
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;
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);
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,