pitivi r1368 - in trunk/pitivi: timeline ui



Author: edwardrv
Date: Fri Nov 28 17:03:40 2008
New Revision: 1368
URL: http://svn.gnome.org/viewvc/pitivi?rev=1368&view=rev

Log:
moved edge snapping code into core (edge snapping is effectively disabled with this commit

Modified:
   trunk/pitivi/timeline/objects.py
   trunk/pitivi/ui/complextimeline.py

Modified: trunk/pitivi/timeline/objects.py
==============================================================================
--- trunk/pitivi/timeline/objects.py	(original)
+++ trunk/pitivi/timeline/objects.py	Fri Nov 28 17:03:40 2008
@@ -86,6 +86,9 @@
     # pending UID (int) => objects (list of BrotherObjects and extra field)
     __waiting_for_pending_objects__ = {}
 
+    __deadband = 0
+    __edges = []
+
     def __init__(self, **unused_kw):
         self._linked = None
         self._brother = None
@@ -121,6 +124,13 @@
         self._linkObject(obj)
         self._linked._linkObject(self)
 
+    def getLinkedObject(self):
+        """
+        Returns the object currently linked to this one.
+        This is NOT guaranteed to be the brother
+        """
+        return self.linked
+
     def unlinkObject(self):
         """
         unlink from the current linked object
@@ -332,6 +342,11 @@
         "start-duration-changed" : ["start", "duration"]
         }
 
+    # for edge snapping
+    __edges = []
+    __deadband = 0
+    __do_updates = True
+
     def __init__(self, factory=None, start=gst.CLOCK_TIME_NONE,
                  duration=0, media_type=MEDIA_TYPE_NONE, name="", **kwargs):
         BrotherObjects.__init__(self, **kwargs)
@@ -441,15 +456,27 @@
             self._start = start
             self.gnlobject.set_property("start", long(start))
 
-    def _startDurationChangedCb(self, gnlobject, prop):
+    def setStartDurationTime(self, start=gst.CLOCK_TIME_NONE, duration=0):
+        """ sets the start and/or duration time """
+        self._setStartDurationTime(start, duration)
+        if self.linked:
+            self.linked._setStartDurationTime(start, duration)
+
+    def snapStartDurationTime(self, start=gst.CLOCK_TIME_NONE, duration=0):
+        """ sets the start and/or duration time, with edge snapping """
+        self.setStartDurationTime(TimelineObject.snapObjToEdge(self, start),
+            duration)
+
+    def _startDurationChangedCb(self, gnlobject, property):
         """ start/duration time has changed """
         gst.log("self:%r , gnlobject:%r %r" % (self, gnlobject, self.gnlobject))
         if not gnlobject == self.gnlobject:
-            gst.warning("We're receiving signals from an object we dont' control (self.gnlobject:%r, gnlobject:%r)" % (self.gnlobject, gnlobject))
-        self.gnlobject.debug("property:%s" % prop.name)
+            gst.warning("Receiving signals from object we don't control (ours:%r,sender:%r)"
+                % (self.gnlobject, gnlobject))
+        self.gnlobject.debug("property:%s" % property.name)
         start = gst.CLOCK_TIME_NONE
         duration = 0
-        if prop.name == "start":
+        if property.name == "start":
             start = gnlobject.get_property("start")
             gst.log("start: %s => %s" % (gst.TIME_ARGS(self._start),
                                          gst.TIME_ARGS(start)))
@@ -457,7 +484,7 @@
                 start = gst.CLOCK_TIME_NONE
             else:
                 self._start = long(start)
-        elif prop.name == "duration":
+        elif property.name == "duration":
             duration = gnlobject.get_property("duration")
             gst.log("duration: %s => %s" % (gst.TIME_ARGS(self._duration),
                                             gst.TIME_ARGS(duration)))
@@ -466,6 +493,8 @@
             else:
                 self.gnlobject.debug("duration changed:%s" % gst.TIME_ARGS(duration))
                 self._duration = long(duration)
+        # be sure to update edges
+        TimelineObject.updateEdges()
         self.emit("start-duration-changed", self._start, self._duration)
 
 
@@ -503,3 +532,72 @@
             self._setFactory(obj)
         else:
             BrotherObjects.pendingObjectCreated(self, obj, field)
+
+    def isAudio(self):
+        return self.media_type == MEDIA_TYPE_AUDIO
+
+    def isVideo(self):
+        return self.media_type == MEDIA_TYPE_VIDEO
+
+     ## code for keeping track of edit points, and snapping timestamps to the
+    ## nearest edit point. We do this here so we can keep track of edit points
+    ## for all layers/tracks.
+
+    @classmethod
+    def setDeadband(cls, db):
+        cls.__deadband = db
+
+    def enableEdgeUpdates(cls):
+        cls.__do_updates = True
+        cls.updateEdges()
+
+    def disableEdgeUpdates(cls):
+        cls.__do_updates = False
+
+    @classmethod
+    def updateEdges(cls):
+        if not cls.__do_updates:
+            return
+        #FIXME: this might be more efficient if we used a binary sort tree,
+        # filter out duplicate edges in linear time
+        edges = {}
+        for obj in cls. __instances__:
+                # start/end of object both considered "edit points"
+                edges[obj.start] = None
+                edges[obj.start + obj.duration] = None
+                # TODO: add other critical object points when these are
+                # implemented
+                # TODO: filtering mechanism
+        cls.__edges = edges.keys()
+        cls.__edges.sort()
+
+    @classmethod
+    def snapTimeToEdge(cls, time):
+        """Returns the input time or the nearest edge"""
+
+        res, diff = closest_item(cls.__edges, time)
+        if diff <= cls.__deadband:
+            return res
+        return time
+
+    @classmethod
+    def snapObjToEdit(cls, obj, time):
+        """Returns the input time or the edge which is closest to either the
+        start or finish time. The input time is interpreted as the start time
+        of obj."""
+
+        # need to find the closest edge to both the left and right sides of
+        # the object we are draging.
+        duration = obj.duration
+        left_res, left_diff = closest_item(cls.__edges, time)
+        right_res, right_diff = closest_item(cls.__edges, time + duration)
+        if left_diff <= right_diff:
+            res = left_res
+            diff = left_diff
+        else:
+            res = right_res - duration
+            diff = right_diff
+        if diff <= cls.__deadband:
+            return res
+        return time
+

Modified: trunk/pitivi/ui/complextimeline.py
==============================================================================
--- trunk/pitivi/ui/complextimeline.py	(original)
+++ trunk/pitivi/ui/complextimeline.py	Fri Nov 28 17:03:40 2008
@@ -256,16 +256,13 @@
     def _start_drag(self, item):
         item.raise_(None)
         self._draging = True
-        #self.canvas.block_size_request(True)
-        self.canvas.update_editpoints()
 
     def _end_drag(self, unused_item):
         self.canvas.block_size_request(False)
 
     def _move_source_cb(self, item, pos):
         element = item.element
-        element.setStartDurationTime(max(self.canvas.snap_obj_to_edit(element,
-            self.pixelToNs(pos[0])), 0))
+        element.setStartDurationTime(max(self.pixelToNs(pos[0]), 0))
 
     # FIXME: these two methods should be in the ComplexTimelineObject class at least, or in
     # their own class possibly. But they're here because they do
@@ -282,7 +279,7 @@
         #  min(start) = end - element.factory.duration
         new_start =  max(0,
             cur_end - element.factory.duration,
-            self.canvas.snap_time_to_edit(self.pixelToNs(pos[0])))
+            self.pixelToNs(pos[0]))
         new_duration = cur_end - new_start
         new_media_start = element.media_start + (new_start - element.media_start)
         element.setStartDurationTime(new_start, new_duration)
@@ -293,9 +290,7 @@
         element = item.element
         cur_start = element.start
         new_end = min(cur_start + element.factory.duration,
-            max(cur_start,
-                self.canvas.snap_time_to_edit(
-                    self.pixelToNs(pos[0] + width(item)))))
+            max(cur_start, self.pixelToNs(pos[0] + width(item))))
         new_duration = new_end - element.start
 
         element.setStartDurationTime(gst.CLOCK_TIME_NONE, new_duration)
@@ -413,8 +408,6 @@
     def __init__(self, layerinfolist):
         goocanvas.Canvas.__init__(self)
         self._selected_sources = []
-        self._editpoints = []
-        self._deadband = 0
         self._timeline_position = 0
 
         self._block_size_request = False
@@ -471,62 +464,6 @@
             self.set_bounds(0, 0, w, h)
         return True
 
-## code for keeping track of edit points, and snapping timestamps to the
-## nearest edit point. We do this here so we can keep track of edit points
-## for all layers/tracks.
-
-    # FIXME: move this code into the core. The core should provide some method
-    # for being notified that updates need to happen, though in some cases
-    # we'll probably want this to update automatically. In other cases we'll
-    # want the UI to be able to disable it altogether. But what we're doing
-    # here is duplicating information that already exists in the core. As we
-    # add features to the core, like Critical Points (Keyframes), this code
-    # will have to be updated. Bad.
-
-    def update_editpoints(self):
-        #FIXME: this might be more efficient if we used a binary sort tree,
-        # updated only when the timeline actually changes instead of before
-        # every drag operation. possibly concerned this could lead to a
-        # noticible lag on large timelines
-
-        # using a dictionary to silently filter out duplicate entries
-        # this list: it will screw up the edge-snaping algorithm
-        edges = {}
-        for layer in self.layerInfoList:
-            for obj in layer.composition.condensed:
-                # start/end of object both considered "edit points"
-                edges[obj.start] = None
-                edges[obj.start + obj.duration] = None
-        self._editpoints = edges.keys()
-        self._editpoints.sort()
-
-    def snap_time_to_edit(self, time):
-        res, diff = closest_item(self._editpoints, time)
-        if diff <= self._deadband:
-            return res
-        return time
-
-    def snap_time_to_playhead(self, time):
-        if abs(time - self._timeline_position)  <= self._deadband:
-            return self._timeline_position
-        return time
-
-    def snap_obj_to_edit(self, obj, time):
-        # need to find the closest edge to both the left and right sides of
-        # the object we are draging.
-        duration = obj.duration
-        left_res, left_diff = closest_item(self._editpoints, time)
-        right_res, right_diff = closest_item(self._editpoints, time + duration)
-        if left_diff <= right_diff:
-            res = left_res
-            diff = left_diff
-        else:
-            res = right_res - duration
-            diff = right_diff
-        if diff <= self._deadband:
-            return res
-        return time
-
 ## mouse callbacks
 
     def _mouseEnterCb(self, unused_item, unused_target, event):
@@ -565,10 +502,9 @@
         self._razor.props.visibility = goocanvas.ITEM_VISIBLE
         return True
 
-    def _razorMovedCb(self, unused_canvas, event):
+    def _razorMovedCb(self, canvas, event):
         x = event_coords(self, event)[0]
-        self._razor.props.x = self.nsToPixel(self.snap_time_to_playhead(
-            self.pixelToNs(x)))
+        self._razor.props.x = self.nsToPixel(self.pixelToNs(x))
         return True
 
     def _razorClickedCb(self, unused_canvas, event):
@@ -590,8 +526,7 @@
             if item.get_data("selectable"):
                 parent = item.get_parent()
                 gst.log("attempting to split source at position %d" %  x)
-                self._splitSource(parent, self.snap_time_to_playhead(
-                    self.pixelToNs(x)))
+                self._splitSource(parent, self.pixelToNs(x))
         return True
 
     # FIXME: this DEFINITELY needs to be in the core. Also, do we always want



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