[pitivi] Avoid collapses when trimming. Fixes #589694.



commit 268d057cc1a06a5dcce05c2a6c05aaa67b7d7e84
Author: Alessandro Decina <alessandro d gmail com>
Date:   Wed Jul 29 20:21:23 2009 +0200

    Avoid collapses when trimming. Fixes #589694.

 pitivi/timeline/timeline.py |   68 +++++++++++++++++++++++++++++++++++++------
 tests/test_timeline.py      |   62 ++++++++++++++++++++++++++++++++-------
 tests/test_track.py         |   23 ++++++++++++--
 3 files changed, 130 insertions(+), 23 deletions(-)
---
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index ca153a5..0cb05a0 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -1011,7 +1011,7 @@ class EditingContext(object):
         pass
 
     def _rippleTo(self, position, priority):
-        pass
+        return position, priority
 
     def _finishDefault(self):
         pass
@@ -1037,6 +1037,17 @@ class EditingContext(object):
 
         return position, priority
 
+    def _getGapsAtPriority(self, priority, timeline_objects):
+        gaps = SmallestGapsFinder(timeline_objects)
+        prio_diff = priority - self.focus.priority
+
+        for timeline_object in timeline_objects:
+            gaps.update(*Gap.findAroundObject(timeline_object,
+                    timeline_object.priority + prio_diff))
+
+        return gaps.left_gap, gaps.right_gap
+
+
 class MoveContext(EditingContext):
 
     """An editing context which sets the start point of the editing targets.
@@ -1098,14 +1109,9 @@ class MoveContext(EditingContext):
             timeline_objects = self.timeline_objects_plus_ripple
         else:
             timeline_objects = self.timeline_objects
-        gaps = SmallestGapsFinder(timeline_objects)
-        prio_diff = priority - self.focus.priority
-
-        for timeline_object in timeline_objects:
-            gaps.update(*Gap.findAroundObject(timeline_object,
-                    timeline_object.priority + prio_diff))
 
-        return gaps.left_gap, gaps.right_gap
+        return EditingContext._getGapsAtPriority(self,
+                priority, timeline_objects)
 
     def setMode(self, mode):
         if mode == self.ROLL:
@@ -1224,6 +1230,12 @@ class TrimStartContext(EditingContext):
         EditingContext.__init__(self, timeline, focus, other)
         self.adjacent = timeline.edges.getObjsAdjacentToStart(focus)
         self.adjacent_originals = self._saveValues(self.adjacent)
+        if isinstance(self.focus, TrackObject):
+            focus_timeline_object = self.focus.timeline_object
+        else:
+            focus_timeline_object = self.focus
+        self.focus_timeline_object = focus_timeline_object
+        self.default_originals = self._saveValues([focus_timeline_object])
 
     def _rollTo(self, position, priority):
         earliest = self.focus.start - self.focus.in_point
@@ -1236,17 +1248,38 @@ class TrimStartContext(EditingContext):
         self._restoreValues(self.adjacent_originals)
 
     def _defaultTo(self, position, priority):
-        earliest = self.focus.start - self.focus.in_point
+        earliest = max(0, self.focus.start - self.focus.in_point)
         self.focus.trimStart(max(position, earliest), snap=self.snap)
 
         return position, priority
 
+    def finish(self):
+        EditingContext.finish(self)
+
+        initial_position = self.default_originals[self.focus_timeline_object][0]
+
+        timeline_objects = [self.focus_timeline_object]
+        left_gap, right_gap = self._getGapsAtPriority(self.focus.priority,
+                timeline_objects)
+
+        if left_gap is invalid_gap:
+            self._defaultTo(initial_position, self.focus.priority)
+            left_gap, right_gap = Gap.findAroundObject(self.focus_timeline_object)
+            position = initial_position - left_gap.duration
+            self._defaultTo(position, self.focus.priority)
+
 class TrimEndContext(EditingContext):
 
     def __init__(self, timeline, focus, other):
         EditingContext.__init__(self, timeline, focus, other)
         self.adjacent = timeline.edges.getObjsAdjacentToEnd(focus)
         self.adjacent_originals = self._saveValues(self.adjacent)
+        if isinstance(self.focus, TrackObject):
+            focus_timeline_object = self.focus.timeline_object
+        else:
+            focus_timeline_object = self.focus
+        self.focus_timeline_object = focus_timeline_object
+        self.default_originals = self._saveValues([focus_timeline_object])
 
     def _rollTo(self, position, priority):
         if self._snap:
@@ -1265,6 +1298,23 @@ class TrimEndContext(EditingContext):
 
         return position, priority
 
+    def finish(self):
+        EditingContext.finish(self)
+
+        initial_position, initial_duration = \
+                self.default_originals[self.focus_timeline_object][0:2]
+        absolute_initial_duration = initial_position + initial_duration
+
+        timeline_objects = [self.focus_timeline_object]
+        left_gap, right_gap = self._getGapsAtPriority(self.focus.priority,
+                timeline_objects)
+
+        if right_gap is invalid_gap:
+            self._defaultTo(absolute_initial_duration, self.focus.priority)
+            left_gap, right_gap = Gap.findAroundObject(self.focus_timeline_object)
+            duration = absolute_initial_duration + right_gap.duration
+            self._defaultTo(duration, self.focus.priority)
+
 class Timeline(Signallable, Loggable):
     """
     Top-level container for L{TimelineObject}s.
