[pitivi: 2/16] Refactor interpolator code slightly.



commit 690a19f0cac506c6de4d96ffe558be2af39d222b
Author: Alessandro Decina <alessandro d gmail com>
Date:   Fri Jul 3 16:28:07 2009 +0200

    Refactor interpolator code slightly.
    
    Make track_object.interpolators a dictionary of the form property_name ->
    (property, interpolator) so that we can lookup interpolators by property_name
    without having to iterate all the keys every time.
    Make it possible to rebuild interpolators when the content of a track_object's
    bin changes.  This commit is part of a larger change to make interpolator operations undoable.

 pitivi/formatters/etree.py    |   10 +++---
 pitivi/timeline/track.py      |   67 ++++++++++++++++++++++++++--------------
 pitivi/ui/trackobject.py      |    2 +-
 tests/test_etree_formatter.py |    4 +-
 4 files changed, 51 insertions(+), 32 deletions(-)
---
diff --git a/pitivi/formatters/etree.py b/pitivi/formatters/etree.py
index 7da1b43..45ca28f 100644
--- a/pitivi/formatters/etree.py
+++ b/pitivi/formatters/etree.py
@@ -329,11 +329,11 @@ class ElementTreeFormatter(Formatter):
 
         element.append(factory_ref)
         element.append(stream_ref)
-        if track_object.interpolators:
-            curves = Element("curves")
-            for property, interpolator in track_object.interpolators.iteritems():
-                curves.append(self._saveInterpolator(interpolator, property))
-            element.append(curves)
+        interpolators = track_object.getInterpolators()
+        curves = Element("curves")
+        for property, interpolator in interpolators.itervalues():
+            curves.append(self._saveInterpolator(interpolator, property))
+        element.append(curves)
 
         self._context.track_objects[track_object] = element
 
diff --git a/pitivi/timeline/track.py b/pitivi/timeline/track.py
index 31c647b..2b899ba 100644
--- a/pitivi/timeline/track.py
+++ b/pitivi/timeline/track.py
@@ -138,10 +138,6 @@ class Interpolator(Signallable, Loggable):
     def __init__(self, trackobject, element, prop):
         Loggable.__init__(self)
         self.debug("track:%r, element:%r, property:%r", trackobject, element, prop)
-        self._element = element
-        self._default = self._element.get_property(prop.name)
-        #self._default = 0
-        self._property = prop
         self._keyframes = []
         # FIXME: get this from the property's param spec
         # NOTE: keyframes necessarily work only on a closed range
@@ -152,11 +148,8 @@ class Interpolator(Signallable, Loggable):
         # each Interpolator. We should instead create a ControlSource for each
         # element. We can't do this until the new controller interface is
         # exposed in gst-python.
-        self.debug("Creating a GstController for element %r and property %s",
-            self._element, prop.name) 
-        self._controller = gst.Controller(self._element, prop.name)
-        self._controller.set_interpolation_mode(prop.name, gst.INTERPOLATE_LINEAR)
-
+        self.attachToElementProperty(prop, element)
+        self._default = self._element.get_property(prop.name)
         self.start = FixedKeyframe(self)
         self.end = FixedKeyframe(self)
         self.start.value = self._default
@@ -164,9 +157,13 @@ class Interpolator(Signallable, Loggable):
         self.end.value = self._default
         self.end.setObjectTime(trackobject.factory.duration)
 
