[pitivi: 3/16] Make TrackObjects reusable once they have been removed from a Track.



commit 9122088baac0e760567c3c931c9ed6580c852a85
Author: Alessandro Decina <alessandro d gmail com>
Date:   Fri Jul 3 16:44:35 2009 +0200

    Make TrackObjects reusable once they have been removed from a Track.
    
    This change makes TrackObjects reusable by decoupling construction and
    initialization. Now you can call makeBin() and releaseBin() in pairs on the same
    object to create/destroy bins keeping the same track object instance (with the
    associated data, eg keyframes).
    With this change, bins are now created when objects are added to a Track
    (Track.addTrackObject) and destroyed when removed from a track
    (Track.removeTrackObject)
    The first visible benefit of this change is that it simplifies TimelineObject
    do/undo operations a lot.

 pitivi/formatters/etree.py       |    7 +++----
 pitivi/timeline/timeline.py      |    1 -
 pitivi/timeline/timeline_undo.py |   35 ++++++-----------------------------
 pitivi/timeline/track.py         |   16 +++++++++-------
 tests/test_etree_formatter.py    |   24 ++++++++++++++++--------
 tests/test_timeline_undo.py      |    2 +-
 tests/test_track.py              |    3 +++
 7 files changed, 38 insertions(+), 50 deletions(-)
---
diff --git a/pitivi/formatters/etree.py b/pitivi/formatters/etree.py
index 45ca28f..99b1e16 100644
--- a/pitivi/formatters/etree.py
+++ b/pitivi/formatters/etree.py
@@ -339,7 +339,7 @@ class ElementTreeFormatter(Formatter):
 
         return element
 
-    def _loadTrackObject(self, element):
+    def _loadTrackObject(self, track, element):
         self.debug("%r", element)
         klass = namedAny(element.attrib["type"])
 
@@ -353,6 +353,7 @@ class ElementTreeFormatter(Formatter):
         for name, value_string in self._filterElementProperties(element):
             value = self._parsePropertyValue(value_string)
             setattr(track_object, name, value)
+        track.addTrackObject(track_object)
         curves_element = element.find("curves")
         if curves_element:
             for curve in curves_element.getchildren():
@@ -389,7 +390,6 @@ class ElementTreeFormatter(Formatter):
 
     def _loadInterpolator(self, element, trackobject):
         interpolator = trackobject.getInterpolator(element.attrib["property"])
-
         start = element.find("start")
         interpolator.start.value = self._parsePropertyValue(
             start.attrib["value"])
@@ -455,8 +455,7 @@ class ElementTreeFormatter(Formatter):
 
         track_objects_element  = element.find("track-objects")
         for track_object_element in track_objects_element:
-            track_object = self._loadTrackObject(track_object_element)
-            track.addTrackObject(track_object)
+            self._loadTrackObject(track, track_object_element)
 
         return track
 
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index 8863811..2adb1c0 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -355,7 +355,6 @@ class TimelineObject(Signallable, Loggable):
                 raise TimelineError(str(e))
 
             other.addTrackObject(other_track_object)
-            track_object.track.addTrackObject(other_track_object)
 
         if self.timeline is not None:
             # if self is not yet in a timeline, the caller needs to add "other"
diff --git a/pitivi/timeline/timeline_undo.py b/pitivi/timeline/timeline_undo.py
index cefb64d..273cae3 100644
--- a/pitivi/timeline/timeline_undo.py
+++ b/pitivi/timeline/timeline_undo.py
@@ -75,16 +75,12 @@ class TimelineObjectAdded(UndoableAction):
     def __init__(self, timeline, timeline_object):
         self.timeline = timeline
         self.timeline_object = timeline_object
-        self.timeline_object_copy = self._copyTimelineObject(timeline_object)
+        self.tracks = dict((track_object, track_object.track)
+                for track_object in timeline_object.track_objects)
 
     def do(self):
-        temporary_timeline_object = \
-                self._copyTimelineObject(self.timeline_object_copy)
-        self.timeline_object.track_objects = []
-        for track_object in temporary_timeline_object.track_objects:
-            track, track_object.track = track_object.track, None
+        for track_object, track in self.tracks.iteritems():
             track.addTrackObject(track_object)
-            self.timeline_object.addTrackObject(track_object)
 
         self.timeline.addTimelineObject(self.timeline_object)
         self._done()
