Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Jam
diff options
context:
space:
mode:
authorNat <natcl@hotmail.com>2007-09-13 16:01:09 (GMT)
committer Nat <natcl@hotmail.com>2007-09-13 16:01:09 (GMT)
commit6d7e6f83bec91d4c3e49fe64d7793f12d1d3509b (patch)
tree013613f48b4f4a3f91d3ea9f1c0511153cd6f2b4 /Jam
parente12dbff4dda5aafbaac98f75f0467ef00dc06c32 (diff)
split
Diffstat (limited to 'Jam')
-rw-r--r--Jam/Block.py895
-rw-r--r--Jam/Desktop.py466
-rw-r--r--Jam/Fillin.py116
-rw-r--r--Jam/GenRythm.py80
-rw-r--r--Jam/JamMain.py1112
-rw-r--r--Jam/Parasite.py349
-rw-r--r--Jam/Picker.py422
-rw-r--r--Jam/Popup.py1397
-rw-r--r--Jam/RythmGenerator.py77
-rw-r--r--Jam/Toolbars.py129
-rw-r--r--Jam/__init__.py0
11 files changed, 0 insertions, 5043 deletions
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