#/* --------------------------- supercollider.py ----------------------------------- */ #/* ;; Kjetil S. Matheussen, 2004. */ #/* */ #/* This program is free software; you can redistribute it and/or */ #/* modify it under the terms of the GNU General Public License */ #/* as published by the Free Software Foundation; either version 2 */ #/* of the License, or (at your option) any later version. */ #/* */ #/* This program is distributed in the hope that it will be useful, */ #/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ #/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ #/* GNU General Public License for more details. */ #/* */ #/* You should have received a copy of the GNU General Public License */ #/* along with this program; if not, write to the Free Software */ #/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #/* */ #/* ---------------------------------------------------------------------------- */ # This file is far from complete, but its a start. # # All variables, classes and methods that are implemented in this file are # tested, and should work. # # It would be easy to read the Supercollider server command reference, and just # implement the missing methods and classes blindly. But I don't want to. When the # implementation is so straight forward as here, its better to it properly. # # So if you need more functionality, you can either just read the Supercollider # server command reference manual and implement the functionality directly # in this file (and send me the changes afterwards!), or send me some python # code you want to make work with this module, and I'll try to # implement it for you. # # Serious missing functionality: Have no way to get reply from server. Have to # find a more advanced OSC implementation than OSC.py 1.2 by Stefan Kersten used now. # # -Kjetil. import OSC,tempfile,xreadlines,os,time,types standardip="127.0.0.1" standardport=57110 startnode=1001; startbuffer=0; sc_head=0 sc_tail=1 sc_before=2 sc_after=3 sc_replace=4 class Server: def __init__(self,magic,ip=standardip,port=standardport): if magic!=1234: print "Server.__init__: Are you sure you know what you are doing?" print "Seems like you probably wanted to use the 'localServer' variable." if ip!=standardip: print "Warning. Ip only supprted for evalSynth (but not tested)." self.ip=ip self.port=port self.freenode=startnode; self.freebuffer=startbuffer; def sendMsg(self,command,*args): def floatToInt(x): if type(x)==types.FloatType: return int(x) else: return x OSC.Message(command,map(floatToInt,args)).sendlocal(self.port) def sendgetMsg(self,command,*args): apply(self.sendMsg,[command]+list(args)) # Simulated (and most probably extremely unaccurate) time used to get a reply. Use with care. time.sleep(1) def dumpOSC(self,code): self.sendMsg("dumpOSC",code); def nextNodeID(self): self.freenode+=1; return self.freenode-1 def nextBufferID(self): self.freebuffer+=1; return self.freebuffer-1; def loadSynthDef(self,name): self.sendgetMsg("/d_load",name) def loadSynthDefDir(self,dir): self.sendMsg("/d_loadDir",dir) def evalSynth(self,synthname): tmpname=tempfile.mktemp(".sc") outfile=open(tmpname,"w") outfile.write('SynthDef("'+synthname+'",{') for line in xreadlines.xreadlines(open(synthname+".sc","r")): outfile.write(line) outfile.write('}).send(Server.new(\localhost,NetAddr("'+self.ip+'",'+str(self.port)+')););\n') outfile.close() os.system("sclang "+tmpname) os.system("rm "+tmpname) localServer=Server(1234) class Node: def __del__(self): self.server.sendMsg("/n_free",self.id) def set(self,*args): apply(self.server.sendMsg,["/n_set",self.id]+list(args)) class Synth(Node): global localServer def __init__(self,name,args=[],position=sc_tail,server=localServer): self.server=server self.id=server.nextNodeID() apply(self.server.sendMsg,["/s_new",name,self.id,position,0]+args) class BufferSuper: def __init__(self,server,numFrames=0,numChannels=1,filename="",startFrame=0): self.server=server self.id=server.nextBufferID() if numChannels==-1: server.sendMsg("/b_allocRead",self.id,filename,startFrame,numFrames,0) else: server.sendMsg("/b_alloc",self.id,numFrames,numChannels,0) def __del__(self): self.server.sendMsg("/b_free",self.id) class Buffer(BufferSuper): def __init__(self,numFrames,numChannels=1,server=localServer): BufferSuper.__init__(self,server,numFrames,numChannels) class BufferRead(BufferSuper): def __init__(self,filename,startFrame=0,numFrames=0,server=localServer): BufferSuper.__init__(self,server,numFrames,-1,filename,startFrame)