Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Schampijer <simon@schampijer.de>2007-06-06 09:03:05 (GMT)
committer Simon Schampijer <simon@schampijer.de>2007-06-06 09:03:05 (GMT)
commit5e3d5a46272437afa59ce53aaef775695828f5e8 (patch)
tree71a46eea816b7a711af0c44164187413242988bb
parentcd2a572b9d2fbc53e03b8be96d7c6edc5a654bd6 (diff)
Moved the csound server to memosono
Added the csound server to memosono (used the osc protocol for the communication with the server), this is not optimal yet since other activities might want to use the sound server as well. Adopted memosono to communicate with the soundserver using osc.
-rw-r--r--csound/__init__.py0
-rw-r--r--csound/csoundserver.py106
-rw-r--r--csound/univorc.csd100
-rwxr-xr-xmemosono.py62
4 files changed, 232 insertions, 36 deletions
diff --git a/csound/__init__.py b/csound/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/csound/__init__.py
diff --git a/csound/csoundserver.py b/csound/csoundserver.py
new file mode 100644
index 0000000..c384300
--- /dev/null
+++ b/csound/csoundserver.py
@@ -0,0 +1,106 @@
+#! /usr/bin/env python
+
+import select
+import os
+import logging
+from threading import Thread
+
+import csnd
+from osc.oscapi import OscApi
+
+class CsoundServer(Thread):
+ CSOUND_PORT = 6783
+ MAX_PINGS = 3
+ TIMEOUT_PING = 10
+ def __init__(self):
+ Thread.__init__(self)
+ self.oscapi = OscApi(self.CSOUND_PORT)
+ self.oscapi.addmethod('/CSOUND/connect', '', self._connect)
+ self.oscapi.addmethod('/CSOUND/pong', '', self._pong)
+ self.oscapi.addmethod('/CSOUND/perform', 's', self._perform)
+ self.oscapi.addmethod('/CSOUND/disconnect', '', self._disconnect)
+ self.oscapi.addmethod('/CSOUND/quit', '', self._quit)
+ self.running = 1
+
+ self.clients = {}
+ self.start()
+
+ def run(self):
+ logging.info('start listening...')
+ self.csound = csnd.Csound()
+
+ while self.running:
+ inputready,outputready,exceptready = select.select([self.oscapi.iosock],[], [], self.TIMEOUT_PING)
+ for s in inputready:
+ if s == self.oscapi.iosock:
+ data, address = s.recvfrom(1024)
+ self.oscapi.handlemsg(data, address)
+ if len(inputready) == 0:
+ self.ping()
+
+ def ping(self):
+ rm = []
+ for client in self.clients:
+ if self.clients[client] == self.MAX_PINGS:
+ rm.append(client)
+ logging.debug('[ping] remove client %s'%str(client))
+ else:
+ self.oscapi.send(client, '/CSOUND/ping', [])
+ self.clients[client]+=1
+ ### print ' [ping] client=%s seq=%s'%(str(client), self.clients[client])
+
+ for elem in rm:
+ del self.clients[elem]
+ if len(self.clients) == 0:
+ self.perf.Stop()
+ self.perf.Join()
+ self.csound.Reset()
+ logging.debug('[csound] stop csound performance')
+
+
+ def _connect(self, *msg):
+ if msg[1] in self.clients:
+ logging.debug('[connect_cb] %s already connected'%str(msg[1]))
+ else:
+ self.clients[msg[1]]=0
+ logging.debug('[connect_cb] %s connected'%str(msg[1]))
+ if len(self.clients) == 1:
+ self.perf = csnd.CsoundPerformanceThread(self.csound)
+ uniorcpath = os.path.join( os.path.dirname(__file__), 'univorc.csd')
+ if not os.path.exists(uniorcpath):
+ logging.error('[csound] univorc not found %s'%uniorcpath)
+ self.csound.Compile(uniorcpath)
+ self.perf.Play()
+ logging.debug('[csound] start csound performance %s'%uniorcpath)
+
+
+ def _disconnect(self, *msg):
+ if msg[1] not in self.clients:
+ logging.debug('[disconnect_cb] %s not connected'%str(msg[1]))
+ else:
+ del self.clients[msg[1]]
+ logging.debug('[disconnect_cb] %s disconnected'%str(msg[1]))
+ if len(self.clients) == 0:
+ self.perf.Stop()
+ self.perf.Join()
+ self.csound.Reset()
+ logging.debug('[csound] stop csound performance')
+
+
+ def _quit(self, *msg):
+ logging.info('stop listening...')
+ self.running = 0
+ self.csound.Reset()
+ self.csound = None
+
+
+ def _pong(self, *msg):
+ self.clients[msg[1]]-=1
+ ### print ' [pong_cb] %s'%str(msg)
+
+
+ def _perform(self, *msg):
+ logging.debug(' [perform_cb] %s'%str(msg[0][2]))
+ self.perf.InputMessage(msg[0][2])
+
+
diff --git a/csound/univorc.csd b/csound/univorc.csd
new file mode 100644
index 0000000..e4264e9
--- /dev/null
+++ b/csound/univorc.csd
@@ -0,0 +1,100 @@
+<CsoundSynthesizer>
+<CsOptions>
+-+rtaudio=alsa -odac -m0 -d -b1024 -B4096
+</CsOptions>
+<CsInstruments>
+sr=22050
+ksmps=100
+nchnls=2
+
+gaudp1 init 0
+gaudp2 init 0
+
+
+/**************************************************************************
+ General Soundfile Player - Used by Memosono
+**************************************************************************/
+
+instr 108
+/* soundfile play control
+ p4 : filename
+ p5 : unique instance ID
+ p6 : output gain (0-1)
+ p7 : udp send gain (0-1)
+ p8 : offset in seconds
+
+ channels:
+ sfplay.<ID>.on - instance control channel (1:on 0: off)
+ sfplay.<ID>.gain - soundfile play gain (0-1)
+ sfplay.<ID>.udpgain - udp send gain (0-1)
+ sfplay.<ID>.flen - holds the channel length
+*/
+S1 strget p4
+inst = p5
+ich filenchnls S1
+iln filelen S1
+ioffset = p8
+
+Slen sprintf "sfplay.%d.flen", p5 ; file length channel
+chnset iln, Slen
+
+if ioffset >= iln then
+turnoff
+else
+iln = iln - ioffset
+endif
+
+Splay sprintf "sfplay.%d.on", inst ; instance control channel
+Sname sprintf "sfplay.%d.fname", inst ; filename channel
+Sgain sprintf "sfplay.%d.gain", inst ; gain channel
+Sudp sprintf "sfplay.%d.udpgain", inst ; udp gain channel
+chnset S1, Sname
+chnset 1, Splay
+chnset p6, Sgain
+chnset p7, Sudp
+event_i "i",109,0,iln,inst,ich,ioffset
+turnoff
+endin
+
+
+instr 109
+/* soundfile player
+ This is the actual soundfile player.
+ It never gets called directly
+*/
+ich = p5
+inst= p4
+ioffset = p6
+Splay sprintf "sfplay.%d.on", inst ; instance control channel
+Sname sprintf "sfplay.%d.fname", inst ; filename channel
+Sgain sprintf "sfplay.%d.gain", inst ; gain channel
+Sudp sprintf "sfplay.%d.udpgain", inst ; udp gain channel
+kon chnget Splay
+kg1 chnget Sgain
+kg2 chnget Sudp
+S1 chnget Sname
+if kon == 0 then
+printf "sfplay:%d OFF\n", 1, inst
+turnoff
+endif
+if ich = 1 then
+a1 diskin2 S1,1,ioffset,1
+a2 = a1
+else
+a1,a2 diskin2 S1,1,ioffset,1
+endif
+ outs a1*kg1, a2*kg1
+gaudp1 = a1*kg2 + gaudp1
+gaudp2 = a2*kg2 + gaudp2
+printf_i "sfplay:%d\n", 1, inst
+endin
+
+
+
+
+</CsInstruments>
+<CsScore>
+f0 600000
+
+</CsScore>
+</CsoundSynthesizer>
diff --git a/memosono.py b/memosono.py
index c91c4ce..9912590 100755
--- a/memosono.py
+++ b/memosono.py
@@ -31,7 +31,9 @@ import gc
from sugar.activity import activity
-from osc.oscapi import OscApi
+from osc.oscapi import OscApi
+from csound.csoundserver import CsoundServer
+
class Server:
def __init__(self, _MEMO, port):
@@ -146,7 +148,7 @@ class Controler(gobject.GObject):
def __init__(self, _MEMO, port):
gobject.GObject.__init__(self)
self._MEMO = _MEMO
- self.sound = 0
+ self.sound = 1
self.replyaddr = (('127.0.0.1', port))
self.serveraddr = (('127.0.0.1', port))
port+=1
@@ -166,6 +168,7 @@ class Controler(gobject.GObject):
self.oscapi.addmethod('/MEMO/tile', 'i', self._tile)
self.oscapi.addmethod('/MEMO/game/match', 'isiii', self._game_match)
self.oscapi.addmethod('/MEMO/game/next', 'ss', self._game_next)
+ self.oscapi.addmethod('/CSOUND/ping', '', self._ping)
self.block = 0
self.count = 0
@@ -174,26 +177,7 @@ class Controler(gobject.GObject):
self.id = 0 ##FIXME give a significant number
def csconnect(self):
- i = 0
- self.cssock = socket.socket()
- if self.cssock:
- while i < 3:
- try:
- self.cssock.connect(('127.0.0.1', 6783))
- logging.info(" Connected to csound server.")
- self.sound = 1
- i = 3
- except:
- logging.error(" Can not connect to csound server. Try again")
- time.sleep(1)
- i += 1
- if i == 3:
- self.cssock.close()
- logging.error(" There will be no sound for memosono.")
- #else:
- # mess = "csound.SetChannel('sfplay.%d.on', 1)\n" % self.id
- # self.cssock.send(mess)
-
+ self.oscapi.send(('127.0.0.1', 6783), "/CSOUND/connect", [])
def init_game(self, playername, numplayers, gamename):
self.emit('gameinit', playername, numplayers, gamename)
@@ -224,13 +208,12 @@ class Controler(gobject.GObject):
self.count+=1
if sound is not '-1':
- self.emit('tileflippedc', tile_number, pic, sound)
+ self.emit('tileflippedc', tile_number, pic, sound)
if self.sound is 1:
if os.path.exists(os.path.join(self._MEMO['_DIR_GSOUNDS'],sound)):
- mess = "perf.InputMessage('i 108 0 3 \"%s\" %s 0.7 0.5 0')\n"%(
- os.path.join(self._MEMO['_DIR_GSOUNDS'],sound),self.id)
- self.cssock.send(mess)
- logging.info(" Read file: "+os.path.join(self._MEMO['_DIR_GSOUNDS'],sound))
+ file = os.path.join(self._MEMO['_DIR_GSOUNDS'],sound)
+ self.oscapi.send(('127.0.0.1', 6783), '/CSOUND/perform', ['i 108 0.0 3.0 "%s" 1 0.7 0.5 0'%file])
+ logging.debug(" Read file: "+os.path.join(self._MEMO['_DIR_GSOUNDS'],sound))
else:
logging.error(" Can not read file: "+os.path.join(self._MEMO['_DIR_GSOUNDS'],sound))
@@ -282,6 +265,9 @@ class Controler(gobject.GObject):
self.emit('fliptile', int(msg[0][4]), requesttype, self.block)
self.emit('fliptile', int(msg[0][5]), requesttype, self.block)
+ def _ping(self, *msg):
+ self.oscapi.send(msg[1], '/CSOUND/pong', [])
+
class Model(gobject.GObject):
__gsignals__ = {
@@ -603,18 +589,22 @@ class MemosonoActivity(activity.Activity):
while(i < _MEMO['_NUM_GRIDPOINTS']):
self.view.buttonObj[i].connect('clicked', self.controler._user_input, i)
i+=1
-
+
+ ### start csound server
+ self.cs = CsoundServer()
+ gtk.gdk.threads_init()
+ self.controler.csconnect()
+
def _cleanup_cb(self, data=None):
- self.controler.oscapi.ioSocket.close()
- self.server.oscapi.ioSocket.close()
+ self.controler.oscapi.send(('127.0.0.1', 6783), "/CSOUND/quit", [])
+ self.controler.oscapi.iosock.close()
+ self.server.oscapi.iosock.close()
logging.debug(" Closed OSC sockets ")
- if self.controler.cssock is not None:
- self.controler.cssock.close()
-
+
def _focus_in(self, event, data=None):
logging.debug(" Memosono is visible: Connect to the Csound-Server. ")
- self.controler.csconnect()
+ self.controler.oscapi.send(('127.0.0.1', 6783), "/CSOUND/connect", [])
+
def _focus_out(self, event, data=None):
logging.debug(" Memosono is invisible: Close the connection to the Csound-Server. ")
- if self.controler.cssock is not None:
- self.controler.cssock.close()
+ self.controler.oscapi.send(('127.0.0.1', 6783), "/CSOUND/disconnect", [])