From 6d7e6f83bec91d4c3e49fe64d7793f12d1d3509b Mon Sep 17 00:00:00 2001 From: Nat Date: Thu, 13 Sep 2007 16:01:09 +0000 Subject: split --- (limited to 'Jam') diff --git a/Jam/Block.py b/Jam/Block.py deleted file mode 100644 index f0789fd..0000000 --- a/Jam/Block.py +++ /dev/null @@ -1,895 +0,0 @@ - -import pygtk -pygtk.require( '2.0' ) -import gtk - -import random - -import Config - -from Util.NoteDB import PARAMETER - -#::: NOTE: -# All the graphics resources are loaded in Desktop and referenced here as necessary -#::: - -class Block(): - - WIDTH = 100 - HEIGHT = 100 - - SNAP = 15 - - PAD = 4 - - KEYSIZE = 26 - KEYMASK_START = 309 - - def __init__( self, owner, data ): - self.owner = owner - self.gc = owner.gc - - self.data = {} - for key in data.keys(): - self.data[key] = data[key] - - self.type = Block - - self.width = Block.WIDTH - self.height = Block.HEIGHT - - self.parent = None - self.canChild = False - self.child = None - self.canParent = False - - self.canSubstitute = False - - self.parentOffest = 0 - - self.dragging = False # is currently dragging - self.placed = False # has been placed on the desktop at least once - - self.firstLoc = True - self.x = -1 - self.y = -1 - - self.active = False - - def dumpToStream( self, ostream, child = False ): - ostream.block_add( ClassToStr[ self.type ], self.active, self.x + self.width//2, self.y + self.height//2, child, self.data ) - if self.child: - self.child.dumpToStream( ostream, True ) - - def destroy( self ): - if self.child: - self.child.destroy() - self.child = None - self.invalidate_rect( not self.dragging ) - - def isPlaced( self ): - return self.placed - - def setPlaced( self, placed ): - self.placed = placed - - def getLoc( self ): - return ( self.x, self.y ) - - def setLoc( self, x, y ): - if x == self.x and y == self.y: return - - if self.firstLoc: - self.firstLoc = False - else: - self.invalidate_rect( not self.dragging ) - - self.x = int(x) - self.y = int(y) - self.endX = self.x + self.width - self.endY = self.y + self.height - - self.invalidate_rect( not self.dragging ) - - if self.child: - self.child.snapToParentLoc( self.getChildAnchor() ) - - def resetLoc( self ): - if self.oldParent != None: - self.oldParent.addChild( self ) - return False - else: - self.setLoc( self.oldLoc[0], self.oldLoc[1] ) - return True - - def getParentAnchor( self ): - return ( self.x + self.parentOffset, self.y ) - - def getChildAnchor( self ): - return ( self.endX, self.y ) - - def snapToParentLoc( self, loc ): - self.setLoc( loc[0] - self.parentOffset, loc[1] ) - - def substitute( self, block ): - pass # override in subclasses - - def testSubstitute( self, block ): - if self.child: - return self.child.testSubstitute( block ) - - def testChild( self, loc ): - - if not self.canParent: - return False - - if self.child: - return self.child.testChild( loc ) - elif abs( self.endX - loc[0] ) < Block.SNAP and abs( self.y - loc[1] ) < Block.SNAP: - return self - - return False - - def addChild( self, child ): - c = self.child - if self.child: - self.removeChild() - - self.child = child - child._addParent( self ) - child.snapToParentLoc( self.getChildAnchor() ) - - if c: - child.addChild( c ) - - def removeChild( self ): - self.child._removeParent() - self.child = None - - def _addParent( self, parent ): - self.parent = parent - - def _removeParent( self ): - self.parent = None - - def getRoot( self ): - if self.parent: return self.parent.getRoot() - return self - - def isActive( self ): - return self.active - - def setActive( self, state ): - self.active = state - self.invalidate_rect( not self.dragging ) - - def getData( self, key ): - return self.data[ key ] - - def setData( self, key, value ): - self.data[ key ] = value - - def testMouseOver( self, event ): - if self.child: - ret = self.child.testMouseOver( event ) - if ret: return ret - - x = event.x - self.x - y = event.y - self.y - - if 0 <= x <= self.width and 0 <= y <= self.height: - return -1 - - return False - - def button_press( self, event ): - - if event.y < self.y or event.y > self.endY: - return False - - return self._button_pressB( event ) - - def _button_pressB( self, event ): - - if event.x < self.x: - return False - - if event.x > self.endX: - if self.child: - return self.child._button_pressB( event ) - else: - return False - - self.oldParent = self.parent - self.oldLoc = ( self.x, self.y ) - self.dragOffset = ( event.x - self.x, event.y - self.y ) - - self._doButtonPress( event ) - - return self - - def _doButtonPress( self, event ): - pass # override in subclasses - - def button_release( self, event ): - if self.dragging: - self.dragging = False - self.placed = True - self.invalidateBranch() - - def motion_notify( self, event ): - - removeFromBlocks = not self.dragging and not self.parent - - if not self.dragging: - self.dragging = True - self.invalidate_rect() - - if self.parent: - self.parent.removeChild() - - self.setLoc( event.x - self.dragOffset[0], event.y - self.dragOffset[1] ) - - return removeFromBlocks - - def _beginDrag( self ): - self.dragging = True - self.dragOffset = ( self.width//2, self.height//2 ) - - def invalidateBranch( self, base = True ): - self.invalidate_rect( base ) - if self.child: - self.child.invalidateBranch( base ) - - def invalidate_rect( self, base = True ): - self.owner.invalidate_rect( self.x, self.y, self.width, self.height, base ) - - def draw( self, startX, startY, stopX, stopY, pixmap ): - if stopY <= self.y or startY >= self.endY: - return False - - self._drawB( startX, startY, stopX, stopY, pixmap ) - - def _drawB( self, startX, startY, stopX, stopY, pixmap ): - - if stopX <= self.x: - return False - - if self.child: - self.child._drawB( startX, startY, stopX, stopY, pixmap ) - - if startX >= self.endX: - return False - - self._doDraw( startX, startY, stopX, stopY, pixmap ) - - return True - - def _doDraw( self, startX, startY, stopX, stopY, pixmap ): - pass # override in subclasses - - def drawHighlight( self, startX, startY, stopX, stopY, pixmap ): - pass # override in subclasses - -class Instrument(Block): - - MASK_START = 0 - - #::: data format: - # { "name": name, "id": instrumentId [, "volume": 0-1, "pan": 0-1, "reverb": 0-1 ] } - #::: - def __init__( self, owner, data ): - Block.__init__( self, owner, data ) - - self.type = Instrument - - self.canParent = True - self.canSubstitute = True - - if not "volume" in self.data.keys(): - self.data["volume"] = 0.5 - if not "pan" in self.data.keys(): - self.data["pan"] = 0.5 - if not "reverb" in self.data.keys(): - self.data["reverb"] = 0 - - self.img = [ self.owner.getInstrumentImage( self.data["id"], False ), - self.owner.getInstrumentImage( self.data["id"], True ) ] - - def setData( self, key, value ): - self.data[ key ] = value - if self.active: - self.owner.updateInstrument( self ) - if self.child and self.child.active: - self.owner.updateLoop( self.child ) - - def substitute( self, block ): - self.data["id"] = block.data["id"] - self.img = [ self.owner.getInstrumentImage( self.data["id"], False ), - self.owner.getInstrumentImage( self.data["id"], True ) ] - self.invalidate_rect( True ) - - if self.child and self.child.active: - self.owner.updateLoop( self.child ) - - def testSubstitute( self, block ): - ret = Block.testSubstitute( self, block ) - if ret: - return ret - - if block.type == Loop: - return False - - if abs( self.x - block.x ) < Block.SNAP and abs( self.y - block.y ) < Block.SNAP: - return self - - return False - - def _doButtonPress( self, event ): # we were hit with a button press - pass - - def button_release( self, event ): - if not self.dragging: - self.owner.activateInstrument( self ) - Block.button_release( self, event ) - - def _doDraw( self, startX, startY, stopX, stopY, pixmap ): - x = max( startX, self.x ) - y = max( startY, self.y ) - endX = min( stopX, self.endX ) - endY = min( stopY, self.endY ) - width = endX - x - height = endY - y - - # 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-Instrument.MASK_START, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) - - # draw block - self.gc.set_clip_origin( self.x-Instrument.MASK_START, self.y-self.height ) - pixmap.draw_drawable( self.gc, self.img[self.active], x-self.x, y-self.y, x, y, width, height ) - - def drawHighlight( self, startX, startY, stopX, stopY, pixmap ): - self.gc.foreground = self.owner.colors["Border_Highlight"] - self.gc.set_clip_origin( self.x-Instrument.MASK_START, self.y ) - pixmap.draw_rectangle( self.gc, True, self.x, self.y, self.width, self.height ) - -class Drum(Block): - - MASK_START = 100 - - KEYRECT = [ Block.PAD - 1, Block.HEIGHT + 1 - Block.PAD - Block.KEYSIZE, Block.KEYSIZE, Block.KEYSIZE ] - KEYRECT += [ KEYRECT[0]+KEYRECT[2], KEYRECT[1]+KEYRECT[3] ] - - #::: data format: - # { "name": name, "id": instrumentId [ , "page": pageId, "volume": 0-1, "reverb": 0-1, "beats": 2-12, "regularity": 0-1, "key": shortcut ] } - #::: - def __init__( self, owner, data ): - Block.__init__( self, owner, data ) - - self.type = Drum - - self.canSubstitute = True - - if not "page" in self.data.keys(): - self.data["page"] = -1 - if not "volume" in self.data.keys(): - self.data["volume"] = 0.5 - if not "reverb" in self.data.keys(): - self.data["reverb"] = 0.0 - if not "beats" in self.data.keys(): - self.data["beats"] = random.randint(2, 12) - if not "regularity" in self.data.keys(): - self.data["regularity"] = random.random() - if "key" not in self.data.keys(): - self.data["key"] = None - - self.owner.mapKey( self.data["key"], self ) - self.keyImage = [ self.owner.getKeyImage( self.data["key"], False ), - self.owner.getKeyImage( self.data["key"], True ) ] - - - self.img = [ self.owner.getInstrumentImage( self.data["id"], False ), - self.owner.getInstrumentImage( self.data["id"], True ) ] - - if self.data["page"] == -1: - self.regenerate() - - def destroy( self ): - self.owner.mapKey( None, self, self.data["key"] ) - self.owner.noteDB.deletePages( [ self.data["page"] ] ) - Block.destroy( self ) - - def setData( self, key, value ): - if key == "beats": - self.data["beats"] = value - self.owner.noteDB.updatePage( self.data["page"], PARAMETER.PAGE_BEATS, value ) - - elif key == "key": - oldKey = self.data["key"] - self.data["key"] = value - self.keyImage = [ self.owner.getKeyImage( value, False ), - self.owner.getKeyImage( value, True ) ] - self.invalidate_rect() - self.owner.mapKey( value, self, oldKey ) - - else: - self.data[key] = value - - if self.active: - self.owner.updateDrum( self ) - - def substitute( self, block ): - self.data["name"] = block.data["name"] - self.data["id"] = block.data["id"] - - self.img = [ self.owner.getInstrumentImage( self.data["id"], False ), - self.owner.getInstrumentImage( self.data["id"], True ) ] - - self.invalidate_rect( True ) - - if self.active: - self.owner.updateDrum() - - def testSubstitute( self, block ): - ret = Block.testSubstitute( self, block ) - if ret: - return ret - - if block.type == Loop: - return False - - if Config.INSTRUMENTSID[block.data["id"]].kit == None: - return False - - if abs( self.x - block.x ) < Block.SNAP and abs( self.y - block.y ) < Block.SNAP: - return self - - return False - - def testMouseOver( self, event ): - ret = self.testWithinKey( event ) - if ret: return ret - - x = event.x - self.x - y = event.y - self.y - - if 0 <= x <= self.width and 0 <= y <= self.height: - return -1 - - return False - - def testWithinKey( self, event ): - x = event.x - self.x - y = event.y - self.y - - if Drum.KEYRECT[0] <= x <= Drum.KEYRECT[4] and Drum.KEYRECT[1] <= y <= Drum.KEYRECT[5]: - return self - - return False - - def _doButtonPress( self, event ): # we were hit with a button press - pass - - def button_release( self, event ): - if not self.dragging: - if self.active: - self.owner.deactivateDrum( self ) - else: - self.owner.activateDrum( self ) - Block.button_release( self, event ) - - def _doDraw( self, startX, startY, stopX, stopY, pixmap ): - x = max( startX, self.x ) - y = max( startY, self.y ) - endX = min( stopX, self.endX ) - endY = min( stopY, self.endY ) - width = endX - x - height = endY - y - - # 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-Drum.MASK_START, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) - - # draw block - self.gc.set_clip_origin( self.x-Drum.MASK_START, self.y-self.height ) - pixmap.draw_drawable( self.gc, self.img[self.active], x-self.x, y-self.y, x, y, width, height ) - - # draw key - self.gc.set_clip_origin( self.x+Drum.KEYRECT[0]-Block.KEYMASK_START, self.y+Drum.KEYRECT[1] ) - pixmap.draw_drawable( self.gc, self.keyImage[ self.active ], 0, 0, self.x+Drum.KEYRECT[0], self.y+Drum.KEYRECT[1], Block.KEYSIZE, Block.KEYSIZE ) - - - def drawHighlight( self, startX, startY, stopX, stopY, pixmap ): - self.gc.foreground = self.owner.colors["Border_Highlight"] - self.gc.set_clip_origin( self.x-Drum.MASK_START, self.y ) - pixmap.draw_rectangle( self.gc, True, self.x, self.y, self.width, self.height ) - - def drawKeyHighlight( self, pixmap ): - self.gc.foreground = self.owner.colors["Border_Highlight"] - self.gc.set_clip_origin( self.x+Drum.KEYRECT[0]-Block.KEYMASK_START, self.y+Drum.KEYRECT[1]-Block.KEYSIZE ) - pixmap.draw_rectangle( self.gc, True, self.x+Drum.KEYRECT[0], self.y+Drum.KEYRECT[1], Block.KEYSIZE, Block.KEYSIZE ) - - def regenerate( self ): - self.data["page"] = self.owner.owner._generateDrumLoop( self.data["id"], self.data["beats"], self.data["regularity"], self.data["reverb"], self.data["page"] ) - if self.active: - self.owner.updateDrum( self ) - - def clear( self ): - self.owner.noteDB.deleteNotesByTrack( [ self.data["page"] ], [ 0 ] ) - -class Loop(Block): - - HEAD = 13 - BEAT = 23 - TAIL = BEAT + Block.PAD - - WIDTH = [ HEAD + BEAT*(n-1) + TAIL for n in range(Config.MAXIMUM_BEATS+1) ] - - BEAT_MUL3 = BEAT*3 - - MASK_START = 200 - MASK_BEAT = MASK_START + HEAD - MASK_TAIL = MASK_START + HEAD + BEAT*3 - - KEYRECT = [ HEAD + Block.PAD, Block.HEIGHT - 2*Block.PAD - Block.KEYSIZE, Block.KEYSIZE, Block.KEYSIZE ] - KEYRECT += [ KEYRECT[0]+KEYRECT[2], KEYRECT[1]+KEYRECT[3] ] - - #::: data format: - # { "name": name, "id": pageId [, "beats": 2-12, "regularity": 0-1, "key": shortcut ] } - #::: - def __init__( self, owner, data ): - Block.__init__( self, owner, data ) - - self.type = Loop - - self.canParent = True - self.canChild = True - self.canSubstitute = True - - self.parentOffset = Loop.HEAD - 4 - - self.data["beats"] = self.owner.noteDB.getPage(self.data["id"]).beats - self.width = Loop.WIDTH[ self.data["beats"] ] - - if "regularity" not in self.data.keys(): - self.data["regularity"] = random.random() - if "key" not in self.data.keys(): - self.data["key"] = None - - self.keyActive = False - self.keyImage = [ self.owner.getKeyImage( self.data["key"], False ), - self.owner.getKeyImage( self.data["key"], True ) ] - - self.img = [ self.owner.getLoopImage( self.data["id"], False ), - self.owner.getLoopImage( self.data["id"], True ) ] - - def destroy( self ): - if self.keyActive: - self.owner.mapKey( None, self, self.data["key"] ) - self.owner.noteDB.deletePages( [ self.data["id"] ] ) - Block.destroy( self ) - - def _updateWidth( self ): - self.invalidateBranch( True ) - - oldWidth = self.width - - self.width = Loop.WIDTH[self.data["beats"]] - self.endX = self.x + self.width - - if self.child: - self.child.snapToParentLoc( self.getChildAnchor() ) - - if oldWidth < self.width: # or block.child: - self.invalidateBranch( True ) - - def updateLoop( self ): - self.updateImage() - self.invalidate_rect() - - if self.active: - self.owner.updateLoop( self.getRoot().child ) - - def updateImage( self ): - self.owner.updateLoopImage( self.data["id"] ) - self.img = [ self.owner.getLoopImage( self.data["id"], False ), - self.owner.getLoopImage( self.data["id"], True ) ] - - def setData( self, key, value ): - - if key == "beats": - self.owner.noteDB.updatePage( self.data["id"], PARAMETER.PAGE_BEATS, value ) - self._updateWidth() - self.updateLoop() - self.data["beats"] = value - - elif key == "key": - oldKey = self.data["key"] - self.data["key"] = value - self.keyImage = [ self.owner.getKeyImage( value, False ), - self.owner.getKeyImage( value, True ) ] - self.invalidate_rect() - if self.keyActive: - self.owner.mapKey( value, self, oldKey ) - - else: - self.data[key] = value - - def substitute( self, block ): - self.invalidateBranch( True ) - - oldWidth = self.width - - newid = self.owner.noteDB.duplicatePages( [ block.data["id"] ] )[block.data["id"]] - self.data["id"] = newid - self.data["beats"] = self.owner.noteDB.getPage(self.data["id"]).beats - - self.updateImage() - self._updateWidth() - - if False: # don't substitute children - if block.child: - c = block.child - after = self - while c: - data = {} - for key in c.data.keys(): - data[key] = c.data[key] - - newid = self.owner.noteDB.duplicatePages( [ data["id"] ] )[data["id"]] - self.owner.updateLoopImage( newid ) - data["id"] = newid - - copy = Loop( self.owner, self.gc, data ) - after.addChild( copy ) - after = copy - c = c.child - elif self.child: - self.child.snapToParentLoc( self.getChildAnchor() ) - - if self.active: - self.owner.updateLoop( self.getRoot().child ) - - def testSubstitute( self, block ): - ret = Block.testSubstitute( self, block ) - if ret: - return ret - - if block.type != Loop: - return False - - if abs( self.x - block.x ) < Block.SNAP and abs( self.y - block.y ) < Block.SNAP: - return self - - return False - - def setActive( self, state ): - Block.setActive( self, state ) - - if self.child: - self.child.setActive( state ) - - def addChild( self, child ): - Block.addChild( self, child ) - if self.active: - child.setActive( True ) - self.owner.updateLoop( self.getRoot().child ) - - def _addParent( self, parent ): - Block._addParent( self, parent ) - - if self.parent.type == Instrument: - self.keyActive = True - self.owner.mapKey( self.data["key"], self ) - else: - root = self.getRoot() - if root.type == Instrument: - root = root.child - if root.getData("key") == None: - root.setData( "key", self.data["key"] ) - self.setData( "key", None ) - - def _removeParent( self ): - if self.active: - loopRoot = self.getRoot().child - parent = self.parent - else: - loopRoot = None - - self.keyActive = False - self.owner.mapKey( None, self, self.data["key"] ) - - Block._removeParent( self ) - - if loopRoot == self: - self.owner.deactivateLoop( loopRoot ) - elif loopRoot != None: - self.setActive( False ) - parent.child = None # disconnect us before updating - self.owner.updateLoop( loopRoot ) - - def testMouseOver( self, event ): - ret = self.testWithinKey( event ) - if ret: return ret - - x = event.x - self.x - y = event.y - self.y - - if 0 <= x <= self.width and 0 <= y <= self.height: - return -1 - - return False - - def testWithinKey( self, event ): - if not self.keyActive: - return False - - x = event.x - self.x - y = event.y - self.y - - if Loop.KEYRECT[0] <= x <= Loop.KEYRECT[4] and Loop.KEYRECT[1] <= y <= Loop.KEYRECT[5]: - return self - - return False - - def _doButtonPress( self, event ): # we were hit with a button press - pass - - def button_release( self, event ): - if not self.dragging: - if self.active: - root = self.getRoot() - self.owner.deactivateLoop( root.child ) - else: - root = self.getRoot() - if root.type == Instrument: # must be attached to an instrument - self.owner.activateLoop( root.child ) - Block.button_release( self, event ) - - def _doDraw( self, startX, startY, stopX, stopY, pixmap ): - y = max( startY, self.y ) - endY = min( stopY, self.endY ) - height = endY - y - - loop = self.img[ 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: - x = max( startX, self.x ) - endX = min( stopX, self.x + Loop.HEAD ) - width = endX - x - - # draw border - self.gc.set_clip_origin( self.x-Loop.MASK_START, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) - - # draw block - self.gc.set_clip_origin( self.x-Loop.MASK_START, self.y-self.height ) - pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height ) - - #-- draw beats ---------------------------------------- - - 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: - break - elif curx + Loop.BEAT_MUL3 > startX: - x = max( startX, curx ) - endX = min( stopX, curx + Loop.BEAT_MUL3 ) - width = endX - x - - # draw border - self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) - - # draw block - self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y-self.height ) - pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height ) - - curx += Loop.BEAT_MUL3 - beats -= 3 - if beats and curx < stopX: - endX = curx + Loop.BEAT*beats - if endX > startX: - x = max( startX, curx ) - endX = min( stopX, endX ) - width = endX - x - - # draw border - self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) - - # draw block - self.gc.set_clip_origin( curx-Loop.MASK_BEAT, self.y-self.height ) - pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height ) - - curx += Loop.BEAT*beats - - - #-- draw tail ----------------------------------------- - - if curx < stopX: - x = max( startX, curx ) - endX = min( stopX, self.endX ) - width = endX - x - - # draw border - self.gc.set_clip_origin( curx-Loop.MASK_TAIL, self.y ) - pixmap.draw_rectangle( self.gc, True, x, y, width, height ) - - # draw block - self.gc.set_clip_origin( curx-Loop.MASK_TAIL, self.y-self.height ) - pixmap.draw_drawable( self.gc, loop, x-self.x, y-self.y, x, y, width, height ) - - #-- draw key ------------------------------------------ - if self.keyActive: - self.gc.set_clip_origin( self.x+Loop.KEYRECT[0]-Block.KEYMASK_START, self.y+Loop.KEYRECT[1] ) - pixmap.draw_drawable( self.gc, self.keyImage[ self.active ], 0, 0, self.x+Loop.KEYRECT[0], self.y+Loop.KEYRECT[1], Block.KEYSIZE, Block.KEYSIZE ) - - def drawHighlight( self, startX, startY, stopX, stopY, pixmap ): - self.gc.foreground = self.owner.colors["Border_Highlight"] - - #-- draw head ----------------------------------------- - - self.gc.set_clip_origin( self.x-Loop.MASK_START, self.y ) - pixmap.draw_rectangle( self.gc, True, self.x, self.y, Loop.HEAD, self.height ) - - #-- draw beats ---------------------------------------- - - 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 ) - pixmap.draw_rectangle( self.gc, True, x, self.y, Loop.BEAT_MUL3, self.height ) - - x += Loop.BEAT_MUL3 - beats -= 3 - if beats: - width = Loop.BEAT*beats - - self.gc.set_clip_origin( x-Loop.MASK_BEAT, self.y ) - pixmap.draw_rectangle( self.gc, True, x, self.y, width, self.height ) - - x += width - - #-- draw tail ----------------------------------------- - - self.gc.set_clip_origin( x-Loop.MASK_TAIL, self.y ) - pixmap.draw_rectangle( self.gc, True, x, self.y, Loop.TAIL, self.height ) - - def drawKeyHighlight( self, pixmap ): - self.gc.foreground = self.owner.colors["Border_Highlight"] - self.gc.set_clip_origin( self.x+Loop.KEYRECT[0]-Block.KEYMASK_START, self.y+Loop.KEYRECT[1]-Block.KEYSIZE ) - pixmap.draw_rectangle( self.gc, True, self.x+Loop.KEYRECT[0], self.y+Loop.KEYRECT[1], Block.KEYSIZE, Block.KEYSIZE ) - - def clear( self ): - self.owner.noteDB.deleteNotesByTrack( [ self.data["id"] ], [ 0 ] ) - - self.updateImage() - - self.invalidate_rect() - - if self.active: - self.owner.updateLoop( self.getRoot().child ) - - -StrToClass = { - "Instrument": Instrument, - "Drum": Drum, - "Loop": Loop - } - -ClassToStr = { - Instrument: "Instrument", - Drum: "Drum", - Loop: "Loop" - } diff --git a/Jam/Desktop.py b/Jam/Desktop.py deleted file mode 100644 index 7b1acba..0000000 --- a/Jam/Desktop.py +++ /dev/null @@ -1,466 +0,0 @@ - -import pygtk -pygtk.require( '2.0' ) -import gtk - -import Config - -from gettext import gettext as _ - -from Jam import Block -from Jam import Popup - -class Desktop( gtk.EventBox ): - - def __init__( self, owner ): - gtk.EventBox.__init__( self ) - - self.owner = owner - - self.drawingArea = gtk.DrawingArea() - self.add( self.drawingArea ) - - # take drawing setup from owner - self.gc = owner.gc - self.colors = owner.colors - self.blockMask = owner.blockMask - - self.noteDB = owner.noteDB - - self.dirtyRectToAdd = gtk.gdk.Rectangle() # used by the invalidate_rect function - self.screenBuf = None - self.screenBufDirty = False - self.screenBufDirtyRect = gtk.gdk.Rectangle() - - self.blocks = [] # items on the desktop - self.activeInstrument = None - self.activeDrum = None - - self.loops = {} # dict of playing loops by loop root - self.drums = [] # list of active drums - - self.add_events(gtk.gdk.POINTER_MOTION_MASK|gtk.gdk.POINTER_MOTION_HINT_MASK) - - self.connect( "size-allocate", self.on_size_allocate ) - self.connect( "button-press-event", self.on_button_press ) - self.connect( "button-release-event", self.on_button_release ) - self.connect( "motion-notify-event", self.on_motion_notify ) - self.drawingArea.connect( "expose-event", self.on_expose ) - - self.clickedBlock = None - self.possibleParent = None - self.possibleSubstitute = None - self.dragging = False - self.possibleDelete = False - self.overKey = False - - #-- Popups -------------------------------------------- - self.rightClicked = False - - self.popup = {} - self.popup[Popup.Instrument] = Popup.Instrument( _("Instrument Properties"), self.owner ) - self.popup[Popup.Drum] = Popup.Drum( _("Drum Kit Properties"), self.owner ) - self.popup[Popup.Loop] = Popup.Loop( _("Loop Properties"), self.owner ) - self.popup[Popup.Shortcut] = Popup.Shortcut( _("Assign Key"), self.owner ) - - def dumpToStream( self, ostream ): - for b in self.blocks: - b.dumpToStream( ostream ) - - def on_size_allocate( self, widget, allocation ): - if self.screenBuf == None or self.alloc.width != allocation.width or self.alloc.height != allocation.height: - win = gtk.gdk.get_default_root_window() - self.screenBuf = gtk.gdk.Pixmap( win, allocation.width, allocation.height ) - self.invalidate_rect( 0, 0, allocation.width, allocation.height ) - self.alloc = allocation - self.absoluteLoc = [0,0] - parent = self.get_parent() - while parent: - alloc = parent.get_allocation() - self.absoluteLoc[0] += alloc.x - self.absoluteLoc[1] += alloc.y - parent = parent.get_parent() - return False - - def getLoopIds( self ): - return [ self.loops[loop] for loop in self.loops ] - - #========================================================== - # Blocks - - def addBlock( self, blockClass, blockData, loc = (-1,-1), drag = False ): - - block = blockClass( self, blockData ) - - if loc[0] != -1: x = loc[0] - else: x = self.alloc.width//2 - if loc[1] != -1: y = loc[1] - elif drag: y = self.alloc.height - block.height//2 - else: y = self.alloc.height//2 - - if drag: - win = gtk.gdk.get_default_root_window() - display = win.get_display() - screen = display.get_default_screen() - 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: - self.blocks.append( block ) - block.setLoc( x - block.width//2, y - block.height//2 ) - - if blockClass == Block.Instrument: - pass - elif blockClass == Block.Drum: - pass - elif blockClass == Block.Loop: - pass - - return block - - def deleteBlock( self, block ): - if block.type == Block.Instrument: - if block == self.activeInstrument: - self.activeInstrument = None - for i in range(len(self.blocks)-1, -1, -1): - if self.blocks[i].type == Block.Instrument: - self.activateInstrument( self.blocks[i] ) - break - - elif block.type == Block.Drum: - if block == self.activeDrum: - self.deactivateDrum() - - elif block.type == Block.Loop: - pass - - if block in self.blocks: - block.invalidate_rect( True ) - self.blocks.remove( block ) - - block.destroy() - - def _clearDesktop( self ): - for i in range( len(self.blocks)-1, -1, -1 ): - self.deleteBlock( self.blocks[i] ) - - def mapKey( self, key, block, oldKey = None ): - self.owner.mapKey( key, block, oldKey ) - - def getInstrumentImage( self, id, active = False ): - return self.owner.getInstrumentImage( id, active ) - - def getKeyImage( self, key, active = False ): - return self.owner.getKeyImage( key, active ) - - def getLoopImage( self, id, active = False ): - return self.owner.getLoopImage( id, active ) - - def updateLoopImage( self, id ): - self.owner.updateLoopImage( id ) - - #========================================================== - # State - - def activateInstrument( self, block ): - if self.activeInstrument: - self.activeInstrument.setActive( False ) - - block.setActive( True ) - self.activeInstrument = block - - self.updateInstrument( block ) - - def updateInstrument( self, block ): - data = block.data - self.owner._updateInstrument( data["id"], data["volume"], data["pan"], data["reverb"] ) - - def activateDrum( self, block ): - for drum in self.drums: - self.deactivateDrum( drum ) - - block.setActive( True ) - self.drums.append( block ) - - self.updateDrum( block, True ) - - def deactivateDrum( self, block ): - self.owner._stopDrum( self.loops[block] ) - del self.loops[block] - - block.setActive( False ) - self.drums.remove( block ) - - def updateDrum( self, block, firstTime = False ): - data = block.data - - if firstTime: - loopId = None - else: - loopId = self.loops[block] - - self.loops[block] = self.owner._playDrum( data["id"], data["page"], data["volume"], data["reverb"], data["beats"], data["regularity"], loopId ) - - def activateLoop( self, block ): - block.setActive( True ) - - self.updateLoop( block, True ) - - def deactivateLoop( self, block ): - block.setActive( False ) - - self.owner._stopLoop( self.loops[block] ) - del self.loops[block] - - def updateLoop( self, block, firstTime = False ): - inst = block.parent.data - - tune = [] - itr = block - while itr != None: - tune.append( itr.data["id"] ) - itr = itr.child - - if firstTime: - loopId = None - else: - loopId = self.loops[block] - - self.loops[block] = self.owner._playLoop( inst["id"], inst["volume"], inst["reverb"], tune, loopId ) - - #========================================================== - # Mouse - - def on_button_press( self, widget, event ): - - if event.button == 3: - self.rightClicked = True - - hit = False - for i in range(len(self.blocks)-1, -1, -1): - hit = self.blocks[i].button_press( event ) - if hit: - self.clickedBlock = hit - break - - def on_button_release( self, widget, event ): - - if event.button == 3: # Right Click - if self.clickedBlock: - if self.clickedBlock.type == Block.Instrument: - self.popup[Popup.Instrument].setBlock( self.clickedBlock ) - elif self.clickedBlock.type == Block.Drum: - self.popup[Popup.Drum].setBlock( self.clickedBlock ) - elif self.clickedBlock.type == Block.Loop: - self.popup[Popup.Loop].setBlock( self.clickedBlock ) - - self.clickedBlock = None - self.rightClicked = False - self.overKey = False # just in case - return - - if self.overKey: - self.popup[Popup.Shortcut].setBlock( self.clickedBlock ) - self.overKey.invalidate_rect( False ) - self.overKey = False - self.clickedBlock = None - return - - if self.possibleDelete: - self.possibleDelete = False - self.deleteBlock( self.clickedBlock ) - self.clickedBlock = None - self.possibleParent = None - self.possibleSubstitute = None - self.dragging = False - - if self.dragging: - self.dragging = False - - if self.possibleParent: - self.possibleParent.addChild( self.clickedBlock ) - root = self.possibleParent.getRoot() - self.blocks.remove(root) - self.blocks.append(root) - root.invalidateBranch( True ) - self.possibleParent = None - elif self.possibleSubstitute: - self.possibleSubstitute.substitute( self.clickedBlock ) - if self.clickedBlock.isPlaced(): - if self.clickedBlock.resetLoc(): - self.blocks.append( self.clickedBlock ) - else: - self.deleteBlock( self.clickedBlock ) - self.clickedBlock = None - if self.possibleSubstitute.type == Block.Instrument: - self.activateInstrument( self.possibleSubstitute ) - self.possibleSubstitute = None - else: - self.blocks.append( self.clickedBlock ) - - if self.clickedBlock: - self.clickedBlock.button_release( event ) - self.clickedBlock = None - - - def on_motion_notify( self, widget, event ): - - if self.rightClicked: - return - - if self.clickedBlock and self.overKey: - return - - if event.is_hint or widget != self: - x, y, state = self.window.get_pointer() - event.x = float(x) - event.y = float(y) - event.state = state - - blockCount = len(self.blocks) - - if not self.clickedBlock: - if self.popup[Popup.Shortcut].is_up(): - return - for i in range(blockCount-1, -1, -1): - over = self.blocks[i].testMouseOver( event ) - if over == -1: - break # over block but no hotspot - if over: - if self.overKey != self.blocks[i]: - if self.overKey: - self.overKey.invalidate_rect( False ) - self.overKey = over - self.overKey.invalidate_rect( False ) - return - if self.overKey: - self.overKey.invalidate_rect( False ) - self.overKey = False - return - - self.dragging = True - - if self.clickedBlock.motion_notify( event ): # first drag of root block, remove from self.blocks - self.blocks.remove( self.clickedBlock ) - blockCount = len(self.blocks) - - if event.y < 0 or event.y > self.alloc.height: - self.possibleDelete = True - return - else: - self.possibleDelete = False - - if self.clickedBlock.canChild and blockCount: - for i in range(blockCount-1, -1, -1): - handled = self.blocks[i].testChild( self.clickedBlock.getParentAnchor() ) - if handled: - if self.possibleParent != handled: - if self.possibleParent: - self.possibleParent.invalidate_rect( False ) - self.possibleParent = handled - self.possibleParent.invalidate_rect( False ) - break - if not handled and self.possibleParent: - self.possibleParent.invalidate_rect( False ) - self.possibleParent = None - - if self.clickedBlock.canSubstitute and blockCount: - for i in range(blockCount-1, -1, -1): - handled = self.blocks[i].testSubstitute( self.clickedBlock ) - if handled: - if self.possibleSubstitute != handled: - if self.possibleSubstitute: - self.possibleSubstitute.invalidate_rect( False ) - self.possibleSubstitute = handled - self.possibleSubstitute.invalidate_rect( False ) - break - if not handled and self.possibleSubstitute: - self.possibleSubstitute.invalidate_rect( False ) - self.possibleSubstitute = None - - def _beginDrag( self, block ): - block._beginDrag() - self.clickedBlock = block - self.dragging = True - - #========================================================== - # Drawing - - def draw( self ): - - startX = self.screenBufDirtyRect.x - startY = self.screenBufDirtyRect.y - stopX = startX + self.screenBufDirtyRect.width - stopY = startY + self.screenBufDirtyRect.height - - self.gc.set_clip_rectangle( self.screenBufDirtyRect ) - - # draw background - self.gc.foreground = self.colors["bg"] - self.screenBuf.draw_rectangle( self.gc, True, startX, startY, self.screenBufDirtyRect.width, self.screenBufDirtyRect.height ) - - # draw blocks - self.gc.set_clip_mask( self.blockMask ) - for block in self.blocks: - block.draw( startX, startY, stopX, stopY, self.screenBuf ) - - self.screenBufDirty = False - - def on_expose( self, DA, event ): - - if self.screenBufDirty: - self.draw() - - self.drawingAreaDirty = False - - startX = event.area.x - startY = event.area.y - stopX = event.area.x + event.area.width - stopY = event.area.y + event.area.height - - self.gc.set_clip_rectangle( event.area ) - - # draw base - DA.window.draw_drawable( self.gc, self.screenBuf, startX, startY, startX, startY, event.area.width, event.area.height ) - - if self.possibleDelete: - return - - self.gc.set_clip_mask( self.blockMask ) - - # draw possible parent - if self.possibleParent: - self.possibleParent.drawHighlight( startX, startY, stopX, stopY, DA.window ) - - # draw dragged objects - if self.dragging: - self.clickedBlock.draw( startX, startY, stopX, stopY, DA.window ) - - # draw possible substitute - if self.possibleSubstitute: - self.possibleSubstitute.drawHighlight( startX, startY, stopX, stopY, DA.window ) - - # draw key highlight - if self.overKey: - self.overKey.drawKeyHighlight( DA.window ) - - def invalidate_rect( self, x, y, width, height, base = True ): - self.dirtyRectToAdd.x = x - self.dirtyRectToAdd.y = y - self.dirtyRectToAdd.width = width - self.dirtyRectToAdd.height = height - - #print "dirty %d %d %d %d %d %d" % (x, y, width, height, x+width, y+height) - if base: # the base image has been dirtied - if not self.screenBufDirty: - self.screenBufDirtyRect.x = x - self.screenBufDirtyRect.y = y - self.screenBufDirtyRect.width = width - self.screenBufDirtyRect.height = height - else: - self.screenBufDirtyRect = self.screenBufDirtyRect.union( self.dirtyRectToAdd ) - self.screenBufDirty = True - if self.drawingArea.window != None: - self.drawingArea.window.invalidate_rect( self.dirtyRectToAdd, True ) - self.drawingAreaDirty = True - diff --git a/Jam/Fillin.py b/Jam/Fillin.py deleted file mode 100644 index 72e2ae3..0000000 --- a/Jam/Fillin.py +++ /dev/null @@ -1,116 +0,0 @@ -import pygtk -pygtk.require( '2.0' ) -import gtk -import gobject - -from RythmGenerator import * -from Util.CSoundClient import new_csound_client -from Util.NoteDB import Note -import Config - -class Fillin: - def __init__( self, nbeats, tempo, instrument, reverb, volume ): - self.notesList = [] - self.barCount = 0 - self.gate = 0 - self.nbeats = nbeats - self.tempo = tempo - self.instrument = instrument - self.reverb = reverb - self.volume = volume - self.onsets = [] - self.pitchs = [] - self.playBackTimeout = None - self.loopId = 0 - self.csnd = new_csound_client() - - def reset( self ): - self.barCount = 0 - self.gate = 0 - - def setLoopId( self, id ): - self.loopId = id - - def setProperties( self, tempo, instrument, volume, beats, reverb ): - self.setTempo( tempo ) - self.setInstrument( instrument ) - self.setVolume( volume ) - self.setBeats( beats ) - self.setReverb( reverb ) - - def setInstrument( self, instrument ): - self.instrument = instrument - - def setBeats( self, nbeats ): - if self.playBackTimeout != None: - gobject.source_remove( self.playBackTimeout ) - - self.nbeats = nbeats - self.clear() - self.reset() - - def setTempo( self, tempo ): - self.tempo = tempo - if self.playBackTimeout != None: - gobject.source_remove( self.playBackTimeout ) - self.play() - - def setReverb( self, reverb ): - self.reverb = reverb - - def setVolume( self, volume ): - self.volume = volume - - def play( self ): - if self.playBackTimeout == None: - self.playBackTimeout = gobject.timeout_add( int(60000/self.tempo/8), self.handleClock ) - self.handleClock() - - def stop( self ): - if self.playBackTimeout != None: - gobject.source_remove( self.playBackTimeout ) - self.clear() - - def clear( self ): - if self.notesList: - for n in self.notesList: - self.csnd.loopDelete(n, self.loopId) - self.notesList = [] - - def handleClock( self ): - tick = self.csnd.loopGetTick( self.loopId ) - if tick < ( Config.TICKS_PER_BEAT / 2 + 1 ): - if self.gate == 0: - self.gate = 1 - self.barCount += 1 - self.barCount %= 4 - if self.barCount == 1: - self.clear() - - if tick > ( ( Config.TICKS_PER_BEAT * self.nbeats ) - ( Config.TICKS_PER_BEAT / 2 ) - 1 ): - if self.gate == 1: - self.gate = 0 - if self.barCount == 3: - self.regenerate() - return True - - def unavailable( self, onsets, pitchs ): - self.onsets = onsets - self.pitchs = pitchs - - def regenerate(self): - def flatten(ll): - rval = [] - for l in ll: - rval += l - return rval - i = 500 - self.notesList= [] - for x in flatten( generator(self.instrument, self.nbeats, 0.4, 0.1, self.reverb) ): - if x.onset not in self.onsets or x.pitch not in self.pitchs: - x.amplitude = x.amplitude*self.volume - n = Note(0, x.trackId, i, x) - self.notesList.append(n) - i += 1 - self.csnd.loopPlay(n,1, loopId = self.loopId ) #add as active - diff --git a/Jam/GenRythm.py b/Jam/GenRythm.py deleted file mode 100644 index d0e23e3..0000000 --- a/Jam/GenRythm.py +++ /dev/null @@ -1,80 +0,0 @@ -import random -import Config - -from Generation.GenerationConstants import GenerationConstants -from Generation.Utils import * - -class GenRythm: - def drumRythmSequence(self, instrumentName, nbeats, density, regularity ): - rythmSequence = [] - binSelection = [] - downBeats = [] - upBeats = [] - beats = [] - countDown = 0 - onsetTime = None - - if Config.INSTRUMENTS[instrumentName].instrumentRegister == Config.PUNCH: - registerDensity = 0.5 - downBeatRecurence = 4 - downBeats = [x for x in GenerationConstants.DRUM_PUNCH_ACCENTS[ nbeats ]] - for downBeat in downBeats: - upBeats.append( downBeat + Config.TICKS_PER_BEAT / 2 ) - - if Config.INSTRUMENTS[instrumentName].instrumentRegister == Config.LOW: - registerDensity =1 - downBeatRecurence = 4 - downBeats = [x for x in GenerationConstants.DRUM_LOW_ACCENTS[ nbeats ]] - for downBeat in downBeats: - upBeats.append( downBeat + Config.TICKS_PER_BEAT / 2 ) - - if Config.INSTRUMENTS[instrumentName].instrumentRegister == Config.MID: - registerDensity = .75 - downBeatRecurence = 1 - downBeats = [x for x in GenerationConstants.DRUM_MID_ACCENTS[ nbeats ]] - for downBeat in downBeats: - upBeats.append( downBeat + Config.TICKS_PER_BEAT / 4 ) - - if Config.INSTRUMENTS[instrumentName].instrumentRegister == Config.HIGH: - registerDensity = 1.5 - downBeatRecurence = 1 - downBeats = [x for x in GenerationConstants.DRUM_HIGH_ACCENTS[ nbeats ]] - for downBeat in downBeats: - upBeats.append( downBeat + Config.TICKS_PER_BEAT / 4 ) - - realDensity = density * registerDensity - if realDensity > 1.: - realDensity = 1. - - list = range( int( realDensity * len( downBeats ) ) ) - for i in list: - if random.random() < ( regularity * downBeatRecurence ) and binSelection.count( 1 ) < len( downBeats ): - binSelection.append( 1 ) - else: - if binSelection.count( 0 ) < len( downBeats ): - binSelection.append( 0 ) - else: - binSelection.append( 1 ) - - countDown = binSelection.count( 1 ) - - length = len(downBeats) - 1 - for i in range( countDown ): - ran1 = random.randint(0, length) - ran2 = random.randint(0, length) - randMin = min(ran1, ran2) - onsetTime = downBeats.pop(randMin) - rythmSequence.append( onsetTime ) - length -= 1 - - length = len(upBeats) - 1 - for i in range( len( binSelection ) - countDown ): - ran1 = random.randint(0, length) - ran2 = random.randint(0, length) - randMin = min(ran1, ran2) - onsetTime = upBeats.pop(randMin) - rythmSequence.append( onsetTime ) - length -= 1 - - rythmSequence.sort() - return rythmSequence diff --git a/Jam/JamMain.py b/Jam/JamMain.py deleted file mode 100644 index c339ae6..0000000 --- a/Jam/JamMain.py +++ /dev/null @@ -1,1112 +0,0 @@ - -import pygtk -pygtk.require( '2.0' ) -import gtk -import pango - -from SubActivity import SubActivity - -import os, sys, shutil - -import Config -from gettext import gettext as _ -import sugar.graphics.style as style - -from Jam.Desktop import Desktop -import Jam.Picker as Picker -import Jam.Block as Block -from Jam.Toolbars import JamToolbar, 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 -from Util.NoteDB import Note, Page - -from Util import ControlStream - -import xdrlib -import time -import gobject -import Util.Network as Net -from sugar.presence import presenceservice -from sugar.graphics.xocolor import XoColor - -from math import sqrt - -class JamMain(SubActivity): - - def __init__(self, activity, set_mode): - SubActivity.__init__(self, set_mode) - - self.activity = activity - - self.instrumentDB = InstrumentDB.getRef() - self.noteDB = NoteDB.NoteDB() - - #-- initial settings ---------------------------------- - self.tempo = Config.PLAYER_TEMPO - self.beatDuration = 60.0/self.tempo - self.ticksPerSecond = Config.TICKS_PER_BEAT*self.tempo/60.0 - self.volume = 0.5 - - self.csnd = new_csound_client() - for i in range(0,9): - self.csnd.setTrackVolume( 100, i ) - self.csnd.setMasterVolume( self.volume*100 ) # csnd expects a range 0-100 for now - self.csnd.setTempo( self.tempo ) - - self.paused = False - - presenceService = presenceservice.get_instance() - self.xoOwner = presenceService.get_owner() - - #-- 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 ) - - xoColorKey = self.xoOwner.props.color - if not xoColorKey: - xoColorKey = ( "#8D8D8D,#FFDDEA" ) - xoColor = XoColor( xoColorKey ) - - 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 ), - "black": colormap.alloc_color( style.COLOR_BLACK.get_html() ), - #"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( xoColor.get_stroke_color() ), #colormap.alloc_color( "#590000" ), - "Border_Inactive": colormap.alloc_color( "#8D8D8D" ), - "Border_Highlight": colormap.alloc_color( "#FFFFFF" ), - "Bg_Active": colormap.alloc_color( xoColor.get_fill_color() ), #colormap.alloc_color( "#FFDDEA" ), - "Bg_Inactive": colormap.alloc_color( "#DBDBDB" ), - "Preview_Note_Fill": colormap.alloc_color( Config.BG_COLOR ), - "Preview_Note_Border": colormap.alloc_color( Config.FG_COLOR ), - "Preview_Note_Selected": colormap.alloc_color( style.COLOR_WHITE.get_html() ), - "Note_Fill_Active": lighten( colormap, "#590000" ), # base "Border_Active" - "Note_Fill_Inactive": lighten( colormap, "#8D8D8D" ), # base "Border_Inactive" - "Beat_Line": colormap.alloc_color( "#959595" ) } - 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() - 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.blockMask = gtk.gdk.bitmap_create_from_data( None, bitmap, pix.get_width(), pix.get_height() ) - - pix = gtk.gdk.pixbuf_new_from_file( Config.IMAGE_ROOT+"sampleBG.png" ) - self.sampleBg = gtk.gdk.Pixmap( win, pix.get_width(), pix.get_height() ) - self.sampleBg.draw_pixbuf( self.gc, pix, 0, 0, 0, 0, pix.get_width(), pix.get_height(), gtk.gdk.RGB_DITHER_NONE ) - self.sampleBg.endOffset = pix.get_width()-5 - 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" ): - self.prepareInstrumentImage( inst.id, inst.img ) - - #-- Loop Images --------------------------------------- - self.loopImage = {} # get filled in through updateLoopImage - self.loopImageActive = {} # - - #-- Key Images ---------------------------------------- - self.keyImage = {} - self.keyImageActive = {} - # use hardware key codes to work on any keyboard layout (hopefully) - self.valid_shortcuts = { 18:"9", 19:"0", 20:"-", 21:"=", - 32:"O", 33:"P", 34:"[", 35:"]", - 47:";", 48:"'", 51:"\\", - 60:".", 61:"/", - None:" " } - for key in self.valid_shortcuts.keys(): - self.prepareKeyImage( key ) - - #-- Toolbars ------------------------------------------ - self.activity.activity_toolbar.keep.show() - - self.jamToolbar = JamToolbar( self ) - self.activity.toolbox.add_toolbar( _("Jam"), self.jamToolbar ) - - self.desktopToolbar = DesktopToolbar( self ) - self.activity.toolbox.add_toolbar( _("Desktop"), self.desktopToolbar ) - - #-- GUI ----------------------------------------------- - if True: # GUI - self.modify_bg( gtk.STATE_NORMAL, self.colors["bg"] ) # window bg - - self.GUI = {} - self.GUI["mainVBox"] = gtk.VBox() - self.add( self.GUI["mainVBox"] ) - - #-- Desktop ------------------------------------------- - self.desktop = self.GUI["desktop"] = Desktop( self ) - self.GUI["mainVBox"].pack_start( self.GUI["desktop"] ) - - #-- Bank ---------------------------------------------- - separator = gtk.Label( " " ) - separator.set_size_request( -1, style.TOOLBOX_SEPARATOR_HEIGHT ) - self.GUI["mainVBox"].pack_start( separator, False ) - self.GUI["notebook"] = gtk.Notebook() - self.GUI["notebook"].set_scrollable( True ) - self.GUI["notebook"].modify_bg( gtk.STATE_NORMAL, self.colors["Picker_Bg"] ) # active tab - self.GUI["notebook"].modify_bg( gtk.STATE_ACTIVE, self.colors["Picker_Bg_Inactive"] ) # inactive tab - self.GUI["notebook"].props.tab_vborder = style.TOOLBOX_TAB_VBORDER - self.GUI["notebook"].props.tab_hborder = style.TOOLBOX_TAB_HBORDER - self.GUI["notebook"].set_size_request( -1, 160 ) - self.GUI["notebook"].connect( "switch-page", self.setPicker ) - self.GUI["mainVBox"].pack_start( self.GUI["notebook"], False, False ) - self.pickers = {} - self.pickerScroll = {} - for type in [ Picker.Instrument, Picker.Drum, Picker.Loop ]: - self.pickers[type] = type( self ) - - def prepareLabel( name ): - label = gtk.Label( _(name) ) - label.set_alignment( 0.0, 0.5 ) - label.modify_fg( gtk.STATE_NORMAL, self.colors["Picker_Fg"] ) - label.modify_fg( gtk.STATE_ACTIVE, self.colors["Picker_Fg"] ) - return label - - self.GUI["notebook"].append_page( self.pickers[Picker.Drum], prepareLabel("Drum Kits") ) - self.GUI["notebook"].append_page( self.pickers[Picker.Loop], prepareLabel("Loops") ) - - sets = self.instrumentDB.getLabels()[:] - sets.sort() - for set in sets: - page = gtk.HBox() - page.set = set - self.GUI["notebook"].append_page( page, prepareLabel( set ) ) - - self.show_all() - - self.GUI["notebook"].set_current_page( 0 ) - - #-- Keyboard ------------------------------------------ - self.key_dict = {} - self.nextTrack = 1 - self.keyboardListener = None - self.recordingNote = None - - self.keyMap = {} - - # default instrument - self._updateInstrument( Config.INSTRUMENTS["kalimba"].instrumentId, 0.5 ) - self.instrumentStack = [] - - #-- Drums --------------------------------------------- - self.drumLoopId = None - # use dummy values for now - self.drumFillin = Fillin( 2, 100, Config.INSTRUMENTS["drum1kit"].instrumentId, 0, 1 ) - - #-- Desktops ------------------------------------------ - self.curDesktop = None - # copy preset desktops - path = Config.TAM_TAM_ROOT+"/Resources/Desktops/" - filelist = os.listdir( path ) - for file in filelist: - shutil.copyfile( path+file, Config.SCRATCH_DIR+file ) - - #-- Network ------------------------------------------- - self.network = Net.Network() - self.network.addWatcher( self.networkStatusWatcher ) - self.network.connectMessage( Net.HT_SYNC_REPLY, self.processHT_SYNC_REPLY ) - self.network.connectMessage( Net.HT_TEMPO_UPDATE, self.processHT_TEMPO_UPDATE ) - self.network.connectMessage( Net.PR_SYNC_QUERY, self.processPR_SYNC_QUERY ) - self.network.connectMessage( Net.PR_TEMPO_QUERY, self.processPR_TEMPO_QUERY ) - self.network.connectMessage( Net.PR_REQUEST_TEMPO_CHANGE, self.processPR_REQUEST_TEMPO_CHANGE ) - - # sync - self.syncQueryStart = {} - self.syncTimeout = None - self.heartbeatLoop = self.csnd.loopCreate() - self.csnd.loopSetNumTicks( Config.TICKS_PER_BEAT, self.heartbeatLoop ) - self.heartbeatStart = time.time() - self.csnd.loopStart( self.heartbeatLoop ) - - # data packing classes - self.packer = xdrlib.Packer() - self.unpacker = xdrlib.Unpacker("") - - # handle forced networking - if self.network.isHost(): - self.updateSync() - self.syncTimeout = gobject.timeout_add( 1000, self.updateSync ) - elif self.network.isPeer(): - self.sendTempoQuery() - self.syncTimeout = gobject.timeout_add( 1000, self.updateSync ) - - #-- Final Set Up -------------------------------------- - self.setVolume( self.volume ) - self.setTempo( self.tempo ) - self.activity.toolbox.set_current_toolbar(1) # JamToolbar - self.setDesktop( 0, True ) - - - #========================================================== - # SubActivity Handlers - - def onActivate( self, arg ): - SubActivity.onActivate( self, arg ) - - def onDeactivate( self ): - SubActivity.onDeactivate( self ) - - def onDestroy( self ): - SubActivity.onDestroy( self ) - - # clear up scratch folder - path = Config.SCRATCH_DIR - filelist = os.listdir( path ) - for file in filelist: - os.remove( path+file ) - - - #========================================================== - # Playback - - def onKeyPress( self, widget, event ): - key = event.hardware_keycode - - if key in self.keyMap.keys(): - activate = True - for block in self.keyMap[key]: - if block.isActive(): - activate = False - break - if activate: - for block in self.keyMap[key]: - if not block.isActive(): - if block.type == Block.Drum: self.desktop.activateDrum( block ) - elif block.type == Block.Loop: self.desktop.activateLoop( block ) - else: - for block in self.keyMap[key]: - if block.isActive(): - if block.type == Block.Drum: self.desktop.deactivateDrum( block ) - elif block.type == Block.Loop: self.desktop.deactivateLoop( block ) - return - - if self.key_dict.has_key( key ): # repeated press - return - - if Config.KEY_MAP_PIANO.has_key( key ): - pitch = Config.KEY_MAP_PIANO[key] - inst = Config.INSTRUMENTSID[self.instrument["id"]] - - if inst.kit: # drum kit - if pitch in GenerationConstants.DRUMPITCH: - pitch = GenerationConstants.DRUMPITCH[pitch] - csnote = self._playNote( key, - 36, - self.instrument["amplitude"]*0.5, # trackVol*noteVol - self.instrument["pan"], - 100, - inst.kit[pitch].instrumentId, - self.instrument["reverb"] ) - else: - if event.state == gtk.gdk.MOD1_MASK: - pitch += 5 - - if inst.csoundInstrumentId == Config.INST_PERC: #Percussions resonance - duration = 60 - else: - duration = -1 - - csnote = self._playNote( key, - pitch, - self.instrument["amplitude"]*0.5, # trackVol*noteVol - self.instrument["pan"], - duration, - self.instrument["id"], - self.instrument["reverb"] ) - - if self.keyboardListener: - self.keyboardListener.recordNote( csnote.pitch ) - self.recordingNote = True - - def onKeyRelease( self, widget, event ): - key = event.hardware_keycode - - if self.key_dict.has_key( key ): - self._stopNote( key ) - - if self.recordingNote: - if self.keyboardListener: - self.keyboardListener.finishNote() - self.recordingNote = False - - def _playNote( self, key, pitch, amplitude, pan, duration, instrumentId, reverb ): - self.key_dict[key] = CSoundNote( 0, # onset - pitch, - amplitude, - pan, - duration, - self.nextTrack, - instrumentId, - reverbSend = reverb, - tied = True, - mode = 'mini' ) - self.nextTrack += 1 - if self.nextTrack > 8: - self.nextTrack = 1 - self.csnd.play(self.key_dict[key], 0.3) - - return self.key_dict[key] - - def _stopNote( self, key ): - csnote = self.key_dict[key] - if Config.INSTRUMENTSID[ csnote.instrumentId ].csoundInstrumentId == Config.INST_TIED: - csnote.duration = .5 - csnote.decay = 0.7 - csnote.tied = False - self.csnd.play(csnote, 0.3) - del self.key_dict[key] - - def _updateInstrument( self, id, volume, pan = 0, reverb = 0 ): - self.instrument = { "id": id, - "amplitude": volume, - "pan": pan, - "reverb": reverb } - - def pushInstrument( self, instrument ): - self.instrumentStack.append( self.instrument ) - self.instrument = instrument - - def popInstrument( self ): - self.instrument = self.instrumentStack.pop() - - def _playDrum( self, id, pageId, volume, reverb, beats, regularity, loopId = None ): - - if loopId == None: # create new loop - startTick = 0 - firstTime = True - else: # update loop - startTick = self.csnd.loopGetTick( loopId ) - self.csnd.loopDestroy( loopId ) - firstTime = False - - loopId = self.csnd.loopCreate() - - # TODO update track volume - - noteOnsets = [] - notePitchs = [] - for n in self.noteDB.getNotesByTrack( pageId, 0 ): - n.pushState() - noteOnsets.append( n.cs.onset ) - notePitchs.append( n.cs.pitch ) - n.cs.amplitude = volume * n.cs.amplitude # TODO remove me once track volume is working - n.cs.reverbSend = reverb - self.csnd.loopPlay( n, 1, loopId = loopId ) #add as active - n.popState() - - ticks = self.noteDB.getPage( pageId ).ticks - - self.csnd.loopSetNumTicks( ticks, loopId ) - - self.drumFillin.setLoopId( loopId ) - self.drumFillin.setProperties( self.tempo, Config.INSTRUMENTSID[id].name, volume, beats, reverb ) - self.drumFillin.unavailable( noteOnsets, notePitchs ) - - self.drumFillin.play() - - # sync to heartbeat - if False: # firstTime: # always force first note to play rather than snaping to nearest beat.. good idea? - startTick = ticks - Config.TICKS_PER_BEAT + self.csnd.loopGetTick( self.heartbeatLoop ) - else: - while startTick > ticks: # align with last beat - startTick -= Config.TICKS_PER_BEAT - beatTick = int(startTick) % Config.TICKS_PER_BEAT - heartTick = self.csnd.loopGetTick( self.heartbeatLoop ) - if beatTick > heartTick: - if beatTick - heartTick < heartTick + Config.TICKS_PER_BEAT - beatTick: - startTick = (int(startTick)//Config.TICKS_PER_BEAT)*Config.TICKS_PER_BEAT + self.csnd.loopGetTick( self.heartbeatLoop ) - else: - startTick = (1 + int(startTick)//Config.TICKS_PER_BEAT)*Config.TICKS_PER_BEAT + self.csnd.loopGetTick( self.heartbeatLoop ) - else: - if heartTick - beatTick < beatTick + Config.TICKS_PER_BEAT - heartTick: - startTick = (int(startTick)//Config.TICKS_PER_BEAT)*Config.TICKS_PER_BEAT + self.csnd.loopGetTick( self.heartbeatLoop ) - else: - startTick = (-1 + int(startTick)//Config.TICKS_PER_BEAT)*Config.TICKS_PER_BEAT + self.csnd.loopGetTick( self.heartbeatLoop ) - - if startTick >= ticks: - startTick -= ticks - elif startTick < 0: - startTick += ticks - - self.csnd.loopSetTick( startTick, loopId ) - - if not self.paused: - self.csnd.loopStart( loopId ) - - return loopId - - def _stopDrum( self, loopId ): - self.drumFillin.stop() - self.csnd.loopDestroy( loopId ) - - def _playLoop( self, id, volume, reverb, tune, loopId = None, force = False ): - if loopId == None: # create new loop - startTick = 0 - firstTime = True - else: # update loop - startTick = self.csnd.loopGetTick( loopId ) - self.csnd.loopDestroy( loopId ) - firstTime = False - - loopId = self.csnd.loopCreate() - - # TODO update track volume - - inst = Config.INSTRUMENTSID[id] - - offset = 0 - for page in tune: - for n in self.noteDB.getNotesByTrack( page, 0 ): - n.pushState() - n.cs.instrumentId = id - n.cs.amplitude = volume * n.cs.amplitude # TODO remove me once track volume is working - n.cs.reverbSend = reverb - if inst.kit: # drum kit - if n.cs.pitch in GenerationConstants.DRUMPITCH: - n.cs.pitch = GenerationConstants.DRUMPITCH[n.cs.pitch] - n.cs.onset += offset - self.csnd.loopPlay( n, 1, loopId = loopId ) - n.popState() - offset += self.noteDB.getPage(page).ticks - - - self.csnd.loopSetNumTicks( offset, loopId ) - - # sync to heartbeat - if False: # firstTime: # always force first note to play rather than snaping to nearest beat.. good idea? - startTick = offset - Config.TICKS_PER_BEAT + self.csnd.loopGetTick( self.heartbeatLoop ) - else: - while startTick > offset: # align with last beat - startTick -= Config.TICKS_PER_BEAT - beatTick = int(startTick) % Config.TICKS_PER_BEAT - heartTick = self.csnd.loopGetTick( self.heartbeatLoop ) - if beatTick > heartTick: - if beatTick - heartTick < heartTick + Config.TICKS_PER_BEAT - beatTick: - startTick = (int(startTick)//Config.TICKS_PER_BEAT)*Config.TICKS_PER_BEAT + self.csnd.loopGetTick( self.heartbeatLoop ) - else: - startTick = (1 + int(startTick)//Config.TICKS_PER_BEAT)*Config.TICKS_PER_BEAT + self.csnd.loopGetTick( self.heartbeatLoop ) - else: - if heartTick - beatTick < beatTick + Config.TICKS_PER_BEAT - heartTick: - startTick = (int(startTick)//Config.TICKS_PER_BEAT)*Config.TICKS_PER_BEAT + self.csnd.loopGetTick( self.heartbeatLoop ) - else: - startTick = (-1 + int(startTick)//Config.TICKS_PER_BEAT)*Config.TICKS_PER_BEAT + self.csnd.loopGetTick( self.heartbeatLoop ) - - if startTick >= offset: - startTick -= offset - elif startTick < 0: - startTick += offset - - - self.csnd.loopSetTick( startTick, loopId ) - - if not self.paused or force: - self.csnd.loopStart( loopId ) - - return loopId - - def _stopLoop( self, loopId ): - self.csnd.loopDestroy( loopId ) - - def setPaused( self, paused ): - if self.paused == paused: - return - - loops = self.desktop.getLoopIds() - - if self.paused: # unpause - self.paused = False - for loop in loops: - self.csnd.loopStart( loop ) - else: # pause - self.paused = True - for loop in loops: - self.csnd.loopPause( loop ) - - #========================================================== - # Generate - - def _generateDrumLoop( self, instrumentId, beats, regularity, reverb, pageId = -1 ): - def flatten(ll): - rval = [] - for l in ll: - rval += l - return rval - - notes = flatten( generator( Config.INSTRUMENTSID[instrumentId].name, beats, 0.8, regularity, reverb) ) - - if pageId == -1: - page = Page( beats ) - pageId = self.noteDB.addPage( -1, page ) - else: - self.noteDB.deleteNotesByTrack( [ pageId ], [ 0 ] ) - - if len(notes): - self.noteDB.addNotes( [ pageId, 0, len(notes) ] + notes + [-1] ) - - return pageId - - def _generateTrack( self, instrumentId, page, track, parameters, algorithm ): - dict = { track: { page: self.noteDB.getCSNotesByTrack( page, track ) } } - instruments = { page: [ Config.INSTRUMENTSID[instrumentId].name for i in range(Config.NUMBER_OF_TRACKS) ] } - beatsOfPages = { page: self.noteDB.getPage(page).beats } - - algorithm( parameters, - [ 0.5 for i in range(Config.NUMBER_OF_TRACKS) ], - instruments, - self.tempo, - beatsOfPages, - [ track ], - [ page ], - dict, - 4) - - # filter & fix input ...WTF!? - for track in dict: - for page in dict[track]: - for note in dict[track][page]: - intdur = int(note.duration) - note.duration = intdur - note.pageId = page - note.trackId = track - - # prepare the new notes - newnotes = [] - for tid in dict: - for pid in dict[tid]: - newnotes += dict[tid][pid] - - # delete the notes and add the new - self.noteDB.deleteNotesByTrack( [ page ], [ track ] ) - - self.noteDB.addNotes( - [ page, track, len(dict[track][page]) ] - + dict[track][page] - + [ -1 ] ) - - - #========================================================== - # Get/Set - - def getVolume( self ): - return self.volume - - def setVolume( self, volume ): - self.jamToolbar.volumeSlider.set_value( volume ) - - def _setVolume( self, volume ): - self.volume = volume - self.csnd.setMasterVolume( self.volume*100 ) # csnd expects a range 0-100 for now - - def getTempo( self ): - return self.tempo - - def setTempo( self, tempo ): - self.jamToolbar.tempoSlider.set_value( tempo ) - - def _setTempo( self, tempo ): - if self.network.isHost() or self.network.isOffline(): - t = time.time() - percent = self.heartbeatElapsed() / self.beatDuration - - self.tempo = tempo - self.beatDuration = 60.0/self.tempo - self.ticksPerSecond = Config.TICKS_PER_BEAT*self.tempo/60.0 - self.csnd.setTempo( self.tempo ) - - if self.network.isHost() or self.network.isOffline(): - self.heatbeatStart = t - percent*self.beatDuration - self.updateSync() - self.sendTempoUpdate() - - def getInstrument( self ): - return self.instrument - - def getDesktop( self ): - return self.desktop - - def _clearDesktop( self, save = True ): - if self.curDesktop == None: - return - - if save: - self._saveDesktop() - - self.desktop._clearDesktop() - - self.curDesktop = None - - def setDesktop( self, desktop, force = False ): - radiobtn = self.desktopToolbar.getDesktopButton( desktop ) - if force and radiobtn.get_active(): - self._setDesktop( desktop ) - else: - radiobtn.set_active( True ) - - def _setDesktop( self, desktop ): - self._clearDesktop() - - self.curDesktop = desktop - - TTTable = ControlStream.TamTamTable( self.noteDB, jam = self ) - - filename = self.getDesktopScratchFile( self.curDesktop ) - try: - stream = open( filename, "r" ) - TTTable.parseFile( stream ) - stream.close() - except IOError, (errno, strerror): - if Config.DEBUG > 3: print "IOError:: _setDesktop:", errno, strerror - - def getInstrumentImage( self, id, active = False ): - if active: return self.instrumentImageActive[id] - else: return self.instrumentImage[id] - - def getKeyImage( self, key, active = False ): - if active: return self.keyImageActive[key] - else: return self.keyImage[key] - - 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]: - pass - elif page == self.pickers[Picker.Loop]: - pass - else: - self.pickers[Picker.Instrument].setFilter( ( page.set ) ) - parent = self.pickers[Picker.Instrument].get_parent() - if parent != page: - if parent != None: - parent.remove( self.pickers[Picker.Instrument] ) - page.add( self.pickers[Picker.Instrument] ) - - def setKeyboardListener( self, listener ): - self.keyboardListener = listener - - def mapKey( self, key, block, oldKey = None ): - if oldKey != None and block in self.keyMap[oldKey]: - self.keyMap[oldKey].remove( block ) - - if key == None: - return - - if key not in self.keyMap.keys(): - self.keyMap[key] = [] - - if block not in self.keyMap[key]: - self.keyMap[key].append( block ) - - #========================================================== - # 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 prepareKeyImage( self, key ): - win = gtk.gdk.get_default_root_window() - pangolayout = self.create_pango_layout( _(self.valid_shortcuts[key]) ) - fontDesc = pango.FontDescription( "bold" ) - pangolayout.set_font_description( fontDesc ) - extents = pangolayout.get_pixel_extents() - x = ( Block.Block.KEYSIZE - extents[1][2] ) // 2 - y = ( Block.Block.KEYSIZE - extents[1][3] ) // 2 - - pixmap = gtk.gdk.Pixmap( win, Block.Block.KEYSIZE, Block.Block.KEYSIZE ) - self.gc.foreground = self.colors["Border_Inactive"] - pixmap.draw_rectangle( self.gc, True, 0, 0, Block.Block.KEYSIZE, Block.Block.KEYSIZE ) - self.gc.foreground = self.colors["Bg_Inactive"] - pixmap.draw_layout( self.gc, x, y, pangolayout ) - self.keyImage[key] = pixmap - - pixmap = gtk.gdk.Pixmap( win, Block.Block.KEYSIZE, Block.Block.KEYSIZE ) - self.gc.foreground = self.colors["Border_Active"] - pixmap.draw_rectangle( self.gc, True, 0, 0, Block.Block.KEYSIZE, Block.Block.KEYSIZE ) - self.gc.foreground = self.colors["Bg_Active"] - pixmap.draw_layout( self.gc, x, y, pangolayout ) - self.keyImageActive[key] = pixmap - - 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 )) - - #========================================================== - # Load/Save - - def _saveDesktop( self ): - if self.curDesktop == None: - return - - filename = self.getDesktopScratchFile( self.curDesktop ) - if os.path.isfile( filename ): - os.remove( filename ) - - try: - scratch = open( filename, "w" ) - stream = ControlStream.TamTamOStream(scratch) - - self.noteDB.dumpToStream( stream, True ) - self.desktop.dumpToStream( stream ) - - scratch.close() - except IOError, (errno, strerror): - if Config.DEBUG > 3: print "IOError:: _saveDesktop:", errno, strerror - - def getDesktopScratchFile( self, i ): - return Config.SCRATCH_DIR+"desktop%d" % i - - def handleJournalLoad( self, filepath ): - - self._clearDesktop( False ) - - TTTable = ControlStream.TamTamTable( self.noteDB, jam = self ) - - try: - stream = open( filepath, "r" ) - TTTable.parseFile( stream ) - stream.close() - - self.setVolume( TTTable.masterVolume ) - self.setTempo( TTTable.tempo ) - - except IOError, (errno, strerror): - if Config.DEBUG > 3: print "IOError:: handleJournalLoad:", errno, strerror - - def handleJournalSave( self, filepath ): - - self._saveDesktop() - - try: - streamF = open( filepath, "w" ) - stream = ControlStream.TamTamOStream( streamF ) - - for i in range(10): - desktop_file = self.getDesktopScratchFile( i ) - stream.desktop_store( desktop_file, i ) - - stream.desktop_set( self.curDesktop ) - - stream.master_vol( self.volume ) - stream.tempo( self.tempo ) - - streamF.close() - - except IOError, (errno, strerror): - if Config.DEBUG > 3: print "IOError:: handleJournalSave:", errno, strerror - - #========================================================== - # Network - - #-- Activity ---------------------------------------------- - - def shared( self, activity ): - if Config.DEBUG: print "miniTamTam:: successfully shared, start host mode" - self.activity._shared_activity.connect( "buddy-joined", self.buddy_joined ) - self.activity._shared_activity.connect( "buddy-left", self.buddy_left ) - self.network.setMode( Net.MD_HOST ) - self.updateSync() - self.syncTimeout = gobject.timeout_add( 1000, self.updateSync ) - - def joined( self, activity ): - if Config.DEBUG: - print "miniTamTam:: joined activity!!" - for buddy in self.activity._shared_activity.get_joined_buddies(): - print buddy.props.ip4_address - - def buddy_joined( self, activity, buddy ): - if Config.DEBUG: - print "buddy joined " + str(buddy) - try: - print buddy.props.ip4_address - except: - print "bad ip4_address" - if self.network.isHost(): - if buddy == self.xoOwner: - return - if buddy.props.ip4_address: - self.network.introducePeer( buddy.props.ip4_address ) - else: - print "miniTamTam:: new buddy does not have an ip4_address!!" - - def buddy_left( self, activity, buddy): - if Config.DEBUG: print "buddy left" - - #def joined( self, activity ): - # if Config.DEBUG: print "miniTamTam:: successfully joined, wait for host" - # self.net.waitForHost() - - #-- Senders ----------------------------------------------- - - def sendSyncQuery( self ): - self.packer.pack_float(random.random()) - hash = self.packer.get_buffer() - self.packer.reset() - self.syncQueryStart[hash] = time.time() - self.network.send( Net.PR_SYNC_QUERY, hash) - - def sendTempoUpdate( self ): - self.packer.pack_int(self.tempo) - self.network.sendAll( Net.HT_TEMPO_UPDATE, self.packer.get_buffer() ) - self.packer.reset() - - def sendTempoQuery( self ): - self.network.send( Net.PR_TEMPO_QUERY ) - - def requestTempoChange( self, val ): - self.packer.pack_int(val) - self.network.send( Net.PR_REQUEST_TEMPO_CHANGE, self.packer.get_buffer() ) - self.packer.reset() - - #-- Handlers ---------------------------------------------- - - def networkStatusWatcher( self, mode ): - if mode == Net.MD_OFFLINE: - if self.syncTimeout: - gobject.source_remove( self.syncTimeout ) - self.syncTimeout = None - if mode == Net.MD_PEER: - self.updateSync() - if not self.syncTimeout: - self.syncTimeout = gobject.timeout_add( 1000, self.updateSync ) - self.sendTempoQuery() - - def processHT_SYNC_REPLY( self, sock, message, data ): - t = time.time() - hash = data[0:4] - latency = t - self.syncQueryStart[hash] - self.unpacker.reset(data[4:8]) - nextBeat = self.unpacker.unpack_float() - #print "mini:: got sync: next beat in %f, latency %d" % (nextBeat, latency*1000) - self.heartbeatStart = t + nextBeat - self.beatDuration - latency/2 - self.correctSync() - self.syncQueryStart.pop(hash) - - def processHT_TEMPO_UPDATE( self, sock, message, data ): - self.unpacker.reset(data) - val = self.unpacker.unpack_int() - if self.tempoSliderActive: - self.delayedTempo = val - return - self.tempoAdjustment.handler_block( self.tempoAdjustmentHandler ) - self.tempoAdjustment.set_value( val ) - self._updateTempo( val ) - self.tempoAdjustment.handler_unblock( self.tempoAdjustmentHandler ) - self.sendSyncQuery() - - def processPR_SYNC_QUERY( self, sock, message, data ): - self.packer.pack_float(self.nextHeartbeat()) - self.network.send( Net.HT_SYNC_REPLY, data + self.packer.get_buffer(), sock ) - self.packer.reset() - - def processPR_TEMPO_QUERY( self, sock, message, data ): - self.packer.pack_int(self.tempo) - self.network.send( Net.HT_TEMPO_UPDATE, self.packer.get_buffer(), to = sock ) - self.packer.reset() - - def processPR_REQUEST_TEMPO_CHANGE( self, sock, message, data ): - if self.tempoSliderActive: - return - self.unpacker.reset(data) - val = self.unpacker.unpack_int() - self.tempoAdjustment.set_value( val ) - - #========================================================== - # Sync - - def nextHeartbeat( self ): - delta = time.time() - self.heartbeatStart - return self.beatDuration - (delta % self.beatDuration) - - def nextHeartbeatInTicks( self ): - delta = time.time() - self.heartbeatStart - next = self.beatDuration - (delta % self.beatDuration) - return self.ticksPerSecond*next - - def heartbeatElapsed( self ): - delta = time.time() - self.heartbeatStart - return delta % self.beatDuration - - def heartbeatElapsedTicks( self ): - delta = time.time() - self.heartbeatStart - return self.ticksPerSecond*(delta % self.beatDuration) - - def updateSync( self ): - if self.network.isOffline(): - return False - elif self.network.isWaiting(): - return True - elif self.network.isHost(): - self.correctSync() - else: - self.sendSyncQuery() - return True - - def correctSync( self ): - curTick = self.csnd.loopGetTick( self.heartbeatLoop ) - curTicksIn = curTick % Config.TICKS_PER_BEAT - ticksIn = self.heartbeatElapsedTicks() - err = curTicksIn - ticksIn - if err > Config.TICKS_PER_BEAT_DIV2: - err -= Config.TICKS_PER_BEAT - elif err < -Config.TICKS_PER_BEAT_DIV2: - err += Config.TICKS_PER_BEAT - correct = curTick - err - if correct > Config.TICKS_PER_BEAT: - correct -= Config.TICKS_PER_BEAT - elif correct < 0: - correct += Config.TICKS_PER_BEAT - #print "correct:: %f ticks, %f ticks in, %f expected, %f err, correct %f" % (curTick, curTicksIn, ticksIn, err, correct) - if abs(err) > 0.25: - self.csnd.adjustTick(-err) - - diff --git a/Jam/Parasite.py b/Jam/Parasite.py deleted file mode 100644 index 084d092..0000000 --- a/Jam/Parasite.py +++ /dev/null @@ -1,349 +0,0 @@ -import pygtk -pygtk.require( '2.0' ) -import gtk - -import Config - -from Util.NoteDB import PARAMETER -from Util.CSoundClient import new_csound_client - -class LoopParasite: - - def __init__( self, noteDB, owner, note ): - self.noteDB = noteDB - self.owner = owner - self.note = note - - self.firstTransform = True - self.x = 0 - self.y = 0 - self.width = 1 - self.height = Config.NOTE_HEIGHT - - self.selected = False - self.potentialDeselect = False - - self.oldOnset = -1 - self.oldEnd = -1 - self.oldPitch = -1 - self.oldAmplitude = -1 - self.oldBeats = -1 - self.lastDragO = 0 - self.lastDragP = 0 - self.lastDragD = 0 - - self.gc = self.owner.gc - self.colors = self.owner.colors - - self.updateParameter( None, None ) - - def attach( self ): - return self - - def destroy( self ): - if self.selected: - self.owner.deselectNotes( { self.note.track: [self] } ) - else: # if we were deselected above the rect has already been invalidated - self.owner.invalidatePreview( self.x, self.y, self.width, self.height, self.note.page, True ) - - def updateParameter( self, parameter, value ): - self.end = self.note.cs.onset + self.note.cs.duration - - self.updateTransform() - - def getId( self ): - return self.note.id - - def getStartTick( self ): - return self.note.cs.onset - - def getEndTick( self ): - return self.end - - def testOnset( self, start, stop ): - return self.note.cs.onset >= start and self.note.cs.onset < stop - - def getPitch( self ): - return self.note.cs.pitch - - def updateTransform( self, force = False ): - if self.note.page == self.owner.getPage(): - if not self.firstTransform: - oldX = self.x - oldY = self.y - oldEndX = self.x + self.width - dirty = True - else: - dirty = False - - beats = self.noteDB.getPage( self.note.page ).beats - if force or self.note.cs.onset != self.oldOnset or beats != self.oldBeats: - self.x = self.owner.ticksToPixels( beats, self.note.cs.onset ) - self.oldOnset = self.note.cs.onset - if force or self.end != self.oldEnd or self.note.cs.onset != self.oldOnset or beats != self.oldBeats: - self.width = self.owner.ticksToPixels( beats, self.end ) - self.x - self.oldEnd = self.end - if force or self.note.cs.pitch != self.oldPitch: - self.y = self.owner.pitchToPixels( self.note.cs.pitch ) - self.oldPitch = self.note.cs.pitch - self.oldBeats = beats - - if dirty: - if self.firstTransform: - self.owner.invalidatePreview( self.x, self.y, self.width, self.height, self.note.page, True ) - else: - x = min( self.x, oldX ) - y = min( self.y, oldY ) - endx = max( self.x + self.width, oldEndX ) - endy = max( self.y, oldY ) + self.height - self.owner.invalidatePreview( x, y, endx-x, endy-y, self.note.page, True ) - - self.firstTransform = False - - def updateDragLimits( self, dragLimits, leftBound, rightBound, widthBound, maxRightBound ): - left = leftBound - self.note.cs.onset - right = rightBound - self.note.cs.duration - self.note.cs.onset - up = Config.MAXIMUM_PITCH - self.note.cs.pitch - down = Config.MINIMUM_PITCH - self.note.cs.pitch - short = Config.MINIMUM_NOTE_DURATION - self.note.cs.duration - long = widthBound - self.note.cs.duration - self.note.cs.onset - - if dragLimits[0][0] < left: dragLimits[0][0] = left - if dragLimits[0][1] > right: dragLimits[0][1] = right - if dragLimits[1][0] < down: dragLimits[1][0] = down - if dragLimits[1][1] > up: dragLimits[1][1] = up - if dragLimits[2][0] < short: dragLimits[2][0] = short - if dragLimits[2][1] > long: dragLimits[2][1] = long - - # store the current loc as a reference point - self.baseOnset = self.note.cs.onset - self.basePitch = self.note.cs.pitch - self.baseDuration = self.note.cs.duration - - def playSampleNote( self, full=True ): - secs_per_tick = 0.025 - csnd = new_csound_client() - - if full: - onset = self.note.cs.onset - instrumentId = self.note.cs.instrumentId - self.note.cs.onset = 0 - self.note.cs.instrumentId = self.owner.instrument["id"] - csnd.play( self.note.cs, 0.024) - self.note.cs.onset = onset - self.note.cs.instrumentId = instrumentId - else: - onset = self.note.cs.onset - duration = self.note.cs.duration - instrumentId = self.note.cs.instrumentId - self.note.cs.onset = 0 - self.note.cs.duration = 10 - self.note.cs.instrumentId = self.owner.instrument["id"] - csnd.play( self.note.cs, 0.024) - self.note.cs.onset = onset - self.note.cs.duration = duration - self.note.cs.instrumentId = instrumentId - - #======================================================= - # Events - - # handleButtonPress returns: - # -2, not a hit but there was X overlap - # -1, event occurs before us so don't bother checking any later notes - # 0, event didn't hit - # 1, event was handled - def handleButtonPress( self, emitter, event ): - eX = event.x - self.x - if eX < 0: - return -1 # event occurs before us, no point in checking further - if eX > self.width: - return 0 # no X overlap - - eY = event.y - self.y - if eY < 0 or eY > self.height: - return -2 # not a hit, but it was in our X range - - if event.button == 3: - print "Show some note parameters!?!" - #self.noteParameters = NoteParametersWindow( self.note, self.getNoteParameters ) - return 1 # handled - - playSample = False - - if event.type == gtk.gdk._2BUTTON_PRESS: # select bar - self.potentialDeselect = False - start = 0 - check = self.note.cs.onset - Config.TICKS_PER_BEAT - while start <= check: start += Config.TICKS_PER_BEAT - stop = start + Config.TICKS_PER_BEAT - check += self.note.cs.duration - while stop < check: stop += Config.TICKS_PER_BEAT - emitter.selectNotesByBar( self.note.track, start, stop ) - elif event.type == gtk.gdk._3BUTTON_PRESS: # select track - self.potentialDeselect = False - emitter.selectNotesByTrack( self.note.track ) - else: - if self.selected: # we already selected, might want to delected - self.potentialDeselect = True - else: - emitter.selectNotes( { self.note.track: [ self ] } ) - playSample = True - - percent = eX/self.width - if percent < 0.3: emitter.setCurrentAction( "note-drag-onset", self ) - elif percent > 0.7: emitter.setCurrentAction( "note-drag-duration", self ) - else: - emitter.setCurrentAction( "note-drag-pitch", self ) - if playSample: self.playSampleNote() - - return 1 - - def handleButtonRelease( self, emitter, event, buttonPressCount ): - - if self.potentialDeselect: - self.potentialDeselect = False - emitter.deselectNotes( { self.note.track: [ self ] } ) - - emitter.doneCurrentAction() - - return True - - def noteDragOnset( self, do, stream ): - self.potentialDeselect = False - if do != self.lastDragO: - self.lastDragO = do - stream += [ self.note.id, self.baseOnset + do ] - - def noteDragPitch( self, dp, stream ): - self.potentialDeselect = False - if dp != self.lastDragP: - self.lastDragP = dp - stream += [ self.note.id, self.basePitch + dp ] - - def noteDragDuration( self, dd, stream ): - self.potentialDeselect = False - if dd != self.lastDragD: - self.lastDragD = dd - stream += [ self.note.id, self.baseDuration + dd ] - - def doneNoteDrag( self, emitter ): - self.baseOnset = self.note.cs.onset - self.basePitch = self.note.cs.pitch - self.baseDuration = self.note.cs.duration - - self.lastDragO = 0 - self.lastDragP = 0 - self.lastDragD = 0 - - def noteDecOnset( self, step, leftBound, stream ): - if self.selected: - if leftBound < self.note.cs.onset: - onset = max( self.note.cs.onset+step, leftBound ) - stream += [ self.note.id, onset ] - return onset + self.note.cs.duration - return self.end - - def noteIncOnset( self, step, rightBound, stream ): - if self.selected: - if rightBound > self.end: - onset = min( self.end+step, rightBound ) - self.note.cs.duration - stream += [ self.note.id, onset ] - return onset - return self.note.cs.onset - - def noteDecPitch( self, step, stream ): - if self.note.cs.pitch > Config.MINIMUM_PITCH: - stream += [ self.note.id, max( self.note.cs.pitch+step, Config.MINIMUM_PITCH ) ] - - def noteIncPitch( self, step, stream ): - if self.note.cs.pitch < Config.MAXIMUM_PITCH: - stream += [ self.note.id, min( self.note.cs.pitch+step, Config.MAXIMUM_PITCH ) ] - - def noteDecDuration( self, step, stream ): - if self.note.cs.duration > Config.MINIMUM_NOTE_DURATION: - stream += [ self.note.id, max( self.note.cs.duration+step, Config.MINIMUM_NOTE_DURATION ) ] - - def noteIncDuration( self, step, rightBound, stream ): - if self.selected: - if self.end < rightBound: - stream += [ self.note.id, min( self.end+step, rightBound ) - self.note.cs.onset ] - - def noteDecVolume( self, step, stream ): - if self.note.cs.amplitude > 0: - stream += [ self.note.id, max( self.note.cs.amplitude+step, 0 ) ] - - def noteIncVolume( self, step, stream ): - if self.note.cs.amplitude < 1: - stream += [ self.note.id, min( self.note.cs.amplitude+step, 1 ) ] - - def handleMarqueeSelect( self, emitter, start, stop ): - intersectionY = [ max(start[1],self.y), min(stop[1],self.y+self.height) ] - if intersectionY[0] > intersectionY[1]: - return False - - intersectionX = [ max(start[0],self.x), min(stop[0],self.x+self.width) ] - if intersectionX[0] > intersectionX[1]: - return False - - return True - - # updateTooltip returns: - # -2, not a hit but there was X overlap - # -1, event occurs before us so don't bother checking any later notes - # 0, event didn't hit - # 1, event was handled - def updateTooltip( self, emitter, event ): - eX = event.x - self.x - if eX < 0: - return -1 # event occurs before us, no point in checking further - if eX > self.width: - return 0 # no X overlap - - eY = event.y - self.y - if eY < 0 or eY > self.height: - return -2 # not a hit, but it was in our X range - - percent = eX/self.width - if percent < 0.3: emitter.setCursor("drag-onset") - elif percent > 0.7: emitter.setCursor("drag-duration") - else: emitter.setCursor("drag-pitch") - - return 1 # we handled it - - #======================================================= - # Selection - - def setSelected( self, state ): - if self.selected != state: - self.selected = state - self.owner.invalidatePreview( self.x, self.y, self.width, self.height, self.note.page ) - return True # state changed - return False # state is the same - - def getSelected( self ): - return self.selected - - #======================================================= - # Draw - - def draw( self, win, gc, 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 - - # draw fill - self.gc.foreground = self.colors["Preview_Note_Fill"] - self.gc.set_clip_origin( self.x, self.y-self.owner.sampleNoteHeight ) - self.owner.previewBuffer.draw_rectangle( self.gc, True, self.x+1, self.y+1, self.width-2, self.owner.sampleNoteHeight-2 ) - # draw border - if self.selected: - self.gc.foreground = self.colors["Preview_Note_Selected"] - else: - self.gc.foreground = self.colors["Preview_Note_Border"] - self.gc.set_clip_origin( self.x, self.y ) - endX = self.x + self.width - 3 - self.owner.previewBuffer.draw_rectangle( self.gc, True, self.x, self.y, self.width-3, self.owner.sampleNoteHeight ) - self.gc.set_clip_origin( endX-self.owner.sampleNoteMask.endOffset, self.y ) - self.owner.previewBuffer.draw_rectangle( self.gc, True, endX, self.y, 3, self.owner.sampleNoteHeight ) - - return True # we drew something - diff --git a/Jam/Picker.py b/Jam/Picker.py deleted file mode 100644 index b69a73f..0000000 --- a/Jam/Picker.py +++ /dev/null @@ -1,422 +0,0 @@ - -import pygtk -pygtk.require( '2.0' ) -import gtk - -import os - -import random #TEMP -import sets - -import Config -from gettext import gettext as _ - -from sugar.graphics.palette import Palette, WidgetInvoker - -from Util import ControlStream -from Util import InstrumentDB - -from Jam import Block - -class Picker( gtk.HBox ): - - def __init__( self, owner, filter = None ): - gtk.HBox.__init__( self ) - - self.owner = owner - - # take drawing setup from owner - self.gc = owner.gc - self.colors = owner.colors - self.blockMask = owner.blockMask - - self.filter = filter - - self.desktop = owner.getDesktop() - - self.scrollLeft = gtk.Button( "<" ) - self.scrollLeft.connect( "clicked", self.doScroll, "left" ) - self.pack_start( self.scrollLeft, False, False ) - - self.scrolledWindow = gtk.ScrolledWindow() - self.scrolledWindow.set_policy( gtk.POLICY_ALWAYS, gtk.POLICY_NEVER ) - self.pack_start( self.scrolledWindow ) - self.hadjustment = self.scrolledWindow.get_hadjustment() - self.hadjustment.connect( "changed", self.scrollChanged ) - self.hadjustment.connect( "value-changed", self.scrollChanged ) - - self.scrollRight = gtk.Button( ">" ) - self.scrollRight.connect( "clicked", self.doScroll, "right" ) - self.pack_start( self.scrollRight, False, False ) - - self.pickerBox = gtk.HBox() - self.scrolledWindow.add_with_viewport( self.pickerBox ) - self.pickerBox.get_parent().modify_bg( gtk.STATE_NORMAL, self.colors["Picker_Bg"] ) - - # spacers - self.pickerBox.pack_start( gtk.Label(" "), True, True ) - self.pickerBox.pack_end( gtk.Label(" "), True, True ) - - self.show_all() - - self.scroll = {} - self.scroll[filter] = 0 - - self.blocks = [] - - def addBlock( self, data, name, block = None ): - if block == None: - block = gtk.Button( name ) - - # tooltip - block._palette = Palette( name ) - block._palette.props.invoker = WidgetInvoker(block) - block._palette.props.invoker._position_hint = WidgetInvoker.AT_CURSOR - - block.add_events( gtk.gdk.BUTTON_PRESS_MASK - | gtk.gdk.BUTTON_RELEASE_MASK - | gtk.gdk.ENTER_NOTIFY_MASK - | gtk.gdk.LEAVE_NOTIFY_MASK - | gtk.gdk.POINTER_MOTION_MASK - | gtk.gdk.POINTER_MOTION_HINT_MASK ) - block.connect( "button-press-event", self.on_button_press ) - block.connect( "button-release-event", self.on_button_release ) - block.connect( "motion-notify-event", self.on_motion_notify ) - block.data = data - - self.blocks.append( block ) - - if self._testAgainstFilter( block ): - self.pickerBox.pack_start( block, False, False, 3 ) - - block.show_all() - - return block - - def getFilter( self ): - return filter - - def setFilter( self, filter ): - if filter == self.filter: - return - - self.scroll[self.filter] = self.hadjustment.get_value() - - self.filter = filter - - for block in self.pickerBox.get_children()[1:-1]: # outside children are spacers - self.pickerBox.remove( block ) - - for block in self.blocks: - if self._testAgainstFilter( block ): - self.pickerBox.pack_start( block, False, False, 3 ) - - if self.scroll.has_key( filter ): - self.hadjustment.set_value( self.scroll[filter] ) - else: - self.hadjustment.set_value( 0 ) - self.scroll[filter] = 0 - - def _testAgainstFilter( self, block ): - return True - - def doScroll( self, widget, data ): - if data == "left": - val = max( self.hadjustment.get_property("lower"), self.hadjustment.get_value() - self.hadjustment.get_property("page_increment") ) - else: - val = min( self.hadjustment.get_property("upper") - self.hadjustment.get_property("page_size"), self.hadjustment.get_value() + self.hadjustment.get_property("page_increment") ) - - self.hadjustment.set_value( val ) - - def scrollChanged( self, widget ): - val = self.hadjustment.get_value() - if val == 0: - self.scrollLeft.set_sensitive( False ) - else: - self.scrollLeft.set_sensitive( True ) - - if val >= self.hadjustment.get_property( "upper" ) - self.hadjustment.get_property("page_size"): - self.scrollRight.set_sensitive( False ) - else: - self.scrollRight.set_sensitive( True ) - - def on_button_press( self, widget, event ): - pass - - def on_button_release( self, widget, event ): - self.desktop.on_button_release( widget, event ) - - def on_motion_notify( self, widget, event ): - self.desktop.on_motion_notify( widget, event ) - - -class Instrument( Picker ): - - 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" ): - self.addBlock( inst.id ) - - def addBlock( self, id ): - # match data structure of Block.Instrument - data = { "name": _(Config.INSTRUMENTSID[id].name), - "id": id } - - win = gtk.gdk.get_default_root_window() - width = Block.Instrument.WIDTH - height = Block.Instrument.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 ) - - # draw border - self.gc.foreground = self.colors["Border_Inactive"] - self.gc.set_clip_origin( -Block.Instrument.MASK_START, 0 ) - pixmap.draw_rectangle( self.gc, True, 0, 0, width, height ) - - # draw block - inst = self.owner.getInstrumentImage( data["id"] ) - self.gc.set_clip_origin( -Block.Instrument.MASK_START, -height ) - pixmap.draw_drawable( self.gc, inst, 0, 0, 0, 0, width, 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 _testAgainstFilter( self, block ): - if "All" in self.filter: - return True - - for label in self.instrumentDB.getInstrument( block.data["id"] ).labels: - if label in self.filter: - return True - - return False - - def on_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 ) - - block = self.desktop.addBlock( Block.Instrument, widget.data, loc, True ) - self.desktop.activateInstrument( block ) - - -class Drum( Picker ): - - def __init__( self, owner, filter = None ): - Picker.__init__( self, owner, filter ) - - self.type = Drum - - self.instrumentDB = InstrumentDB.getRef() - - for inst in self.instrumentDB.getSet( "kit" ): - self.addBlock( inst.id ) - - def addBlock( self, id ): - # match data structure of Block.Drum - data = { "name": _(Config.INSTRUMENTSID[id].name), - "id": id } - - win = gtk.gdk.get_default_root_window() - width = Block.Drum.WIDTH - height = Block.Drum.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 ) - - # draw border - self.gc.foreground = self.colors["Border_Inactive"] - self.gc.set_clip_origin( -Block.Drum.MASK_START, 0 ) - pixmap.draw_rectangle( self.gc, True, 0, 0, width, height ) - - # draw block - inst = self.owner.getInstrumentImage( data["id"] ) - self.gc.set_clip_origin( -Block.Drum.MASK_START, -height ) - pixmap.draw_drawable( self.gc, inst, 0, 0, 0, 0, width, 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 on_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.Drum, widget.data, loc, True ) - - -class Loop( Picker ): - - def __init__( self, owner, filter = None ): - Picker.__init__( self, owner, filter ) - - self.type = Loop - - self.presetLoops = self._scanDirectory( Config.FILES_DIR+"/Loops" ) - - 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( fullpath, 'r' ) - ttt = ControlStream.TamTamTable ( self.owner.noteDB ) - ttt.parseFile( ifile ) - ifile.close() - - curPages = sets.Set( self.owner.noteDB.getTune() ) - newPages = curPages.difference( oldPages ) - - if len(newPages) != 1: - print "ERROR: bad loop file, contains more than one page (or none)" - return -1 - - id = newPages.pop() # new pageId - - self.owner.noteDB.getPage( id ).setLocal( False ) # flag as a global page - - self.addBlock( id, filename[:-4] ) - - return id - - except OSError,e: - print 'ERROR: failed to open file %s for reading\n' % ofilename - return -1 - - def _scanDirectory( self, path ): - 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 on_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 ) - - data = {} - for key in widget.data.keys(): - data[key] = widget.data[key] - - newid = self.owner.noteDB.duplicatePages( [ data["id"] ] )[data["id"]] - self.owner.updateLoopImage( newid ) - data["id"] = newid - - block = self.desktop.addBlock( Block.Loop, data, loc, True ) - - diff --git a/Jam/Popup.py b/Jam/Popup.py deleted file mode 100644 index 9af550c..0000000 --- a/Jam/Popup.py +++ /dev/null @@ -1,1397 +0,0 @@ - -import pygtk -pygtk.require( '2.0' ) -import gtk - -import Config - -from gettext import gettext as _ -from sugar.graphics import style -from sugar.graphics.palette import Palette, Invoker, _palette_observer -import gobject - -import Jam.Block as Block -from Util.NoteDB import PARAMETER -from Util.CSoundNote import CSoundNote -from Util.CSoundClient import new_csound_client -from Jam.Parasite import LoopParasite - -from Generation.Generator import generator1, GenerationParameters - -class SELECTNOTES: - ALL = -1 - NONE = 0 - ADD = 1 - REMOVE = 2 - FLIP = 3 - EXCLUSIVE = 4 - -class NoneInvoker( Invoker ): - - def __init__( self ): - Invoker.__init__( self ) - self._position_hint = Invoker.AT_CURSOR - - def get_rect( self ): - return gtk.gdk.Rectangle( 0, 0, 0, 0 ) - - def get_toplevel( self ): - return None - -class Popup( Palette ): - - def __init__( self, label, owner ): - Palette.__init__( self, label ) - - self.owner = owner - - self.block = None - - self.props.invoker = NoneInvoker() - self.set_group_id( "TamTamPopup" ) - - self._set_state( Palette.SECONDARY ) # skip to fully exposed - - self.connect( "key-press-event", self.on_key_press ) - self.connect( "key-release-event", self.on_key_release ) - - self.connect( "focus_out_event", self.closePopup ) - - def destroy( self ): - pass - - def _leave_notify_event_cb( self, widget, event ): - return # don't popdown() - - def _show( self ): - Palette._show( self ) - - if self._palette_popup_sid != None: - _palette_observer.disconnect( self._palette_popup_sid ) # don't hide when other palettes pop - self._palette_popup_sid = None - - def popup( self, immediate = False ): - self.owner.activity.handler_block(self.owner.activity.focusOutHandler) - self.owner.activity.handler_block(self.owner.activity.focusInHandler) - - Palette.popup( self, immediate ) - - def popdown( self, immediate = False ): - self.block = None - - Palette.popdown( self, immediate ) - - self.owner.activity.handler_unblock(self.owner.activity.focusOutHandler) - self.owner.activity.handler_unblock(self.owner.activity.focusInHandler) - - def updatePosition( self ): - self.props.invoker._cursor_x = -1 - self.props.invoker._cursor_y = -1 - self._update_position() - - def closePopup( self, widget, event ): - self.popdown( True ) - - def on_key_press( self, widget, event ): - self.owner.onKeyPress( widget, event ) - - def on_key_release( self, widget, event ): - self.owner.onKeyRelease( widget, event ) - - def setBlock( self, block ): - if self.is_up(): - self.updatePosition() - else: - self.popup( True ) - - -class Instrument( Popup ): - - def __init__( self, label, owner ): - Popup.__init__( self, label, owner ) - - self.settingBlock = False - - self.GUI = {} - - self.GUI["mainBox"] = gtk.VBox() - self.set_content( self.GUI["mainBox"] ) - - #-- Volume -------------------------------------------- - self.GUI["volumeBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["volumeBox"], padding = style.DEFAULT_PADDING ) - self.GUI["volumeLabel"] = gtk.Label( _("Volume:") ) - self.GUI["volumeLabel"].set_size_request( 100, -1 ) - self.GUI["volumeLabel"].set_alignment( 0.0, 0.5 ) - self.GUI["volumeBox"].pack_start( self.GUI["volumeLabel"], False, padding = style.DEFAULT_PADDING ) - self.GUI["volumeAdjustment"] = gtk.Adjustment( 0.5, 0.0, 1.0, 0.1, 0.1, 0 ) - self.GUI["volumeAdjustment"].connect( 'value-changed', self.handleVolume ) - self.GUI["volumeSlider"] = gtk.HScale( adjustment = self.GUI["volumeAdjustment"] ) - self.GUI["volumeSlider"].set_size_request( 250, -1 ) - self.GUI["volumeSlider"].set_draw_value( False ) - self.GUI["volumeBox"].pack_start( self.GUI["volumeSlider"], False, padding = style.DEFAULT_PADDING ) - self.GUI["volumeImage"] = gtk.Image() - self.GUI["volumeBox"].pack_start( self.GUI["volumeImage"], False, padding = style.DEFAULT_PADDING ) - - #-- Pan ----------------------------------------------- - self.GUI["panBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["panBox"], padding = style.DEFAULT_PADDING ) - self.GUI["panLabel"] = gtk.Label( _("Pan:") ) - self.GUI["panLabel"].set_size_request( 100, -1 ) - self.GUI["panLabel"].set_alignment( 0.0, 0.5 ) - self.GUI["panBox"].pack_start( self.GUI["panLabel"], False, padding = style.DEFAULT_PADDING ) - self.GUI["panAdjustment"] = gtk.Adjustment( 0.5, 0, 1.0, 0.1, 0.1, 0 ) - self.GUI["panAdjustment"].connect( 'value-changed', self.handlePan ) - self.GUI["panSlider"] = gtk.HScale( adjustment = self.GUI["panAdjustment"] ) - self.GUI["panSlider"].set_size_request( 250, -1 ) - self.GUI["panSlider"].set_draw_value( False ) - self.GUI["panBox"].pack_start( self.GUI["panSlider"], False, padding = style.DEFAULT_PADDING ) - self.GUI["panImage"] = gtk.Image() - self.GUI["panBox"].pack_start( self.GUI["panImage"], False, padding = style.DEFAULT_PADDING ) - - #-- Reverb -------------------------------------------- - self.GUI["reverbBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["reverbBox"], padding = style.DEFAULT_PADDING ) - self.GUI["reverbLabel"] = gtk.Label( _("Reverb:") ) - self.GUI["reverbLabel"].set_size_request( 100, -1 ) - self.GUI["reverbLabel"].set_alignment( 0.0, 0.5 ) - self.GUI["reverbBox"].pack_start( self.GUI["reverbLabel"], False, padding = style.DEFAULT_PADDING ) - self.GUI["reverbAdjustment"] = gtk.Adjustment( 0.5, 0, 1.0, 0.1, 0.1, 0 ) - self.GUI["reverbAdjustment"].connect( 'value-changed', self.handleReverb ) - self.GUI["reverbSlider"] = gtk.HScale( adjustment = self.GUI["reverbAdjustment"] ) - self.GUI["reverbSlider"].set_size_request( 250, -1 ) - self.GUI["reverbSlider"].set_draw_value( False ) - self.GUI["reverbBox"].pack_start( self.GUI["reverbSlider"], False, padding = style.DEFAULT_PADDING ) - self.GUI["reverbImage"] = gtk.Image() - self.GUI["reverbBox"].pack_start( self.GUI["reverbImage"], False, padding = style.DEFAULT_PADDING ) - - if False: # TEMP quote out - self.GUI["separator"] = gtk.HSeparator() - self.GUI["mainBox"].pack_start( self.GUI["separator"], padding = style.DEFAULT_PADDING ) - - #-- Export -------------------------------------------- - self.GUI["exportBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["exportBox"], padding = style.DEFAULT_PADDING ) - self.GUI["exportEntry"] = gtk.Entry() - self.GUI["exportEntry"].modify_fg( gtk.STATE_NORMAL, self.owner.colors["black"] ) - self.GUI["exportEntry"].modify_fg( gtk.STATE_ACTIVE, self.owner.colors["black"] ) - self.GUI["exportBox"].pack_start( self.GUI["exportEntry"], padding = style.DEFAULT_PADDING ) - self.GUI["exportButton"] = gtk.Button( "Export" ) - self.GUI["exportBox"].pack_start( self.GUI["exportButton"], False, padding = style.DEFAULT_PADDING ) - - self.GUI["mainBox"].show_all() - - def setBlock( self, block ): - self.settingBlock = True - - self.block = block - self.GUI["volumeAdjustment"].set_value( block.getData( "volume" ) ) - self.GUI["panAdjustment"].set_value( block.getData( "pan" ) ) - self.GUI["reverbAdjustment"].set_value( block.getData( "reverb" ) ) - #self.GUI["exportEntry"].set_text( block.getData( "name" ) ) - - self.settingBlock = False - - Popup.setBlock( self, block ) - - def handleVolume( self, widget ): - if not self.settingBlock: - self.block.setData( "volume", widget.get_value() ) - - def handlePan( self, widget ): - if not self.settingBlock: - self.block.setData( "pan", widget.get_value() ) - - def handleReverb( self, widget ): - if not self.settingBlock: - self.block.setData( "reverb", widget.get_value() ) - - -class Drum( Popup ): - - def __init__( self, label, owner ): - Popup.__init__( self, label, owner ) - - self.settingBlock = False - - self.GUI = {} - - self.GUI["mainBox"] = gtk.VBox() - self.set_content( self.GUI["mainBox"] ) - - #-- Volume -------------------------------------------- - self.GUI["volumeBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["volumeBox"], padding = style.DEFAULT_PADDING ) - self.GUI["volumeLabel"] = gtk.Label( _("Volume:") ) - self.GUI["volumeLabel"].set_size_request( 130, -1 ) - self.GUI["volumeLabel"].set_alignment( 0.0, 0.5 ) - self.GUI["volumeBox"].pack_start( self.GUI["volumeLabel"], False, padding = style.DEFAULT_PADDING ) - self.GUI["volumeAdjustment"] = gtk.Adjustment( 0.5, 0.0, 1.0, 0.1, 0.1, 0 ) - self.GUI["volumeAdjustment"].connect( 'value-changed', self.handleVolume ) - self.GUI["volumeSlider"] = gtk.HScale( adjustment = self.GUI["volumeAdjustment"] ) - self.GUI["volumeSlider"].set_size_request( 250, -1 ) - self.GUI["volumeSlider"].set_draw_value( False ) - self.GUI["volumeBox"].pack_start( self.GUI["volumeSlider"], False, padding = style.DEFAULT_PADDING ) - self.GUI["volumeImage"] = gtk.Image() - self.GUI["volumeBox"].pack_start( self.GUI["volumeImage"], False, padding = style.DEFAULT_PADDING ) - - #-- Reverb -------------------------------------------- - self.GUI["reverbBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["reverbBox"], padding = style.DEFAULT_PADDING ) - self.GUI["reverbLabel"] = gtk.Label( _("Reverb:") ) - self.GUI["reverbLabel"].set_size_request( 130, -1 ) - self.GUI["reverbLabel"].set_alignment( 0.0, 0.5 ) - self.GUI["reverbBox"].pack_start( self.GUI["reverbLabel"], False, padding = style.DEFAULT_PADDING ) - self.GUI["reverbAdjustment"] = gtk.Adjustment( 0.5, 0, 1.0, 0.1, 0.1, 0 ) - self.GUI["reverbAdjustment"].connect( 'value-changed', self.handleReverb ) - self.GUI["reverbSlider"] = gtk.HScale( adjustment = self.GUI["reverbAdjustment"] ) - self.GUI["reverbSlider"].set_size_request( 250, -1 ) - self.GUI["reverbSlider"].set_draw_value( False ) - self.GUI["reverbBox"].pack_start( self.GUI["reverbSlider"], False, padding = style.DEFAULT_PADDING ) - self.GUI["reverbImage"] = gtk.Image() - self.GUI["reverbBox"].pack_start( self.GUI["reverbImage"], False, padding = style.DEFAULT_PADDING ) - - self.GUI["generationSeparator"] = gtk.HSeparator() - self.GUI["mainBox"].pack_start( self.GUI["generationSeparator"], padding = style.DEFAULT_PADDING ) - - #-- Beats --------------------------------------------- - self.GUI["beatsBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["beatsBox"], padding = style.DEFAULT_PADDING ) - self.GUI["beatsLabel"] = gtk.Label( _("Beats:") ) - self.GUI["beatsLabel"].set_size_request( 130, -1 ) - self.GUI["beatsLabel"].set_alignment( 0.0, 0.5 ) - self.GUI["beatsBox"].pack_start( self.GUI["beatsLabel"], False, padding = style.DEFAULT_PADDING ) - self.GUI["beatsAdjustment"] = gtk.Adjustment( 4, 2, Config.MAXIMUM_BEATS, 1, 1, 0 ) - self.GUI["beatsAdjustment"].connect( 'value-changed', self.handleBeats ) - self.GUI["beatsSlider"] = gtk.HScale( adjustment = self.GUI["beatsAdjustment"] ) - self.GUI["beatsSlider"].set_size_request( 250, -1 ) - self.GUI["beatsSlider"].set_draw_value( False ) - self.GUI["beatsBox"].pack_start( self.GUI["beatsSlider"], False, padding = style.DEFAULT_PADDING ) - self.GUI["beatsImage"] = gtk.Image() - self.GUI["beatsBox"].pack_start( self.GUI["beatsImage"], False, padding = style.DEFAULT_PADDING ) - - #-- Regularity ---------------------------------------- - self.GUI["regularityBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["regularityBox"], padding = style.DEFAULT_PADDING ) - self.GUI["regularityLabel"] = gtk.Label( _("Regularity:") ) - self.GUI["regularityLabel"].set_size_request( 130, -1 ) - self.GUI["regularityLabel"].set_alignment( 0.0, 0.5 ) - self.GUI["regularityBox"].pack_start( self.GUI["regularityLabel"], False, padding = style.DEFAULT_PADDING ) - self.GUI["regularityAdjustment"] = gtk.Adjustment( 0.5, 0.0, 1.0, 0.1, 0.1, 0 ) - self.GUI["regularityAdjustment"].connect( 'value-changed', self.handleRegularity ) - self.GUI["regularitySlider"] = gtk.HScale( adjustment = self.GUI["regularityAdjustment"] ) - self.GUI["regularitySlider"].set_size_request( 250, -1 ) - self.GUI["regularitySlider"].set_draw_value( False ) - self.GUI["regularityBox"].pack_start( self.GUI["regularitySlider"], False, padding = style.DEFAULT_PADDING ) - self.GUI["regularityImage"] = gtk.Image() - self.GUI["regularityBox"].pack_start( self.GUI["regularityImage"], False, padding = style.DEFAULT_PADDING ) - - #-- Generate ------------------------------------------ - self.GUI["generateBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["generateBox"], padding = style.DEFAULT_PADDING ) - self.GUI["regenerateButton"] = gtk.Button( "Regenerate" ) - self.GUI["regenerateButton"].connect( "clicked", self.handleRegenerate ) - self.GUI["generateBox"].pack_start( self.GUI["regenerateButton"], True, False, padding = style.DEFAULT_PADDING ) - self.GUI["clearButton"] = gtk.Button( "Clear" ) - self.GUI["clearButton"].connect( "clicked", self.handleClear ) - self.GUI["generateBox"].pack_start( self.GUI["clearButton"], True, False, padding = style.DEFAULT_PADDING ) - - self.GUI["mainBox"].show_all() - - def setBlock( self, block ): - self.settingBlock = True - - self.block = block - self.GUI["volumeAdjustment"].set_value( block.getData( "volume" ) ) - self.GUI["reverbAdjustment"].set_value( block.getData( "reverb" ) ) - self.GUI["beatsAdjustment"].set_value( block.getData( "beats" ) ) - self.GUI["regularityAdjustment"].set_value( block.getData( "regularity" ) ) - - self.settingBlock = False - - Popup.setBlock( self, block ) - - def handleVolume( self, widget ): - if not self.settingBlock: - self.block.setData( "volume", widget.get_value() ) - - def handleReverb( self, widget ): - if not self.settingBlock: - self.block.setData( "reverb", widget.get_value() ) - - def handleBeats( self, widget ): - # snap to 0 decimal places - val = widget.get_value() - if round( val ) != val: - widget.set_value( round( val ) ) - return - - if not self.settingBlock: - self.block.setData( "beats", int(round( widget.get_value() )) ) - - def handleRegularity( self, widget ): - if not self.settingBlock: - self.block.setData( "regularity", widget.get_value() ) - - def handleRegenerate( self, widget ): - self.block.regenerate() - - def handleClear( self, widget ): - self.block.clear() - -class Loop( Popup ): - - def __init__( self, label, owner ): - Popup.__init__( self, label, owner ) - - self.settingBlock = False - - self.gc = self.owner.gc - self.colors = self.owner.colors - self.sampleNoteMask = self.owner.sampleNoteMask - - self.noteDB = self.owner.noteDB - self.csnd = new_csound_client() - - self.GUI = {} - - self.GUI["mainBox"] = gtk.VBox() - self.set_content( self.GUI["mainBox"] ) - - #-- Beats --------------------------------------------- - self.GUI["beatsBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["beatsBox"], padding = style.DEFAULT_PADDING ) - self.GUI["beatsLabel"] = gtk.Label( _("Beats:") ) - self.GUI["beatsLabel"].set_size_request( 130, -1 ) - self.GUI["beatsLabel"].set_alignment( 0.0, 0.5 ) - self.GUI["beatsBox"].pack_start( self.GUI["beatsLabel"], False, padding = style.DEFAULT_PADDING ) - self.GUI["beatsAdjustment"] = gtk.Adjustment( 4, 2, Config.MAXIMUM_BEATS, 1, 1, 0 ) - self.GUI["beatsAdjustment"].connect( 'value-changed', self.handleBeats ) - self.GUI["beatsSlider"] = gtk.HScale( adjustment = self.GUI["beatsAdjustment"] ) - self.GUI["beatsSlider"].set_size_request( 250, -1 ) - self.GUI["beatsSlider"].set_draw_value( False ) - self.GUI["beatsBox"].pack_start( self.GUI["beatsSlider"], False, padding = style.DEFAULT_PADDING ) - self.GUI["beatsImage"] = gtk.Image() - self.GUI["beatsBox"].pack_start( self.GUI["beatsImage"], False, padding = style.DEFAULT_PADDING ) - - #-- Regularity ---------------------------------------- - self.GUI["regularityBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["regularityBox"], padding = style.DEFAULT_PADDING ) - self.GUI["regularityLabel"] = gtk.Label( _("Regularity:") ) - self.GUI["regularityLabel"].set_size_request( 130, -1 ) - self.GUI["regularityLabel"].set_alignment( 0.0, 0.5 ) - self.GUI["regularityBox"].pack_start( self.GUI["regularityLabel"], False, padding = style.DEFAULT_PADDING ) - self.GUI["regularityAdjustment"] = gtk.Adjustment( 0.5, 0.0, 1.0, 0.1, 0.1, 0 ) - self.GUI["regularityAdjustment"].connect( 'value-changed', self.handleRegularity ) - self.GUI["regularitySlider"] = gtk.HScale( adjustment = self.GUI["regularityAdjustment"] ) - self.GUI["regularitySlider"].set_size_request( 250, -1 ) - self.GUI["regularitySlider"].set_draw_value( False ) - self.GUI["regularityBox"].pack_start( self.GUI["regularitySlider"], False, padding = style.DEFAULT_PADDING ) - self.GUI["regularityImage"] = gtk.Image() - self.GUI["regularityBox"].pack_start( self.GUI["regularityImage"], False, padding = style.DEFAULT_PADDING ) - - #-- Generate ------------------------------------------ - self.GUI["generateBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["generateBox"], padding = style.DEFAULT_PADDING ) - self.GUI["regenerateButton"] = gtk.Button( "Regenerate" ) - self.GUI["regenerateButton"].connect( "clicked", self.handleRegenerate ) - self.GUI["generateBox"].pack_start( self.GUI["regenerateButton"], True, False, padding = style.DEFAULT_PADDING ) - self.GUI["clearButton"] = gtk.Button( "Clear" ) - self.GUI["clearButton"].connect( "clicked", self.handleClear ) - self.GUI["generateBox"].pack_start( self.GUI["clearButton"], True, False, padding = style.DEFAULT_PADDING ) - self.GUI["recordButton"] = gtk.ToggleButton( "Record" ) - self.GUI["recordButton"].connect( "toggled", self.handleRecord ) - self.GUI["generateBox"].pack_start( self.GUI["recordButton"], True, False, padding = style.DEFAULT_PADDING ) - - #-- Preview ------------------------------------------- - self.GUI["previewBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["previewBox"], padding = style.DEFAULT_PADDING ) - self.GUI["previewEventBox"] = gtk.EventBox() - self.GUI["previewEventBox"].add_events(gtk.gdk.POINTER_MOTION_MASK|gtk.gdk.POINTER_MOTION_HINT_MASK) - self.GUI["previewEventBox"].connect( "button-press-event", self.handlePreviewPress ) - self.GUI["previewEventBox"].connect( "button-release-event", self.handlePreviewRelease ) - self.GUI["previewEventBox"].connect( "motion-notify-event", self.handlePreviewMotion ) - self.GUI["previewEventBox"].connect( "leave-notify-event", self.handlePreviewLeave ) - self.GUI["previewBox"].pack_start( self.GUI["previewEventBox"], True, padding = style.DEFAULT_PADDING ) - self.previewDA = self.GUI["previewDA"] = gtk.DrawingArea() - self.GUI["previewDA"].connect( "size-allocate", self.handlePreviewAlloc ) - self.GUI["previewDA"].connect( "expose-event", self.handlePreviewExpose ) - self.GUI["previewEventBox"].add( self.GUI["previewDA"] ) - - self.GUI["mainBox"].show_all() - - self.previewDA.alloced = False - self.previewDirty = False - self.previewDirtyRect = gtk.gdk.Rectangle( 0, 0, 0, 0 ) - self.dirtyRectToAdd = gtk.gdk.Rectangle( 0, 0, 0, 0 ) - - self.sampleBg = self.owner.sampleBg - self.GUI["previewDA"].set_size_request( -1, self.sampleBg.get_size()[1] ) - self.sampleNoteHeight = self.owner.sampleNoteHeight - self.sampleNoteMask = self.owner.sampleNoteMask - - self.pitchPerPixel = float(Config.NUMBER_OF_POSSIBLE_PITCHES-1) / (self.sampleBg.get_size()[1] - self.sampleNoteHeight) - self.pixelsPerPitch = float(self.sampleBg.get_size()[1] - self.sampleNoteHeight)/(Config.MAXIMUM_PITCH - Config.MINIMUM_PITCH) - # Temporary Initialization - self.pixelsPerTick = [0] + [ 1 for i in range(1,Config.MAXIMUM_BEATS+1) ] - self.ticksPerPixel = [0] + [ 1 for i in range(1,Config.MAXIMUM_BEATS+1) ] - - self.cursor = { \ - "default": None, \ - "drag-onset": gtk.gdk.Cursor(gtk.gdk.SB_RIGHT_ARROW), \ - "drag-pitch": gtk.gdk.Cursor(gtk.gdk.BOTTOM_SIDE), \ - "drag-duration": gtk.gdk.Cursor(gtk.gdk.RIGHT_SIDE), \ - "drag-playhead": gtk.gdk.Cursor(gtk.gdk.SB_H_DOUBLE_ARROW), \ - "pencil": gtk.gdk.Cursor(gtk.gdk.PENCIL), \ - "paste": gtk.gdk.Cursor(gtk.gdk.CENTER_PTR), \ - "error": None } - - self.recording = False - self.recordLoop = None - self.recordingNote = None - - self.owner.noteDB.addListener( self, LoopParasite ) - - def destroy( self ): - self.owner.noteDB.deleteListener( self ) - - Popup.destroy() - - def setBlock( self, block ): - self.settingBlock = True - - if self.GUI["recordButton"].get_active(): - self.GUI["recordButton"].set_active( False ) - - self.block = block - self.GUI["beatsAdjustment"].set_value( block.getData( "beats" ) ) - self.GUI["regularityAdjustment"].set_value( block.getData( "regularity" ) ) - - root = block.getRoot() - if root.type == Block.Instrument: - self.instrument = { "id": root.getData( "id" ), - "amplitude": root.getData( "volume" ), - "pan": root.getData( "pan" ), - "reverb": root.getData( "reverb" ) } - else: - self.instrument = self.owner.getInstrument() - - self.curPage = block.getData("id") - self.curBeats = block.getData("beats") - - self.selectedNotes = [ [] for i in range(Config.NUMBER_OF_TRACKS) ] - - self.curAction = False # stores the current mouse action - self.curActionObject = False # stores the object that in handling the action - - self.lastDO = self.lastDP = self.lastDrumDP = self.lastDD = None - - self.clickButton = 0 # used in release and motion events to make sure we where actually the widget originally clicked. (hack for popup windows) - self.buttonPressCount = 1 # used on release events to indicate double/triple releases - self.clickLoc = [0,0] # location of the last click - self.marqueeLoc = False # current drag location of the marquee - self.marqueeRect = [[0,0],[0,0]] - - self.playheadT = 0 - self.playheadX = Config.TRACK_SPACING_DIV2 - - self.settingBlock = False - - if self.previewDA.alloced: - self.invalidatePreview( 0, 0, self.previewDA.width, self.previewDA.height, -1, True ) - - Popup.setBlock( self, block ) - - def popdown( self, immediate = False ): - self.applyNoteSelection( SELECTNOTES.NONE, 0, [], self.curPage ) - - if self.GUI["recordButton"].get_active(): - self.GUI["recordButton"].set_active( False ) - - Popup.popdown( self, immediate ) - - def getPage( self ): - if self.block != None: - return self.block.getData("id") - else: - return -1 - - #======================================================= - # Handelers - - def handleBeats( self, widget ): - # snap to 0 decimal places - val = widget.get_value() - if round( val ) != val: - widget.set_value( round( val ) ) - return - - if not self.settingBlock: - self.curBeats = int(round( widget.get_value() )) - self.block.setData( "beats", self.curBeats ) - for n in self.owner.noteDB.getNotesByTrack( self.getPage(), 0, self ): - n.updateTransform( True ) - self.invalidatePreview( 0, 0, self.previewDA.width, self.previewDA.height ) - - if self.recordLoop: - self.recordLoop = self.owner._playLoop( self.instrument["id"], self.instrument["amplitude"], self.instrument["reverb"], [ self.curPage ], self.recordLoop, force = True ) - - def handleRegularity( self, widget ): - if not self.settingBlock: - self.block.setData( "regularity", widget.get_value() ) - - def handleRegenerate( self, widget ): - parameters = GenerationParameters( - rythmRegularity = self.block.getData( "regularity" ), - pitchRegularity = self.block.getData( "regularity" ) ) - - self.owner._generateTrack( self.instrument["id"], self.curPage, 0, parameters, generator1 ) - - self.block.updateLoop() - - if self.recordLoop: - self.recordLoop = self.owner._playLoop( self.instrument["id"], self.instrument["amplitude"], self.instrument["reverb"], [ self.curPage ], self.recordLoop, force = True ) - - def handleClear( self, widget ): - self.block.clear() - - if self.recordLoop: - self.recordLoop = self.owner._playLoop( self.instrument["id"], self.instrument["amplitude"], self.instrument["reverb"], [ self.curPage ], self.recordLoop, force = True ) - - def handleRecord( self, widget ): - if widget.get_active(): - self.startRecording() - else: - self.stopRecording() - - def handlePreviewPress( self, widget, event ): - if event.button != 1: - return - - self.clickButton = event.button - - if event.type == gtk.gdk._2BUTTON_PRESS: self.buttonPressCount = 2 - elif event.type == gtk.gdk._3BUTTON_PRESS: self.buttonPressCount = 3 - else: self.buttonPressCount = 1 - - self.clickLoc = [ int(event.x), int(event.y) ] - - page = self.block.getData("id") - beats = self.block.getData("beats") - - notes = self.noteDB.getNotesByTrack( page, 0, self ) - last = len(notes)-1 - handled = 0 - for n in range(last+1): - handled = notes[n].handleButtonPress( self, event ) - if handled == 0: - continue - elif handled == 1: - if not self.curAction: self.curAction = True # it was handled but no action was declared, set curAction to True anyway - return - else: # all other options mean we can stop looking - break - - if not handled or handled == -1: # event didn't overlap any notes, so we can draw - pitch = min( self.pixelsToPitchFloor( self.clickLoc[1] - self.previewDA.height + self.sampleNoteHeight//2 ), Config.NUMBER_OF_POSSIBLE_PITCHES-1) + Config.MINIMUM_PITCH - onset = self.pixelsToTicksFloor( beats, self.clickLoc[0] ) - cs = CSoundNote( onset, - pitch, - 0.75, - 0.5, - 1, - 0, - instrumentId = self.instrument["id"] ) - cs.pageId = page - id = self.noteDB.addNote( -1, page, 0, cs ) - n = self.noteDB.getNote( page, 0, id, self ) - self.selectNotes( { 0:[n] }, True ) - n.playSampleNote( False ) - - noteS = self.noteDB.getNotesByTrack( page, 0 ) - for note in noteS: - if note.cs.onset < onset and (note.cs.onset + note.cs.duration) > onset: - self.noteDB.updateNote(self.curPage, 0, note.id, PARAMETER.DURATION, onset - note.cs.onset) - - self.updateDragLimits() - self.clickLoc[0] += self.ticksToPixels( beats, 1 ) - self.setCurrentAction( "note-drag-duration", n ) - self.setCursor("drag-duration") - - def handlePreviewRelease( self, widget, event ): - if not self.clickButton: return # we recieved this event but were never clicked! (probably a popup window was open) - self.clickButton = 0 - - if event.button != 1: - return - - if not self.curAction: - self.applyNoteSelection( SELECTNOTES.NONE, 0, [], self.curPage ) - return - - if not self.curActionObject: # there was no real action to carry out - self.curAction = False - return - - if self.curActionObject != self: - self.curActionObject.handleButtonRelease( self, event, self.buttonPressCount ) - self.updateTooltip( event ) - else: - # we're doing the action ourselves - if self.curAction == "marquee": self.doneMarquee( event ) - self.updateTooltip( event ) - - def handlePreviewMotion( self, widget, event ): - if event.is_hint: - x, y, state = self.previewDA.window.get_pointer() - event.x = float(x) - event.y = float(y) - event.state = state - - if not self.clickButton: # we recieved this event but were never clicked! (probably a popup window was open) - self.updateTooltip( event ) - return - - if event.state & gtk.gdk.BUTTON1_MASK: - if not self.curAction: # no action is in progress yet we're dragging, start a marquee - self.setCurrentAction( "marquee", self ) - - if self.curAction == "note-drag-onset": - self.noteDragOnset( event ) - - elif self.curAction == "note-drag-duration": - self.noteDragDuration( event ) - - elif self.curAction == "note-drag-pitch": - self.noteDragPitch( event ) - - #elif self.curAction == "note-drag-pitch-drum": - # self.noteDragPitch( event, True ) - - elif self.curAction == "marquee": - self.updateMarquee( event ) - else: - self.updateTooltip( event ) - - def handlePreviewLeave( self, widget, event ): - self.setCursor("default") - - def handlePreviewAlloc( self, widget, allocation ): - self.previewDA.alloced = True - win = gtk.gdk.get_default_root_window() - self.previewDA.width = allocation.width - self.previewDA.height = allocation.height - self.previewBuffer = gtk.gdk.Pixmap( win, allocation.width, allocation.height ) - self.clearClipMask = gtk.gdk.Rectangle( 0, 0, allocation.width, allocation.height ) - - self.pixelsPerTick = [0] + [ self.previewDA.width/float(i*Config.TICKS_PER_BEAT) for i in range(1,Config.MAXIMUM_BEATS+1) ] - self.ticksPerPixel = [0] + [ 1.0/self.pixelsPerTick[i] for i in range(1,Config.MAXIMUM_BEATS+1) ] - - self.beatSpacing = [[0]] - for i in range(1,Config.MAXIMUM_BEATS+1): - self.beatSpacing.append( [ self.ticksToPixels( i, Config.TICKS_PER_BEAT*j ) for j in range(i) ] ) - - for n in self.owner.noteDB.getNotes( self ): - n.updateTransform( True ) - - self.invalidatePreview( 0, 0, allocation.width, allocation.height, -1, True ) - - def on_key_press( self, widget, event ): - keyval = event.keyval - - # backspace and del keys - if keyval == gtk.keysyms.Delete or keyval == gtk.keysyms.BackSpace: - if len( self.selectedNotes[0] ): - self.owner.noteDB.deleteNotes( - [ self.curPage, 0, len( self.selectedNotes[0] ) ] - + [ n.note.id for n in self.selectedNotes[0] ] - + [ -1 ] ) - self.block.updateLoop() - else: - self.owner.onKeyPress( widget, event ) - - #======================================================= - # Drawing - - def previewDraw( self ): - startX = self.previewDirtyRect.x - startY = self.previewDirtyRect.y - stopX = self.previewDirtyRect.x + self.previewDirtyRect.width - stopY = self.previewDirtyRect.y + self.previewDirtyRect.height - - page = self.block.getData("id") - beats = self.owner.noteDB.getPage(page).beats - - self.gc.set_clip_rectangle( self.previewDirtyRect ) - - # draw background - self.previewBuffer.draw_drawable( self.gc, self.sampleBg, 0, 0, 0, 0, self.previewDA.width-5, self.previewDA.height ) - self.previewBuffer.draw_drawable( self.gc, self.sampleBg, self.sampleBg.endOffset, 0, self.previewDA.width-5, 0, 5, self.previewDA.height ) - - # draw beat lines - self.gc.set_line_attributes( Config.BEAT_LINE_SIZE, gtk.gdk.LINE_ON_OFF_DASH, gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER ) - self.gc.foreground = self.colors["Beat_Line"] - for i in range(1,beats): - x = self.beatSpacing[beats][i] - self.previewBuffer.draw_line( self.gc, x, 1, x, self.previewDA.height-1 ) - - # draw notes - self.gc.set_clip_mask( self.sampleNoteMask ) - notes = self.owner.noteDB.getNotesByTrack( page, 0, self ) - for n in notes: - if not n.draw( self.previewBuffer, self.gc, startX, stopX ): break - - self.previewDirty = False - - def handlePreviewExpose( self, widget, event ): - if self.previewDirty: - self.previewDraw() - - self.gc.set_clip_rectangle( event.area ) - - # draw base - widget.window.draw_drawable( self.gc, self.previewBuffer, event.area.x, event.area.y, event.area.x, event.area.y, event.area.width, event.area.height ) - - if self.marqueeLoc: # draw the selection rect - 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.colors["Preview_Note_Selected"] - widget.window.draw_rectangle( self.gc, False, self.marqueeRect[0][0], self.marqueeRect[0][1], self.marqueeRect[1][0], self.marqueeRect[1][1] ) - - if self.recording: # draw playhead - self.gc.set_line_attributes( Config.PLAYHEAD_SIZE, gtk.gdk.LINE_SOLID, gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER ) - self.gc.foreground = self.colors["black"] - widget.window.draw_line( self.gc, self.playheadX, event.area.y, self.playheadX, event.area.y + event.area.height ) - - def invalidatePreview( self, x, y, width, height, page = -1, base = True ): - if page != -1 and page != self.getPage(): - return - - self.dirtyRectToAdd.x = x - self.dirtyRectToAdd.y = y - self.dirtyRectToAdd.width = width - self.dirtyRectToAdd.height = height - - if base: # the base image has been dirtied - if not self.previewDirty: - self.previewDirtyRect.x = x - self.previewDirtyRect.y = y - self.previewDirtyRect.width = width - self.previewDirtyRect.height = height - else: - self.previewDirtyRect = self.previewDirtyRect.union( self.dirtyRectToAdd ) - self.previewDirty = True - - if self.previewDA.window != None: - self.previewDA.window.invalidate_rect( self.dirtyRectToAdd, True ) - - #======================================================= - # Recording - - def startRecording( self ): - if self.recording: - return - - #self.owner.setPaused( True ) - self.owner.pushInstrument( self.instrument ) - self.owner.setKeyboardListener( self ) - - self.recordLoop = self.owner._playLoop( self.instrument["id"], self.instrument["amplitude"], self.instrument["reverb"], [ self.curPage ], force = True ) - self.updatePlayhead() - self.recordTimeout = gobject.timeout_add( 20, self._record_timeout ) - self.recording = True - - def stopRecording( self ): - if not self.recording: - return - - #self.owner.setPaused( False ) - self.owner.popInstrument() - self.owner.setKeyboardListener( None ) - - gobject.source_remove( self.recordTimeout ) - self.recording = False - - if self.recordingNote: - self.finishNote() - - self.owner._stopLoop( self.recordLoop ) - self.recordLoop = None - self.clearPlayhead() - - def recordNote( self, pitch ): - onset = self.csnd.loopGetTick( self.recordLoop ) - #onset = Config.DEFAULT_GRID * int(onset / Config.DEFAULT_GRID + 0.5) - - cs = CSoundNote( onset, - pitch, - 0.75, - 0.5, - Config.DEFAULT_GRID, - 0, - instrumentId = self.instrument["id"] ) - cs.pageId = self.curPage - - for n in self.noteDB.getNotesByTrack( self.curPage, 0 ): - if onset < n.cs.onset: - break - if onset >= n.cs.onset + n.cs.duration: - continue - if onset < n.cs.onset + n.cs.duration - 2: - self.noteDB.deleteNote( n.page, n.track, n.id ) - elif onset - n.cs.onset < 1: - self.noteDB.deleteNote( n.page, n.track, n.id ) - else: - self.noteDB.updateNote( n.page, n.track, n.id, PARAMETER.DURATION, onset - n.cs.onset ) - break - - self.recordingNote = self.noteDB.addNote( -1, self.curPage, 0, cs ) - - self.recordLoop = self.owner._playLoop( self.instrument["id"], self.instrument["amplitude"], self.instrument["reverb"], [ self.curPage ], self.recordLoop, force = True ) - - def finishNote( self ): - self.recordingNote = None - - self.block.updateLoop() - - def _updateNote( self ): - tick = self.csnd.loopGetTick( self.recordLoop ) - #tick = Config.DEFAULT_GRID * int(tick / Config.DEFAULT_GRID + 0.5) - - note = self.noteDB.getNote( self.curPage, 0, self.recordingNote ) - - if tick < note.cs.onset: - tick = self.noteDB.getPage( self.curPage ).ticks - self.noteDB.updateNote( note.page, note.track, note.id, PARAMETER.DURATION, tick - note.cs.onset ) - for n in self.noteDB.getNotesByTrack( self.curPage, 0 ): - if n.cs.onset <= note.cs.onset: - continue - if n.cs.onset > note.cs.onset and n.cs.onset < note.cs.onset + note.cs.duration: - self.noteDB.deleteNote( n.page, n.track, n.id ) - else: - break - self.finishNote() - elif tick > note.cs.onset + note.cs.duration: - self.noteDB.updateNote( note.page, note.track, note.id, PARAMETER.DURATION, tick - note.cs.onset ) - for n in self.noteDB.getNotesByTrack( self.curPage, 0 ): - if n.cs.onset <= note.cs.onset: - continue - if n.cs.onset > note.cs.onset and n.cs.onset < note.cs.onset + note.cs.duration: - self.noteDB.deleteNote( n.page, n.track, n.id ) - else: - break - - def _record_timeout( self ): - self.updatePlayhead() - if self.recordingNote: - self._updateNote() - return True - - def updatePlayhead( self ): - ticks = self.csnd.loopGetTick( self.recordLoop ) - if self.playheadT != ticks: - self.invalidatePreview( self.playheadX-Config.PLAYHEAD_SIZE/2, 0, Config.PLAYHEAD_SIZE, self.previewDA.height, self.curPage, False ) - self.playheadX = self.ticksToPixels( self.curBeats, ticks ) - self.invalidatePreview( self.playheadX-Config.PLAYHEAD_SIZE/2, 0, Config.PLAYHEAD_SIZE, self.previewDA.height, self.curPage, False ) - self.playheadT = ticks - - return True - - def clearPlayhead( self ): - self.invalidatePreview( self.playheadX-Config.PLAYHEAD_SIZE/2, 0, Config.PLAYHEAD_SIZE, self.previewDA.height, self.curPage, False ) - - #======================================================= - # Actions - - def setCurrentAction( self, action, obj = None ): - if self.curAction: - self.doneCurrentAction() - - self.curAction = action - self.curActionObject = obj - - if action == "note-drag-onset": self.updateDragLimits() - elif action == "note-drag-duration": self.updateDragLimits() - elif action == "note-drag-pitch": self.updateDragLimits() - #elif action == "note-drag-pitch-drum": self.updateDragLimits() - - def doneCurrentAction( self ): - if not self.curAction: return - action = self.curAction - self.curAction = False - - if action == "note-drag-onset": self.doneNoteDrag( action ) - elif action == "note-drag-duration": self.doneNoteDrag( action ) - elif action == "note-drag-pitch": self.doneNoteDrag( action ) - #elif action == "note-drag-pitch-drum": self.doneNoteDrag( action ) - - def selectionChanged( self ): - if self.curAction == "note-drag-onset": self.updateDragLimits() - elif self.curAction == "note-drag-duration": self.updateDragLimits() - elif self.curAction == "note-drag-pitch": self.updateDragLimits() - #elif self.curAction == "note-drag-pitch-drum": self.updateDragLimits() - - def applyNoteSelection( self, mode, trackN, which, page = -1 ): - if page == -1: page = self.curPage - if mode == SELECTNOTES.ALL: - track = self.noteDB.getNotesByTrack( page, trackN, self ) - map( lambda note:note.setSelected( True ), track ) - self.selectedNotes[trackN] = [] - map( lambda note:self.selectedNotes[trackN].append(note), track ) - elif mode == SELECTNOTES.NONE: - track = self.selectedNotes[trackN] #self.noteDB.getNotesByTrack( page, trackN, self ) - map( lambda note:note.setSelected( False ), track ) - self.selectedNotes[trackN] = [] - elif mode == SELECTNOTES.ADD: - for note in which: - if note.setSelected( True ): - self.selectedNotes[trackN].append( note ) - elif mode == SELECTNOTES.REMOVE: - for note in which: - if note.setSelected( False ): - self.selectedNotes[trackN].remove( note ) - elif mode == SELECTNOTES.FLIP: - for note in which: - if note.getSelected(): - note.setSelected( False ) - self.selectedNotes[trackN].remove( note ) - else: - note.setSelected( True ) - self.selectedNotes[trackN].append( note ) - elif mode == SELECTNOTES.EXCLUSIVE: - notes = self.noteDB.getNotesByTrack( page, trackN, self ) - for n in range(len(notes)): - if notes[n] in which: - if notes[n].setSelected( True ): - self.selectedNotes[trackN].append( notes[n] ) - else: - if notes[n].setSelected( False ): - self.selectedNotes[trackN].remove( notes[n] ) - - def selectNotesByBar( self, trackN, start, stop, page = -1 ): - for i in range(Config.NUMBER_OF_TRACKS): - if i == trackN: - notes = [] - track = self.noteDB.getNotesByTrack( self.curPage, trackN, self ) - for n in range(len(track)): - if track[n].testOnset( start, stop ): notes.append(track[n]) - if not Config.ModKeys.ctrlDown: self.applyNoteSelection( SELECTNOTES.EXCLUSIVE, trackN, notes, page ) - else: self.applyNoteSelection( SELECTNOTES.ADD, trackN, notes, page ) - else: - if not Config.ModKeys.ctrlDown: self.applyNoteSelection( SELECTNOTES.NONE, i, [], page ) - self.selectionChanged() - - def selectNotesByTrack( self, trackN, page = -1 ): - if Config.ModKeys.ctrlDown: - self.applyNoteSelection( SELECTNOTES.ALL, trackN, [], page ) - else: - for i in range(Config.NUMBER_OF_TRACKS): - if i == trackN: self.applyNoteSelection( SELECTNOTES.ALL, trackN, [], page ) - else: self.applyNoteSelection( SELECTNOTES.NONE, i, [], page ) - self.selectionChanged() - - def selectNotes( self, noteDic, ignoreCtrl = False, page = -1 ): - if Config.ModKeys.ctrlDown and not ignoreCtrl: - for i in noteDic: - self.applyNoteSelection( SELECTNOTES.FLIP, i, noteDic[i], page ) - else: - for i in range(Config.NUMBER_OF_TRACKS): - if i in noteDic: self.applyNoteSelection( SELECTNOTES.EXCLUSIVE, i, noteDic[i], page ) - else: self.applyNoteSelection( SELECTNOTES.NONE, i, [], page ) - self.selectionChanged() - - def deselectNotes( self, noteDic, page = -1 ): - for i in noteDic: - self.applyNoteSelection( SELECTNOTES.REMOVE, i, noteDic[i], page ) - self.selectionChanged() - - def clearSelectedNotes( self, page = -1 ): - for i in range(Config.NUMBER_OF_TRACKS): - self.applyNoteSelection( SELECTNOTES.NONE, i, [], page ) - self.selectionChanged() - - def updateDragLimits( self ): - self.dragLimits = [ [-9999,9999], [-9999,9999], [-9999,9999] ] # initialize to big numbers! - maxRightBound = self.noteDB.getPage(self.curPage).ticks - - for i in range(Config.NUMBER_OF_TRACKS): - if not len(self.selectedNotes[i]): continue # no selected notes here - - track = self.noteDB.getNotesByTrack( self.curPage, i, self ) - leftBound = 0 - skip = True # skip the first note - for n in range(len(track)): - if skip: - skip = False - thisNote = track[n] - continue - nextNote = track[n] - if not thisNote.getSelected(): - leftBound = thisNote.getEndTick() - else: - if not nextNote.getSelected(): - rightBound = min( nextNote.getStartTick(), maxRightBound ) - widthBound = rightBound - else: - rightBound = maxRightBound - widthBound = min( nextNote.getStartTick(), maxRightBound ) - thisNote.updateDragLimits( self.dragLimits, leftBound, rightBound, widthBound, maxRightBound ) - thisNote = nextNote - # do the last note - if thisNote.getSelected(): - thisNote.updateDragLimits( self.dragLimits, leftBound, maxRightBound, maxRightBound, maxRightBound ) - - def noteDragOnset( self, event ): - do = self.pixelsToTicks( self.curBeats, event.x - self.clickLoc[0] ) - do = min( self.dragLimits[0][1], max( self.dragLimits[0][0], do ) ) - - if do != self.lastDO: - self.lastDO = do - stream = [] - for i in range(Config.NUMBER_OF_TRACKS): - tstream = [] - for note in self.selectedNotes[i]: - note.noteDragOnset( do, tstream ) - if len(tstream): - stream += [ self.curPage, i, PARAMETER.ONSET, len(tstream)//2 ] + tstream - if len(stream): - self.noteDB.updateNotes( stream + [-1] ) - - def noteDragDuration( self, event ): - dd = self.pixelsToTicks( self.curBeats, event.x - self.clickLoc[0] ) - dd = min( self.dragLimits[2][1], max( self.dragLimits[2][0], dd ) ) - - if dd != self.lastDD: - self.lastDD = dd - stream = [] - for i in range(Config.NUMBER_OF_TRACKS): - tstream = [] - for note in self.selectedNotes[i]: - note.noteDragDuration( dd, tstream ) - if len(tstream): - stream += [ self.curPage, i, PARAMETER.DURATION, len(tstream)//2 ] + tstream - if len(stream): - self.noteDB.updateNotes( stream + [-1] ) - - def noteDragPitch( self, event, drum = False ): - if not drum: dp = self.pixelsToPitch( event.y - self.clickLoc[1] ) - else: dp = self.pixelsToPitchDrum( event.y - self.clickLoc[1] ) - dp = min( self.dragLimits[1][1], max( self.dragLimits[1][0], dp ) ) - - if dp != self.lastDP: - self.lastDP = dp - stream = [] - for i in range(Config.NUMBER_OF_TRACKS): - tstream = [] - for note in self.selectedNotes[i]: - note.noteDragPitch( dp, tstream ) - if len(tstream): - stream += [ self.curPage, i, PARAMETER.PITCH, len(tstream)//2 ] + tstream - if len(stream): - self.noteDB.updateNotes( stream + [-1] ) - - self.curActionObject.playSampleNote( True ) - - def doneNoteDrag( self, action ): - # if action == "note-drag-pitch" or action == "note-drag-pitch-drum": - # self.curActionObject.playSampleNote() - - self.lastDO = self.lastDP = self.lastDrumDP = self.lastDD = None - - for i in range(Config.NUMBER_OF_TRACKS): - for note in self.selectedNotes[i]: - note.doneNoteDrag( self ) - - self.block.updateLoop() - - def noteStepOnset( self, step ): - stream = [] - for i in range(Config.NUMBER_OF_TRACKS): - if not len(self.selectedNotes[i]): continue # no selected notes here - - tstream = [] - track = self.noteDB.getNotesByTrack( self.curPage, i, self ) - if step < 0: # moving to the left, iterate forwards - leftBound = 0 - for n in range(len(track)): - leftBound = track[n].noteDecOnset( step, leftBound, tstream ) - else: # moving to the right, iterate backwards - rightBound = self.noteDB.getPage(self.curPage).ticks - for n in range(len(track)-1, -1, -1 ): - rightBound = track[n].noteIncOnset( step, rightBound, tstream ) - - if len(tstream): - stream += [ self.curPage, i, PARAMETER.ONSET, len(tstream)//2 ] + tstream - - if len(stream): - self.noteDB.updateNotes( stream + [-1] ) - - def noteStepPitch( self, step ): - stream = [] - for i in range(Config.NUMBER_OF_TRACKS): - if not len(self.selectedNotes[i]): continue # no selected notes here - - tstream = [] - if step < 0: - for n in self.selectedNotes[i]: - n.noteDecPitch( step, tstream ) - else: - for n in self.selectedNotes[i]: - n.noteIncPitch( step, tstream ) - - if len(tstream): - stream += [ self.curPage, i, PARAMETER.PITCH, len(tstream)//2 ] + tstream - - if len(stream): - self.noteDB.updateNotes( stream + [-1] ) - - def noteStepDuration( self, step ): - stream = [] - for i in range(Config.NUMBER_OF_TRACKS): - if not len(self.selectedNotes[i]): continue # no selected notes here - - tstream = [] - if step < 0: - for n in self.selectedNotes[i]: - n.noteDecDuration( step, tstream ) - else: - track = self.noteDB.getNotesByTrack( self.curPage, i, self ) - for j in range(len(track)-1): - track[j].noteIncDuration( step, track[j+1].getStartTick(), tstream ) - track[len(track)-1].noteIncDuration( step, self.noteDB.getPage(self.curPage).ticks, tstream ) - - if len(tstream): - stream += [ self.curPage, i, PARAMETER.DURATION, len(tstream)//2 ] + tstream - - if len(stream): - self.noteDB.updateNotes( stream + [-1] ) - - def noteStepVolume( self, step ): - stream = [] - for i in range(Config.NUMBER_OF_TRACKS): - if not len(self.selectedNotes[i]): continue # no selected notes here - - tstream = [] - if step < 0: - for n in self.selectedNotes[i]: - n.noteDecVolume( step, tstream ) - else: - for n in self.selectedNotes[i]: - n.noteIncVolume( step, tstream ) - - if len(tstream): - stream += [ self.curPage, i, PARAMETER.AMPLITUDE, len(tstream)//2 ] + tstream - - if len(stream): - self.noteDB.updateNotes( stream + [-1] ) - - def updateMarquee( self, event ): - if self.marqueeLoc: - oldX = self.marqueeRect[0][0] - oldEndX = self.marqueeRect[0][0] + self.marqueeRect[1][0] - oldY = self.marqueeRect[0][1] - oldEndY = self.marqueeRect[0][1] + self.marqueeRect[1][1] - else: - oldX = oldEndX = self.clickLoc[0] - oldY = oldEndY = self.clickLoc[1] - - self.marqueeLoc = [ int(event.x), int(event.y) ] - if self.marqueeLoc[0] < 0: self.marqueeLoc[0] = 0 - elif self.marqueeLoc[0] > self.previewDA.width: self.marqueeLoc[0] = self.previewDA.width - if self.marqueeLoc[1] < 0: self.marqueeLoc[1] = 0 - elif self.marqueeLoc[1] > self.previewDA.height: self.marqueeLoc[1] = self.previewDA.height - - if self.marqueeLoc[0] > self.clickLoc[0]: - self.marqueeRect[0][0] = self.clickLoc[0] - self.marqueeRect[1][0] = self.marqueeLoc[0] - self.clickLoc[0] - else: - self.marqueeRect[0][0] = self.marqueeLoc[0] - self.marqueeRect[1][0] = self.clickLoc[0] - self.marqueeLoc[0] - if self.marqueeLoc[1] > self.clickLoc[1]: - self.marqueeRect[0][1] = self.clickLoc[1] - self.marqueeRect[1][1] = self.marqueeLoc[1] - self.clickLoc[1] - else: - self.marqueeRect[0][1] = self.marqueeLoc[1] - self.marqueeRect[1][1] = self.clickLoc[1] - self.marqueeLoc[1] - - x = min( self.marqueeRect[0][0], oldX ) - 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.invalidatePreview( x-1, y-1, width+2, height+2, self.curPage, False ) - - def doneMarquee( self, event ): - if self.marqueeLoc: - stop = [ self.marqueeRect[0][0] + self.marqueeRect[1][0], self.marqueeRect[0][1] + self.marqueeRect[1][1] ] - - select = {} - - intersectionY = [ self.marqueeRect[0][1], stop[1] ] - - notes = [] - track = self.noteDB.getNotesByTrack( self.getPage(), 0, self ) - for n in range(len(track)): - hit = track[n].handleMarqueeSelect( self, - [ self.marqueeRect[0][0], intersectionY[0] ], \ - [ stop[0], intersectionY[1] ] ) - if hit: notes.append(track[n]) - - if len(notes): select[0] = notes - - self.selectNotes( select ) - - self.marqueeLoc = False - self.doneCurrentAction() - - self.invalidatePreview( self.marqueeRect[0][0]-1, self.marqueeRect[0][1]-1, self.marqueeRect[1][0]+2, self.marqueeRect[1][1]+2, self.getPage(), False ) - - def updateTooltip( self, event ): - - notes = self.noteDB.getNotesByTrack( self.getPage(), 0, self ) - handled = 0 - for n in range(len(notes)): - handled = notes[n].updateTooltip( self, event ) - if handled == 0: continue - elif handled == 1: return # event was handled - else: break - - if handled == -2: # event X overlapped with a note - self.setCursor("default") - return - - self.setCursor("pencil") - - def setCursor( self, cursor ): - self.window.set_cursor(self.cursor[cursor]) - - def ticksToPixels( self, beats, ticks ): - return int(round( ticks * self.pixelsPerTick[beats] )) - def pixelsToTicks( self, beats, pixels ): - return int(round( pixels * self.ticksPerPixel[beats] )) - def pitchToPixels( self, pitch ): - return int(round( ( Config.MAXIMUM_PITCH - pitch ) * self.pixelsPerPitch )) - def ticksToPixelsFloor( self, beats, ticks ): - return int( ticks * self.pixelsPerTick[beats] ) - def pixelsToTicksFloor( self, beats, pixels ): - return int( pixels * self.ticksPerPixel[beats] ) - def pixelsToPitch( self, pixels ): - return int(round(-pixels*self.pitchPerPixel)) - def pitchToPixelsFloor( self, pitch ): - return int(( Config.MAXIMUM_PITCH - pitch ) * self.pixelsPerPitch ) - def pixelsToPitchFloor( self, pixels ): - return int(-pixels*self.pitchPerPixel) - - -class Shortcut( Popup ): - - def __init__( self, label, owner ): - Popup.__init__( self, label, owner ) - - self.gc = self.owner.gc - - self.GUI = {} - - self.GUI["mainBox"] = gtk.VBox() - self.set_content( self.GUI["mainBox"] ) - - #-- Keys ---------------------------------------------- - # match keycodes from JamMain.valid_shortcuts - layout = [ [ 0.0, [ 18, 19, 20, 21 ] ], - [ 0.3, [ 32, 33, 34, 35 ] ], - [ 1.7, [ 47, 48, 51 ] ], - [ 1.1, [ 60, 61 ] ] ] - - self.GUI["keyBox"] = gtk.VBox() - self.GUI["mainBox"].pack_start( self.GUI["keyBox"], padding = style.DEFAULT_PADDING - 2 ) - - for row in layout: - offset = row[0] - hbox = gtk.HBox() - self.GUI["keyBox"].pack_start( hbox, padding = 2 ) - separator = gtk.Label("") - separator.set_size_request( int(Block.Block.KEYSIZE*row[0]) + style.DEFAULT_PADDING, -1 ) - hbox.pack_start( separator, False ) - separator = gtk.Label("") - separator.set_size_request( style.DEFAULT_PADDING, -1 ) - hbox.pack_end( separator, False ) - for key in row[1]: - self.GUI[key] = gtk.ToggleButton() - self.GUI[key].connect( "expose-event", self.keyExpose ) - self.GUI[key].connect( "toggled", self.keyToggled ) - self.GUI[key].set_size_request( Block.Block.KEYSIZE, Block.Block.KEYSIZE ) - self.GUI[key].key = key - self.GUI[key].image = [ self.owner.getKeyImage( key, False ), - self.owner.getKeyImage( key, True ) ] - hbox.pack_start( self.GUI[key], False, padding = 2 ) - - #-- None ---------------------------------------------- - self.GUI["noneBox"] = gtk.HBox() - self.GUI["mainBox"].pack_start( self.GUI["noneBox"], padding = style.DEFAULT_PADDING ) - self.GUI["noneButton"] = gtk.Button( _("None") ) - self.GUI["noneButton"].connect( "clicked", self.handleNone ) - self.GUI["noneBox"].pack_start( self.GUI["noneButton"], True, False, padding = style.DEFAULT_PADDING ) - - self.GUI["mainBox"].show_all() - - self.key = None - - def setBlock( self, block ): - self.ignoreToggle = True - - self.block = block - self.key = self.block.getData( "key" ) - - if self.key != None: - self.GUI[self.key].set_active( True ) - - self.ignoreToggle = False - - Popup.setBlock( self, block ) - - def on_key_press( self, widget, event ): - key = event.hardware_keycode - if key in self.owner.valid_shortcuts.keys(): - self.block.setData( "key", key ) - if self.key != None: # clear old key - self.ignoreToggle = True - self.GUI[self.key].set_active( False ) - self.key = None - self.ignoreToggle = False - self.popdown( True ) - else: - self.owner.onKeyPress( widget, event ) - - def keyExpose( self, widget, event ): - self.gc.set_clip_mask( self.owner.blockMask ) - self.gc.set_clip_origin( event.area.x - Block.Block.KEYMASK_START, event.area.y ) - widget.window.draw_drawable( self.gc, widget.image[widget.get_active()], 0, 0, event.area.x, event.area.y, event.area.width, event.area.height ) - return True - - def keyToggled( self, widget ): - if self.ignoreToggle: - return - - if widget.get_active(): - self.block.setData( "key", widget.key ) - - self.ignoreToggle = True - - if self.key != None: # clear old key - self.GUI[self.key].set_active( False ) - self.key = None - - widget.set_active( False ) - - self.ignoreToggle = False - - self.popdown( True ) - - def handleNone( self, widget ): - if self.key != None: - self.ignoreToggle = True - self.GUI[self.key].set_active( False ) - self.key = None - self.ignoreToggle = False - - self.block.setData( "key", None ) - - self.popdown( True ) diff --git a/Jam/RythmGenerator.py b/Jam/RythmGenerator.py deleted file mode 100644 index 4740160..0000000 --- a/Jam/RythmGenerator.py +++ /dev/null @@ -1,77 +0,0 @@ -import random - -import Config -from Util.CSoundNote import CSoundNote -from Generation.GenerationConstants import GenerationConstants -from GenRythm import GenRythm - -def generator( instrument, nbeats, density, regularity, reverbSend ): - - makeRythm = GenRythm() - - noteDuration = GenerationConstants.DOUBLE_TICK_DUR / 2 - trackId = 5 - pan = 0.5 - attack = 0.005 - decay = 0.095 - filterType = 0 - filterCutoff = 1000 - tied = False - mode = 'mini' - - def makePitchSequence(length, drumPitch): - pitchSequence = [] - append = pitchSequence.append - list = range(length) - max = len(drumPitch) - 1 - for i in list: - append(drumPitch[ random.randint( 0, max ) ] ) - return pitchSequence - - def makeGainSequence( onsetList ): - gainSequence = [] - append = gainSequence.append - for onset in onsetList: - if onset == 0: - gain = random.uniform(GenerationConstants.GAIN_MID_MAX_BOUNDARY, GenerationConstants.GAIN_MAX_BOUNDARY) - elif ( onset % Config.TICKS_PER_BEAT) == 0: - gain = random.uniform(GenerationConstants.GAIN_MID_MIN_BOUNDARY, GenerationConstants.GAIN_MID_MAX_BOUNDARY) - else: - gain = random.uniform(GenerationConstants.GAIN_MIN_BOUNDARY, GenerationConstants.GAIN_MID_MIN_BOUNDARY) - append(gain) - return gainSequence - - def pageGenerate( regularity, drumPitch ): - barLength = Config.TICKS_PER_BEAT * nbeats - - #print 'pageGenerate drumPitch[0] ', drumPitch[0] - currentInstrument = Config.INSTRUMENTS[ instrument ].kit[ drumPitch[0] ].name - - rythmSequence = makeRythm.drumRythmSequence(currentInstrument, nbeats, density, regularity) - pitchSequence = makePitchSequence(len(rythmSequence), drumPitch ) - gainSequence = makeGainSequence(rythmSequence) - - trackNotes = [] - list = range(len(rythmSequence)) - for i in list: - trackNotes.append( CSoundNote( rythmSequence[i], pitchSequence[i], gainSequence[i], - pan, noteDuration, trackId, - Config.INSTRUMENTS[instrument].instrumentId, attack, - decay, reverbSend, filterType, filterCutoff, tied, mode)) - return trackNotes - -################################################################################## - # begin generate() - if regularity > 0.75: - streamOfPitch = GenerationConstants.DRUM_COMPLEXITY1 - elif regularity > 0.5: - streamOfPitch = GenerationConstants.DRUM_COMPLEXITY2 - elif regularity > 0.25: - streamOfPitch = GenerationConstants.DRUM_COMPLEXITY3 - else: - streamOfPitch = GenerationConstants.DRUM_COMPLEXITY4 - - trackNotes = [] - for drumPitch in streamOfPitch: - trackNotes.append(pageGenerate( regularity, drumPitch )) - return trackNotes diff --git a/Jam/Toolbars.py b/Jam/Toolbars.py deleted file mode 100644 index 8a45c01..0000000 --- a/Jam/Toolbars.py +++ /dev/null @@ -1,129 +0,0 @@ - -import pygtk -pygtk.require( '2.0' ) -import gtk - -from gettext import gettext as _ - -from sugar.graphics.palette import Palette, WidgetInvoker -from sugar.graphics.radiotoolbutton import RadioToolButton - -import Config - - -class JamToolbar( gtk.Toolbar ): - - def __init__( self, owner ): - gtk.Toolbar.__init__( self ) - - self.owner = owner - - self.toolItem = {} - - self.volumeImg = gtk.Image() - - self.volumeAdjustment = gtk.Adjustment( 0.0, 0, 1.0, 0.1, 0.1, 0 ) - self.volumeAdjustment.connect( 'value-changed', self.handleVolume ) - self.volumeSlider = gtk.HScale( adjustment = self.volumeAdjustment ) - self.volumeSlider.set_size_request( 450, -1 ) - self.volumeSlider.set_draw_value( False ) - self._add_tooltip( self.volumeSlider, _("Master Volume") ) - self._insert_widget( self.volumeSlider, -1 ) - self._insert_widget( self.volumeImg, -1 ) - - self._insert_separator( True ) - - self.tempoImg = gtk.Image() - - self.tempoAdjustment = gtk.Adjustment( Config.PLAYER_TEMPO_LOWER, Config.PLAYER_TEMPO_LOWER, Config.PLAYER_TEMPO_UPPER+1, 10, 10, 0 ) - self.tempoAdjustment.connect( 'value-changed', self.handleTempo ) - self.tempoSlider = gtk.HScale( adjustment = self.tempoAdjustment ) - self.tempoSlider.set_size_request( 450, -1 ) - self.tempoSlider.set_draw_value( False ) - self._add_tooltip( self.tempoSlider, _("Tempo") ) - self._insert_widget( self.tempoSlider, -1 ) - self._insert_widget( self.tempoImg, -1 ) - - self.show_all() - - #def _add_palette( self, widget, palette, position = Palette.DEFAULT ): - def _add_palette( self, widget, palette ): - widget._palette = palette - widget._palette.props.invoker = WidgetInvoker( widget ) - #widget._palette.set_property( "position", position ) - - def _add_tooltip( self, widget, tooltip ): - #self._add_palette( widget, Palette( tooltip ), Palette.DEFAULT ) - self._add_palette( widget, Palette( tooltip ) ) - - def _insert_widget( self, widget, pos ): - self.toolItem[ widget ] = gtk.ToolItem() - self.toolItem[ widget ].add( widget ) - self.insert( self.toolItem[ widget ], pos ) - - def _insert_separator( self, expand = False ): - separator = gtk.SeparatorToolItem() - separator.set_draw( False ) - separator.set_expand( expand ) - self.insert( separator, -1 ) - - def mapRange( self, value, ilower, iupper, olower, oupper ): - if value == iupper: - return oupper - return olower + int( (oupper-olower+1)*(value-ilower)/float(iupper-ilower) ) - - - def handleVolume( self, widget ): - self.owner._setVolume( widget.get_value() ) - - img = self.mapRange( widget.value, widget.lower, widget.upper, 0, 3 ) - self.volumeImg.set_from_file(Config.TAM_TAM_ROOT + '/icons/volume' + str(img) + '.svg') - - def handleTempo( self, widget ): - self.owner._setTempo( widget.get_value() ) - - img = self.mapRange( widget.value, widget.lower, widget.upper, 1, 8 ) - self.tempoImg.set_from_file(Config.TAM_TAM_ROOT + '/icons/tempo' + str(img) + '.svg') - - -class DesktopToolbar( gtk.Toolbar ): - - def __init__( self, owner ): - gtk.Toolbar.__init__( self ) - - self.owner = owner - - self._insert_separator( True ) - - self.desktop = [] - - btn = RadioToolButton( 'preset1', group = None ) - btn.connect( 'toggled', self.setDesktop, 0 ) - btn.set_tooltip( _('Desktop 1') ) - self.insert( btn, -1 ) - self.desktop.append( btn ) - - for i in range(2,11): - btn = RadioToolButton( 'preset%d'%i, group = self.desktop[0] ) - btn.connect( 'toggled', self.setDesktop, i-1 ) - btn.set_tooltip( _('Desktop %d'%i) ) - self.insert( btn, -1 ) - self.desktop.append( btn ) - - self._insert_separator( True ) - - self.show_all() - - def _insert_separator( self, expand = False ): - separator = gtk.SeparatorToolItem() - separator.set_draw( False ) - separator.set_expand( expand ) - self.insert( separator, -1 ) - - def getDesktopButton( self, which ): - return self.desktop[which] - - def setDesktop( self, widget, which ): - if widget.get_active(): - self.owner._setDesktop( which ) - diff --git a/Jam/__init__.py b/Jam/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/Jam/__init__.py +++ /dev/null -- cgit v0.9.1