--- /dev/null
+import socket, struct
+import Events, Logger
+
+def osc_string(s) :
+ n = (len(s)+1)%4
+ if n : return s+'\0'*(5-n)
+ else : return s+'\0'
+
+
+def osc_command(url,*args):
+ tag=","
+ argstring=""
+ for arg in args :
+ if type(arg) is int:
+ tag += 'i'
+ argstring += struct.pack(">I",arg)
+ elif type(arg) is str:
+ tag += 's'
+ argstring += osc_string(arg)
+ elif type(arg) is float:
+ tag += 'f'
+ argstring += struct.pack(">f",arg)
+ else:
+ raise RunstimeError, "Invalid OSC argument"
+ return osc_string(url) + osc_string(tag) + argstring
+
+
+def osc_getstr(data):
+ i = data.index('\0')
+ s = data[:i]
+ n = (i+1)%4
+ if n : data = data[i+(5-n):]
+ else : data = data[i+1:]
+ return (s,data)
+
+
+def osc_parse(data):
+ url,data = osc_getstr(data)
+ tag,data = osc_getstr(data)
+ values = []
+ for code in tag[1:]:
+ if code == 'i':
+ values.append(struct.unpack(">i",data[:4])[0])
+ data = data[4:]
+ elif code == 's':
+ v,data = osc_getstr(data)
+ values.append(v)
+ elif code == 'f':
+ values.append(struct.unpack(">f",data[:4])[0])
+ data = data[4:]
+ else:
+ raise RuntimeError, "Unknown OSC parameter type received"
+ return (url, values)
+
+
+class OSCServer(Events.EventSource):
+
+ def __init__(self, addr, context):
+ Events.EventSource.__init__(self,
+ socket.socket(socket.AF_INET, socket.SOCK_DGRAM),
+ context)
+ self._addr = addr
+ self.fd().bind(addr)
+ self._handlers = {}
+
+ def registerHandler(self, addr, cb):
+ self._handlers[addr] = cb
+
+ def command(self, target, path, *args):
+ if args and type(args[0]) in (tuple, list) : args = args[0]
+ Logger.log('osc','osc://%s:%s%s %s'
+ % (target[0], target[1], path,
+ ' '.join(map(repr,args))))
+ self.fd().sendto(osc_command(path, *args),target)
+
+ def readEvents(self):
+ data, addr = self.fd().recvfrom(1024)
+ path, args = osc_parse(data)
+ Logger.log('oscrcv','osc://%s:%s%s %s' % (addr[0], addr[1], path,
+ ' '.join(map(repr,args))))
+ handler = self._handlers.get(addr)
+ if handler:
+ return handler(path, args)
+ else:
+ return []
+
+ def localUrl(self):
+ return 'osc://%s:%s' % self._addr