@@ -93,43 +89,24 @@ class TimelineObjectAdded(UndoableAction):
         self.timeline.removeTimelineObject(self.timeline_object, deep=True)
         self._undone()
 
-    def _copyTimelineObject(self, timeline_object):
-        copy = timeline_object.copy()
-        for (track_object_copy, track_object) in \
-                    zip(copy.track_objects, timeline_object.track_objects):
-            track_object_copy.track = track_object.track
-
-        return copy
-
 class TimelineObjectRemoved(UndoableAction):
     def __init__(self, timeline, timeline_object):
         self.timeline = timeline
         self.timeline_object = timeline_object
-        self.timeline_object_copy = self._copyTimelineObject(timeline_object)
+        self.tracks = dict((track_object, track_object.track)
+                for track_object in timeline_object.track_objects)
 
     def do(self):
         self.timeline.removeTimelineObject(self.timeline_object, deep=True)
         self._done()
 
     def undo(self):
-        temporary_timeline_object = \
-                self._copyTimelineObject(self.timeline_object_copy)
-        for track_object in temporary_timeline_object.track_objects:
-            track, track_object.track = track_object.track, None
+        for track_object, track in self.tracks.iteritems():
             track.addTrackObject(track_object)
 
-        self.timeline_object.track_objects = temporary_timeline_object.track_objects
         self.timeline.addTimelineObject(self.timeline_object)
         self._undone()
 
-    def _copyTimelineObject(self, timeline_object):
-        copy = timeline_object.copy()
-        for (track_object_copy, track_object) in \
-                    zip(copy.track_objects, timeline_object.track_objects):
-            track_object_copy.track = track_object.track
-
-        return copy
-
 class TimelineLogObserver(object):
     propertyChangedAction = TimelineObjectPropertyChanged
     timelineObjectAddedAction = TimelineObjectAdded
diff --git a/pitivi/timeline/track.py b/pitivi/timeline/track.py
index 2b899ba..183c7dd 100644
--- a/pitivi/timeline/track.py
+++ b/pitivi/timeline/track.py
@@ -275,7 +275,6 @@ class TrackObject(Signallable, Loggable):
         self.interpolators = {}
         self._rebuild_interpolators = True
         self.gnl_object = obj = self._makeGnlObject()
-        self.makeBin()
         self.trimmed_start = 0
         self.keyframes = []
 
@@ -344,6 +343,9 @@ class TrackObject(Signallable, Loggable):
             media_duration=self.media_duration, priority=self.priority)
         other.trimmed_start = self.trimmed_start
 
+        if self.track is not None:
+            self.track.addTrackObject(other)
+
         interpolators = self.getInterpolators()
         for property, interpolator in interpolators.itervalues():
             other_interpolator = other.getInterpolator(property.name)
@@ -507,18 +509,16 @@ class TrackObject(Signallable, Loggable):
 
     def makeBin(self):
         if self.stream is None:
-            raise TrackError
+            raise TrackError()
         if self.gnl_object is None:
-            raise TrackError
+            raise TrackError()
 
         bin = self.factory.makeBin(self.stream)
         self.gnl_object.add(bin)
         self._maybeBuildInterpolators()
 
     def releaseBin(self):
-        elts = list(self.gnl_object.elements())
-        if elts:
-            bin = elts[0]
+        for bin in list(self.gnl_object.elements()):
             self.gnl_object.remove(bin)
             bin.set_state(gst.STATE_NULL)
             self.factory.releaseBin(bin)
@@ -684,6 +684,8 @@ class Track(Signallable):
         except gst.AddError:
             raise TrackError()
 
+        track_object.makeBin()
+
         track_object.track = weakref.proxy(self)
         self.track_objects.append(track_object)
 
@@ -705,7 +707,7 @@ class Track(Signallable):
             raise TrackError()
 
         self._disconnectFromTrackObject(track_object)
-        track_object.release()
+        track_object.releaseBin()
 
         self.track_objects.remove(track_object)
         track_object.track = None
diff --git a/tests/test_etree_formatter.py b/tests/test_etree_formatter.py
index 21e6aba..f46db02 100644
--- a/tests/test_etree_formatter.py
+++ b/tests/test_etree_formatter.py
@@ -123,6 +123,8 @@ class TestFormatterSave(TestCase):
                 start=10 * gst.SECOND, duration=20 * gst.SECOND,
                 in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
                 priority=10)
