[pitivi: 2/8] Fix some overlap checks.



commit 32bbd39204ad02ac732e78023c178cbb3e045905
Author: Alessandro Decina <alessandro d gmail com>
Date:   Fri Jul 31 19:04:38 2009 +0200

    Fix some overlap checks.
    
    This commit makes Timeline.get(Next|Prev)TimelineObject aware of tracks, fixing
    overlap checks editing objects having the same priority but different track.

 pitivi/timeline/gap.py      |    8 ++-
 pitivi/timeline/timeline.py |   58 +++++++++++++++++++++----
 pitivi/timeline/track.py    |   10 +++--
 pitivi/utils.py             |   26 ++++--------
 tests/test_timeline.py      |   97 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 165 insertions(+), 34 deletions(-)
---
diff --git a/pitivi/timeline/gap.py b/pitivi/timeline/gap.py
index c99e8a9..99f9d9b 100644
--- a/pitivi/timeline/gap.py
+++ b/pitivi/timeline/gap.py
@@ -34,12 +34,13 @@ class Gap(object):
         return cmp(self.duration, other.duration)
 
     @classmethod
-    def findAroundObject(self, timeline_object, priority=-1):
+    def findAroundObject(self, timeline_object, priority=-1, tracks=None):
         from pitivi.timeline.timeline import TimelineError
 
         timeline = timeline_object.timeline
         try:
-            prev = timeline.getPreviousTimelineObject(timeline_object, priority)
+            prev = timeline.getPreviousTimelineObject(timeline_object,
+                    priority, tracks)
         except TimelineError:
             left_object = None
             right_object = timeline_object
@@ -54,7 +55,8 @@ class Gap(object):
         left_gap = Gap(left_object, right_object, start, duration)
 
         try:
-            next = timeline.getNextTimelineObject(timeline_object, priority)
+            next = timeline.getNextTimelineObject(timeline_object,
+                    priority, tracks)
         except TimelineError:
             left_object = timeline_object
             right_object = None
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index 0cb05a0..77e8ed8 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -1037,13 +1037,14 @@ class EditingContext(object):
 
         return position, priority
 
-    def _getGapsAtPriority(self, priority, timeline_objects):
+    def _getGapsAtPriority(self, priority, timeline_objects, tracks=None):
         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))
+            left_gap, right_gap = Gap.findAroundObject(timeline_object,
+                    timeline_object.priority + prio_diff, tracks)
+            gaps.update(left_gap, right_gap)
 
         return gaps.left_gap, gaps.right_gap
 
@@ -1061,13 +1062,18 @@ class MoveContext(EditingContext):
         latest = 0
         self.default_originals = {}
         self.timeline_objects = set([])
+        self.tracks = set([])
         all_objects = set(other)
         all_objects.add(focus)
         for obj in all_objects:
             if isinstance(obj, TrackObject):
                 timeline_object = obj.timeline_object
+                self.tracks.add(obj.track)
             else:
                 timeline_object = obj
+                timeline_object_tracks = set(track_object.track for track_object
+                        in timeline_object.track_objects)
+                self.tracks.update(timeline_object_tracks)
 
             self.timeline_objects.add(timeline_object)
 
@@ -1111,7 +1117,7 @@ class MoveContext(EditingContext):
             timeline_objects = self.timeline_objects
 
         return EditingContext._getGapsAtPriority(self,
-                priority, timeline_objects)
+                priority, timeline_objects, self.tracks)
 
     def setMode(self, mode):
         if mode == self.ROLL:
@@ -1230,10 +1236,15 @@ class TrimStartContext(EditingContext):
         EditingContext.__init__(self, timeline, focus, other)
         self.adjacent = timeline.edges.getObjsAdjacentToStart(focus)
         self.adjacent_originals = self._saveValues(self.adjacent)
+        self.tracks = set([])
         if isinstance(self.focus, TrackObject):
             focus_timeline_object = self.focus.timeline_object
+            self.tracks.add(self.focus.track)
         else:
             focus_timeline_object = self.focus
+            tracks = set(track_object.track for track_object in
+                    focus.track_objects)
+            self.tracks.update(tracks)
         self.focus_timeline_object = focus_timeline_object
         self.default_originals = self._saveValues([focus_timeline_object])
 
