Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Jam
diff options
context:
space:
mode:
authoramartin <olpc@xo-05-28-21.localdomain>2007-08-27 07:41:25 (GMT)
committer amartin <olpc@xo-05-28-21.localdomain>2007-08-27 07:41:25 (GMT)
commit7eb4faf55a3935217f24bff9fd1f1ff2618c93ec (patch)
tree83e6983b075f68f10caefbef64fd4be42f059ecf /Jam
parent42ca65d2e583639cdbb0a6af921ddf2dae75af54 (diff)
Jam Loops
Diffstat (limited to 'Jam')
-rw-r--r--Jam/Block.py57
-rw-r--r--Jam/Desktop.py13
-rw-r--r--Jam/JamMain.py201
-rw-r--r--Jam/Picker.py128
4 files changed, 309 insertions, 90 deletions
diff --git a/Jam/Block.py b/Jam/Block.py
index 5eaf53e..c86a53b 100644
--- a/Jam/Block.py
+++ b/Jam/Block.py
@@ -69,10 +69,10 @@ class Block():
else:
self.invalidate_rect( not self.dragging )
- self.x = x
- self.y = y
- self.endX = x + self.width
- self.endY = y + self.height
+ self.x = int(x)
+ self.y = int(y)
+ self.endX = self.x + self.getWidth()
+ self.endY = self.y + self.height
self.invalidate_rect( not self.dragging )
@@ -91,6 +91,9 @@ class Block():
def snapToParentLoc( self, loc ):
self.setLoc( loc[0] - self.parentOffset, loc[1] )
+ def getWidth( self ):
+ return self.width
+
def substitute( self, block ):
pass # override in subclasses
@@ -183,7 +186,7 @@ class Block():
def _beginDrag( self ):
self.dragging = True
- self.dragOffset = ( self.width//2, self.height//2 )
+ self.dragOffset = ( self.getWidth()//2, self.height//2 )
def invalidateBranch( self, base = True ):
self.invalidate_rect( base )
@@ -191,7 +194,7 @@ class Block():
self.child.invalidateBranch( base )
def invalidate_rect( self, base = True ):
- self.owner.invalidate_rect( self.x, self.y, self.width, self.height, base )
+ self.owner.invalidate_rect( self.x, self.y, self.getWidth(), self.height, base )
def draw( self, startX, startY, stopX, stopY, pixmap ):
if stopY <= self.y or startY >= self.endY:
@@ -380,6 +383,8 @@ class Loop(Block):
BEAT = 23
TAIL = BEAT + 4
+ WIDTH = [ HEAD + BEAT*(n-1) + TAIL for n in range(Config.MAXIMUM_BEATS+1) ]
+
BEAT_MUL3 = BEAT*3
MASK_START = 200
@@ -387,20 +392,22 @@ class Loop(Block):
MASK_TAIL = MASK_START + HEAD + BEAT*3
#::: data format:
- # { "name": name, "beats": 2-12 }
+ # { "name": name, "id": pageId }
#:::
def __init__( self, owner, graphics_context, data ):
Block.__init__( self, owner, graphics_context, data )
self.type = Loop
- self.width = Loop.HEAD + Loop.BEAT*(data["beats"]-1) + Loop.TAIL
-
self.canParent = True
self.canChild = True
self.parentOffset = Loop.HEAD - 4
+ def getWidth( self ):
+ beats = self.owner.noteDB.getPage(self.data["id"]).beats
+ return Loop.WIDTH[beats]
+
def _doButtonPress( self, event ): # we were hit with a button press
pass
@@ -409,6 +416,10 @@ class Loop(Block):
endY = min( stopY, self.endY )
height = endY - y
+ loop = self.owner.getLoopImage( self.data["id"], self.active )
+ if self.active: self.gc.foreground = self.owner.colors["Border_Active"]
+ else: self.gc.foreground = self.owner.colors["Border_Inactive"]
+
#-- draw head -----------------------------------------
if self.x + Loop.HEAD > startX:
@@ -417,20 +428,16 @@ class Loop(Block):
width = endX - x
# draw border
- if self.active: self.gc.foreground = self.owner.colors["Border_Active"]
- else: self.gc.foreground = self.owner.colors["Border_Inactive"]
self.gc.set_clip_origin( self.x-Loop.MASK_START, self.y )
pixmap.draw_rectangle( self.gc, True, x, y, width, height )
# draw block
- if self.active: self.gc.foreground = self.owner.colors["Bg_Active"]
- else: self.gc.foreground = self.owner.colors["Bg_Inactive"]
self.gc.set_clip_origin( self.x-Loop.MASK_START, self.y-self.height )
- pixmap.draw_rectangle( self.gc, True, x, y, width, height )
+ pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height )
#-- draw beats ----------------------------------------
- beats = self.data["beats"] - 1 # last beat is drawn with the tail
+ beats = self.owner.noteDB.getPage(self.data["id"]).beats - 1 # last beat is drawn with the tail
curx = self.x + Loop.HEAD
while beats > 3:
if curx >= stopX:
@@ -441,16 +448,12 @@ class Loop(Block):
width = endX - x
# draw border
- if self.active: self.gc.foreground = self.owner.colors["Border_Active"]
- else: self.gc.foreground = self.owner.colors["Border_Inactive"]
self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y )
pixmap.draw_rectangle( self.gc, True, x, y, width, height )
# draw block
- if self.active: self.gc.foreground = self.owner.colors["Bg_Active"]
- else: self.gc.foreground = self.owner.colors["Bg_Inactive"]
self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y-self.height )
- pixmap.draw_rectangle( self.gc, True, x, y, width, height )
+ pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height )
curx += Loop.BEAT_MUL3
beats -= 3
@@ -464,16 +467,12 @@ class Loop(Block):
width = endX - x
# draw border
- if self.active: self.gc.foreground = self.owner.colors["Border_Active"]
- else: self.gc.foreground = self.owner.colors["Border_Inactive"]
self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y )
pixmap.draw_rectangle( self.gc, True, x, y, width, height )
# draw block
- if self.active: self.gc.foreground = self.owner.colors["Bg_Active"]
- else: self.gc.foreground = self.owner.colors["Bg_Inactive"]
self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y-self.height )
- pixmap.draw_rectangle( self.gc, True, x, y, width, height )
+ pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height )
curx += Loop.BEAT*beats
@@ -487,16 +486,12 @@ class Loop(Block):
width = endX - x
# draw border
- if self.active: self.gc.foreground = self.owner.colors["Border_Active"]
- else: self.gc.foreground = self.owner.colors["Border_Inactive"]
self.gc.set_clip_origin( curx-Loop.MASK_TAIL, self.y )
pixmap.draw_rectangle( self.gc, True, x, y, width, height )
# draw block
- if self.active: self.gc.foreground = self.owner.colors["Bg_Active"]
- else: self.gc.foreground = self.owner.colors["Bg_Inactive"]
self.gc.set_clip_origin( curx-Loop.MASK_TAIL, self.y-self.height )
- pixmap.draw_rectangle( self.gc, True, x, y, width, height )
+ pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height )
def drawHighlight( self, startX, startY, stopX, stopY, pixmap ):
@@ -509,7 +504,7 @@ class Loop(Block):
#-- draw beats ----------------------------------------
- beats = self.data["beats"] - 1 # last beat is drawn with the tail
+ beats = self.owner.noteDB.getPage(self.data["id"]).beats - 1 # last beat is drawn with the tail
x = self.x + Loop.HEAD
while beats > 3:
self.gc.set_clip_origin( x-Loop.MASK_BEAT, self.y )
diff --git a/Jam/Desktop.py b/Jam/Desktop.py
index b4b4bda..1a99cee 100644
--- a/Jam/Desktop.py
+++ b/Jam/Desktop.py
@@ -20,7 +20,9 @@ class Desktop( gtk.EventBox ):
# take drawing setup from owner
self.gc = owner.gc
self.colors = owner.colors
- self.clipMask = owner.clipMask
+ self.blockMask = owner.blockMask
+
+ self.noteDB = owner.noteDB
self.dirtyRectToAdd = gtk.gdk.Rectangle() # used by the invalidate_rect function
self.screenBuf = None
@@ -78,7 +80,7 @@ class Desktop( gtk.EventBox ):
win = gtk.gdk.get_default_root_window()
display = win.get_display()
screen = display.get_default_screen()
- display.warp_pointer( screen, self.absoluteLoc[0] + x, self.absoluteLoc[1] + y )
+ display.warp_pointer( screen, int(self.absoluteLoc[0] + x), int(self.absoluteLoc[1] + y) )
self._beginDrag( block )
block.setLoc( x - block.width//2, y - block.height//2 )
else:
@@ -117,6 +119,9 @@ class Desktop( gtk.EventBox ):
def getInstrumentImage( self, id, active = False ):
return self.owner.getInstrumentImage( id, active )
+ def getLoopImage( self, id, active = False ):
+ return self.owner.getLoopImage( id, active )
+
#==========================================================
# State
@@ -274,7 +279,7 @@ class Desktop( gtk.EventBox ):
self.screenBuf.draw_rectangle( self.gc, True, startX, startY, self.screenBufDirtyRect.width, self.screenBufDirtyRect.height )
# draw blocks
- self.gc.set_clip_mask( self.clipMask )
+ self.gc.set_clip_mask( self.blockMask )
for block in self.blocks:
block.draw( startX, startY, stopX, stopY, self.screenBuf )
@@ -300,7 +305,7 @@ class Desktop( gtk.EventBox ):
if self.possibleDelete:
return
- self.gc.set_clip_mask( self.clipMask )
+ self.gc.set_clip_mask( self.blockMask )
# draw possible parent
if self.possibleParent:
diff --git a/Jam/JamMain.py b/Jam/JamMain.py
index 1421da3..8751c74 100644
--- a/Jam/JamMain.py
+++ b/Jam/JamMain.py
@@ -18,6 +18,8 @@ from Jam.Toolbars import DesktopToolbar
from Util.CSoundNote import CSoundNote
from Util.CSoundClient import new_csound_client
import Util.InstrumentDB as InstrumentDB
+from Util import NoteDB
+
from Fillin import Fillin
from RythmGenerator import generator
from Generation.GenerationConstants import GenerationConstants
@@ -33,6 +35,7 @@ class JamMain(SubActivity):
self.activity = activity
self.instrumentDB = InstrumentDB.getRef()
+ self.noteDB = NoteDB.NoteDB()
#-- initial settings ----------------------------------
self.tempo = Config.PLAYER_TEMPO
@@ -46,22 +49,40 @@ class JamMain(SubActivity):
self.csnd.loopSetTempo( self.tempo )
#-- Drawing -------------------------------------------
+ def darken( colormap, hex ):
+ hexToDec = { "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 }
+ r = int( 0.7*(16*hexToDec[hex[1]] + hexToDec[hex[2]]) )
+ g = int( 0.7*(16*hexToDec[hex[3]] + hexToDec[hex[4]]) )
+ b = int( 0.7*(16*hexToDec[hex[5]] + hexToDec[hex[6]]) )
+ return colormap.alloc_color( r*256, g*256, b*256 )
+ def lighten( colormap, hex ):
+ hexToDec = { "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 }
+ r = 255 - int( 0.7*(255-(16*hexToDec[hex[1]] + hexToDec[hex[2]])) )
+ g = 255 - int( 0.7*(255-(16*hexToDec[hex[3]] + hexToDec[hex[4]])) )
+ b = 255 - int( 0.7*(255-(16*hexToDec[hex[5]] + hexToDec[hex[6]])) )
+ return colormap.alloc_color( r*256, g*256, b*256 )
+
win = gtk.gdk.get_default_root_window()
self.gc = gtk.gdk.GC( win )
colormap = gtk.gdk.colormap_get_system()
- self.colors = { "bg": colormap.alloc_color( Config.PANEL_BCK_COLOR ),
- "Picker_Bg": colormap.alloc_color( "#404040" ),
- "Picker_Bg_Inactive": colormap.alloc_color( "#808080" ),
- #"Picker_Bg": colormap.alloc_color( style.COLOR_TOOLBAR_GREY.get_html() ),
- #"Picker_Bg_Inactive": colormap.alloc_color( style.COLOR_BUTTON_GREY.get_html() ),
- "Picker_Fg": colormap.alloc_color( style.COLOR_WHITE.get_html() ),
- "Border_Active": colormap.alloc_color( "#FF6000" ),
- "Border_Inactive": colormap.alloc_color( "#8D8D8D" ),
- "Border_Highlight": colormap.alloc_color( "#FFFFFF" ),
- "Bg_Active": colormap.alloc_color( "#9400BE" ),
- "Bg_Inactive": colormap.alloc_color( "#DBDBDB" ) }
-
- if True: # load clipmask
+ self.colors = { "bg": colormap.alloc_color( Config.PANEL_BCK_COLOR ),
+ "Picker_Bg": colormap.alloc_color( "#404040" ),
+ "Picker_Bg_Inactive": colormap.alloc_color( "#808080" ),
+ #"Picker_Bg": colormap.alloc_color( style.COLOR_TOOLBAR_GREY.get_html() ),
+ #"Picker_Bg_Inactive": colormap.alloc_color( style.COLOR_BUTTON_GREY.get_html() ),
+ "Picker_Fg": colormap.alloc_color( style.COLOR_WHITE.get_html() ),
+ "Border_Active": colormap.alloc_color( "#FF6000" ),
+ "Border_Inactive": colormap.alloc_color( "#8D8D8D" ),
+ "Border_Highlight": colormap.alloc_color( "#FFFFFF" ),
+ "Bg_Active": colormap.alloc_color( "#9400BE" ),
+ "Bg_Inactive": colormap.alloc_color( "#DBDBDB" ),
+ "Note_Fill_Active": lighten( colormap, "#FF6000" ), # base "Border_Active"
+ "Note_Fill_Inactive": lighten( colormap, "#8D8D8D" ) } # base "Border_Inactive"
+ self.colors[ "Note_Border_Active"] = self.colors["Border_Active"]
+ self.colors[ "Note_Border_Inactive"] = self.colors["Border_Inactive"]
+
+
+ if True: # load block clipmask
pix = gtk.gdk.pixbuf_new_from_file(Config.IMAGE_ROOT+'jam-blockMask.png')
pixels = pix.get_pixels()
stride = pix.get_rowstride()
@@ -83,37 +104,51 @@ class JamMain(SubActivity):
bitmap += "%c" % byte
byte = 0
shift = 0
- self.clipMask = gtk.gdk.bitmap_create_from_data( None, bitmap, pix.get_width(), pix.get_height() )
+ self.blockMask = gtk.gdk.bitmap_create_from_data( None, bitmap, pix.get_width(), pix.get_height() )
+
+ self.sampleNoteHeight = 7
+ if True: # load sample note clipmask
+ pix = gtk.gdk.pixbuf_new_from_file(Config.IMAGE_ROOT+'sampleNoteMask.png')
+ pixels = pix.get_pixels()
+ stride = pix.get_rowstride()
+ channels = pix.get_n_channels()
+ bitmap = ""
+ byte = 0
+ shift = 0
+ for j in range(pix.get_height()):
+ offset = stride*j
+ for i in range(pix.get_width()):
+ r = pixels[i*channels+offset]
+ if r != "\0": byte += 1 << shift
+ shift += 1
+ if shift > 7:
+ bitmap += "%c" % byte
+ byte = 0
+ shift = 0
+ if shift > 0:
+ bitmap += "%c" % byte
+ byte = 0
+ shift = 0
+ self.sampleNoteMask = gtk.gdk.bitmap_create_from_data( None, bitmap, pix.get_width(), pix.get_height() )
+ self.sampleNoteMask.endOffset = pix.get_width()-3
+
+ self.loopPitchOffset = 4
+ self.loopTickOffset = 13
+ self.pitchPerPixel = float(Config.NUMBER_OF_POSSIBLE_PITCHES-1) / (Block.Loop.HEIGHT - 2*self.loopPitchOffset - self.sampleNoteHeight)
+ self.pixelsPerPitch = float(Block.Loop.HEIGHT - 2*self.loopPitchOffset - self.sampleNoteHeight)/(Config.MAXIMUM_PITCH - Config.MINIMUM_PITCH)
+ self.pixelsPerTick = Block.Loop.BEAT/float(Config.TICKS_PER_BEAT)
+ self.ticksPerPixel = 1.0/self.pixelsPerTick
#-- Instrument Images ---------------------------------
self.instrumentImage = {}
self.instrumentImageActive = {}
- for inst in self.instrumentDB.getSet( "all" ):
- try:
- pix = gtk.gdk.pixbuf_new_from_file(inst.img)
- x = (Block.Block.WIDTH-pix.get_width())//2
- y = (Block.Block.HEIGHT-pix.get_height())//2
- img = gtk.gdk.Pixmap( win, Block.Block.WIDTH, Block.Block.HEIGHT )
- self.gc.foreground = self.colors["Bg_Inactive"]
- img.draw_rectangle( self.gc, True, 0, 0, Block.Block.WIDTH, Block.Block.HEIGHT )
- img.draw_pixbuf( self.gc, pix, 0, 0, x, y, pix.get_width(), pix.get_height(), gtk.gdk.RGB_DITHER_NONE )
- self.instrumentImage[inst.id] = img
- img = gtk.gdk.Pixmap( win, Block.Block.WIDTH, Block.Block.HEIGHT )
- self.gc.foreground = self.colors["Bg_Active"]
- img.draw_rectangle( self.gc, True, 0, 0, Block.Block.WIDTH, Block.Block.HEIGHT )
- img.draw_pixbuf( self.gc, pix, 0, 0, x, y, pix.get_width(), pix.get_height(), gtk.gdk.RGB_DITHER_NONE )
- self.instrumentImageActive[inst.id] = img
- except:
- if Config.DEBUG >= 5: print "JamMain:: file does not exist: " + inst.img
- img = gtk.gdk.Pixmap( win, Block.Block.WIDTH, Block.Block.HEIGHT )
- self.gc.foreground = self.colors["Bg_Inactive"]
- img.draw_rectangle( self.gc, True, 0, 0, Block.Block.WIDTH, Block.Block.HEIGHT )
- self.instrumentImage[inst.id] = img
- img = gtk.gdk.Pixmap( win, Block.Block.WIDTH, Block.Block.HEIGHT )
- self.gc.foreground = self.colors["Bg_Active"]
- img.draw_rectangle( self.gc, True, 0, 0, Block.Block.WIDTH, Block.Block.HEIGHT )
- self.instrumentImageActive[inst.id] = img
-
+ for inst in self.instrumentDB.getSet( "All" ):
+ self.prepareInstrumentImage( inst.id, inst.img )
+
+ #-- Loop Images ---------------------------------------
+ self.loopImage = {} # get filled in through updateLoopImage
+ self.loopImageActive = {} #
+
#-- Toolbars ------------------------------------------
self.desktopToolbar = DesktopToolbar( self )
self.activity.toolbox.add_toolbar( _("Desktop"), self.desktopToolbar )
@@ -315,6 +350,10 @@ class JamMain(SubActivity):
if active: return self.instrumentImageActive[id]
else: return self.instrumentImage[id]
+ def getLoopImage( self, id, active = False ):
+ if active: return self.loopImageActive[id]
+ else: return self.loopImage[id]
+
def setPicker( self, widget, pagePointer, page_num ):
page = self.GUI["notebook"].get_nth_page( page_num )
if page == self.pickers[Picker.Drum]:
@@ -328,4 +367,86 @@ class JamMain(SubActivity):
if parent != None:
parent.remove( self.pickers[Picker.Instrument] )
page.add( self.pickers[Picker.Instrument] )
+
+ #==========================================================
+ # Pixmaps
+
+ def prepareInstrumentImage( self, id, img_path ):
+ try:
+ win = gtk.gdk.get_default_root_window()
+ pix = gtk.gdk.pixbuf_new_from_file( img_path )
+ x = (Block.Block.WIDTH-pix.get_width())//2
+ y = (Block.Block.HEIGHT-pix.get_height())//2
+ img = gtk.gdk.Pixmap( win, Block.Block.WIDTH, Block.Block.HEIGHT )
+ self.gc.foreground = self.colors["Bg_Inactive"]
+ img.draw_rectangle( self.gc, True, 0, 0, Block.Block.WIDTH, Block.Block.HEIGHT )
+ img.draw_pixbuf( self.gc, pix, 0, 0, x, y, pix.get_width(), pix.get_height(), gtk.gdk.RGB_DITHER_NONE )
+ self.instrumentImage[id] = img
+ img = gtk.gdk.Pixmap( win, Block.Block.WIDTH, Block.Block.HEIGHT )
+ self.gc.foreground = self.colors["Bg_Active"]
+ img.draw_rectangle( self.gc, True, 0, 0, Block.Block.WIDTH, Block.Block.HEIGHT )
+ img.draw_pixbuf( self.gc, pix, 0, 0, x, y, pix.get_width(), pix.get_height(), gtk.gdk.RGB_DITHER_NONE )
+ self.instrumentImageActive[id] = img
+ except:
+ if Config.DEBUG >= 5: print "JamMain:: file does not exist: " + img_path
+ img = gtk.gdk.Pixmap( win, Block.Block.WIDTH, Block.Block.HEIGHT )
+ self.gc.foreground = self.colors["Bg_Inactive"]
+ img.draw_rectangle( self.gc, True, 0, 0, Block.Block.WIDTH, Block.Block.HEIGHT )
+ self.instrumentImage[id] = img
+ img = gtk.gdk.Pixmap( win, Block.Block.WIDTH, Block.Block.HEIGHT )
+ self.gc.foreground = self.colors["Bg_Active"]
+ img.draw_rectangle( self.gc, True, 0, 0, Block.Block.WIDTH, Block.Block.HEIGHT )
+ self.instrumentImageActive[id] = img
+
+ def _drawNotes( self, pixmap, beats, notes, active ):
+ self.gc.set_clip_mask( self.sampleNoteMask )
+ for note in notes: # draw N notes
+ x = self.ticksToPixels( note.cs.onset )
+ endX = self.ticksToPixels( note.cs.onset + note.cs.duration ) - 3 # include end cap offset
+ width = endX - x
+ if width < 5:
+ width = 5
+ endX = x + width
+ y = self.pitchToPixels( note.cs.pitch )
+ # draw fill
+ if active: self.gc.foreground = self.colors["Note_Fill_Active"]
+ else: self.gc.foreground = self.colors["Note_Fill_Inactive"]
+ self.gc.set_clip_origin( x, y-self.sampleNoteHeight )
+ pixmap.draw_rectangle( self.gc, True, x+1, y+1, width+1, self.sampleNoteHeight-2 )
+ # draw border
+ if active: self.gc.foreground = self.colors["Note_Border_Active"]
+ else: self.gc.foreground = self.colors["Note_Border_Inactive"]
+ self.gc.set_clip_origin( x, y )
+ pixmap.draw_rectangle( self.gc, True, x, y, width, self.sampleNoteHeight )
+ self.gc.set_clip_origin( endX-self.sampleNoteMask.endOffset, y )
+ pixmap.draw_rectangle( self.gc, True, endX, y, 3, self.sampleNoteHeight )
+ def updateLoopImage( self, id ):
+ page = self.noteDB.getPage( id )
+
+ win = gtk.gdk.get_default_root_window()
+ width = Block.Loop.WIDTH[page.beats]
+ height = Block.Loop.HEIGHT
+
+ self.gc.set_clip_rectangle( gtk.gdk.Rectangle( 0, 0, width, height ) )
+
+ pixmap = gtk.gdk.Pixmap( win, width, height )
+ self.gc.foreground = self.colors["Bg_Inactive"]
+ pixmap.draw_rectangle( self.gc, True, 0, 0, width, height )
+ self._drawNotes( pixmap, page.beats, self.noteDB.getNotesByTrack( id, 0 ), False )
+ self.loopImage[id] = pixmap
+
+ self.gc.set_clip_rectangle( gtk.gdk.Rectangle( 0, 0, width, height ) )
+
+ pixmap = gtk.gdk.Pixmap( win, width, height )
+ self.gc.foreground = self.colors["Bg_Active"]
+ pixmap.draw_rectangle( self.gc, True, 0, 0, width, height )
+ self._drawNotes( pixmap, page.beats, self.noteDB.getNotesByTrack( id, 0 ), True )
+ self.loopImageActive[id] = pixmap
+
+ def ticksToPixels( self, ticks ):
+ return self.loopTickOffset + int(round( ticks * self.pixelsPerTick ))
+ def pitchToPixels( self, pitch ):
+ return self.loopPitchOffset + int(round( ( Config.MAXIMUM_PITCH - pitch ) * self.pixelsPerPitch ))
+
+
diff --git a/Jam/Picker.py b/Jam/Picker.py
index 2364d94..52c948f 100644
--- a/Jam/Picker.py
+++ b/Jam/Picker.py
@@ -3,6 +3,8 @@ import pygtk
pygtk.require( '2.0' )
import gtk
+import os
+
import random #TEMP
import sets
@@ -11,10 +13,10 @@ from gettext import gettext as _
from sugar.graphics.palette import Palette, WidgetInvoker
-import Util.ControlStream
-import Util.InstrumentDB as InstrumentDB
+from Util import ControlStream
+from Util import InstrumentDB
-import Jam.Block as Block
+from Jam import Block
class Picker( gtk.HBox ):
@@ -26,7 +28,7 @@ class Picker( gtk.HBox ):
# take drawing setup from owner
self.gc = owner.gc
self.colors = owner.colors
- self.clipMask = owner.clipMask
+ self.blockMask = owner.blockMask
self.filter = filter
@@ -151,14 +153,14 @@ class Picker( gtk.HBox ):
class Instrument( Picker ):
- def __init__( self, owner, filter = ( "all" ) ):
+ def __init__( self, owner, filter = ( "All" ) ):
Picker.__init__( self, owner, filter )
self.type = Instrument
self.instrumentDB = InstrumentDB.getRef()
- for inst in self.instrumentDB.getSet( "all" ):
+ for inst in self.instrumentDB.getSet( "All" ):
self.addBlock( inst.id )
def addBlock( self, id ):
@@ -177,7 +179,7 @@ class Instrument( Picker ):
self.gc.foreground = self.colors["Picker_Bg"]
pixmap.draw_rectangle( self.gc, True, 0, 0, width, height )
- self.gc.set_clip_mask( self.clipMask )
+ self.gc.set_clip_mask( self.blockMask )
# draw border
self.gc.foreground = self.colors["Border_Inactive"]
@@ -199,7 +201,7 @@ class Instrument( Picker ):
Picker.addBlock( self, data, data["name"], block )
def _testAgainstFilter( self, block ):
- if "all" in self.filter:
+ if "All" in self.filter:
return True
for label in self.instrumentDB.getInstrument( block.data["id"] ).labels:
@@ -243,7 +245,7 @@ class Drum( Picker ):
self.gc.foreground = self.colors["Picker_Bg"]
pixmap.draw_rectangle( self.gc, True, 0, 0, width, height )
- self.gc.set_clip_mask( self.clipMask )
+ self.gc.set_clip_mask( self.blockMask )
# draw border
self.gc.foreground = self.colors["Border_Inactive"]
@@ -278,13 +280,16 @@ class Loop( Picker ):
self.type = Loop
- self.addBlock( {}, "Loop" )
+ self.presetLoops = self._scanDirectory( Config.FILES_DIR+"/Loops" )
- def _loadFile( self, path ):
+ def _loadFile( self, fullpath, filename ):
+ if filename[-4:] != ".ttl":
+ if Config.DEBUG >= 3: print "WARNING: incorrect extension on loop file: " + filename
+ return -1
try:
oldPages = sets.Set( self.owner.noteDB.getTune() )
- ifile = open( path, 'r' )
+ ifile = open( fullpath, 'r' )
ttt = ControlStream.TamTamTable ( self.owner.noteDB )
ttt.parseFile( ifile )
ifile.close()
@@ -295,19 +300,112 @@ class Loop( Picker ):
if len(newPages) != 1:
print "ERROR: bad loop file, contains more than one page (or none)"
return -1
+
+ id = newPages.pop() # new pageId
+
+ self.addBlock( id, filename[:-4] )
- return newPages.pop() # new pageId
+ return id
except OSError,e:
print 'ERROR: failed to open file %s for reading\n' % ofilename
+ return -1
def _scanDirectory( self, path ):
- pass
+ dirlist = os.listdir( path )
+ ids = []
+ for fpath in dirlist:
+ id = self._loadFile( path+"/"+fpath, fpath )
+ if id != -1: ids.append(id)
+ return ids
+
+ def addBlock( self, id, name ):
+ # match data structure of Block.Loop
+ data = { "name": _(name),
+ "id": id }
+
+ self.owner.updateLoopImage( data["id"] )
+ loop = self.owner.getLoopImage( data["id"] )
+
+ page = self.owner.noteDB.getPage( id )
+
+ win = gtk.gdk.get_default_root_window()
+ width = Block.Loop.WIDTH[page.beats]
+ height = Block.Loop.HEIGHT
+ pixmap = gtk.gdk.Pixmap( win, width, height )
+
+ self.gc.set_clip_rectangle( gtk.gdk.Rectangle( 0, 0, width, height ) )
+
+ # draw bg
+ self.gc.foreground = self.colors["Picker_Bg"]
+ pixmap.draw_rectangle( self.gc, True, 0, 0, width, height )
+
+ self.gc.set_clip_mask( self.blockMask )
+ self.gc.foreground = self.owner.colors["Border_Inactive"]
+
+ #-- draw head -----------------------------------------
+
+ # draw border
+ self.gc.set_clip_origin( -Block.Loop.MASK_START, 0 )
+ pixmap.draw_rectangle( self.gc, True, 0, 0, Block.Loop.HEAD, height )
+
+ # draw block
+ self.gc.set_clip_origin( -Block.Loop.MASK_START, -height )
+ pixmap.draw_drawable( self.gc, loop, 0, 0, 0, 0, Block.Loop.HEAD, height )
+
+ #-- draw beats ----------------------------------------
+
+ beats = page.beats - 1 # last beat is drawn with the tail
+ curx = Block.Loop.HEAD
+ while beats > 3:
+ # draw border
+ self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, 0 )
+ pixmap.draw_rectangle( self.gc, True, curx, 0, Block.Loop.BEAT_MUL3, height )
+
+ # draw block
+ self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, -height )
+ pixmap.draw_drawable( self.gc, loop, curx, 0, curx, 0, Block.Loop.BEAT_MUL3, height )
+
+ curx += Block.Loop.BEAT_MUL3
+ beats -= 3
+
+ if beats:
+ w = Block.Loop.BEAT*beats
+
+ # draw border
+ self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, 0 )
+ pixmap.draw_rectangle( self.gc, True, curx, 0, w, height )
+
+ # draw block
+ self.gc.set_clip_origin( curx-Block.Loop.MASK_BEAT, -height )
+ pixmap.draw_drawable( self.gc, loop, curx, 0, curx, 0, w, height )
+
+ curx += w
+
+ #-- draw tail -----------------------------------------
+
+ # draw border
+ self.gc.set_clip_origin( curx-Block.Loop.MASK_TAIL, 0 )
+ pixmap.draw_rectangle( self.gc, True, curx, 0, Block.Loop.TAIL, height )
+
+ # draw block
+ self.gc.set_clip_origin( curx-Block.Loop.MASK_TAIL, -height )
+ pixmap.draw_drawable( self.gc, loop, curx, 0, curx, 0, Block.Loop.TAIL, height )
+
+ image = gtk.Image()
+ image.set_from_pixmap( pixmap, None )
+
+ block = gtk.EventBox()
+ block.modify_bg( gtk.STATE_NORMAL, self.colors["Picker_Bg"] )
+ block.add( image )
+
+ Picker.addBlock( self, data, data["name"], block )
+
def button_press( self, widget, event ):
walloc = widget.get_allocation()
salloc = self.scrolledWindow.get_allocation()
loc = ( walloc.x + salloc.x + event.x - self.hadjustment.get_value(), -1 )
- self.desktop.addBlock( Block.Loop, { "beats": random.randint(1,8) }, loc, True )
+ self.desktop.addBlock( Block.Loop, widget.data, loc, True )