summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThibault Saunier <tsaunier@igalia.com>2018-03-18 11:03:00 -0300
committerThibault Saunier <tsaunier@igalia.com>2018-03-18 11:31:17 -0300
commitbd142e285d11110cc97d2d63a9c5d25ec8463a36 (patch)
treedb117c4b38d02172dcc477058e25e8f189b00118
parent31e7ca2ef799e06338fc3d2e8c178f1bbea704ce (diff)
clip: Make sure to create transition after a clip is splitted
In the (now tested) scenario where we have a transition on the right side of a clip we are splitting, auto transitions can't be created because we resize the clip after adding the new one, meaning that there are 3 elements in the "transition zone", we need to force auto transition creation after the splitting. Fixes https://gitlab.gnome.org/GNOME/pitivi/issues/2142
-rw-r--r--ges/ges-clip.c7
-rw-r--r--ges/ges-internal.h3
-rw-r--r--ges/ges-timeline.c11
-rw-r--r--tests/check/python/common.py19
-rw-r--r--tests/check/python/test_timeline.py78
5 files changed, 103 insertions, 15 deletions
diff --git a/ges/ges-clip.c b/ges/ges-clip.c
index 34ac6fab..70c7ee36 100644
--- a/ges/ges-clip.c
+++ b/ges/ges-clip.c
@@ -1385,6 +1385,13 @@ ges_clip_split (GESClip * clip, guint64 position)
_set_duration0 (GES_TIMELINE_ELEMENT (clip), old_duration);
+ if (GES_TIMELINE_ELEMENT_TIMELINE (clip)) {
+ for (tmp = GES_CONTAINER_CHILDREN (new_object); tmp; tmp = tmp->next) {
+ timeline_create_transitions (GES_TIMELINE_ELEMENT_TIMELINE (tmp->data),
+ tmp->data);
+ }
+ }
+
return new_object;
}
diff --git a/ges/ges-internal.h b/ges/ges-internal.h
index 9eaf01ff..502b11ba 100644
--- a/ges/ges-internal.h
+++ b/ges/ges-internal.h
@@ -125,6 +125,9 @@ G_GNUC_INTERNAL
void
timeline_fill_gaps (GESTimeline *timeline);
+G_GNUC_INTERNAL void
+timeline_create_transitions (GESTimeline * timeline, GESTrackElement * track_element);
+
G_GNUC_INTERNAL
void
track_resort_and_fill_gaps (GESTrack *track);
diff --git a/ges/ges-timeline.c b/ges/ges-timeline.c
index 9febf1f2..aba57882 100644
--- a/ges/ges-timeline.c
+++ b/ges/ges-timeline.c
@@ -1065,8 +1065,9 @@ _create_transitions_on_layer (GESTimeline * timeline, GESLayer * layer,
}
/* @track_element must be a GESSource */
-static void
-create_transitions (GESTimeline * timeline, GESTrackElement * track_element)
+void
+timeline_create_transitions (GESTimeline * timeline,
+ GESTrackElement * track_element)
{
GESTrack *track;
GList *layer_node;
@@ -1220,7 +1221,7 @@ start_tracking_track_element (GESTimeline * timeline,
timeline->priv->movecontext.needs_move_ctx = TRUE;
timeline_update_duration (timeline);
- create_transitions (timeline, trackelement);
+ timeline_create_transitions (timeline, trackelement);
}
}
@@ -2598,7 +2599,7 @@ trackelement_start_changed_cb (GESTrackElement * child,
timeline->priv->snapping_distance == 0)
timeline->priv->movecontext.needs_move_ctx = TRUE;
- create_transitions (timeline, child);
+ timeline_create_transitions (timeline, child);
}
}
@@ -2668,7 +2669,7 @@ trackelement_duration_changed_cb (GESTrackElement * child,
timeline->priv->movecontext.needs_move_ctx = TRUE;
}
- create_transitions (timeline, child);
+ timeline_create_transitions (timeline, child);
}
}
diff --git a/tests/check/python/common.py b/tests/check/python/common.py
index 23d81e99..81e78557 100644
--- a/tests/check/python/common.py
+++ b/tests/check/python/common.py
@@ -55,6 +55,7 @@ def create_main_loop():
mainloop.run = run
return mainloop
+
def create_project(with_group=False, saved=False):
"""Creates a project with two clips in a group."""
project = GES.Project()
@@ -78,6 +79,7 @@ def create_project(with_group=False, saved=False):
return timeline
+
class GESTest(unittest.TestCase):
def _log(self, func, format, *args):
string = format
@@ -105,9 +107,22 @@ class GESTest(unittest.TestCase):
class GESSimpleTimelineTest(GESTest):
+ def __init__(self, *args):
+ self.track_types = [GES.TrackType.AUDIO, GES.TrackType.VIDEO]
+ super(GESSimpleTimelineTest, self).__init__(*args)
+
def setUp(self):
- self.timeline = GES.Timeline.new_audio_video()
- self.assertEqual(len(self.timeline.get_tracks()), 2)
+ self.timeline = GES.Timeline.new()
+ for track_type in self.track_types:
+ self.assertIn(
+ track_type, [GES.TrackType.AUDIO, GES.TrackType.VIDEO])
+ if track_type == GES.TrackType.AUDIO:
+ self.timeline.add_track(GES.AudioTrack.new())
+ else:
+ self.timeline.add_track(GES.VideoTrack.new())
+
+ self.assertEqual(len(self.timeline.get_tracks()),
+ len(self.track_types))
self.layer = self.timeline.append_layer()
def add_clip(self, start, in_point, duration):
diff --git a/tests/check/python/test_timeline.py b/tests/check/python/test_timeline.py
index f7d3556e..1769b5fc 100644
--- a/tests/check/python/test_timeline.py
+++ b/tests/check/python/test_timeline.py
@@ -45,6 +45,7 @@ class TestTimeline(unittest.TestCase):
project = GES.Project.new(uri=timeline.get_asset().props.uri)
loaded_called = False
+
def loaded(unused_project, unused_timeline):
nonlocal loaded_called
loaded_called = True
@@ -62,6 +63,59 @@ class TestTimeline(unittest.TestCase):
self.assertTrue(loaded_called)
handle.assert_not_called()
+
+class TestSplitting(GESSimpleTimelineTest):
+ def setUp(self):
+ self.track_types = [GES.TrackType.AUDIO]
+ super(TestSplitting, self).setUp()
+
+ def assertTimelineTopology(self, topology):
+ res = []
+ for layer in self.timeline.get_layers():
+ layer_timings = []
+ for clip in layer.get_clips():
+ layer_timings.append(
+ (type(clip), clip.props.start, clip.props.duration))
+
+ res.append(layer_timings)
+
+ self.assertEqual(topology, res)
+ return res
+
+ def test_spliting_with_auto_transition_on_the_left(self):
+ self.timeline.props.auto_transition = True
+ clip1 = self.add_clip(0, 0, 100)
+ clip2 = self.add_clip(50, 0, 100)
+ self.assertTimelineTopology([
+ [ # Unique layer
+ (GES.TestClip, 0, 100),
+ (GES.TransitionClip, 50, 50),
+ (GES.TestClip, 50, 100)
+ ]
+ ])
+
+ clip1.split(25)
+ self.assertTimelineTopology([
+ [ # Unique layer
+ (GES.TestClip, 0, 25),
+ (GES.TestClip, 25, 75),
+ (GES.TransitionClip, 50, 50),
+ (GES.TestClip, 50, 100),
+ ]
+ ])
+
+ clip2.split(125)
+ self.assertTimelineTopology([
+ [ # Unique layer
+ (GES.TestClip, 0, 25),
+ (GES.TestClip, 25, 75),
+ (GES.TransitionClip, 50, 50),
+ (GES.TestClip, 50, 75),
+ (GES.TestClip, 125, 25),
+ ]
+ ])
+
+
class TestEditing(GESSimpleTimelineTest):
def test_transition_disappears_when_moving_to_another_layer(self):
@@ -71,7 +125,8 @@ class TestEditing(GESSimpleTimelineTest):
self.assertEquals(len(self.layer.get_clips()), 4)
layer2 = self.timeline.append_layer()
- clip2.edit([], layer2.get_priority(), GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, clip2.props.start)
+ clip2.edit([], layer2.get_priority(), GES.EditMode.EDIT_NORMAL,
+ GES.Edge.EDGE_NONE, clip2.props.start)
self.assertEquals(len(self.layer.get_clips()), 1)
self.assertEquals(len(layer2.get_clips()), 1)
@@ -83,7 +138,8 @@ class TestEditing(GESSimpleTimelineTest):
self.assertEquals(len(all_clips), 4)
layer2 = self.timeline.append_layer()
- clip1.edit([], layer2.get_priority(), GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, clip1.props.start)
+ clip1.edit([], layer2.get_priority(), GES.EditMode.EDIT_RIPPLE,
+ GES.Edge.EDGE_NONE, clip1.props.start)
self.assertEquals(self.layer.get_clips(), [])
self.assertEquals(set(layer2.get_clips()), set(all_clips))
@@ -94,7 +150,8 @@ class TestEditing(GESSimpleTimelineTest):
all_clips = self.layer.get_clips()
self.assertEquals(len(all_clips), 4)
- clip1.edit([], self.layer.get_priority(), GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, clip2.props.start + 1)
+ clip1.edit([], self.layer.get_priority(), GES.EditMode.EDIT_RIPPLE,
+ GES.Edge.EDGE_NONE, clip2.props.start + 1)
self.assertEquals(set(self.layer.get_clips()), set(all_clips))
def test_transition_rippling_over_does_not_create_another_transition(self):
@@ -103,14 +160,17 @@ class TestEditing(GESSimpleTimelineTest):
clip1 = self.add_clip(0, 0, 17 * Gst.SECOND)
clip2 = clip1.split(7.0 * Gst.SECOND)
# Make a transition between the two clips
- clip1.edit([], self.layer.get_priority(), GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 4.5 * Gst.SECOND)
+ clip1.edit([], self.layer.get_priority(),
+ GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 4.5 * Gst.SECOND)
# Rippl clip1 and check that transitions ar always the sames
all_clips = self.layer.get_clips()
self.assertEquals(len(all_clips), 4)
- clip1.edit([], self.layer.get_priority(), GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, 41.5 * Gst.SECOND)
+ clip1.edit([], self.layer.get_priority(), GES.EditMode.EDIT_RIPPLE,
+ GES.Edge.EDGE_NONE, 41.5 * Gst.SECOND)
self.assertEquals(len(self.layer.get_clips()), 4)
- clip1.edit([], self.layer.get_priority(), GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, 35 * Gst.SECOND)
+ clip1.edit([], self.layer.get_priority(),
+ GES.EditMode.EDIT_RIPPLE, GES.Edge.EDGE_NONE, 35 * Gst.SECOND)
self.assertEquals(len(self.layer.get_clips()), 4)
@@ -156,7 +216,9 @@ class TestTransitions(GESSimpleTimelineTest):
clip2.connect("notify::start", property_changed_cb)
# Move clip2 to create a transition with clip1.
- clip2.edit([], self.layer.get_priority(), GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 50)
+ clip2.edit([], self.layer.get_priority(),
+ GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 50)
# The clip-added signal is emitted twice, once for the video
# transition and once for the audio transition.
- self.assertEqual(signals, ["notify::start", "clip-added", "clip-added"])
+ self.assertEqual(
+ signals, ["notify::start", "clip-added", "clip-added"])