+        track = Track(video_stream)
+        track.addTrackObject(track_object)
 
         # create an interpolator and insert it into the track object
         fakevol = gst.element_factory_make("volume")
@@ -185,6 +187,8 @@ class TestFormatterSave(TestCase):
                 start=10 * gst.SECOND, duration=20 * gst.SECOND,
                 in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
                 priority=10)
+        track = Track(video_stream)
+        track.addTrackObject(track_object)
 
         element = self.formatter._saveTrackObject(track_object)
         element_ref = self.formatter._saveTrackObjectRef(track_object)
@@ -229,6 +233,8 @@ class TestFormatterSave(TestCase):
                 start=10 * gst.SECOND, duration=20 * gst.SECOND,
                 in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
                 priority=10)
+        track = Track(video_stream)
+        track.addTrackObject(track_object)
 
         self.formatter._saveTrackObject(track_object)
 
@@ -256,7 +262,8 @@ class TestFormatterSave(TestCase):
                 start=10 * gst.SECOND, duration=20 * gst.SECOND,
                 in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
                 priority=10)
-
+        track = Track(video_stream)
+        track.addTrackObject(track_object)
         self.formatter._saveTrackObject(track_object)
 
         timeline_object = TimelineObject(source1)
@@ -279,11 +286,11 @@ class TestFormatterSave(TestCase):
                 in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
                 priority=10)
 
-        self.formatter._saveTrackObject(track_object)
-
         track = Track(video_stream)
         track.addTrackObject(track_object)
 
+        self.formatter._saveTrackObject(track_object)
+
         timeline_object = TimelineObject(source1)
         timeline_object.addTrackObject(track_object)
 
@@ -316,11 +323,11 @@ class TestFormatterSave(TestCase):
                 in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
                 priority=10)
 
-        self.formatter._saveTrackObject(track_object)
-
         track = Track(video_stream)
         track.addTrackObject(track_object)
 
+        self.formatter._saveTrackObject(track_object)
+
         timeline_object = TimelineObject(source1)
         timeline_object.addTrackObject(track_object)
 
@@ -425,8 +432,9 @@ class TestFormatterLoad(TestCase):
                 mode=str(mode))
         end = SubElement(curve, "end", value=str(10 % 2), mode="2")
 
+        track = Track(stream)
         # point gun at foot; pull trigger
-        track_object = self.formatter._loadTrackObject(element)
+        track_object = self.formatter._loadTrackObject(track, element)
         self.failUnless(isinstance(track_object, SourceTrackObject))
         self.failUnlessEqual(track_object.factory, factory)
         self.failUnlessEqual(track_object.stream, stream)
@@ -557,11 +565,11 @@ class TestFormatterLoad(TestCase):
                 in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
                 priority=10)
 
-        self.formatter._saveTrackObject(track_object)
-
         track = Track(video_stream)
         track.addTrackObject(track_object)
 
+        self.formatter._saveTrackObject(track_object)
+
         timeline_object = TimelineObject(source1)
         timeline_object.addTrackObject(track_object)
 
diff --git a/tests/test_timeline_undo.py b/tests/test_timeline_undo.py
index bca4ccf..1db741f 100644
--- a/tests/test_timeline_undo.py
+++ b/tests/test_timeline_undo.py
@@ -142,7 +142,7 @@ class  TestTimelineUndo(TestCase):
 
         self.timeline.addTimelineObject(self.timeline_object1)
         self.action_log.begin("remove clip")
-        self.timeline.removeTimelineObject(self.timeline_object1)
+        self.timeline.removeTimelineObject(self.timeline_object1, deep=True)
         self.action_log.commit()
 
         self.failUnlessEqual(len(stacks), 1)
diff --git a/tests/test_track.py b/tests/test_track.py
index 47129bf..8647f13 100644
--- a/tests/test_track.py
+++ b/tests/test_track.py
@@ -219,10 +219,13 @@ class TestTrackObject(TestCase):
         factory.duration = DURATION
         stream_ = AudioStream(gst.Caps("audio/x-raw-int"))
         obj = SourceTrackObject(factory, stream_)
+        track = Track(stream_)
+        track.addTrackObject(obj)
 
         obj.start = 3 * gst.SECOND
         obj.duration = DURATION
 
+
         # create a zig-zag volume curve
         interpolator = obj.getInterpolator("volume")
         expected = dict(((t * gst.SECOND, (t % 2, gst.INTERPOLATE_LINEAR))



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