Re: [jokosher-devel] Six weeks till the freeze
- From: "Jens Geiregat" <jens geiregat gmail com>
- To: "Jens Geiregat" <jens geiregat gmail com>, Jokosher <jokosher-devel-list gnome org>
- Subject: Re: [jokosher-devel] Six weeks till the freeze
- Date: Tue, 19 Sep 2006 16:59:16 +0200
On 9/19/06, John Green <john thegreens co uk> wrote:
On Tue, Sep 19, 2006 at 11:13:36AM +0200, Jens Geiregat wrote:
>
> I tried to do that for the timeline some weeks ago. In stead of
> drawing a savedLine the size of the visible area, I prepared a
> savedLine three times the size of the visible area and used that as
> long as possible. I never got it to work 100% right, but if you want
> it, I'll send you the code.
Excellent :) That would be great. You can mail it to me at this address.
--
John Green
Hi,
I attached my modified TimeLine.py. I don't remember what the problems
with it were, but I hope its usefull for you.
Jens
import gtk
import pango
import gobject
import gst
import time
#=========================================================================
class TimeLine(gtk.DrawingArea):
""" This class handles drawing the time line display.
"""
__gtype_name__ = 'TimeLine'
_NUM_LINES = 5 # Number of 'short' lines + 1
#_____________________________________________________________________
def __init__(self, project, timelinebar, mainview):
""" project - reference to the active project
"""
gtk.DrawingArea.__init__(self)
self.project = project
self.timelinebar = timelinebar
self.mainview = mainview
self.project.transport.AddListener(self)
self.project.AddListener(self)
self.height = 44
self.buttonDown = False
self.dragging = False
self.set_events(gtk.gdk.POINTER_MOTION_MASK |
gtk.gdk.BUTTON_PRESS_MASK |
gtk.gdk.BUTTON_RELEASE_MASK)
self.connect("expose-event", self.OnDraw)
self.connect("button_release_event", self.onMouseUp)
self.connect("button_press_event", self.onMouseDown)
self.connect("motion_notify_event", self.onMouseMove)
self.connect("size_allocate", self.OnAllocate)
self.savedLine = None
self.savedLinePiece = None
self.scrollTime = 0
self.pixelsBefore = 0
self.startTime = 0
#_____________________________________________________________________
def OnAllocate(self, widget, allocation):
self.allocation = allocation
#Redraw timeline
self.DrawLine(widget)
#_____________________________________________________________________
def OnDraw(self, widget, event):
""" Fires off the drawing operation. """
viewStart = self.project.viewStart
viewScale = self.project.viewScale
width = self.get_allocation().width
position = self.project.transport.position
x = int(round((position - viewStart) * viewScale))
newtime = time.time()
if x >= (width * 0.8):
if newtime > (self.scrollTime + 1/30.):
self.scrollTime = newtime
self.project.SetViewStart(position - ((width * 0.8)/viewScale))
#return
if self.savedLine == None:
self.DrawLine(widget)
# if self.project.transport.RedrawTimeLine:
# self.project.transport.RedrawTimeLine = False
# self.DrawLine(widget)
# if self.project.RedrawTimeLine:
# self.project.RedrawTimeLine = False
# self.DrawLine(widget)
d = widget.window
gc = d.new_gc()
# redraw area from saved image
ix = ((viewStart-self.startTime) * viewScale) + event.area.x# + self.pixelsBefore
if ix > width:
print "RELOAD! ix = %d, width = %d"%(ix, width)
self.DrawLine(widget)#, viewStart=self.project.transport.position)
ix = (viewStart * viewScale) + event.area.x + self.pixelsBefore
d.draw_image(gc, self.savedLine, ix,
event.area.y, event.area.x, event.area.y,
event.area.width, event.area.height)
# Draw play cursor position
col = gc.get_colormap().alloc_color("#FF0000")
gc.set_foreground(col)
d.draw_line(gc, x, 0, x, self.get_allocation().height)
#_____________________________________________________________________
def DrawLine(self, widget, viewStart=None):
""" Draws the timeline and saves it to memory
- Must be called initially and to redraw the timeline
after moving the project start
"""
d = widget.window
# 0.75 + 1 + 0.75 = 2.5
d = gtk.gdk.Pixmap(d, self.get_allocation().width * 2.5, self.get_allocation().height)
gc = d.new_gc()
y = 0
col = gc.get_colormap().alloc_color("#FFFFFF")
gc.set_foreground(col)
gc.set_fill(gtk.gdk.SOLID)
d.draw_rectangle( gc, True,
0,
0,
*(d.get_size()))
col = gc.get_colormap().alloc_color("#555555")
gc.set_foreground(col)
d.draw_rectangle( gc, False,
0,
0,
*(d.get_size()))
transport = self.project.transport
x = 0
if transport.mode == transport.MODE_BARS_BEATS:
# Calculate our scroll offset
pos = (self.project.viewStart / 60.) * transport.bpm
beat = int(pos)
offset = pos - beat
if offset > 0.:
x -= offset * ((self.project.viewScale * 60.) / transport.bpm)
x += (self.project.viewScale * 60.) / transport.bpm
beat += 1
while x < self.get_allocation().width:
# Draw the beat/bar divisions
ix = int(x)
if beat % transport.meter_nom:
d.draw_line(gc, ix, int(self.get_allocation().height/1.2), ix, self.get_allocation().height)
else:
d.draw_line(gc, ix, int(self.get_allocation().height/2), ix, self.get_allocation().height)
# Draw the bar number
l = pango.Layout(self.create_pango_context())
l.set_text(str((beat / transport.meter_nom)+1))
d.draw_layout(gc, ix, 5, l)
beat += 1
x += (60. / transport.bpm ) * self.project.viewScale
else:
# Working in milliseconds here. Using seconds gives modulus problems because they're floats
viewScale = self.project.viewScale / 1000.
# if not viewStart:
# viewStart = int(self.project.viewStart * 1000)
# else:
# print "got: %f, real: %f"%(viewStart, self.project.viewStart)
# viewStart = int(viewStart * 1000)
viewStart = int(self.project.transport.position * 1000)
factor, displayMilliseconds = self.GetZoomFactor(viewScale)
pixelsBefore = self.get_allocation().width * 0.75
timeBefore = pixelsBefore / viewScale
viewStart = int(viewStart - timeBefore)
firstBlock = viewStart % (self._NUM_LINES * factor)
if firstBlock > 0:
firstBlock -= self._NUM_LINES * factor # Time where the block with the viewStart starts.
x = firstBlock * viewScale
self.pixelsBefore = pixelsBefore + x
msec = viewStart - firstBlock
self.startTime = msec / 1000.
# Draw ticks up to the end of our display
if not self.savedLinePiece:
self.DrawLinePiece(widget, viewScale, factor)
l = pango.Layout(self.create_pango_context())
x=0
while x < self.get_allocation().width * 10:
ix = int(x)
width = int(self._NUM_LINES * factor * viewScale)
d.draw_image(gc, self.savedLinePiece, 0,
0, ix, 0,
width, self.get_allocation().height)
# Draw the bar number
if msec >=0:
if displayMilliseconds:
#Should use transportmanager for this...
l.set_text("%d:%02d:%03d"%((msec/1000) / 60, (msec/1000) % 60, msec%1000) )
else:
l.set_text("%d:%02d"%((msec/1000) / 60, (msec/1000) % 60))
d.draw_layout(gc, ix, 5, l)
msec += self._NUM_LINES * factor
x += self._NUM_LINES * viewScale * factor
self.savedLine = d.get_image(0, 0, *(d.get_size()))
#_____________________________________________________________________
def DrawLinePiece(self, widget, viewScale, factor):
"""
Draws a piece of the timeline:
> |<
> | | | | |<
This piece can then be painted repeatedly to self.savedLine.
"""
window = widget.window
window = gtk.gdk.Pixmap(window, self._NUM_LINES * factor * viewScale, self.get_allocation().height)
gc = window.new_gc()
col = gc.get_colormap().alloc_color("#FFFFFF")
gc.set_foreground(col)
window.draw_rectangle( gc, True,
0,
0,
*(window.get_size()))
col = gc.get_colormap().alloc_color("#555555")
gc.set_foreground(col)
x = 0
window.draw_line(gc, x, int(self.get_allocation().height/2.), x, self.get_allocation().height)
for i in range(self._NUM_LINES - 1):
x += viewScale * factor
ix = int(x)
window.draw_line(gc, ix, int(self.get_allocation().height/1.2), ix, self.get_allocation().height)
self.savedLinePiece = window.get_image(0, 0, *(window.get_size()))
#_____________________________________________________________________
def do_size_request(self, requisition):
requisition.width = self.get_allocation().width
requisition.height = self.height
#_____________________________________________________________________
def OnStateChanged(self, obj, change=None):
"""
Called when there is a change fo state in transport
manager.Could be one of
* Mode changed from bars/beats to minutes or vice versa
(requires a complete redraw of timeline - flag set)
* Change in playing position -only needs partial redraw
* Project change e.g. a scroll or zoom change
(requires a complete redraw of timeline - flag set)
"""
if self.project.transport.RedrawTimeLine or self.project.RedrawTimeLine:
self.queue_draw()
return
x1 = round((self.project.transport.PrevPosition - self.project.viewStart) * self.project.viewScale)
x2 = round((self.project.transport.position - self.project.viewStart) * self.project.viewScale)
self.queue_draw_area(int(x1)-1, 0, 3, self.get_allocation().height)
self.queue_draw_area(int(x2)-1, 0, 3, self.get_allocation().height)
#_____________________________________________________________________
def onMouseDown(self, widget, event):
self.buttonDown = True
self.dragging = False
self.moveHead(event.x)
return True
#_____________________________________________________________________
def onMouseMove(self, widget, event):
if not self.buttonDown:
return
self.dragging = True
self.moveHead(event.x)
#_____________________________________________________________________
def onMouseUp(self, widget, event):
self.dragging = False
self.buttonDown = False
#_____________________________________________________________________
def moveHead(self, xpos):
pos = self.project.viewStart + xpos/ self.project.viewScale
self.project.transport.SeekTo(pos)
#_____________________________________________________________________
def GetZoomFactor(self, viewScale):
"""
To be used for drawing the MODE_HOURS_MINS_SECS timeline
Returns:
- an integer factor to be multiplied with the viewScale to zoom the timeline in/out
- a boolean indicating if milliseconds should be displayed
The default factor is 1000, meaning that the distance between the short lines of the timeline
symbolizes 1000 milliseconds. The code will increase of decrease this factor to keep the
timeline readable. The factors can be set with the zoomLevels array. This array
contains zoom levels that support precision from 20 ms to 1 minute. More extreme zoom
levels could be added, but would never be reached because the viewScale is limited.
"""
shortTextWidth = 28 # for '0:00' notation
longTextWidth = 56 # for '0:00:000' notation
textWidth = shortTextWidth
whiteSpace = 50
factor = 1000 # Default factor is 1 second for 1 line
zoomLevels = [20, 100, 200, 1000, 4000, 12000, 60000]
if (textWidth + whiteSpace) > (self._NUM_LINES * factor * viewScale):
factor = zoomLevels[zoomLevels.index(factor) + 1]
while (textWidth + whiteSpace) > (self._NUM_LINES * factor * viewScale) and factor != zoomLevels[-1]:
factor = zoomLevels[zoomLevels.index(factor) + 1]
else:
while (textWidth + whiteSpace) < (factor * viewScale) and factor != zoomLevels[0]:
factor = zoomLevels[zoomLevels.index(factor) - 1]
if factor == 200:
textWidth = longTextWidth
return factor, (factor < 200) # 0.2 * 5 = 1.0 second, if the interval is smaller, milliseconds are needed
#=========================================================================
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]