Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/CsoundAPI.py
diff options
context:
space:
mode:
Diffstat (limited to 'CsoundAPI.py')
-rw-r--r--CsoundAPI.py614
1 files changed, 614 insertions, 0 deletions
diff --git a/CsoundAPI.py b/CsoundAPI.py
new file mode 100644
index 0000000..018950a
--- /dev/null
+++ b/CsoundAPI.py
@@ -0,0 +1,614 @@
+##################################################
+# CsoundAPI.py
+#
+# Jeremy Flores, flores1@mit.edu
+# last modified 01/29/08
+
+import socket
+import threading
+import select
+import os
+import thread
+#import curses
+from time import sleep
+
+from codes import * # where we store values for the message codes (i.e. CONNECTED=1, etc.)
+
+import gobject
+
+IO_MASKS = gobject.IO_IN | gobject.IO_PRI | gobject.IO_ERR | gobject.IO_HUP
+
+waiton_endflg = 0
+
+class CsoundAPI(threading.Thread):
+
+ def __init__(self, address='localhost', port=7000, is_gtk=True, timeout=5, error_callback = None):
+ super(CsoundAPI, self).__init__()
+ self._deactivate = False
+ self._is_gtk = is_gtk # if it's going to be used in PyGTK, set this to True. If used from a terminal, set to False (to specify the thread type)
+ self._error_callback = error_callback
+ if str(address) != address:
+ print "Error: address must be a string"
+ return False
+ if int(port) != port:
+ print "Error: port must be an integer value"
+ return False
+ self._address = address
+ self._port = port
+ self._message_queue = [] # an ordered list of messages that we expect and the corresponding callbacks that will handle them when they arrive
+
+# HOST = '18.85.18.29' # The remote host
+# PORT = 42000 # The same port as used by the server
+
+# self.scratchSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+# self.scratchSock.connect((HOST, PORT))
+
+ self._connect(timeout)
+ self._waiton_endflg = 0
+
+ def _connect(self, timeout):
+ print "Connecting to Csound..."
+ self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self._socket.settimeout(timeout)
+ self._socket.connect( (self._address, self._port) )
+ self._isConnected = True
+ if self._is_gtk == True:
+ gobject.io_add_watch(self._socket, IO_MASKS, self.gtk_run) # this will monitor self._socket for inputs in a separate thread
+ else:
+ self.start() # this will call self.start() in a separate thread
+
+ def gtk_run(self, socket, condition):
+ data = ''
+ try:
+ data = socket.recv(8)
+ if data != None:
+ if len(data) != 0:
+ self._parseReceived(data)
+ else:
+ print "**Csound server failed... disconnecting1"
+ if self._error_callback != None:
+ if self._deactivate == False:
+ print "recover callback()"
+ self._error_callback()
+ else:
+ print "ignore recover callback()"
+ self._isConnected = False
+ socket.close()
+ else:
+ print "**Csound server failed... disconnecting2"
+ if self._error_callback != None:
+ if self._deactivate == False:
+ print "recover callback()"
+ self._error_callback()
+ else:
+ print "ignore recover callback()"
+ self._isConnected = False
+ socket.close()
+ except:
+ pass
+ return self._isConnected
+
+
+ def run(self):
+ data = ''
+ while self._isConnected == True:
+ try:
+ data = self._socket.recv(8)
+ if data != None:
+ if len(data) != 0:
+ self._parseReceived(data)
+ else:
+ print "**Csound server failed... disconnecting1"
+ self._isConnected = False
+ self._socket.close()
+ else:
+ print "**Csound server failed... disconnecting2"
+ self._isConnected = False
+ self._socket.close()
+ except:
+ pass
+
+ def _parseReceived(self, buffer):
+ recv_code = int(buffer[0:2])
+ size = int(buffer[3:8])
+
+ callback = self._error_callback # if we receive something from CS and our message queue doesn't know how to handle it, send the data to the error_callback fcn.
+
+ for message in self._message_queue: # for each message in our message queue
+ code = message[0] # look up the code for this particular message
+ if code == recv_code: # if the type received matches the code recorded in our message
+ callback = message[1] # redefine our callback from the default error_callback to the one recorded in our message
+ if code != BUFTIMER and code != P2TIMER and code != UL_BEAT: # if not registered
+ print code,callback
+ self._message_queue.remove(message) # delete the message from our queue
+ break # break the loop since we found the first message that corresponds to the received type
+
+ try:
+ data = self._socket.recv(size)
+# print 'Received data:',data
+
+ if data != None:
+ if callback != None: # if the callback has been registered
+ callback(data) # execute the function that callback points to, passing to it the information contained in data
+ if len(data) == 0:
+ print "**Csound server failed... disconnecting3"
+ self._isConnected = False
+ self._socket.close()
+ else:
+ print "**Csound server failed... disconnecting4"
+ self._isConnected = False
+ self._socket.close()
+ except:
+ pass
+
+ def newInstance(self):
+ self._sendString("%2d %5d" %(NEW_INST, 0))
+
+ def setOrcName(self, str):
+ self._sendString("%2d %5d" %(ORCFIL, len(str)))
+ self._sendString(str)
+
+ def setScoName(self, str):
+ self._sendString("%2d %5d" %(SCOFIL, len(str)))
+ self._sendString(str)
+
+ def setMidiName(self, str):
+ self._sendString("%2d %5d" %(MIDFIL, len(str)))
+ self._sendString(str)
+
+ def sendOrcStr(self, str):
+ self._sendString("%2d %5d" %(ORCSTR, len(str)))
+ self._sendString(str)
+
+ def sendScoStr(self, str):
+ self._sendString("%2d %5d" %(SCOSTR, len(str)))
+ self._sendString(str)
+
+ def setAlias(self, alias, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_ALIAS, len(alias)))
+ self._sendString(alias)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def getAlias(self, str, callback):
+ self._sendString("%2d %5d" %(GET_ALIAS, len(str)))
+ self._sendString(str)
+ self._message_queue.append([GET_ALIAS, callback])
+
+ def setVolume(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_VOLUME, len(str_val)))
+ self._sendString(str_val)
+
+ def getVolume(self, callback):
+ self._sendString("%2d %5d" %(GET_VOLUME, 0))
+ self._message_queue.append([GET_VOLUME, callback])
+
+ def setMasterVolume(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_MAS_VOL, len(str_val)))
+ self._sendString(str_val)
+
+ def getMasterVolume(self, callback):
+ self._sendString("%2d %5d" %(GET_MAS_VOL, 0))
+ self._message_queue.append([GET_MAS_VOL, callback])
+
+ def setTempo(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_TEMPO, len(str_val)))
+ self._sendString(str_val)
+
+ def getTempo(self, callback):
+ self._sendString("%2d %5d" %(GET_TEMPO, 0))
+ self._message_queue.append([GET_TEMPO, callback])
+
+ def setMidiSpeed(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_MIDISPEED, len(str_val)))
+ self._sendString(str_val)
+
+ def getMidiSpeed(self, callback):
+ self._sendString("%2d %5d" %(GET_MIDISPEED, 0))
+ self._message_queue.append([GET_MIDISPEED, callback])
+
+ def setMsgLevel(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_MSGLEVEL, len(str_val)))
+ self._sendString(str_val)
+
+ def getMsgLevel(self, callback):
+ self._sendString("%2d %5d" %(GET_MSGLEVEL, 0))
+ self._message_queue.append([GET_MSGLEVEL, callback])
+
+ def setDisplays(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_DISPLAYS, len(str_val)))
+ self._sendString(str_val)
+
+ def setGraphics(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_GRAPHICS, len(str_val)))
+ self._sendString(str_val)
+
+ def sendBeat(self):
+ self._sendString("%2d %5d" %(BEAT_EVT, 0))
+
+ def sendLinevt(self, str):
+ self._sendString("%2d %5d" %(LINE_EVT, len(str)))
+ self._sendString(str)
+
+ def sendClearLines(self):
+ self._sendString("%2d %5d" %(CLR_LINES, 0))
+
+ def setUploadBeat(self, val, callback):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(UL_BEAT, len(str_val)))
+ self._sendString(str_val)
+ self._message_queue.append([UL_BEAT, callback])
+
+
+
+
+ def sendSVOpen(self):
+ self._sendString("%2d %5d" %(SVOPEN, 0))
+
+ def setInsRemote(self, insno, IPadrs, instance):
+ str_val = str(insno)
+ self._sendString("%2d %5d" %(INSREMOTE, len(str_val)))
+ self._sendString(str_val)
+ self._sendString("%2d" %(len(IPadrs)))
+ self._sendString(IPadrs)
+ str_val = str(instance)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def setInsGlobal(self, insno, IPadrs, instance):
+ str_val = str(insno)
+ self._sendString("%2d %5d" %(INSGLOBAL, len(str_val)))
+ self._sendString(str_val)
+ self._sendString("%2d" %(len(IPadrs)))
+ self._sendString(IPadrs)
+ str_val = str(instance)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def setMidiRemote(self, chnum, IPadrs, instance):
+ str_val = str(chnum)
+ self._sendString("%2d %5d" %(MIDIREMOTE, len(str_val)))
+ self._sendString(str_val)
+ self._sendString("%2d" %(len(IPadrs)))
+ self._sendString(IPadrs)
+ str_val = str(instance)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def setMidiGlobal(self, chnum, IPadrs, instance):
+ str_val = str(chnum)
+ self._sendString("%2d %5d" %(MIDIGLOBAL, len(str_val)))
+ self._sendString(str_val)
+ self._sendString("%2d" %(len(IPadrs)))
+ self._sendString(IPadrs)
+ str_val = str(instance)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def setAudioRemoteSI(self, IPadrs):
+ self._sendString("%2d %5d" %(AUDREMOTE_SI, len(IPadrs)))
+ self._sendString(IPadrs)
+
+ def setAudioGlobalSI(self, IPadrs):
+ self._sendString("%2d %5d" %(AUDGLOBAL_SI, len(IPadrs)))
+ self._sendString(IPadrs)
+
+ def setAudioRemoteSO(self, IPadrs):
+ self._sendString("%2d %5d" %(AUDREMOTE_SO, len(IPadrs)))
+ self._sendString(IPadrs)
+
+ def setAudioGlobalSO(self, IPadrs):
+ self._sendString("%2d %5d" %(AUDGLOBAL_SO, len(IPadrs)))
+ self._sendString(IPadrs)
+
+ def setXtraScoreEvents(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_SCOREVT, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraMidiNoteOns(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_MIDINOTEON, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraMidiNoteOffs(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_MIDINOTEOFF, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraMidiEvents(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_MIDIEVT, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraMidiMessages(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_MIDIMSG, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraSysexMessages(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_SYSEXMSG, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraAudioBufsSI(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_AUDBUF_SI, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraAudioBufsSO(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_AUDBUF_SO, len(str_val)))
+ self._sendString(str_val)
+
+
+ def setNetStats(self, val1, val2):
+ str_val = str(val1)
+ self._sendString("%2d %5d" %(NET_STATS, len(str_val)))
+ self._sendString(str_val)
+ str_val = str(val2)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def sendPrintStats(self, str):
+ self._sendString("%2d %5d" %(PRINT_STATS, len(str)))
+ self._sendString(str)
+
+
+ def setIOBufFrames(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(IOBUFFRAMES, len(str_val)))
+ self._sendString(str_val)
+
+ def setBufTimer(self, val, callback):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(BUFTIMER, len(str_val)))
+ self._sendString(str_val)
+ self._message_queue.append([BUFTIMER, callback])
+
+ def setP2Timer(self, val, callback):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(P2TIMER, len(str_val)))
+ self._sendString(str_val)
+ self._message_queue.append([P2TIMER, callback])
+
+ def setOMaxLag(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(OMAXLAGG, len(str_val)))
+ self._sendString(str_val)
+
+ def setInName(self, str):
+ self._sendString("%2d %5d" %(INNAME, len(str)))
+ self._sendString(str)
+
+ def setOutName(self, str):
+ self._sendString("%2d %5d" %(OUTNAME, len(str)))
+ self._sendString(str)
+
+ def setIntAudio(self):
+ self._sendString("%2d %5d" %(INTAUDIO, 0))
+
+ def sendPrep(self):
+ self._sendString("%2d %5d" %(PREP, 0))
+
+ def sendPlay(self):
+ self._sendString("%2d %5d" %(PLAY, 0))
+
+ def sendPlayForTime(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(PLAY_FOR_TIME, len(str_val)))
+ self._sendString(str_val)
+
+ def sendPause(self):
+ self._sendString("%2d %5d" %(PAUSE, 0))
+
+ def sendResume(self):
+ self._sendString("%2d %5d" %(RESUME, 0))
+
+ def sendPlayAll(self):
+ self._sendString("%2d %5d" %(PLAYALL, 0))
+
+ def sendPlayAllForTime(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(PLAYALL_FOR_TIME, len(str_val)))
+ self._sendString(str_val)
+
+ def sendPauseAll(self):
+ self._sendString("%2d %5d" %(PAUSEALL, 0))
+
+ def sendResumeAll(self):
+ self._sendString("%2d %5d" %(RESUMEALL, 0))
+
+ def sendDeactivateWithCallback(self, callback):
+ self._sendString("%2d %5d" %(DEACTIVATE, 0))
+ self._message_queue.append([DEACTIVATE, callback])
+
+ def sendDeactivate(self):
+ self._sendString("%2d %5d" %(DEACTIVATE, 0))
+
+ def sendReactivateWithCallback(self, callback):
+ self._sendString("%2d %5d" %(REACTIVATE, 0))
+ self._message_queue.append([REACTIVATE, callback])
+
+ def sendReactivate(self):
+ self._sendString("%2d %5d" %(REACTIVATE, 0))
+
+ def sendRewind(self):
+ self._sendString("%2d %5d" %(REWIND1, 0))
+
+ def sendRewindAll(self):
+ self._sendString("%2d %5d" %(REWINDALL, 0))
+
+ def sendFastFwdForTime(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(FASTFWD_FOR_TIME, len(str_val)))
+ self._sendString(str_val)
+
+ def sendFastFwdToTime(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(FASTFWD_TO_TIME, len(str_val)))
+ self._sendString(str_val)
+
+ def sendEcho(self, callback):
+ print "send Echo"
+ self._sendString("%2d %5d" %(ECHO, 0))
+ self._message_queue.append([ECHO, callback])
+ print "return, caller will wait for the echo-back"
+
+ def sendDestroyWithCallback(self, callback):
+ print "send Destroy with callback"
+ self._sendString("%2d %5d" %(RELEASE_INST, 0))
+ self._message_queue.append([RELEASE_INST, callback])
+ print "return, caller will wait for the callback"
+
+ def sendDestroy(self): # this releases the Cs instance
+ print "send Destroy"
+ self._sendString("%2d %5d" %(RELEASE_INST, 0))
+ self._message_queue.append([RELEASE_INST, release_inst_callback])
+ global release_inst_callback_flag
+ release_inst_callback_flag = 1
+ print "sendDestroy() waiting for callback"
+ while release_inst_callback_flag == 1:
+ sleep(1)
+ print "callback caught, exit sendDestroy"
+
+ def setP2Timer(self, val, callback):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(P2TIMER, len(str_val)))
+ self._sendString(str_val)
+ self._message_queue.append([P2TIMER, callback])
+
+ def sendDisconnect(self): # this releases the CL struct & closes the socket
+ self._sendString("%2d %5d" %(CL_DISCONNECT, 0))
+
+ def serverCloseio(self): # just close the server current io
+ print "api.serverCloseio()"
+ self._sendString("%2d %5d" %(SV_CLOSEIO, 0))
+
+ def enterLineInputMode(self): #should be cleaned up to be threaded etc.
+ i = True
+ print "Line Input Mode"
+ print "type score lines, or type 'exit'"
+ while i:
+ strinput = raw_input("")
+ if (strinput == "exit"):
+ i = False
+ else:
+ self.sendLinevt(strinput);
+ print "end of Line Input mode"
+
+ def enterBeatInputMode(self): #should be cleaned up to be threaded etc.
+ stdscr = curses.initscr()
+# curses.start_color()
+ curses.noecho()
+ curses.cbreak()
+ stdscr.keypad(1)
+# curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
+# i = True
+# stdscr.addstr("Beat Input Mode\n", curses.color_pair(1))
+# stdscr.addstr("press any button to enter a beat,\n", curses.color_pair(1))
+# stdscr.addstr("or q to exit this mode\n", curses.color_pair(1))
+# stdscr.refresh()
+ while 1:
+ c = stdscr.getch()
+ if c == ord('q'):
+ break
+ else:
+ self.sendBeat();
+# stdscr.addstr("exited Beat Input mode\n", curses.color_pair(1))
+# stdscr.refresh()
+ curses.nocbreak(); stdscr.keypad(0); curses.echo()
+ curses.endwin()
+
+ def _sendString(self, string):
+ try:
+ self._socket.send(string)
+ except socket.error, e:
+ self._isConnected = False
+ self._socket.close()
+
+# def addScratchCallback(self, callback):
+# self.callback = callback
+
+ def close(self):
+ print "Disconnecting from Csound..."
+ self.sendDestroy() # this releases the CS object
+ if self._is_gtk == False:
+ self.sendDisconnect() # this closes the socket
+ self._isConnected = False
+ #should send a command to csound to shut down this socket
+ #self._socket.shutdown(SHUT_RDWR)
+ self._socket.close()
+
+ def waitonEnd(self):
+ self._sendString("%2d %5d" %(WAITON_END, 0))
+ self._message_queue.append([WAITON_END, endsignal])
+ global waiton_endflg
+ waiton_endflg = 1
+ print "setting waiton_endflg"
+ while waiton_endflg == 1:
+ sleep(3)
+ print "end signal caught, exit waitonEnd"
+
+ def serverShutdown(self): # release ALL structs, close ALL sockets & shutdown the Server
+ print "sending Server Shutdown"
+ self._sendString("%2d %5d" %(SV_SHUTDOWN, 0))
+# self._message_queue.append([SV_SHUTDOWN, "shutdown"])
+# self._message_queue.append([SV_SHUTDOWN, shutdownsignal])
+# global shutdown_endflg
+ self._isConnected = False
+ self._socket.close()
+
+ #should send a command to csound to shut down this socket
+# shutdown_endflg = 1
+# print "setting shutdown_endflg"
+# while shutdown_endflg == 1:
+# sleep(1)
+
+ def after_gtk_destroy(self):
+ print "CsoundAPI::after_gtk_destroy()"
+ self.sendDisconnect() # this closes the socket
+ self._isConnected = False
+ #should send a command to csound to shut down this socket
+ #self._socket.shutdown(SHUT_RDWR)
+ self._socket.close()
+
+ def mpClose(self):
+ print "CsoundAPI::mpClose()"
+ #self.sendDestroyWithCallback(self.destorysignal)
+ #3sleep(1)
+ #self.serverCloseio()
+ #sleep(1)
+ print "serverShutDown"
+ self.serverShutdown()
+ #self._isConnected = False
+ #self._socket.close()
+ #sleep(1)
+
+ def destorysignal(self):
+ print "got destroy callback"
+# self.serverShutdown()
+
+def release_inst_callback(self):
+ print "release inst callback received"
+ global release_inst_callback_flag
+ release_inst_callback_flag = 0
+
+def endsignal(self):
+ print "got endsignal"
+ print "clearing waiton_endflg"
+ global waiton_endflg
+ waiton_endflg = 0
+
+def shutdownsignal(self):
+ print "Cserver has shutdown"
+# global shutdown_endflg
+# shutdown_endflg = 0