From 82bce73030735492a017113f0486ebe8aae5fae6 Mon Sep 17 00:00:00 2001 From: amartin Date: Tue, 28 Aug 2007 11:58:27 +0000 Subject: Jam save/load --- diff --git a/Config.py b/Config.py index 4743088..230b7cb 100644 --- a/Config.py +++ b/Config.py @@ -26,6 +26,11 @@ print 'INFO: loaded TAMTAM_ROOT=%s' % TAM_TAM_ROOT #PATHS +SCRATCH_DIR = TAM_TAM_ROOT + "/.scratch/" +try: # can't add .scratch to git for some reason so make sure it exists here + os.mkdir( SCRATCH_DIR ) +except: + pass SOUNDS_DIR = TAM_TAM_ROOT + "/Resources/Sounds" FILES_DIR = TAM_TAM_ROOT + "/Resources" TUNE_DIR='/' diff --git a/Jam/Block.py b/Jam/Block.py index 5695987..424b257 100644 --- a/Jam/Block.py +++ b/Jam/Block.py @@ -18,9 +18,9 @@ class Block(): SNAP = 15 - def __init__( self, owner, graphics_context, data ): + def __init__( self, owner, data ): self.owner = owner - self.gc = graphics_context + self.gc = owner.gc self.data = {} for key in data.keys(): @@ -50,7 +50,7 @@ class Block(): self.active = False def dumpToStream( self, ostream, child = False ): - ostream.block_add( ClassToStr[ self.type ], self.x, self.y, child, self.data ) + 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 ) @@ -76,7 +76,7 @@ class Block(): self.x = int(x) self.y = int(y) - self.endX = self.x + self.getWidth() + self.endX = self.x + self.width self.endY = self.y + self.height self.invalidate_rect( not self.dragging ) @@ -85,7 +85,12 @@ class Block(): self.child.snapToParentLoc( self.getChildAnchor() ) def resetLoc( self ): - self.setLoc( self.oldLoc[0], self.oldLoc[1] ) + 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 ) @@ -96,14 +101,12 @@ class Block(): def snapToParentLoc( self, loc ): self.setLoc( loc[0] - self.parentOffset, loc[1] ) - def getWidth( self ): - return self.width - def substitute( self, block ): pass # override in subclasses def testSubstitute( self, block ): - return False + if self.child: + return self.child.testSubstitute( block ) def testChild( self, loc ): @@ -118,10 +121,17 @@ class Block(): 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 @@ -158,6 +168,7 @@ class Block(): else: return False + self.oldParent = self.parent self.oldLoc = ( self.x, self.y ) self.dragOffset = ( event.x - self.x, event.y - self.y ) @@ -191,7 +202,7 @@ class Block(): def _beginDrag( self ): self.dragging = True - self.dragOffset = ( self.getWidth()//2, self.height//2 ) + self.dragOffset = ( self.width//2, self.height//2 ) def invalidateBranch( self, base = True ): self.invalidate_rect( base ) @@ -199,7 +210,7 @@ class Block(): self.child.invalidateBranch( base ) def invalidate_rect( self, base = True ): - self.owner.invalidate_rect( self.x, self.y, self.getWidth(), self.height, base ) + 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: @@ -235,8 +246,8 @@ class Instrument(Block): #::: data format: # { "name": name, "id": instrumentId [, "volume": 0-1 ] } #::: - def __init__( self, owner, graphics_context, data ): - Block.__init__( self, owner, graphics_context, data ) + def __init__( self, owner, data ): + Block.__init__( self, owner, data ) self.type = Instrument @@ -255,8 +266,15 @@ class Instrument(Block): 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 ): - if self.type == Loop: + 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: @@ -303,8 +321,8 @@ class Drum(Block): #::: data format: # { "name": name, "id": instrumentId [, "volume": 0-1, "beats": 2-12, "regularity": 0-1, "seed": 0-1 ] } #::: - def __init__( self, owner, graphics_context, data ): - Block.__init__( self, owner, graphics_context, data ) + def __init__( self, owner, data ): + Block.__init__( self, owner, data ) self.type = Drum @@ -336,7 +354,11 @@ class Drum(Block): self.owner.updateDrum() def testSubstitute( self, block ): - if self.type == Loop: + ret = Block.testSubstitute( self, block ) + if ret: + return ret + + if block.type == Loop: return False if Config.INSTRUMENTSID[block.data["id"]].kit == None: @@ -400,31 +422,85 @@ class Loop(Block): #::: data format: # { "name": name, "id": pageId } #::: - def __init__( self, owner, graphics_context, data ): - Block.__init__( self, owner, graphics_context, data ) + 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 + beats = self.owner.noteDB.getPage(self.data["id"]).beats + self.width = Loop.WIDTH[beats] + + self.img = [ self.owner.getLoopImage( self.data["id"], False ), + self.owner.getLoopImage( self.data["id"], True ) ] + + def destroy( self ): + self.owner.noteDB.deletePages( [ self.data["id"] ] ) + Block.destroy( self ) + def substitute( self, block ): - self.data["id"] = block.data["id"] + self.invalidateBranch( True ) - self.img = [ self.owner.getInstrumentImage( self.data["id"], False ), - self.owner.getInstrumentImage( self.data["id"], True ) ] + oldWidth = self.width - self.invalidate_rect( True ) + newid = self.owner.noteDB.duplicatePages( [ block.data["id"] ] )[block.data["id"]] + self.owner.updateLoopImage( newid ) + self.data["id"] = newid - if self.active: - self.owner.updateDrum() + self.img = [ self.owner.getLoopImage( self.data["id"], False ), + self.owner.getLoopImage( self.data["id"], True ) ] - def getWidth( self ): beats = self.owner.noteDB.getPage(self.data["id"]).beats - return Loop.WIDTH[beats] - + self.width = Loop.WIDTH[beats] + self.endX = self.x + self.width + + 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.child: + self.child.snapToParentLoc( self.getChildAnchor() ) + + if oldWidth < self.width: # or block.child: + self.invalidateBranch( True ) + + 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 ) @@ -472,7 +548,7 @@ class Loop(Block): endY = min( stopY, self.endY ) height = endY - y - loop = self.owner.getLoopImage( self.data["id"], self.active ) + 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"] diff --git a/Jam/Desktop.py b/Jam/Desktop.py index 40b5675..a28a917 100644 --- a/Jam/Desktop.py +++ b/Jam/Desktop.py @@ -51,8 +51,8 @@ class Desktop( gtk.EventBox ): def dumpToStream( self, ostream ): for b in self.blocks: - block.dumpToStream( ostream ) - + b.dumpToStream( ostream ) + def 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() @@ -73,7 +73,7 @@ class Desktop( gtk.EventBox ): def addBlock( self, blockClass, blockData, loc = (-1,-1), drag = False ): - block = blockClass( self, self.gc, blockData ) + block = blockClass( self, blockData ) if loc[0] != -1: x = loc[0] else: x = self.alloc.width//2 @@ -93,12 +93,14 @@ class Desktop( gtk.EventBox ): block.setLoc( x - block.width//2, y - block.height//2 ) if blockClass == Block.Instrument: - self.activateInstrument( block ) + 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: @@ -121,12 +123,19 @@ class Desktop( gtk.EventBox ): block.destroy() + def _clearDesktop( self ): + for i in range( len(self.blocks)-1, -1, -1 ): + self.deleteBlock( self.blocks[i] ) + def getInstrumentImage( self, id, active = False ): return self.owner.getInstrumentImage( id, active ) def getLoopImage( self, id, active = False ): return self.owner.getLoopImage( id, active ) + def updateLoopImage( self, id ): + self.owner.updateLoopImage( id ) + #========================================================== # State @@ -226,12 +235,13 @@ class Desktop( gtk.EventBox ): elif self.possibleSubstitute: self.possibleSubstitute.substitute( self.clickedBlock ) if self.clickedBlock.isPlaced(): - self.clickedBlock.resetLoc() - self.blocks.append( self.clickedBlock ) + if self.clickedBlock.resetLoc(): + self.blocks.append( self.clickedBlock ) else: self.deleteBlock( self.clickedBlock ) self.clickedBlock = None - self.activateInstrument( self.possibleSubstitute ) + if self.possibleSubstitute.type == Block.Instrument: + self.activateInstrument( self.possibleSubstitute ) self.possibleSubstitute = None else: self.blocks.append( self.clickedBlock ) diff --git a/Jam/Fillin.py b/Jam/Fillin.py index f17fe01..8f31489 100644 --- a/Jam/Fillin.py +++ b/Jam/Fillin.py @@ -21,12 +21,16 @@ class Fillin: 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 ) @@ -70,11 +74,11 @@ class Fillin: def clear( self ): if self.notesList: for n in self.notesList: - self.csnd.loopDelete(n) + self.csnd.loopDelete(n, self.loopId) self.notesList = [] def handleClock( self ): - tick = self.csnd.loopGetTick() + tick = self.csnd.loopGetTick( self.loopId ) if tick < ( Config.TICKS_PER_BEAT / 2 + 1 ): if self.gate == 0: self.gate = 1 @@ -108,5 +112,5 @@ class Fillin: n = Note(0, x.trackId, i, x) self.notesList.append(n) i += 1 - self.csnd.loopPlay(n,1) #add as active + self.csnd.loopPlay(n,1, loopId = self.loopId ) #add as active diff --git a/Jam/JamMain.py b/Jam/JamMain.py index 5763ffa..69b9677 100644 --- a/Jam/JamMain.py +++ b/Jam/JamMain.py @@ -5,6 +5,8 @@ import gtk from SubActivity import SubActivity +import os, sys, shutil + import Config from gettext import gettext as _ import sugar.graphics.style as style @@ -25,6 +27,8 @@ from RythmGenerator import generator from Generation.GenerationConstants import GenerationConstants from Util.NoteDB import Note +from Util import ControlStream + from math import sqrt class JamMain(SubActivity): @@ -212,20 +216,39 @@ class JamMain(SubActivity): self._updateInstrument( Config.INSTRUMENTS["kalimba"].instrumentId, 0.5 ) #-- Drums --------------------------------------------- + self.drumLoopId = None # use dummy values for now self.drumFillin = Fillin( 2, 100, Config.INSTRUMENTS["drum1kit"].instrumentId, self.reverb, 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 ) + + self._setDesktop( 0 ) + + #========================================================== # SubActivity Handlers def onActivate( self, arg ): - pass + SubActivity.onActivate( self, arg ) def onDeactivate( self ): - pass + SubActivity.onDeactivate( self ) def onDestroy( self ): - pass + SubActivity.onDestroy( self ) + + # clear up scratch folder + path = Config.SCRATCH_DIR + filelist = os.listdir( path ) + for file in filelist: + os.remove( path+file ) + #========================================================== # Playback @@ -313,31 +336,35 @@ class JamMain(SubActivity): rval += l return rval + if self.drumLoopId != None: + self._stopDrum() + + self.drumLoopId = self.csnd.loopCreate() + noteOnsets = [] notePitchs = [] i = 0 - self.noteList= [] - self.csnd.loopClear() for x in flatten( generator( Config.INSTRUMENTSID[id].name, beats, 0.8, regularity, self.reverb) ): x.amplitude = x.amplitude * volume noteOnsets.append(x.onset) notePitchs.append(x.pitch) n = Note(0, x.trackId, i, x) - self.noteList.append( (x.onset, n) ) i = i + 1 - self.csnd.loopPlay(n,1) #add as active - self.csnd.loopSetNumTicks( beats * Config.TICKS_PER_BEAT ) + self.csnd.loopPlay( n, 1, loopId = self.drumLoopId ) #add as active + self.csnd.loopSetNumTicks( beats * Config.TICKS_PER_BEAT, self.drumLoopId ) + self.drumFillin.setLoopId( self.drumLoopId ) self.drumFillin.setProperties( self.tempo, Config.INSTRUMENTSID[id].name, volume, beats, self.reverb ) self.drumFillin.unavailable( noteOnsets, notePitchs ) self.drumFillin.play() - self.csnd.loopSetTick(0) - self.csnd.loopStart() + #self.csnd.loopSetTick( 0 ) + self.csnd.loopStart( self.drumLoopId ) def _stopDrum( self ): self.drumFillin.stop() - self.csnd.loopPause() + self.csnd.loopDestroy( self.drumLoopId ) + self.drumLoopId = None def _playLoop( self, id, volume, tune, loopId = None ): if loopId == None: # create new loop @@ -348,25 +375,26 @@ class JamMain(SubActivity): self.csnd.loopDestroy( loopId ) loopId = self.csnd.loopCreate() + inst = Config.INSTRUMENTSID[id] + offset = 0 - print "------------", loopId, tune - temp = [] for page in tune: for n in self.noteDB.getNotesByTrack( page, 0 ): - temp.append( n ) n.pushState() n.cs.instrumentId = id + 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 - print temp self.csnd.loopSetNumTicks( offset, loopId ) while startTick > offset: # align with last beat - startTick -= Config.TICK_PER_BEAT + startTick -= Config.TICKS_PER_BEAT self.csnd.loopSetTick( startTick, loopId ) @@ -489,3 +517,97 @@ class JamMain(SubActivity): return self.loopPitchOffset + int(round( ( Config.MAXIMUM_PITCH - pitch ) * self.pixelsPerPitch )) + #========================================================== + # 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 ): + self.desktopToolbar.desktop[desktop].set_active( True ) + + def _setDesktop( self, desktop ): + if self.curDesktop == desktop: + return + + 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: + if Config.DEBUG > 3: print "ERROR:: setDesktop: unable to open file: " + filename + + #========================================================== + # 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: + print "ERROR:: _clearDesktop: unable to open file: " + filename + + 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() + except: + if Config.DEBUG > 3: print "ERROR:: handleJournalLoad:", sys.exc_info()[0] + + def handleJournalSave( self, filepath ): + + self._saveDesktop() + + try: + streamF = open( filepath, "w" ) + stream = ControlStream.TamTamOStream( streamF ) + + for i in range(10): + desktop_file = Config.TAM_TAM_ROOT+"/.scratch/desktop%d" % i + stream.desktop_store( desktop_file, i ) + + stream.desktop_set( self.curDesktop ) + + streamF.close() + + self.curDesktop = None + except: + if Config.DEBUG > 3: print "ERROR:: handleJournalSave:", sys.exc_info()[0] + + diff --git a/Jam/Picker.py b/Jam/Picker.py index cfff3e6..f41f1b2 100644 --- a/Jam/Picker.py +++ b/Jam/Picker.py @@ -214,7 +214,9 @@ class Instrument( Picker ): 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.Instrument, widget.data, loc, True ) + + block = self.desktop.addBlock( Block.Instrument, widget.data, loc, True ) + self.desktop.activateInstrument( block ) class Drum( Picker ): @@ -302,6 +304,8 @@ class Loop( Picker ): return -1 id = newPages.pop() # new pageId + + self.owner.noteDB.getPage( id ).local = False # flag as a global page self.addBlock( id, filename[:-4] ) @@ -412,9 +416,9 @@ class Loop( Picker ): data[key] = widget.data[key] newid = self.owner.noteDB.duplicatePages( [ data["id"] ] )[data["id"]] + self.owner.updateLoopImage( newid ) data["id"] = newid - self.owner.updateLoopImage( data["id"] ) - self.desktop.addBlock( Block.Loop, data, loc, True ) + block = self.desktop.addBlock( Block.Loop, data, loc, True ) diff --git a/Jam/Toolbars.py b/Jam/Toolbars.py index ecb710b..892a139 100644 --- a/Jam/Toolbars.py +++ b/Jam/Toolbars.py @@ -3,6 +3,10 @@ import pygtk pygtk.require( '2.0' ) import gtk +from gettext import gettext as _ + +from sugar.graphics.radiotoolbutton import RadioToolButton + class DesktopToolbar( gtk.Toolbar ): def __init__( self, owner ): @@ -10,4 +14,24 @@ class DesktopToolbar( gtk.Toolbar ): self.owner = owner + 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.show_all() + + def setDesktop( self, widget, which ): + if widget.get_active(): + self.owner._setDesktop( which ) diff --git a/Resources/Desktops/desktop0 b/Resources/Desktops/desktop0 new file mode 100644 index 0000000..e99d154 --- /dev/null +++ b/Resources/Desktops/desktop0 @@ -0,0 +1 @@ +block_add Drum False 242 336 False {'name': 'drum5kit', 'regularity': 0.17265378043653012, 'volume': 0.5, 'beats': 3, 'seed': 0.61058227696419964, 'id': 137} diff --git a/Resources/Desktops/desktop1 b/Resources/Desktops/desktop1 new file mode 100644 index 0000000..1968c02 --- /dev/null +++ b/Resources/Desktops/desktop1 @@ -0,0 +1,2 @@ +block_add Drum False 288 428 False {'name': 'drum5kit', 'regularity': 0.55739138706691516, 'volume': 0.5, 'beats': 3, 'seed': 0.40400200285530108, 'id': 137} +block_add Drum False 456 417 False {'name': 'drum2kit', 'regularity': 0.21178540292062842, 'volume': 0.5, 'beats': 11, 'seed': 0.26067544837978218, 'id': 134} diff --git a/Resources/Desktops/desktop2 b/Resources/Desktops/desktop2 new file mode 100644 index 0000000..b246e12 --- /dev/null +++ b/Resources/Desktops/desktop2 @@ -0,0 +1,3 @@ +block_add Drum False 329 455 False {'name': 'drum5kit', 'regularity': 0.59168723930026823, 'volume': 0.5, 'beats': 7, 'seed': 0.22358471931510959, 'id': 137} +block_add Drum False 446 437 False {'name': 'drum2kit', 'regularity': 0.91451132020332826, 'volume': 0.5, 'beats': 2, 'seed': 0.80359268442224474, 'id': 134} +block_add Drum False 550 442 False {'name': 'drum1kit', 'regularity': 0.78617895417481898, 'volume': 0.5, 'beats': 6, 'seed': 0.50959461680345752, 'id': 133} diff --git a/Resources/Desktops/desktop3 b/Resources/Desktops/desktop3 new file mode 100644 index 0000000..c0279e3 --- /dev/null +++ b/Resources/Desktops/desktop3 @@ -0,0 +1,4 @@ +block_add Drum False 231 435 False {'name': 'drum5kit', 'regularity': 0.77762903492440216, 'volume': 0.5, 'beats': 12, 'seed': 0.60460119964597236, 'id': 137} +block_add Drum False 357 432 False {'name': 'drum2kit', 'regularity': 0.33132865921684251, 'volume': 0.5, 'beats': 2, 'seed': 0.77648751169745833, 'id': 134} +block_add Drum False 493 431 False {'name': 'drum1kit', 'regularity': 0.55491998189711023, 'volume': 0.5, 'beats': 9, 'seed': 0.28875083580746963, 'id': 133} +block_add Drum False 619 438 False {'name': 'drum4kit', 'regularity': 0.67386875098251309, 'volume': 0.5, 'beats': 10, 'seed': 0.15028821889546284, 'id': 136} diff --git a/Resources/Desktops/desktop4 b/Resources/Desktops/desktop4 new file mode 100644 index 0000000..c2db664 --- /dev/null +++ b/Resources/Desktops/desktop4 @@ -0,0 +1,5 @@ +block_add Drum False 182 358 False {'name': 'drum5kit', 'regularity': 0.21830374396919894, 'volume': 0.5, 'beats': 8, 'seed': 0.0884116631518711, 'id': 137} +block_add Drum False 295 325 False {'name': 'drum2kit', 'regularity': 0.24065691474281459, 'volume': 0.5, 'beats': 8, 'seed': 0.96964596655679636, 'id': 134} +block_add Drum False 436 436 False {'name': 'drum1kit', 'regularity': 0.48215301880971018, 'volume': 0.5, 'beats': 8, 'seed': 0.96143042906234688, 'id': 133} +block_add Drum False 600 430 False {'name': 'drum4kit', 'regularity': 0.52916944578760694, 'volume': 0.5, 'beats': 4, 'seed': 0.25477250939622931, 'id': 136} +block_add Drum False 777 407 False {'name': 'drum3kit', 'regularity': 0.33047412968769607, 'volume': 0.5, 'beats': 11, 'seed': 0.61185926492466869, 'id': 135} diff --git a/Resources/Desktops/desktop5 b/Resources/Desktops/desktop5 new file mode 100644 index 0000000..81b4cc2 --- /dev/null +++ b/Resources/Desktops/desktop5 @@ -0,0 +1,6 @@ +block_add Drum False 175 375 False {'name': 'drum5kit', 'regularity': 0.90015096104373171, 'volume': 0.5, 'beats': 6, 'seed': 0.52233572417201268, 'id': 137} +block_add Drum False 275 272 False {'name': 'drum2kit', 'regularity': 0.81725416939007489, 'volume': 0.5, 'beats': 3, 'seed': 0.28506667436101629, 'id': 134} +block_add Drum False 486 354 False {'name': 'drum1kit', 'regularity': 0.67764269721336123, 'volume': 0.5, 'beats': 7, 'seed': 0.69297743070367435, 'id': 133} +block_add Drum False 667 433 False {'name': 'drum4kit', 'regularity': 0.5860273409956076, 'volume': 0.5, 'beats': 8, 'seed': 0.1487598780244116, 'id': 136} +block_add Drum False 709 259 False {'name': 'drum3kit', 'regularity': 0.30976478341586478, 'volume': 0.5, 'beats': 2, 'seed': 0.640931695278254, 'id': 135} +block_add Drum False 839 465 False {'name': 'drum4kit', 'regularity': 0.1176562189553173, 'volume': 0.5, 'beats': 8, 'seed': 0.3968320964117491, 'id': 136} diff --git a/Resources/Desktops/desktop6 b/Resources/Desktops/desktop6 new file mode 100644 index 0000000..05ed65b --- /dev/null +++ b/Resources/Desktops/desktop6 @@ -0,0 +1,7 @@ +block_add Drum False 260 411 False {'name': 'drum5kit', 'regularity': 0.00099551426528621256, 'volume': 0.5, 'beats': 5, 'seed': 0.27840219088235596, 'id': 137} +block_add Drum False 353 360 False {'name': 'drum2kit', 'regularity': 0.31826067497762844, 'volume': 0.5, 'beats': 5, 'seed': 0.22627774476445939, 'id': 134} +block_add Drum False 461 507 False {'name': 'drum1kit', 'regularity': 0.24776068456325329, 'volume': 0.5, 'beats': 2, 'seed': 0.14699764155157424, 'id': 133} +block_add Drum False 548 397 False {'name': 'drum4kit', 'regularity': 0.78706580174700747, 'volume': 0.5, 'beats': 12, 'seed': 0.39682822879897905, 'id': 136} +block_add Drum False 732 394 False {'name': 'drum3kit', 'regularity': 0.9471817294630962, 'volume': 0.5, 'beats': 2, 'seed': 0.49021316200287002, 'id': 135} +block_add Drum False 856 500 False {'name': 'drum3kit', 'regularity': 0.29380418366786754, 'volume': 0.5, 'beats': 6, 'seed': 0.68783001902378305, 'id': 135} +block_add Drum False 642 296 False {'name': 'drum4kit', 'regularity': 0.33697457598218428, 'volume': 0.5, 'beats': 12, 'seed': 0.9520676955870041, 'id': 136} diff --git a/Resources/Desktops/desktop7 b/Resources/Desktops/desktop7 new file mode 100644 index 0000000..c38824f --- /dev/null +++ b/Resources/Desktops/desktop7 @@ -0,0 +1,8 @@ +block_add Drum False 273 376 False {'name': 'drum5kit', 'regularity': 0.14996288819410908, 'volume': 0.5, 'beats': 11, 'seed': 0.97865782454708972, 'id': 137} +block_add Drum False 430 437 False {'name': 'drum2kit', 'regularity': 0.22686486764388736, 'volume': 0.5, 'beats': 12, 'seed': 0.20156164102134011, 'id': 134} +block_add Drum False 587 476 False {'name': 'drum1kit', 'regularity': 0.5023786258393923, 'volume': 0.5, 'beats': 6, 'seed': 0.53584602645586388, 'id': 133} +block_add Drum False 631 311 False {'name': 'drum4kit', 'regularity': 0.63118726500905431, 'volume': 0.5, 'beats': 9, 'seed': 0.81751963172248665, 'id': 136} +block_add Drum False 769 529 False {'name': 'drum3kit', 'regularity': 0.16208618912427697, 'volume': 0.5, 'beats': 7, 'seed': 0.31378267309795727, 'id': 135} +block_add Drum False 439 259 False {'name': 'drum4kit', 'regularity': 0.065648010744176588, 'volume': 0.5, 'beats': 2, 'seed': 0.96047862380592997, 'id': 136} +block_add Drum False 494 345 False {'name': 'drum2kit', 'regularity': 0.59831266615900935, 'volume': 0.5, 'beats': 6, 'seed': 0.78044240161229295, 'id': 134} +block_add Drum False 276 232 False {'name': 'drum5kit', 'regularity': 0.1472993196679786, 'volume': 0.5, 'beats': 7, 'seed': 0.081751227986034847, 'id': 137} diff --git a/Resources/Desktops/desktop8 b/Resources/Desktops/desktop8 new file mode 100644 index 0000000..50772ef --- /dev/null +++ b/Resources/Desktops/desktop8 @@ -0,0 +1,9 @@ +block_add Drum False 194 311 False {'name': 'drum5kit', 'regularity': 0.086528345958863495, 'volume': 0.5, 'beats': 8, 'seed': 0.30475937412840726, 'id': 137} +block_add Drum False 345 274 False {'name': 'drum2kit', 'regularity': 0.89583779126715557, 'volume': 0.5, 'beats': 10, 'seed': 0.98185842149303015, 'id': 134} +block_add Drum False 486 323 False {'name': 'drum1kit', 'regularity': 0.023166532511794236, 'volume': 0.5, 'beats': 2, 'seed': 0.49717529146341177, 'id': 133} +block_add Drum False 567 124 False {'name': 'drum4kit', 'regularity': 0.2386146842020036, 'volume': 0.5, 'beats': 8, 'seed': 0.70995470197070898, 'id': 136} +block_add Drum False 603 330 False {'name': 'drum4kit', 'regularity': 0.18866579742299305, 'volume': 0.5, 'beats': 12, 'seed': 0.026020774927881907, 'id': 136} +block_add Drum False 504 437 False {'name': 'drum1kit', 'regularity': 0.9221379089954207, 'volume': 0.5, 'beats': 7, 'seed': 0.65776662628744698, 'id': 133} +block_add Drum False 815 400 False {'name': 'drum1kit', 'regularity': 0.56255856724700692, 'volume': 0.5, 'beats': 9, 'seed': 0.83950039804663834, 'id': 133} +block_add Drum False 741 547 False {'name': 'drum3kit', 'regularity': 0.15542009855247862, 'volume': 0.5, 'beats': 8, 'seed': 0.50941294313358909, 'id': 135} +block_add Drum False 620 446 False {'name': 'drum2kit', 'regularity': 0.19832159880741562, 'volume': 0.5, 'beats': 8, 'seed': 0.90486534173232447, 'id': 134} diff --git a/Resources/Desktops/desktop9 b/Resources/Desktops/desktop9 new file mode 100644 index 0000000..eb0367d --- /dev/null +++ b/Resources/Desktops/desktop9 @@ -0,0 +1,10 @@ +block_add Drum False 387 448 False {'name': 'drum5kit', 'regularity': 0.46533609055143399, 'volume': 0.5, 'beats': 10, 'seed': 0.5268677064825078, 'id': 137} +block_add Drum False 471 387 False {'name': 'drum2kit', 'regularity': 0.99977743388869933, 'volume': 0.5, 'beats': 3, 'seed': 0.83316131695736351, 'id': 134} +block_add Drum False 582 520 False {'name': 'drum1kit', 'regularity': 0.16832481238745933, 'volume': 0.5, 'beats': 5, 'seed': 0.53670066220388379, 'id': 133} +block_add Drum False 621 335 False {'name': 'drum4kit', 'regularity': 0.81846644469923291, 'volume': 0.5, 'beats': 4, 'seed': 0.33583725098298478, 'id': 136} +block_add Drum False 763 456 False {'name': 'drum3kit', 'regularity': 0.24166263102033714, 'volume': 0.5, 'beats': 2, 'seed': 0.44193114642028852, 'id': 135} +block_add Drum False 590 183 False {'name': 'drum4kit', 'regularity': 0.95065092402626417, 'volume': 0.5, 'beats': 2, 'seed': 0.59560637194277388, 'id': 136} +block_add Drum False 208 259 False {'name': 'drum1kit', 'regularity': 0.54878672652226335, 'volume': 0.5, 'beats': 3, 'seed': 0.64042203865497094, 'id': 133} +block_add Drum False 342 265 False {'name': 'drum5kit', 'regularity': 0.57022694452966061, 'volume': 0.5, 'beats': 10, 'seed': 0.17715880194748179, 'id': 137} +block_add Drum False 261 386 False {'name': 'drum2kit', 'regularity': 0.19510485939664513, 'volume': 0.5, 'beats': 10, 'seed': 0.61936224302968201, 'id': 134} +block_add Drum False 877 201 False {'name': 'drum1kit', 'regularity': 0.90346441146326784, 'volume': 0.5, 'beats': 4, 'seed': 0.69406727073158425, 'id': 133} diff --git a/Resources/Loops/loop1.ttl b/Resources/Loops/loop1.ttl index 5c988f3..97bb9a6 100644 --- a/Resources/Loops/loop1.ttl +++ b/Resources/Loops/loop1.ttl @@ -3,7 +3,3 @@ note_add 92 2 0 0 29 0.75 0.5 24 0 88 0.005 0.098 0.1 0 1000 0 edit note_add 93 2 0 24 44 0.75 0.5 7 0 88 0.005 0.098 0.1 0 1000 0 edit note_add 94 2 0 36 44 0.75 0.5 6 0 88 0.005 0.098 0.1 0 1000 0 edit note_add 95 2 0 48 32 0.75 0.5 24 0 88 0.005 0.098 0.1 0 1000 0 edit -tune_set 2 -track_vol 50 50 50 50 50 -master_vol 50 -tempo 100 diff --git a/Resources/Loops/loop2.ttl b/Resources/Loops/loop2.ttl index 872d4fa..2e5e7ea 100644 --- a/Resources/Loops/loop2.ttl +++ b/Resources/Loops/loop2.ttl @@ -42,7 +42,3 @@ note_add 112 16 0 8 36 0.75 0.5 1 0 88 0.005 0.098 0.1 0 1000 0 edit note_add 113 16 0 9 34 0.75 0.5 1 0 88 0.005 0.098 0.1 0 1000 0 edit note_add 114 16 0 10 36 0.75 0.5 1 0 88 0.005 0.098 0.1 0 1000 0 edit note_add 115 16 0 11 34 0.75 0.5 1 0 88 0.005 0.098 0.1 0 1000 0 edit -tune_set 16 -track_vol 50 50 50 50 50 -master_vol 50 -tempo 75 diff --git a/Resources/Loops/loop3.ttl b/Resources/Loops/loop3.ttl index f749fb6..4b6bdd6 100644 --- a/Resources/Loops/loop3.ttl +++ b/Resources/Loops/loop3.ttl @@ -7,7 +7,3 @@ note_add 120 16 0 12 24 0.75 0.5 3 0 88 0.005 0.098 0.1 0 1000 0 edit note_add 121 16 0 15 24 0.75 0.5 3 0 88 0.005 0.098 0.1 0 1000 0 edit note_add 122 16 0 18 38 0.75 0.5 3 0 88 0.005 0.098 0.1 0 1000 0 edit note_add 123 16 0 21 45 0.75 0.5 3 0 88 0.005 0.098 0.1 0 1000 0 edit -tune_set 16 -track_vol 50 50 50 50 50 -master_vol 50 -tempo 75 diff --git a/TamTam.py b/TamTam.py index 3119f28..ac4a8dd 100755 --- a/TamTam.py +++ b/TamTam.py @@ -134,6 +134,7 @@ class TamTam(Activity): if mode == 'jam': if not (mode in self.modeList): + self.metadata['title'] = 'TamTam Jam' self.modeList[mode] = JamMain(self, self.set_mode) self.mode = mode @@ -259,7 +260,9 @@ class TamTam(Activity): def read_file(self,file_path): subactivity_name = self.metadata['tamtam_subactivity'] - if subactivity_name == 'edit' or subactivity_name == 'synth': + if subactivity_name == 'edit' \ + or subactivity_name == 'synth' \ + or subactivity_name == 'jam': self.set_mode(subactivity_name) self.modeList[subactivity_name].handleJournalLoad(file_path) elif subactivity_name == 'mini': @@ -271,14 +274,17 @@ class TamTam(Activity): if self.mode == 'edit': self.metadata['tamtam_subactivity'] = self.mode self.modeList[self.mode].handleJournalSave(file_path) - if self.mode == 'synth': + elif self.mode == 'synth': self.metadata['tamtam_subactivity'] = self.mode self.modeList[self.mode].handleJournalSave(file_path) - if self.mode == 'mini': + elif self.mode == 'mini': self.metadata['tamtam_subactivity'] = self.mode f = open(file_path,'w') f.close() - + elif self.mode == 'jam': + self.metadata['tamtam_subactivity'] = self.mode + self.modeList[self.mode].handleJournalSave(file_path) + if __name__ == "__main__": if len(sys.argv) > 1 : diff --git a/Util/ControlStream.py b/Util/ControlStream.py index bc58b7a..e76c19b 100644 --- a/Util/ControlStream.py +++ b/Util/ControlStream.py @@ -4,6 +4,8 @@ import time import Config +import os + from Util import NoteDB from Util.CSoundNote import CSoundNote from Util.CSoundClient import new_csound_client @@ -39,11 +41,6 @@ class TamTamOStream: self.file.write( " ".join([str(i) for i in l])) self.file.write('\n') - def tune_set(self, tune): - self.file.write('tune_set ') - self.file.write(" ".join([str(t) for t in tune])) - self.file.write('\n') - def track_vol(self, vols): self.file.write('track_vol ') self.file.write(" ".join([str(t) for t in vols])) @@ -59,13 +56,30 @@ class TamTamOStream: self.file.write(str(tempo)) self.file.write('\n') - def block_add( self, typeStr, x, y, child, data ): - l = [ "block_add", typeStr, str(x), str(y), str(child), str(data) ] + def block_add( self, typeStr, active, centerX, centerY, child, data ): + l = [ "block_add", typeStr, str(active), str(centerX), str(centerY), str(child), str(data) ] + self.file.write( " ".join([str(i) for i in l])) + self.file.write('\n') + + def desktop_store( self, filename, id ): + self.file.write( "desktop_store %d\n" % id ) + try: + file = open( filename, "r" ) + for line in file: + self.file.write( line ) + file.close() + except: + if Config.DEBUG > 3: print "ERROR:: desktop_store could not open file: " + filename + self.file.write( "desktop_store END\n" ) + + def desktop_set( self, id ): + self.file.write( "desktop_set %d\n" % id ) class TamTamTable: - def __init__(self, noteDB): + def __init__(self, noteDB = None, jam = None ): self.noteDB = noteDB + self.jam = jam self.csnd = new_csound_client() self.pid = {} #stream_pid : local_pid @@ -78,17 +92,16 @@ class TamTamTable: 'track_vol':self.track_vol, 'master_vol':self.master_vol, 'tempo':self.tempo, - 'tune_set':self.tune_set, 'block_add':self.block_add, + 'desktop_store':self.desktop_store, + 'desktop_set':self.desktop_set, 'sleep':self.sleep, 'quit':self.quit} def parseFile(self, ifile): table = self.parseTable() - while True: - l = ifile.readline() - if l == '\n': break - if l == '': break + self.file = ifile + for l in self.file: cmdlist = l.split() if len(cmdlist) > 0: if cmdlist[0] not in table: @@ -151,29 +164,49 @@ class TamTamTable: def tempo(self, argv): self.tempo = argv[0] - def tune_set(self, argv): - if Config.DEBUG > 3: print 'tune_set', argv - - if Config.DEBUG > 3: print 'ERROR: tune_set is not handled properly by mainwindow yet... skipping\n' - return - - self.noteDB.tune = [int(i) for i in argv] - pids = self.noteDB.pages.keys() - pids_to_del = [pid for pid in self.noteDB.pages.keys() - if pid not in self.noteDB.tune] - self.noteDB.deletePages( pids_to_del ) - def block_add( self, argv ): - print "----------", argv - type = Block.StrToClass[argv[0]] - x = int( argv[1] ) - y = int( argv[2] ) - child = bool( argv[3] ) + blockClass = Block.StrToClass[argv[0]] + active = eval( argv[1] ) + x = int( argv[2] ) + y = int( argv[3] ) + child = eval( argv[4] ) data = "" - for str in argv[4:]: + for str in argv[5:]: data += str data = eval( data ) - self.desktop.addBlock( cls, data, ( x, y ) ) + + if blockClass == Block.Loop: + data["id"] = self.pid[ data["id"] ] + self.jam.updateLoopImage( data["id"] ) + + if child: + block = blockClass( self.jam.getDesktop(), data ) + self.lastBlock.addChild( block ) + else: + block = self.jam.getDesktop().addBlock( blockClass, data, ( x, y ) ) + + if blockClass == Block.Instrument and active: + self.jam.getDesktop().activateInstrument( block ) + + self.lastBlock = block + + def desktop_store( self, argv ): + filename = self.jam.getDesktopScratchFile( int( argv[0] ) ) + #try: + if os.path.isfile( filename ): + os.remove( filename ) + + file = open( filename, "w" ) + for line in self.file: + if line == "desktop_store END\n": + break + file.write( line ) + file.close + #except: + # if Config.DEBUG > 3: print "ERROR:: desktop_store could not open file: " + filename + + def desktop_set( self, argv ): + self.jam.setDesktop( int( argv[0] ) ) def sleep(self, argv): t = float(argv[0]) diff --git a/Util/NoteDB.py b/Util/NoteDB.py index 0b6c6b9..cd8d1ca 100644 --- a/Util/NoteDB.py +++ b/Util/NoteDB.py @@ -34,7 +34,7 @@ class Note: self.cs = self.csStack.pop() class Page: - def __init__( self, beats, color = 0, instruments = False ): # , tempo, insruments, color = 0 ): + def __init__( self, beats, color = 0, instruments = False, local = True ): # , tempo, insruments, color = 0 ): self.beats = beats self.ticks = beats*Config.TICKS_PER_BEAT @@ -45,6 +45,8 @@ class Page: else: self.instruments = instruments[:] + self.local = local # page local/global? + self.nextNoteId = 0 # first note will be 1 def genId( self ): @@ -106,14 +108,12 @@ class NoteDB: self.clipboard = [] # stores copied cs notes self.clipboardArea = [] # stores the limits and tracks for each page in the clipboard - def dumpToStream(self, ostream): + def dumpToStream( self, ostream, localOnly = False ): for pid in self.tune: - ostream.page_add(pid, self.pages[pid]) - for pid in self.noteD: - for tid in xrange( len( self.noteD[pid])): - for nid in self.noteD[pid][tid]: - ostream.note_add(self.noteD[pid][tid][nid]) - ostream.tune_set(self.tune) + if not localOnly or self.pages[pid].local: + ostream.page_add(pid, self.pages[pid]) + for note in self.getNotesByPage( pid ): + ostream.note_add( note ) #-- private -------------------------------------------- def _genId( self ): -- cgit v0.9.1