pitivi r1368 - in trunk/pitivi: timeline ui
- From: edwardrv svn gnome org
- To: svn-commits-list gnome org
- Subject: pitivi r1368 - in trunk/pitivi: timeline ui
- Date: Fri, 28 Nov 2008 17:03:40 +0000 (UTC)
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]