Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorolipet <olpc@localhost.localdomain>2007-01-15 11:02:19 (GMT)
committer olipet <olpc@localhost.localdomain>2007-01-15 11:02:19 (GMT)
commit20c60d6a435599dad56e97b0ce9d7efc6f02c4d4 (patch)
tree9039ee1a1be14f76923c3457d98bf6b7ba585a7a
parentd94ce096e869d1802f709c64fbc0fc70ab143fbf (diff)
parent158d399d97c52554659f1725425700724eafc514 (diff)
Merge branch 'master' of git+ssh://olipet@dev.laptop.org/git/projects/tamtam
-rw-r--r--Config.py39
-rw-r--r--Edit/MainWindow.py8
-rw-r--r--Edit/NoteInterface.py73
-rw-r--r--Edit/TrackInterface.py222
-rwxr-xr-xResources/Images/note.pngbin0 -> 3677 bytes
-rwxr-xr-xResources/Images/noteSelected.pngbin0 -> 3904 bytes
-rwxr-xr-xResources/Images/trackBG.pngbin0 -> 4387 bytes
-rwxr-xr-xResources/Images/trackBGDrum.pngbin0 -> 4717 bytes
-rwxr-xr-xResources/Images/trackBGDrumSelected.pngbin0 -> 4511 bytes
-rwxr-xr-xResources/Images/trackBGSelected.pngbin0 -> 4215 bytes
-rw-r--r--Util/Sound.py276
-rwxr-xr-x[-rw-r--r--]scripts/olpc_get_stuff.sh10
12 files changed, 476 insertions, 152 deletions
diff --git a/Config.py b/Config.py
index 342f85e..b4b3ad1 100644
--- a/Config.py
+++ b/Config.py
@@ -2,6 +2,16 @@
import os
+if os.path.isfile("DEBUG"):
+ f = open("DEBUG")
+ l = f.read(10)
+ if len(l): DEBUG = int( l )
+ else: DEBUG = 99
+else:
+ DEBUG = False
+print "Debug Level %d" % (DEBUG)
+
+
TAM_TAM_ROOT = os.path.dirname(os.path.abspath(__file__))
PREF_DIR = '/tamtam'
print 'INFO: loaded TAMTAM_ROOT=%s' % TAM_TAM_ROOT
@@ -350,24 +360,33 @@ UNLOAD_TABLES_COMMAND = \
LANGUAGE = 'En'
IMAGE_ROOT = TAM_TAM_ROOT + '/Resources/Images/'
-NOTE_HEIGHT = 6 # pixels
-NOTE_BORDER_SIZE = 1
-NOTE_BORDER_SIZE_DIV2 = NOTE_BORDER_SIZE/2.0
+NOTE_HEIGHT = 9 # pixels
+NOTE_IMAGE_PADDING = 6
+NOTE_IMAGE_PADDING_MUL2 = NOTE_IMAGE_PADDING*2
+NOTE_IMAGE_TAIL = 1059
+NOTE_IMAGE_ENDLENGTH = 12
MAIN_WINDOW_PADDING = 5
-TRACK_SPACING = 1
-BORDER_SIZE = 2
-BORDER_SIZE_DIV2 = BORDER_SIZE/2.0
-BORDER_SIZE_MUL2 = BORDER_SIZE*2
-BEAT_LINE_SIZE = 1
-BEAT_LINE_SIZE_DIV2 = BEAT_LINE_SIZE/2.0
+TRACK_SPACING = 4
+TRACK_SPACING_DIV2 = TRACK_SPACING//2
+TRACK_COLORS = [ ( "#00591B", "#00E847" ), \
+ ( "#6F1200", "#E72500" ), \
+ ( "#004682", "#0090EA" ), \
+ ( "#716D00", "#F9EF00" ), \
+ ( "#37187B", "#4A00ED" ) ]
+BEAT_COLOR = "#999999"
+BEAT_LINE_SIZE = 2
+PLAYHEAD_COLOR = "#666666"
PLAYHEAD_SIZE = 2
-PLAYHEAD_SIZE_DIV2 = PLAYHEAD_SIZE/2.0
+MARQUEE_COLOR = "#FFFFFF"
+MARQUEE_SIZE = 2
INST_BCK_COLOR = '#979DA8'
PANEL_BCK_COLOR = '#FFFFFF'
PANEL_COLOR = '#707F93'
PANEL_RADIUS = 10
+BORDER_SIZE = 2
+
PAGE_BORDER_SIZE = 2
PAGE_SELECTED_BORDER_SIZE = 5
PAGE_WIDTH = 100
diff --git a/Edit/MainWindow.py b/Edit/MainWindow.py
index fe6a89d..9270fab 100644
--- a/Edit/MainWindow.py
+++ b/Edit/MainWindow.py
@@ -265,7 +265,7 @@ class MainWindow( gtk.EventBox ):
self._data['volume'] = Config.DEFAULT_VOLUME
self._data['page_beats'] = [nbeats for p in range(npages)]
- self._data['tempo'] = Config.DEFAULT_TEMPO
+ self._data['tempo'] = Config.PLAYER_TEMPO
self._data['ticks_per_sec'] = self._data['tempo'] * 0.2 # 12 BPM / 60 SPM
self._data['tune'] = []
self._data['notebin'] = []
@@ -466,7 +466,7 @@ class MainWindow( gtk.EventBox ):
self.noteLooper = NoteLooper(
0.2,
- Config.DEFAULT_TEMPO * 0.2 #0.2 currently converts beats per second to seconds_per_tick
+ Config.PLAYER_TEMPO * 0.2 #0.2 currently converts beats per second to seconds_per_tick
)
self.csnd.startTime()
self.noteLooper.startTime()
@@ -1012,6 +1012,10 @@ class MainWindow( gtk.EventBox ):
return False
def destroy( self, widget ):
+
+ if Config.DEBUG:
+ print TP.PrintAll()
+
gtk.main_quit()
def updateNumberOfBars( self, widget = None, data = None ):
diff --git a/Edit/NoteInterface.py b/Edit/NoteInterface.py
index 43ae376..c49a8d8 100644
--- a/Edit/NoteInterface.py
+++ b/Edit/NoteInterface.py
@@ -6,7 +6,7 @@ import Config
class NoteInterface:
- def __init__( self, parent, page, track, note, pitch, onset, duration, amplitude):
+ def __init__( self, parent, page, track, note, pitch, onset, duration, amplitude, image, imageSelected, colors ):
self.parent = parent
self.page = page
self.track = track
@@ -16,8 +16,10 @@ class NoteInterface:
self.y = 0
self.width = 1
self.height = Config.NOTE_HEIGHT
-
- self.updateParams( pitch, onset, duration, amplitude )
+ self.imgX = 0
+ self.imgY = 0
+ self.imgWidth = 1
+ self.imgHeight = self.height + Config.NOTE_IMAGE_PADDING_MUL2
self.selected = False
self.potentialDeselect = False
@@ -25,6 +27,12 @@ class NoteInterface:
self.lastDragO = 0
self.lastDragP = 0
self.lastDragD = 0
+
+ self.image = image
+ self.imageSelected = imageSelected
+ self.baseColors = colors
+
+ self.updateParams( pitch, onset, duration, amplitude )
def destroy( self ):
# nothing to do?
@@ -37,7 +45,10 @@ class NoteInterface:
self.end = onset + duration
self.amplitude = amplitude
- self.bgColour = 1 - ( ( self.amplitude * 0.7 ) + 0.3 )
+ r = self.baseColors[0][0] + int(self.baseColors[1][0]*amplitude)
+ g = self.baseColors[0][1] + int(self.baseColors[1][1]*amplitude)
+ b = self.baseColors[0][2] + int(self.baseColors[1][2]*amplitude)
+ self.color = self.parent.drawingArea.get_colormap().alloc_color( r, g, b, True, True )
self.updateTransform( False )
@@ -55,22 +66,25 @@ class NoteInterface:
def updateTransform( self, onlyX ):
if self.page == self.parent.curPage:
- oldX = self.x
- oldY = self.y
- oldEndX = self.x + self.width
+ oldX = self.imgX
+ oldY = self.imgY
+ oldEndX = self.imgX + self.imgWidth
origin = self.parent.getTrackOrigin( self.track )
self.x = self.parent.ticksToPixels( self.onset )
self.width = self.parent.ticksToPixels( self.end ) - self.x
+ self.imgWidth = self.width + Config.NOTE_IMAGE_PADDING_MUL2
self.x += origin[0]
+ self.imgX = self.x - Config.NOTE_IMAGE_PADDING
if not onlyX:
self.y = self.parent.pitchToPixels( self.pitch ) + origin[1]
-
+ self.imgY = self.y - Config.NOTE_IMAGE_PADDING
+
if self.page == self.parent.curPage:
- x = min( self.x, oldX )
- y = min( self.y, oldY )
- endx = max( self.x + self.width, oldEndX )
- endy = max( self.y, oldY ) + self.height
+ x = min( self.imgX, oldX )
+ y = min( self.imgY, oldY )
+ endx = max( self.imgX + self.imgWidth, oldEndX )
+ endy = max( self.imgY, oldY ) + self.imgHeight
self.parent.invalidate_rect( x, y, endx-x, endy-y )
def updateDragLimits( self, dragLimits, leftBound, rightBound, widthBound ):
@@ -237,7 +251,7 @@ class NoteInterface:
if self.selected != state:
self.selected = state
if self.page == self.parent.curPage:
- self.parent.invalidate_rect( self.x, self.y, self.width, self.height )
+ self.parent.invalidate_rect( self.imgX, self.imgY, self.imgWidth, self.imgHeight )
return True # state changed
return False # state is the same
@@ -247,32 +261,17 @@ class NoteInterface:
#=======================================================
# Selection
- def draw( self, context, startX, stopX ):
- if stopX < self.x: return False # we don't need to draw and no one after us will draw
- if startX > self.x + self.width: return True # we don't need to draw, but maybe a later note does
-
-
- if False:
- context.set_line_width( Config.NOTE_BORDER_SIZE )
+ def draw( self, win, gc, startX, stopX ):
+ if stopX < self.imgX: return False # we don't need to draw and no one after us will draw
+ if startX > self.imgX + self.imgWidth: return True # we don't need to draw, but maybe a later note does
- context.move_to( self.x + Config.NOTE_BORDER_SIZE_DIV2, self.y + Config.NOTE_BORDER_SIZE_DIV2 )
- context.rel_line_to( self.width - Config.NOTE_BORDER_SIZE, 0 )
- context.rel_line_to( 0, self.height - Config.NOTE_BORDER_SIZE )
- context.rel_line_to( -self.width + Config.NOTE_BORDER_SIZE, 0 )
- context.close_path()
-
- context.rectangle(self.x, self.y, self.width, self.height )
+ gc.foreground = self.color
+ win.draw_rectangle( gc, True, self.x+1, self.y+1, self.width-2, self.height-2 )
- #background
- context.set_source_rgb( self.bgColour, self.bgColour, self.bgColour )
- #context.fill_preserve()
- context.fill()
- return True
-
- #border
- if self.selected: context.set_source_rgb( 1, 1, 1 )
- else: context.set_source_rgb( 0, 0, 0 )
- context.stroke()
+ if self.selected: img = self.imageSelected
+ else: img = self.image
+ win.draw_pixbuf( gc, img, 0, 0, self.imgX, self.imgY, self.imgWidth-Config.NOTE_IMAGE_ENDLENGTH, self.imgHeight, gtk.gdk.RGB_DITHER_NONE )
+ win.draw_pixbuf( gc, img, Config.NOTE_IMAGE_TAIL, 0, self.imgX+self.imgWidth-Config.NOTE_IMAGE_ENDLENGTH, self.imgY, Config.NOTE_IMAGE_ENDLENGTH, self.imgHeight, gtk.gdk.RGB_DITHER_NONE )
return True # we drew something
diff --git a/Edit/TrackInterface.py b/Edit/TrackInterface.py
index cb46c0c..4522c0b 100644
--- a/Edit/TrackInterface.py
+++ b/Edit/TrackInterface.py
@@ -29,7 +29,7 @@ class TrackInterface( gtk.EventBox ):
gtk.EventBox.__init__( self )
self.drawingArea = gtk.DrawingArea()
- self.drawingAreaDirty = False # is the drawingArea waiting to draw?
+ self.drawingAreaDirty = False # are we waiting to draw?
self.add( self.drawingArea )
self.dirtyRectToAdd = gtk.gdk.Rectangle() # used by the invalidate_rect function
@@ -61,7 +61,7 @@ class TrackInterface( gtk.EventBox ):
self.marqueeLoc = False # current drag location of the marquee
self.marqueeRect = [[0,0],[0,0]]
- self.playheadX = 0
+ self.playheadX = Config.TRACK_SPACING_DIV2
self.cursor = { \
"default": None, \
@@ -76,12 +76,69 @@ class TrackInterface( gtk.EventBox ):
self.connect( "size-allocate", self.size_allocate )
- self.drawingArea.connect( "expose-event", self.draw )
+ self.drawingArea.connect( "expose-event", self.expose )
self.connect( "button-press-event", self.handleButtonPress )
self.connect( "button-release-event", self.handleButtonRelease )
self.connect( "motion-notify-event", self.handleMotion )
self.onNoteDrag = onNoteDrag
+
+ # prepare drawing stuff
+ hexToInt = { "0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9, "A":10, "B":11, "C":12, "D":13, "E":14, "F":15, "a":10, "b":11, "c":12, "d":13, "e":14, "f":15 }
+ self.trackColors = []
+ for i in Config.TRACK_COLORS:
+ low = ( 256*(hexToInt[i[0][1]]*16+hexToInt[i[0][2]]), 256*(hexToInt[i[0][3]]*16+hexToInt[i[0][4]]), 256*(hexToInt[i[0][5]]*16+hexToInt[i[0][6]]) )
+ high = ( 256*(hexToInt[i[1][1]]*16+hexToInt[i[1][2]]), 256*(hexToInt[i[1][3]]*16+hexToInt[i[1][4]]), 256*(hexToInt[i[1][5]]*16+hexToInt[i[1][6]]) )
+ delta = ( high[0]-low[0], high[1]-low[1], high[2]-low[2] )
+ self.trackColors.append( (low, delta) )
+
+ colormap = self.drawingArea.get_colormap()
+ self.beatColor = colormap.alloc_color( Config.BEAT_COLOR, True, True )
+ self.playheadColor = colormap.alloc_color( Config.PLAYHEAD_COLOR, True, True )
+ self.marqueeColor = colormap.alloc_color( Config.MARQUEE_COLOR, True, True )
+
+ self.image = {}
+ img = gtk.Image()
+ win = gtk.gdk.get_default_root_window()
+ self.gc = gtk.gdk.GC( win )
+
+ def prepareDrawable( name ):
+ img.set_from_file( Config.IMAGE_ROOT+name+".png" )
+ pix = img.get_pixbuf()
+ self.image[name] = gtk.gdk.Pixmap( win, pix.get_width(), pix.get_height() )
+ self.image[name].draw_pixbuf( self.gc, pix, 0, 0, 0, 0, pix.get_width(), pix.get_height(), gtk.gdk.RGB_DITHER_NONE )
+ def preparePixbuf( name ):
+ newimg = gtk.Image()
+ newimg.set_from_file( Config.IMAGE_ROOT+name+".png" )
+ self.image[name] = newimg.get_pixbuf()
+
+ prepareDrawable( "trackBG" )
+ prepareDrawable( "trackBGSelected" )
+ prepareDrawable( "trackBGDrum" )
+ prepareDrawable( "trackBGDrumSelected" )
+ preparePixbuf( "note" )
+ preparePixbuf( "noteSelected" )
+
+ # define dimensions
+ self.width = self.trackFullWidth = self.image["trackBG"].get_size()[0]
+ self.trackWidth = self.width - Config.TRACK_SPACING
+ self.trackFullHeight = self.image["trackBG"].get_size()[1]
+ self.trackHeight = self.trackFullHeight - Config.TRACK_SPACING
+ self.trackFullHeightDrum = self.image["trackBGDrum"].get_size()[1]
+ self.trackHeightDrum = self.trackFullHeightDrum - Config.TRACK_SPACING
+ self.height = self.trackHeight*(Config.NUMBER_OF_TRACKS-1) + self.trackHeightDrum + Config.TRACK_SPACING*Config.NUMBER_OF_TRACKS
+ self.trackLimits = []
+ self.trackRect = []
+ self.drumIndex = Config.NUMBER_OF_TRACKS-1
+ for i in range(self.drumIndex):
+ start = i*(self.trackFullHeight)
+ self.trackLimits.append( (start,start+self.trackFullHeight) )
+ self.trackRect.append( gtk.gdk.Rectangle(Config.TRACK_SPACING_DIV2,start+Config.TRACK_SPACING_DIV2, self.trackWidth, self.trackHeight ) )
+ self.trackLimits.append( ( self.height - self.trackFullHeightDrum, self.height ) )
+ self.trackRect.append( gtk.gdk.Rectangle( Config.TRACK_SPACING_DIV2, self.height - self.trackFullHeightDrum + Config.TRACK_SPACING_DIV2, self.trackWidth, self.trackHeightDrum ) )
+
+ self.pitchPerPixel = float(Config.NUMBER_OF_POSSIBLE_PITCHES-1) / (self.trackHeight - Config.NOTE_HEIGHT)
+ self.pixelsPerPitch = float(self.trackHeight-Config.NOTE_HEIGHT)/(Config.MAXIMUM_PITCH - Config.MINIMUM_PITCH)
#=======================================================
# Module Interface
@@ -105,7 +162,8 @@ class TrackInterface( gtk.EventBox ):
self.pageNoteCount[p] = 0
csnote = noteParams["csnote"][i]
note = NoteInterface( self, p, noteParams["track"][i], noteParams["note"][i], \
- csnote["pitch"], csnote["onset"], csnote["duration"], csnote["amplitude"] )
+ csnote["pitch"], csnote["onset"], csnote["duration"], csnote["amplitude"], \
+ self.image["note"], self.image["noteSelected"], self.trackColors[noteParams["track"][i]] )
while at[p][t] > 0:
if self.note[p][t][at[p][t]-1].getStartTick() < csnote["onset"]: break
at[p][t] -= 1
@@ -172,11 +230,9 @@ class TrackInterface( gtk.EventBox ):
def updateBeatCount( self, beatCount ):
self.beatCount = beatCount
- # make sure this matches the calculation in size_allocate
- self.beatSpacing = (self.fullWidth - Config.BORDER_SIZE_MUL2 + Config.BEAT_LINE_SIZE)/self.beatCount
- self.width = self.beatSpacing * self.beatCount + Config.BORDER_SIZE_MUL2
- self.ticksPerPixel = float(self.beatCount * Config.TICKS_PER_BEAT) / (self.width-2*Config.BORDER_SIZE)
- self.pixelsPerTick = 1/self.ticksPerPixel
+ self.pixelsPerTick = self.trackWidth//(self.beatCount*Config.TICKS_PER_BEAT)
+ self.ticksPerPixel = 1.0/self.pixelsPerTick
+ self.beatSpacing = self.pixelsPerTick*Config.TICKS_PER_BEAT
if self.pageBeatCount[self.curPage] != beatCount:
self.pageBeatCount[self.curPage] = beatCount
@@ -184,13 +240,13 @@ class TrackInterface( gtk.EventBox ):
track = self.note[self.curPage][i]
map( lambda note:note.updateTransform( True ), track )
- if self.drawingArea.window != None:
+ if self.window != None:
self.invalidate_rect( 0, 0, self.fullWidth, self.height )
def setPlayhead( self, ticks ):
- self.invalidate_rect( self.playheadX, 0, Config.PLAYHEAD_SIZE, self.height )
- self.playheadX = self.ticksToPixels( ticks ) + Config.BORDER_SIZE
- self.invalidate_rect( self.playheadX, 0, Config.PLAYHEAD_SIZE, self.height )
+ self.invalidate_rect( self.playheadX-Config.PLAYHEAD_SIZE/2, 0, Config.PLAYHEAD_SIZE, self.height )
+ self.playheadX = self.ticksToPixels( ticks ) + Config.TRACK_SPACING_DIV2
+ self.invalidate_rect( self.playheadX-Config.PLAYHEAD_SIZE/2, 0, Config.PLAYHEAD_SIZE, self.height )
def getSelectedTracks( self ):
r = []
@@ -209,38 +265,13 @@ class TrackInterface( gtk.EventBox ):
# Event Callbacks
def size_allocate( self, widget, allocation ):
+ self.alloc = allocation
width = allocation.width
height = allocation.height
-
- self.drawingArea.set_size_request( width, height )
-
- self.trackHeight = (height - (Config.NUMBER_OF_TRACKS-1)*Config.TRACK_SPACING) / Config.NUMBER_OF_TRACKS
- self.height = self.trackHeight*Config.NUMBER_OF_TRACKS + Config.TRACK_SPACING*(Config.NUMBER_OF_TRACKS-1)
- self.trackLimits = []
- self.trackOrigin = []
- for i in range(Config.NUMBER_OF_TRACKS):
- start = i*(self.trackHeight+Config.TRACK_SPACING)
- self.trackLimits.insert( i, (start,start+self.trackHeight) )
- self.trackOrigin.insert( i, (Config.BORDER_SIZE,start+Config.BORDER_SIZE) )
-
- self.fullWidth = width - 2 # cut off 2 pixels cause otherwise we try to draw on an area that gets cut off!?
-
- # make sure this matches the calculations in updateBeatCount
- self.beatSpacing = (self.fullWidth - Config.BORDER_SIZE_MUL2 + Config.BEAT_LINE_SIZE)/self.beatCount
- self.width = self.beatSpacing * self.beatCount + Config.BORDER_SIZE_MUL2
- self.ticksPerPixel = float(self.beatCount * Config.TICKS_PER_BEAT) / (self.width-2*Config.BORDER_SIZE)
- self.pixelsPerTick = 1/self.ticksPerPixel
-
- self.pitchPerPixel = float(Config.NUMBER_OF_POSSIBLE_PITCHES-1) / (self.trackHeight-2*Config.BORDER_SIZE-Config.NOTE_HEIGHT)
- self.pixelsPerPitch = float(self.trackHeight-2*Config.BORDER_SIZE-Config.NOTE_HEIGHT)/(Config.MAXIMUM_PITCH - Config.MINIMUM_PITCH)
-
- # this could potentially take a loooong time, make sure they don't resize the window very often
- for page in self.note:
- for i in range(Config.NUMBER_OF_TRACKS):
- track = self.note[page][i]
- map( lambda note:note.updateTransform( False ), track )
-
- if self.drawingArea.window != None:
+
+ self.drawingArea.set_size_request( width, height )
+
+ if self.window != None:
self.invalidate_rect( 0, 0, width, height )
def handleButtonPress( self, widget, event ):
@@ -574,7 +605,7 @@ class TrackInterface( gtk.EventBox ):
width = max( self.marqueeRect[0][0] + self.marqueeRect[1][0], oldEndX ) - x
y = min( self.marqueeRect[0][1], oldY )
height = max( self.marqueeRect[0][1] + self.marqueeRect[1][1], oldEndY ) - y
- self.invalidate_rect( x-1, y-1, width+2, height+2 ) # increase by 1 to handle switching quadrants
+ self.invalidate_rect( x-1, y-1, width+2, height+2 )
def doneMarquee( self, event ):
if self.marqueeLoc:
@@ -605,14 +636,15 @@ class TrackInterface( gtk.EventBox ):
self.invalidate_rect( self.marqueeRect[0][0]-1, self.marqueeRect[0][1]-1, self.marqueeRect[1][0]+2, self.marqueeRect[1][1]+2 )
def updatePlayhead( self, event ):
- x = min( self.width - Config.BORDER_SIZE_MUL2 - self.pixelsPerTick, max( Config.BORDER_SIZE, event.x ) )
+ x = min( self.trackWidth - self.pixelsPerTick, max( Config.TRACK_SPACING_DIV2, event.x ) )
self.setPlayhead( self.pixelsToTicks( x ) )
def donePlayhead( self, event ):
- x = min( self.width - Config.BORDER_SIZE_MUL2, max( Config.BORDER_SIZE, event.x ) )
+ x = min( self.trackWidth - self.pixelsPerTick, max( Config.TRACK_SPACING_DIV2, event.x ) )
ticks = self.pixelsToTicks( x )
- print "set playhead to %d ticks" % (ticks)
+ print "set playhead to %d ticks" % (ticks)
+ self.doneCurrentAction()
def updateTooltip( self, event ):
@@ -652,75 +684,69 @@ class TrackInterface( gtk.EventBox ):
#=======================================================
# Drawing
- def draw( self, drawingArea, event ):
+ def expose( self, DA, event ):
TP.ProfileBegin( "TrackInterface::draw" )
startX = event.area.x
startY = event.area.y
stopX = event.area.x + event.area.width
stopY = event.area.y + event.area.height
-
- context = drawingArea.window.cairo_create()
- context.set_antialias(0) # I don't know what to set this to to turn it off, and it doesn't seem to work anyway!?
-
- for i in range( Config.NUMBER_OF_TRACKS):
+
+ #print "%d %d %d %d" % (startX,startY,stopX,stopY)
+
+ self.gc.set_line_attributes( Config.BEAT_LINE_SIZE, gtk.gdk.LINE_ON_OFF_DASH, gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER )
+ # regular tracks
+ for i in range( self.drumIndex ):
if startY > self.trackLimits[i][1]: continue
if stopY < self.trackLimits[i][0]: break
- if False:
- context.set_line_width( Config.BORDER_SIZE )
-
- context.move_to( Config.BORDER_SIZE_DIV2, self.trackLimits[i][0] + Config.BORDER_SIZE_DIV2 )
- context.rel_line_to( self.width - Config.BORDER_SIZE, 0 )
- context.rel_line_to( 0, self.trackHeight - Config.BORDER_SIZE )
- context.rel_line_to( -self.width + Config.BORDER_SIZE, 0 )
- context.close_path()
-
- #draw background
- context.set_source_rgb( 0.75, 0.75, 0.75 )
- context.fill_preserve()
-
+ # draw background
+ if self.trackSelected[i]:
+ DA.window.draw_drawable( self.gc, self.image["trackBGSelected"], 0, 0, 0, self.trackLimits[i][0], self.trackFullWidth, self.trackFullHeight )
else:
- context.rectangle(Config.BORDER_SIZE_DIV2, self.trackLimits[i][0] + Config.BORDER_SIZE_DIV2 , self.width, self.height)
- context.set_source_rgb( 0.75, 0.75, 0.75 )
- context.fill()
-
- # draw border
- if self.trackSelected[i]: context.set_source_rgb( 1, 1, 1 )
- else: context.set_source_rgb( 0, 0, 0 )
- context.stroke()
+ DA.window.draw_drawable( self.gc, self.image["trackBG"], 0, 0, 0, self.trackLimits[i][0], self.trackFullWidth, self.trackFullHeight )
# draw beat lines
- context.set_line_width( Config.BEAT_LINE_SIZE )
- beatStart = Config.BORDER_SIZE + Config.BEAT_LINE_SIZE_DIV2
- context.set_source_rgb( 0.4, 0.4, 0.4 )
+ self.gc.foreground = self.beatColor
+ beatStart = Config.TRACK_SPACING_DIV2
for j in range(1,self.beatCount):
- context.move_to( beatStart + j*self.beatSpacing, self.trackLimits[i][0] + Config.BORDER_SIZE )
- context.rel_line_to( 0, self.trackHeight - Config.BORDER_SIZE_MUL2 )
- context.stroke()
-
+ x = beatStart + j*self.beatSpacing
+ DA.window.draw_line( self.gc, x, self.trackRect[i].y, x, self.trackRect[i].y+self.trackRect[i].height )
+
# draw notes
notes = self.note[self.curPage][i]
for n in range(len(notes)):
- if not notes[n].draw( context, startX, stopX ): break
+ if not notes[n].draw( DA.window, self.gc, startX, stopX ): break
+
+ # drum track
+ if stopY > self.trackLimits[self.drumIndex][0]:
+ # draw background
+ if self.trackSelected[self.drumIndex]:
+ DA.window.draw_drawable( self.gc, self.image["trackBGDrumSelected"], 0, 0, 0, self.trackLimits[self.drumIndex][0], self.trackFullWidth, self.trackFullHeightDrum )
+ else:
+ DA.window.draw_drawable( self.gc, self.image["trackBGDrum"], 0, 0, 0, self.trackLimits[self.drumIndex][0], self.trackFullWidth, self.trackFullHeightDrum )
+
+ # draw beat lines
+ self.gc.foreground = self.beatColor
+ beatStart = Config.TRACK_SPACING_DIV2
+ for j in range(1,self.beatCount):
+ x = beatStart + j*self.beatSpacing
+ DA.window.draw_line( self.gc, x, self.trackRect[self.drumIndex].y, x, self.trackRect[self.drumIndex].y+self.trackRect[self.drumIndex].height )
+ # draw notes
+ notes = self.note[self.curPage][self.drumIndex]
+ for n in range(len(notes)):
+ if not notes[n].draw( DA.window, self.gc, startX, stopX ): break
+
# draw playhead
- context.set_line_width( Config.PLAYHEAD_SIZE )
- context.move_to( self.playheadX + Config.PLAYHEAD_SIZE_DIV2, 0 )
- # do some fancy shit here to grey out muted tracks!?
- context.rel_line_to( 0, self.height )
- context.set_source_rgb( 0, 0, 0 )
- context.stroke()
-
+ self.gc.set_line_attributes( Config.PLAYHEAD_SIZE, gtk.gdk.LINE_SOLID, gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER )
+ self.gc.foreground = self.playheadColor
+ DA.window.draw_line( self.gc, self.playheadX, startY, self.playheadX, stopY )
+
if self.marqueeLoc: # draw the selection rect
- context.set_line_width( 1 )
- context.move_to( self.marqueeRect[0][0] + 0.5, self.marqueeRect[0][1] + 0.5 )
- context.rel_line_to( self.marqueeRect[1][0] - 1, 0 )
- context.rel_line_to( 0, self.marqueeRect[1][1] - 1 )
- context.rel_line_to( -self.marqueeRect[1][0] + 1, 0 )
- context.close_path()
- context.set_source_rgb( 1, 1, 1 )
- context.stroke()
+ self.gc.set_line_attributes( Config.MARQUEE_SIZE, gtk.gdk.LINE_ON_OFF_DASH, gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER )
+ self.gc.foreground = self.marqueeColor
+ DA.window.draw_rectangle( self.gc, False, self.marqueeRect[0][0], self.marqueeRect[0][1], self.marqueeRect[1][0], self.marqueeRect[1][1] )
self.drawingAreaDirty = False
@@ -736,7 +762,7 @@ class TrackInterface( gtk.EventBox ):
#self.queue_draw()
def getTrackOrigin( self, track ):
- return self.trackOrigin[track]
+ return ( self.trackRect[track].x, self.trackRect[track].y )
def ticksToPixels( self, ticks ):
return int(round( ticks * self.pixelsPerTick ))
diff --git a/Resources/Images/note.png b/Resources/Images/note.png
new file mode 100755
index 0000000..03947e4
--- /dev/null
+++ b/Resources/Images/note.png
Binary files differ
diff --git a/Resources/Images/noteSelected.png b/Resources/Images/noteSelected.png
new file mode 100755
index 0000000..f253ff0
--- /dev/null
+++ b/Resources/Images/noteSelected.png
Binary files differ
diff --git a/Resources/Images/trackBG.png b/Resources/Images/trackBG.png
new file mode 100755
index 0000000..b875dda
--- /dev/null
+++ b/Resources/Images/trackBG.png
Binary files differ
diff --git a/Resources/Images/trackBGDrum.png b/Resources/Images/trackBGDrum.png
new file mode 100755
index 0000000..aeb73b2
--- /dev/null
+++ b/Resources/Images/trackBGDrum.png
Binary files differ
diff --git a/Resources/Images/trackBGDrumSelected.png b/Resources/Images/trackBGDrumSelected.png
new file mode 100755
index 0000000..06e1871
--- /dev/null
+++ b/Resources/Images/trackBGDrumSelected.png
Binary files differ
diff --git a/Resources/Images/trackBGSelected.png b/Resources/Images/trackBGSelected.png
new file mode 100755
index 0000000..d1bf236
--- /dev/null
+++ b/Resources/Images/trackBGSelected.png
Binary files differ
diff --git a/Util/Sound.py b/Util/Sound.py
new file mode 100644
index 0000000..be00cb5
--- /dev/null
+++ b/Util/Sound.py
@@ -0,0 +1,276 @@
+import csnd
+import os
+import socket
+import select
+import sys
+import threading
+import time
+import bisect
+
+from sugar import env
+import Config
+
+from Util.CSoundNote import CSoundNote #maybe not actually used, but dependence is there. All notes are assumed to be CSoundNotes
+from Generation.GenerationConstants import GenerationConstants
+
+class Sound:
+ #PRIVATE
+ DRIFT = 0.01 #careful about changing this... coordinate with instrument 5777
+ def loop_work(self, sleeptime):
+ def next( ) :
+ time_time = time.time()
+ #tickhorizon is tick where we'll be after range_sec
+ tickhorizon = self.getTick( self.range_sec + time_time, False )
+ time0_time = self.time0 - self.time_start + self.DRIFT
+
+ if tickhorizon < 0 : return []
+ if len(self.notes) == 0 : return []
+
+ def cache_cmd(secs_per_tick, amplitude, pitch, inst, trackId, duration, tied, fullDuration, overlap, attack, decay, reverbSend, filterType, filterCutoff, pan ):
+ if inst[0:4] == 'drum':
+ if pitch in GenerationConstants.DRUMPITCH:
+ key = GenerationConstants.DRUMPITCH[ pitch ]
+ else:
+ key = pitch
+
+ if inst == 'drum1kit':
+ inst = Config.DRUM1INSTRUMENTS[ key ]
+ if inst == 'drum2kit':
+ inst = Config.DRUM2INSTRUMENTS[ key ]
+ if inst == 'drum3kit':
+ inst = Config.DRUM3INSTRUMENTS[ key ]
+ pitch = 1
+
+ else:
+ pitch = GenerationConstants.TRANSPOSE[ pitch - 24 ]
+
+ # condition for tied notes
+ if Config.INSTRUMENTS[ inst ].csoundInstrumentId == 101 and tied and fullDuration:
+ duration= -1.0
+ # condition for overlaped notes
+ if Config.INSTRUMENTS[ inst ].csoundInstrumentId == 102 and overlap:
+ duration += 1.0
+
+ attack = max( 0.002, duration * attack)
+ decay = max( 0.002, duration * decay)
+
+ rval = Config.PLAY_NOTE_COMMAND_MINUS_DELAY % \
+ ( Config.INSTRUMENTS[ inst ].csoundInstrumentId,
+ trackId,
+ '%f', #delay,
+ duration,
+ pitch,
+ reverbSend,
+ amplitude,
+ pan,
+ Config.INSTRUMENT_TABLE_OFFSET + Config.INSTRUMENTS[ inst ].instrumentId,
+ attack,
+ decay,
+ filterType, filterCutoff )
+ return rval
+
+ def getText(i, secs_per_tick, time_offset):
+ (onset,note,cache,z) = self.notes[i]
+ if cache == '' or note.nchanges != z :
+ self.notes[i] = \
+ (
+ onset,
+ note,
+ cache_cmd(
+ secs_per_tick,
+ note.amplitude, # * track-level mixer rate
+ note.pitch,
+ note.instrumentFlag,
+ note.trackId,
+ note.duration * self.secs_per_tick,
+ note.tied,
+ note.fullDuration,
+ note.overlap,
+ note.attack,
+ note.decay,
+ note.reverbSend,
+ note.filterType,
+ note.filterCutoff,
+ note.pan),
+ note.nchanges
+ )
+ rval = self.notes[i][2] % float(onset * self.secs_per_tick + time_offset)
+ return rval
+
+ prev_secs = (self.loops * self.duration) * self.secs_per_tick
+ rval = []
+ while self.notes[self.hIdx][0] + self.loops * self.duration < tickhorizon:
+ rval.append ( getText(self.hIdx, self.secs_per_tick, prev_secs + time0_time ) )
+ self.hIdx += 1
+ if self.hIdx == len(self.notes):
+ self.hIdx = 0
+ self.loops += 1
+ prev_secs += self.duration * self.secs_per_tick
+
+ return rval
+
+ #thread.start_new_thread( testtimer, (0,) )
+ m = 0.0
+ while self.thread_continue:
+ t0 = time.time()
+ time.sleep(sleeptime)
+ t1 = time.time()
+ if t1 - t0 > 2.0 * sleeptime :
+ print 'critical lagginess: ', t1 - t0
+ if m < t1 - t0:
+ m = t1 - t0
+ print t1, ' timer max = ', m
+ cmds = self.next()
+ for c in cmds:
+ self.perf.InputMessage( '' )
+
+ def __init__(self, orc, range_sec, ticks_per_sec ):
+ self.orc = orc
+ self.up = False
+ self.csound = csnd.Csound()
+
+ self.ticks_per_sec = ticks_per_sec # ticks last this long
+ self.secs_per_tick = 1.0 / ticks_per_sec # precomputed inverse
+ self.range_sec = range_sec # notes are checked-for, this many seconds in advance
+
+ self.duration = 0 # number of ticks in playback loop
+ self.loops = 0 # number of elapsed loops
+ self.notes = [] # sorted list of (onset, noteptr, cache)
+
+ self.time0 = time.time() + 1000000 # the real time at which tick == 0 (sometimes retro-active)
+ self.thread_continue = 1
+ self.thread = thread.start_new_thread( loop_work, (self,0.040) )
+
+ def uninit(self):
+ self.thread_continue = 0
+ self.thread.join()
+ if self.up : self.lower()
+
+ def micRecording( self, table ):
+ mess = Config.MIC_RECORDING_COMMAND % table
+ self.sendText( mess )
+
+ def load_mic_instrument( self, inst ):
+ home_path = env.get_profile_path() + Config.PREF_DIR
+ fileName = home_path + '/' + inst
+ instrumentId = Config.INSTRUMENT_TABLE_OFFSET + int(fileName[-1]) + 6
+ mess = Config.LOAD_INSTRUMENT_COMMAND % ( instrumentId, fileName )
+ self.sendText( mess )
+
+ def startTime(self):
+ if not self.up :
+ debug_print (1, "ERROR: Sound::startTime, performance thread isn't up yet.")
+ return
+ self.perf.InputMessage('i 5999 0.0 60000000')
+ self.time_start = time.time()
+ # if a note event is sent to csound before or simultaneous to this one, then it will not play correctly.
+ # thus we sleep right here, to (ideally) let csound pick up the message.
+ # NB: match this to the constant in the instrument 5777 of the csound orcestra
+ time.sleep(0.1)
+
+ def load_instruments( self ):
+ home_path = env.get_profile_path() + Config.PREF_DIR
+ for instrumentSoundFile in Config.INSTRUMENTS.keys():
+ if instrumentSoundFile[0:3] == 'mic' or instrumentSoundFile[0:3] == 'lab':
+ fileName = home_path + '/' + instrumentSoundFile
+ else:
+ fileName = Config.SOUNDS_DIR + "/" + instrumentSoundFile
+ instrumentId = Config.INSTRUMENT_TABLE_OFFSET + Config.INSTRUMENTS[ instrumentSoundFile ].instrumentId
+ mess = Config.LOAD_INSTRUMENT_COMMAND % ( instrumentId, fileName )
+ self.sendText( mess )
+
+ def raise( self ):
+ if self.up :
+ debug_print(3, 'Sound::raise() already up.')
+ return
+ self.up = True
+ self.perf = csnd.CsoundPerformanceThread(self.csound)
+ self.csound.Compile( self.orc )
+ self.perf.Play()
+ self.load_instruments()
+ debug_print(5, 'Sound::raise succeeded')
+
+ def lower(self):
+ if not self.up :
+ debug_print(3, 'Sound::lower() already down.')
+ return
+ self.up = False
+ self.sendText( Config.UNLOAD_TABLES_COMMAND )
+ self.perf.Stop()
+ rval = self.perf.Join()
+ self.csound.Reset()
+ debug_print(5, 'Sound::lower() succeeded')
+
+ def setMasterVolume(self, volume):
+ self.csound.SetChannel('masterVolume',volume )
+
+ def inputMessage(self, txt):
+ self.perf.InputMessage(txt)
+
+ def loop_setTick( self, tick ):
+ time_time = time.time()
+ self.time0 = time_time - tick * self.secs_per_tick
+ self.loops = tick // self.duration
+ self.hIdx = bisect.bisect_left(self.notes, tick - self.duration * self.loops )
+
+ def loop_setRate( self, ticks_per_sec):
+ if ticks_per_sec != self.ticks_per_sec:
+ secs_per_tick = 1.0 / ticks_per_sec
+
+ time_time = time.time()
+ curtick = self.getTick( time_time, False )
+ curticktime = curtick * self.secs_per_tick + self.time0
+
+ self.ticks_per_sec = ticks_per_sec
+ self.secs_per_tick = secs_per_tick
+ self.time0 = curticktime - curtick * secs_per_tick
+ self.notes = [ (o,n,'',z) for (o,n,c,z) in self.notes ] #clear cache
+ self.loops = 0
+
+ def loop_setDuration( self, duration ):
+ self.time0 += self.loops * self.duration * self.secs_per_tick
+ self.loops = 0
+ self.duration = duration
+
+ def loop_getTick(self, t, domod): #t is for time
+ if domod :
+ return ( int( ( t - self.time0 ) * self.ticks_per_sec ) ) % self.duration
+ else :
+ return ( int( ( t - self.time0 ) * self.ticks_per_sec ) )
+
+ def loop_insert( self, notes):
+ def insertMany():
+ self.notes += [ ( notes[i][0], notes[i][1], '', 0 ) for i in xrange(len(notes)) ]
+ self.notes.sort()
+ def insertFew():
+ for i in xrange(len(notes)):
+ t = (notes[i][0], notes[i][1],'',0)
+ l = bisect.bisect_left(self.notes, t )
+ self.notes.insert(l, t)
+
+ if len(notes) >= 1:
+ insertMany()
+ else:
+ insertFew()
+ self.hIdx = bisect.bisect_left(self.notes, self.getTick(self.range_sec + time.time(), True))
+
+ def loop_remove(self, note):
+ def removeFew():
+ i = 0
+ while i < len(self.notes):
+ if self.notes[i][1] in note:
+ del self.notes[i]
+ else:
+ i += 1
+
+ def removeMany():
+ self.notes = [t for t in self.notes if t[1] not in note]
+
+ if len(idset) >= 0: #just guessing here, should do some timing tests to see if this is good or no
+ removeMany()
+ else:
+ removeFew()
+ self.hIdx = bisect.bisect_left(self.notes, self.getTick(self.range_sec + time.time(), True))
+
+ def loop_clear(self):
+ self.notes = []
diff --git a/scripts/olpc_get_stuff.sh b/scripts/olpc_get_stuff.sh
index ebbd292..9751900 100644..100755
--- a/scripts/olpc_get_stuff.sh
+++ b/scripts/olpc_get_stuff.sh
@@ -12,10 +12,10 @@ echo 'export GIT_AUTHOR_NAME GIT_COMMITTER_NAME in .bashrc'
echo 'edit olpc's .xinitrc file to change the window-manager'
-read USER
-
-mkdir cvs
-cd cvs
-git-clone "git+ssh://$USER@dev.laptop.org/git/projects/tamtam" tamtam
+echo 'this might help you get your git repo back up:'
+echo 'read USER'
+echo 'mkdir cvs'
+echo 'cd cvs'
+echo 'git-clone "git+ssh://$USER@dev.laptop.org/git/projects/tamtam" tamtam'