@@ -1260,7 +1271,7 @@ class TrimStartContext(EditingContext):
 
         timeline_objects = [self.focus_timeline_object]
         left_gap, right_gap = self._getGapsAtPriority(self.focus.priority,
-                timeline_objects)
+                timeline_objects, self.tracks)
 
         if left_gap is invalid_gap:
             self._defaultTo(initial_position, self.focus.priority)
@@ -1274,10 +1285,15 @@ class TrimEndContext(EditingContext):
         EditingContext.__init__(self, timeline, focus, other)
         self.adjacent = timeline.edges.getObjsAdjacentToEnd(focus)
         self.adjacent_originals = self._saveValues(self.adjacent)
+        self.tracks = set([])
         if isinstance(self.focus, TrackObject):
             focus_timeline_object = self.focus.timeline_object
+            self.tracks.add(focus.track)
         else:
             focus_timeline_object = self.focus
+            tracks = set(track_object.track for track_object in
+                    focus.track_objects)
+            self.tracks.update(tracks)
         self.focus_timeline_object = focus_timeline_object
         self.default_originals = self._saveValues([focus_timeline_object])
 
@@ -1307,7 +1323,7 @@ class TrimEndContext(EditingContext):
 
         timeline_objects = [self.focus_timeline_object]
         left_gap, right_gap = self._getGapsAtPriority(self.focus.priority,
-                timeline_objects)
+                timeline_objects, self.tracks)
 
         if right_gap is invalid_gap:
             self._defaultTo(absolute_initial_duration, self.focus.priority)
@@ -1553,20 +1569,42 @@ class Timeline(Signallable, Loggable):
 
         return output_stream_to_track_map
 
-    def getPreviousTimelineObject(self, obj, priority=-1):
-        prev = getPreviousObject(obj, self.timeline_objects, priority)
+    def getPreviousTimelineObject(self, obj, priority=-1, tracks=None):
+        if tracks is None:
+            skip = None
+        else:
+            def skipIfNotInTheseTracks(timeline_object):
+                return self._skipIfNotInTracks(timeline_object, tracks)
+            skip = skipIfNotInTheseTracks
+
+        prev = getPreviousObject(obj, self.timeline_objects,
+                priority, skip=skip)
+
         if prev is None:
             raise TimelineError("no previous timeline object", obj)
 
         return prev
 
-    def getNextTimelineObject(self, obj, priority=-1):
-        next = getNextObject(obj, self.timeline_objects, priority)
+    def getNextTimelineObject(self, obj, priority=-1, tracks=None):
+        if tracks is None:
+            skip = None
+        else:
+            def skipIfNotInTheseTracks(timeline_object):
+                return self._skipIfNotInTracks(timeline_object, tracks)
+            skip = skipIfNotInTheseTracks
+
+        next = getNextObject(obj, self.timeline_objects, priority, skip)
         if next is None:
             raise TimelineError("no next timeline object", obj)
 
         return next
 
