Commit 34719efa authored by Henry Wilkes's avatar Henry Wilkes

timeline-tree: make sure the layer priority refers to an existing layer

If a layer priority sits between the priorities of two layers in the
timeline, i.e. it references a gap in the timeline's layers, then
ges_timeline_append_layer will never fill this gap and create the
desired layer, so the edit in timeline-tree would loop forever. So a
check was added to avoid this.

This would be a usage error, but a user can reasonably end up with a gap
in their layers if they remove a layer from the timeline.

Part-of: <!177>
parent 53d335b4
......@@ -121,6 +121,9 @@ ges_timeline_edit (GESTimeline * timeline, GESTimelineElement * element,
gint64 new_layer_priority, GESEditMode mode, GESEdge edge,
guint64 position, GError ** error);
ges_timeline_layer_priority_in_gap (GESTimeline * timeline, guint layer_priority);
ges_timeline_set_track_selection_error (GESTimeline * timeline,
gboolean was_error,
......@@ -962,6 +962,13 @@ set_layer_priority (GESTimelineElement * element, EditData * data,
data->layer_priority = (guint32) (layer_prio - (gint64) layer_offset);
if (ges_timeline_layer_priority_in_gap (element->timeline,
data->layer_priority)) {
GST_ERROR_OBJECT (element, "Edit layer %" G_GUINT32_FORMAT " would "
"be within a gap in the timeline layers", data->layer_priority);
return FALSE;
GST_INFO_OBJECT (element, "%s will move to layer %" G_GUINT32_FORMAT,
element->name, data->layer_priority);
......@@ -1814,6 +1821,13 @@ perform_element_edit (GESTimelineElement * element, EditData * edit)
if (layer == NULL) {
/* make sure we won't loop forever */
if (ges_timeline_layer_priority_in_gap (timeline, edit->layer_priority)) {
GST_ERROR_OBJECT (element, "Requested layer %" G_GUINT32_FORMAT
" is within a gap in the timeline layers", edit->layer_priority);
goto done;
do {
layer = ges_timeline_append_layer (timeline);
} while (ges_layer_get_priority (layer) < edit->layer_priority);
......@@ -3074,6 +3074,26 @@ ges_timeline_get_layer (GESTimeline * timeline, guint priority)
return layer;
ges_timeline_layer_priority_in_gap (GESTimeline * timeline, guint priority)
GList *tmp;
CHECK_THREAD (timeline);
for (tmp = timeline->layers; tmp; tmp = tmp->next) {
GESLayer *layer = GES_LAYER (tmp->data);
guint tmp_priority = ges_layer_get_priority (layer);
if (tmp_priority == priority)
return FALSE;
else if (tmp_priority > priority)
return TRUE;
return FALSE;
* ges_timeline_paste_element:
* @timeline: The #GESTimeline onto which @element should be pasted
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment