Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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", [])