+    def _skipIfNotInTracks(self, timeline_object, tracks):
+        timeline_object_tracks = set(track_object.track for track_object in
+                timeline_object.track_objects)
+
+        return not tracks.intersection(timeline_object_tracks)
+
     def setSelectionToObj(self, obj, mode):
         """
         Update the timeline's selection with the given object and mode.
diff --git a/pitivi/timeline/track.py b/pitivi/timeline/track.py
index 020c6a2..a951095 100644
--- a/pitivi/timeline/track.py
+++ b/pitivi/timeline/track.py
@@ -20,7 +20,6 @@
 # Boston, MA 02111-1307, USA.
 
 import gst
-import weakref
 
 from pitivi.signalinterface import Signallable
 from pitivi.utils import get_controllable_properties, getPreviousObject, \
@@ -675,9 +674,12 @@ class Track(Signallable):
             self.default_track_object = None
             raise
 
+    def _skipDefaultTrackObject(self, timeline_object):
+        return timeline_object is self.default_track_object
+
     def getPreviousTrackObject(self, obj, priority=-1):
         prev = getPreviousObject(obj, self.track_objects, priority,
-                [self.default_track_object])
+                self._skipDefaultTrackObject)
         if prev is None:
             raise TrackError("no previous track object", obj)
 
@@ -685,7 +687,7 @@ class Track(Signallable):
 
     def getNextTrackObject(self, obj, priority=-1):
         next = getNextObject(obj, self.track_objects, priority,
-                [self.default_track_object])
+                self._skipDefaultTrackObject)
         if next is None:
             raise TrackError("no next track object", obj)
 
@@ -730,7 +732,7 @@ class Track(Signallable):
             raise TrackError()
         track_object.makeBin()
 
-        track_object.track = weakref.proxy(self)
+        track_object.track = self
 
         start_insort_right(self.track_objects, track_object)
 
diff --git a/pitivi/utils.py b/pitivi/utils.py
index 67200aa..02db982 100644
--- a/pitivi/utils.py
+++ b/pitivi/utils.py
@@ -380,21 +380,19 @@ def findObject(obj, objects):
 
     return low
 
-def getPreviousObject(obj, objects, priority=-1, exclude=None):
+def getPreviousObject(obj, objects, priority=-1, skip=None):
     if priority == -1:
         priority = obj.priority
 
-    if exclude is None:
-        exclude = []
-
     obj_index = findObject(obj, objects)
     if obj_index is None:
-        import pdb; pdb.set_trace()
+        raise Exception("woot this should never happen")
     # check if there are same-start objects
     prev_obj_index = obj_index + 1
     while prev_obj_index < len(objects):
         prev_obj = objects[prev_obj_index]
-        if prev_obj in exclude:
+        prev_obj_index += 1
+        if skip is not None and skip(prev_obj):
             continue
 
         if prev_obj.start != obj.start:
@@ -403,36 +401,30 @@ def getPreviousObject(obj, objects, priority=-1, exclude=None):
         if priority is None or prev_obj.priority == priority:
             return prev_obj
 
-        prev_obj_index += 1
 
     # check if there are objects with start < obj.start
     prev_obj_index = obj_index - 1
     while prev_obj_index >= 0:
         prev_obj = objects[prev_obj_index]
-        if prev_obj not in exclude and \
-                (priority is None or \
-                    prev_obj.priority == priority):
+        if (priority is None or prev_obj.priority == priority) \
+                and (skip is None or not skip(prev_obj)):
             return prev_obj
 
         prev_obj_index -= 1
 
     return None
 
-def getNextObject(obj, objects, priority=-1, exclude=None):
+def getNextObject(obj, objects, priority=-1, skip=None):
     if priority == -1:
         priority = obj.priority
 
-    if exclude is None:
-        exclude = []
-
     obj_index = findObject(obj, objects)
     next_obj_index = obj_index + 1
     objs_len = len(objects)
     while next_obj_index < objs_len:
         next_obj = objects[next_obj_index]
-        if next_obj not in exclude and \
-                (priority is None or \
-                    next_obj.priority == priority):
+        if (priority is None or next_obj.priority == priority) and \
+                (skip is None or not skip(next_obj)):
             return next_obj
 
         next_obj_index += 1
diff --git a/tests/test_timeline.py b/tests/test_timeline.py
index 821fca6..2b835f4 100644
--- a/tests/test_timeline.py
+++ b/tests/test_timeline.py
@@ -886,8 +886,49 @@ class TestContexts(TestCase):
         self.failUnlessEqual(self.track_object1.in_point, 0)
         self.failUnlessEqual(self.track_object2.start, gst.SECOND * 15)
         self.failUnlessEqual(self.track_object3.start, gst.SECOND * 25)
+        context.finish()
+
+    def testMoveContextOverlapDifferentTracks(self):
+        # start
+        # track1:          [focus][t2]
+        # track2:  [t3 ]
+        self.track_object1.start = 20 * gst.SECOND
+        self.track_object1.duration = 10 * gst.SECOND
+        self.track_object1.priority = 1
+        self.track_object2.start = 30 * gst.SECOND
+        self.track_object2.duration = 10 * gst.SECOND
+        self.track_object2.priority = 1
+        self.track_object3.start = 1 * gst.SECOND
+        self.track_object3.duration = 10 * gst.SECOND
+        self.track_object3.priority = 1
 
+        # move to
+        # track1:     [focus][t2]
+        # track2:  [t3 ]
+        context = MoveContext(self.timeline, self.track_object1,
+                set([self.track_object2]))
+        context.editTo(gst.SECOND * 1, 0)
+        context.finish()
+        self.failUnlessEqual(self.track_object1.start, 1 * 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.duration,  10 * gst.SECOND)
+        self.failUnlessEqual(self.track_object3.start, 1 * gst.SECOND)
+        self.failUnlessEqual(self.track_object3.duration,  10 * gst.SECOND)
+        
+        # move to
+        # track1:     [focus][t2]
+        # track2:             [t3 ]
+        context = MoveContext(self.timeline, self.track_object3,
+                set([]))
+        context.editTo(gst.SECOND * 10, 0)
         context.finish()
+        self.failUnlessEqual(self.track_object1.start, 1 * 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.duration,  10 * gst.SECOND)
+        self.failUnlessEqual(self.track_object3.start, 10 * gst.SECOND)
+        self.failUnlessEqual(self.track_object3.duration,  10 * gst.SECOND)
 
     def testMoveContextFocusNotEarliest(self):
         #     [t2  ][focus]  [t3     ]
@@ -1189,6 +1230,34 @@ class TestContexts(TestCase):
         self.failUnlessEqual(self.track_object2.in_point, 2 * gst.SECOND)
         self.failUnlessEqual(self.track_object2.duration, 11 * gst.SECOND)
 
+    def testTrimStartContextMarginsDifferentTracks(self):
+        # start
+        # track1:        [focus][t2]
+        # track2:  [t3 ]
+        self.track_object1.start = 20 * gst.SECOND
+        self.track_object1.in_point = 15 * gst.SECOND
+        self.track_object1.duration = 10 * gst.SECOND
+        self.track_object1.priority = 1
+        self.track_object2.start = 30 * gst.SECOND
+        self.track_object2.duration = 10 * gst.SECOND
+        self.track_object2.priority = 1
+        self.track_object3.start = 1 * gst.SECOND
+        self.track_object3.duration = 10 * gst.SECOND
+        self.track_object3.priority = 1
+
+        # trim back to
+        # track1:    [     focus][t2]
+        # track2:  [t3 ]
+        context = TrimStartContext(self.timeline, self.track_object1, set([]))
+        context.editTo(gst.SECOND * 5, 0)
+        context.finish()
+        self.failUnlessEqual(self.track_object1.start, 5 * gst.SECOND)
+        self.failUnlessEqual(self.track_object1.duration,  25 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.start, 30 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.duration,  10 * gst.SECOND)
+        self.failUnlessEqual(self.track_object3.start, 1 * gst.SECOND)
+        self.failUnlessEqual(self.track_object3.duration,  10 * gst.SECOND)
+
     def testTrimEndContext(self):
         self.track_object1.start = 1 * gst.SECOND
         self.track_object1.in_point = 3 * gst.SECOND
@@ -1233,6 +1302,34 @@ class TestContexts(TestCase):
         self.failUnlessEqual(self.track_object2.in_point, 3 * gst.SECOND)
         self.failUnlessEqual(self.track_object2.duration, 10 * gst.SECOND)
 
+    def testTrimEndContextMarginsDifferentTracks(self):
+        # start
+        # track1:  [t1][t2 ]
+        # track2:             [t3 ]
+        self.track_object1.start = 1 * gst.SECOND
+        self.track_object1.duration = 10 * gst.SECOND
+        self.track_object1.priority = 1
+        self.track_object2.start = 10 * gst.SECOND
+        self.track_object2.duration = 10 * gst.SECOND
+        self.track_object2.timeline_object.factory.duration = 30 * gst.SECOND
+        self.track_object2.priority = 1
+        self.track_object3.start = 25 * gst.SECOND
+        self.track_object3.duration = 10 * gst.SECOND
+        self.track_object3.priority = 1
+
+        # extend to
+        # track1:  [t1][t2    ]
+        # track2:           [t3 ]
+        context = TrimEndContext(self.timeline, self.track_object2, set([]))
+        context.editTo(gst.SECOND * 30, 0)
+        context.finish()
+        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
+        self.failUnlessEqual(self.track_object1.duration,  10 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.start, 10 * gst.SECOND)
+        self.failUnlessEqual(self.track_object2.duration,  20 * gst.SECOND)
+        self.failUnlessEqual(self.track_object3.start, 25 * gst.SECOND)
+        self.failUnlessEqual(self.track_object3.duration,  10 * gst.SECOND)
+
     def testEmptyOther(self):
         context = MoveContext(self.timeline, self.track_object1, set())
         context.finish()



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