aboutsummaryrefslogtreecommitdiff
path: root/python/supercollider.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/supercollider.py')
-rw-r--r--python/supercollider.py142
1 files changed, 142 insertions, 0 deletions
diff --git a/python/supercollider.py b/python/supercollider.py
new file mode 100644
index 0000000..88dbaf4
--- /dev/null
+++ b/python/supercollider.py
@@ -0,0 +1,142 @@
+
+#/* --------------------------- 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)
+
+