-        #data = ((self.start.time, self.start.value), (self.end.time,
-        #    self.end.value))
-        #self._controller.set_from_list(prop.name, data)
+    def attachToElementProperty(self, prop, element):
+        self._element = element
+        self._property = prop
+        self.debug("Creating a GstController for element %r and property %s",
+            self._element, prop.name)
+        self._controller = gst.Controller(self._element, prop.name)
+        self._controller.set_interpolation_mode(prop.name, gst.INTERPOLATE_LINEAR)
 
     def newKeyFrame(self, time, value=None, mode=None):
         """add a new keyframe at the specified time, optionally with specified
@@ -275,6 +272,8 @@ class TrackObject(Signallable, Loggable):
         self.stream = stream
         self.track = None
         self.timeline_object = None
+        self.interpolators = {}
+        self._rebuild_interpolators = True
         self.gnl_object = obj = self._makeGnlObject()
         self.makeBin()
         self.trimmed_start = 0
@@ -301,19 +300,36 @@ class TrackObject(Signallable, Loggable):
 
         self._connectToSignals(obj)
 
-        self.interpolators = {}
+    def getInterpolator(self, property_name):
+        self._maybeBuildInterpolators()
 
-        wprops = factory.getInterpolatedProperties(stream).keys()
-        if stream:
-            for sobj, prop in get_controllable_properties(self.gnl_object):
-                if prop.name in wprops:
-                    self.interpolators[prop] = Interpolator(self, sobj, prop)
+        try:
+            return self.interpolators[property_name][1]
+        except KeyError:
+            raise TrackError("no interpolator for '%s'" % property_name)
 
-    def getInterpolator(self, property_name):
-        for prop, interpolator in self.interpolators.iteritems():
-            if property_name == prop.name:
-                return interpolator
-        return None
+    def getInterpolators(self):
+        self._maybeBuildInterpolators()
+        return self.interpolators
+
+    def _maybeBuildInterpolators(self):
+        if not list(self.gnl_object.elements()):
+            raise TrackError("makeBin hasn't been called yet")
+
+        if not self._rebuild_interpolators:
+            return
+
+        self._rebuild_interpolators = False
+
+        factory_properties = self.factory.getInterpolatedProperties(self.stream).keys()
+
+        for gst_object, gst_object_property in \
+                get_controllable_properties(self.gnl_object):
+            if gst_object_property.name not in factory_properties:
+                continue
+
+            self.interpolators[gst_object_property.name] = (gst_object_property,
+                    Interpolator(self, gst_object, gst_object_property))
 
     def release(self):
         self._disconnectFromSignals()
@@ -328,7 +344,8 @@ class TrackObject(Signallable, Loggable):
             media_duration=self.media_duration, priority=self.priority)
         other.trimmed_start = self.trimmed_start
 
-        for property, interpolator in self.interpolators.iteritems():
+        interpolators = self.getInterpolators()
+        for property, interpolator in interpolators.itervalues():
             other_interpolator = other.getInterpolator(property.name)
             other_interpolator.start.value = interpolator.start.value
             other_interpolator.start.mode = interpolator.start.mode
@@ -496,6 +513,7 @@ class TrackObject(Signallable, Loggable):
 
         bin = self.factory.makeBin(self.stream)
         self.gnl_object.add(bin)
+        self._maybeBuildInterpolators()
 
     def releaseBin(self):
         elts = list(self.gnl_object.elements())
@@ -504,6 +522,7 @@ class TrackObject(Signallable, Loggable):
             self.gnl_object.remove(bin)
             bin.set_state(gst.STATE_NULL)
             self.factory.releaseBin(bin)
+        self._rebuild_interpolators = True
 
     def _notifyStartCb(self, obj, pspec):
         self.emit('start-changed', obj.props.start)
diff --git a/pitivi/ui/trackobject.py b/pitivi/ui/trackobject.py
index 06ff164..148c562 100644
--- a/pitivi/ui/trackobject.py
+++ b/pitivi/ui/trackobject.py
@@ -274,7 +274,7 @@ class TrackObject(View, goocanvas.Group, Zoomable):
             self.start_handle, self.end_handle, self.namebg, self.name):
             self.add_child(thing)
 
-        for interpolator in element.interpolators.itervalues():
+        for prop, interpolator in element.getInterpolators().itervalues():
             self.add_child(Curve(element, interpolator, 50))
 
         self.element = element
diff --git a/tests/test_etree_formatter.py b/tests/test_etree_formatter.py
index ca76770..21e6aba 100644
--- a/tests/test_etree_formatter.py
+++ b/tests/test_etree_formatter.py
@@ -128,7 +128,7 @@ class TestFormatterSave(TestCase):
         fakevol = gst.element_factory_make("volume")
         prop = get_controllable_properties(fakevol)[1][1]
         volcurve = Interpolator(track_object, fakevol, prop)
-        track_object.interpolators[prop] = volcurve
+        track_object.interpolators[prop.name] = (prop, volcurve)
 
         # add some points to the interpolator 
         value = float(0)
@@ -136,7 +136,7 @@ class TestFormatterSave(TestCase):
         volcurve.start.value = 0
         for t in xrange(3, 15, 3):
             value = int(t % 2)
-            volcurve.newKeyFrame(time=t * gst.SECOND, value=value)
+            volcurve.newKeyFrame(t * gst.SECOND, value)
         volcurve.end.setObjectTime(15 * gst.SECOND)
         volcurve.end.value = 15 % 2
 



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