From 7eb4faf55a3935217f24bff9fd1f1ff2618c93ec Mon Sep 17 00:00:00 2001 From: amartin Date: Mon, 27 Aug 2007 07:41:25 +0000 Subject: Jam Loops --- (limited to 'Jam') 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 ) -- cgit v0.9.1