diff --git a/tests/test_timeline.py b/tests/test_timeline.py
index 587908d..821fca6 100644
--- a/tests/test_timeline.py
+++ b/tests/test_timeline.py
@@ -1149,33 +1149,54 @@ class TestContexts(TestCase):
     def testTrimStartContext(self):
         self.track_object1.start = 1 * gst.SECOND
         self.track_object1.in_point = 3 * gst.SECOND
-        self.track_object2.start = 1 * gst.SECOND
+        self.track_object1.duration = 10 * gst.SECOND
+        self.track_object2.start = 11 * gst.SECOND
         self.track_object2.in_point = 10 * gst.SECOND
-        self.track_object3.start = 15 * gst.SECOND
+        self.track_object2.duration = 10 * gst.SECOND
+        self.track_object3.start = 25 * gst.SECOND
         self.track_object3.in_point = 20 * gst.SECOND
+        self.track_object3.duration = 10 * gst.SECOND
 
         # set up the initial state of the timeline and create the track object
         # [focus]     [t2   ]     [t3     ]
         context = TrimStartContext(self.timeline, self.track_object1, self.other)
-        context.editTo(gst.SECOND * 10, 0)
+        context.editTo(gst.SECOND * 5, 0)
         context.finish()
 
-        self.failUnlessEqual(self.track_object1.start, 10 * gst.SECOND)
-        self.failUnlessEqual(self.track_object1.in_point, 12 * gst.SECOND)
-        self.failUnlessEqual(self.track_object2.start, 1 * gst.SECOND)
+        self.failUnlessEqual(self.track_object1.start, 5 * gst.SECOND)
+        self.failUnlessEqual(self.track_object1.in_point, 7 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.start, 11 * gst.SECOND)
         self.failUnlessEqual(self.track_object2.in_point, 10 * gst.SECOND)
-        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
+        self.failUnlessEqual(self.track_object3.start, 25 * gst.SECOND)
         self.failUnlessEqual(self.track_object3.in_point, 20 * gst.SECOND)
 
+    def testTrimStartContextMargins(self):
+        self.track_object1.start = 1 * gst.SECOND
+        self.track_object1.in_point = 2 * gst.SECOND
+        self.track_object1.duration = 10 * gst.SECOND
+        self.track_object2.start = 12 * gst.SECOND
+        self.track_object2.in_point = 3 * gst.SECOND
+        self.track_object2.duration = 10 * gst.SECOND
+
+        context = TrimStartContext(self.timeline, self.track_object2, self.other)
+        context.editTo(gst.SECOND * 9, 0)
+        context.finish()
+
+        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
+        self.failUnlessEqual(self.track_object1.in_point, 2 * gst.SECOND)
+        self.failUnlessEqual(self.track_object1.duration, 10 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.start, 11 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.in_point, 2 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.duration, 11 * gst.SECOND)
 
     def testTrimEndContext(self):
         self.track_object1.start = 1 * gst.SECOND
         self.track_object1.in_point = 3 * gst.SECOND
         self.track_object1.duration = 15 * gst.SECOND
-        self.track_object2.start = 1 * gst.SECOND
+        self.track_object2.start = 16 * gst.SECOND
         self.track_object2.in_point = 10 * gst.SECOND
         self.track_object2.duration = 16 * gst.SECOND
-        self.track_object3.start = 15 * gst.SECOND
+        self.track_object3.start = 32 * gst.SECOND
         self.track_object3.in_point = 19 * gst.SECOND
         self.track_object3.duration = 23 * gst.SECOND
 
@@ -1186,13 +1207,32 @@ class TestContexts(TestCase):
         self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
         self.failUnlessEqual(self.track_object1.in_point, 3 * gst.SECOND)
         self.failUnlessEqual(self.track_object1.duration, 9 * gst.SECOND)
-        self.failUnlessEqual(self.track_object2.start, 1 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.start, 16 * gst.SECOND)
         self.failUnlessEqual(self.track_object2.in_point, 10 * gst.SECOND)
         self.failUnlessEqual(self.track_object2.duration, 16 * gst.SECOND)
-        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
+        self.failUnlessEqual(self.track_object3.start, 32 * gst.SECOND)
         self.failUnlessEqual(self.track_object3.in_point, 19 * gst.SECOND)
         self.failUnlessEqual(self.track_object3.duration, 23 * gst.SECOND)
 
+    def testTrimEndContextMargins(self):
+        self.track_object1.start = 1 * gst.SECOND
+        self.track_object1.in_point = 2 * gst.SECOND
+        self.track_object1.duration = 10 * gst.SECOND
+        self.track_object2.start = 12 * gst.SECOND
+        self.track_object2.in_point = 3 * gst.SECOND
+        self.track_object2.duration = 10 * gst.SECOND
+
+        context = TrimEndContext(self.timeline, self.track_object1, self.other)
+        context.editTo(gst.SECOND * 13, 0)
+        context.finish()
+
+        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
+        self.failUnlessEqual(self.track_object1.in_point, 2 * gst.SECOND)
+        self.failUnlessEqual(self.track_object1.duration, 11 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.start, 12 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.in_point, 3 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.duration, 10 * gst.SECOND)
+
     def testEmptyOther(self):
         context = MoveContext(self.timeline, self.track_object1, set())
         context.finish()
diff --git a/tests/test_track.py b/tests/test_track.py
index aa41697..f862d52 100644
--- a/tests/test_track.py
+++ b/tests/test_track.py
@@ -203,16 +203,33 @@ class TestTrackObject(TestCase):
 
         # trim somewhere in the middle
         monitor = TrackSignalMonitor(obj)
-        time = 4 * gst.SECOND
+        time = 7 * gst.SECOND
         obj.trimStart(time)
         self.failUnlessEqual(obj.start, time)
-        self.failUnlessEqual(obj.in_point, 3 * gst.SECOND)
-        self.failUnlessEqual(obj.duration, 8 * gst.SECOND)
+        self.failUnlessEqual(obj.in_point, 6 * gst.SECOND)
+        self.failUnlessEqual(obj.duration, 5 * gst.SECOND)
         self.failUnlessEqual(obj.rate, 1)
         self.failUnlessEqual(monitor.start_changed_count, 1)
         self.failUnlessEqual(monitor.in_point_changed_count, 1)
         self.failUnlessEqual(monitor.duration_changed_count, 1)
 
+        obj.start = 10 * gst.SECOND
+        obj.in_point = 11 * gst.SECOND
+        obj.duration = 15 * gst.SECOND
+
+        # this should be possible
+        monitor = TrackSignalMonitor(obj)
+        time = 0 * gst.SECOND
+        obj.trimStart(time)
+        self.failUnlessEqual(obj.start, 0 * gst.SECOND)
+        self.failUnlessEqual(obj.in_point, 1 * gst.SECOND)
+        self.failUnlessEqual(obj.duration, 25 * gst.SECOND)
+        self.failUnlessEqual(obj.rate, 1)
+        self.failUnlessEqual(monitor.start_changed_count, 1)
+        self.failUnlessEqual(monitor.in_point_changed_count, 1)
+        self.failUnlessEqual(monitor.duration_changed_count, 1)
+
+
     def testSplitObject(self):
         DURATION = 10 * gst.SECOND
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]