diff --git a/stream.py b/stream.py index bd86e9c..96223a6 100755 --- a/stream.py +++ b/stream.py @@ -15,18 +15,56 @@ from Queue import Queue from twisted.internet.task import LoopingCall import fcntl -STREAM_CMD="""tools/gsmdecode|ffmpeg -ar 8000 -ac 1 -f s16le -i /dev/stdin http://127.0.0.1:8090/feed.ffm""" +from twisted.internet.protocol import ProcessProtocol -silence_frame = open("sounds/silence-gsm.gsm", "rb").read() +class StreamingProtocol(ProcessProtocol): + + _silenceFrame = open("sounds/silence-gsm.gsm", "rb").read() + + def __init__(self): + self._frames = Queue() + self._streamTimer = LoopingCall.withCount(self.sendStreamFrame) + + def connectionMade(self): + log.msg("Streaming process started") + self._streamTimer.start(0.20) + + def inConnectionLost(self): + log.msg("connection lost") + self._streamTimer.stop() + + def processExited(self, status): + log.msg("Streaming process exited (%s)" % str(status)) + + def sendStreamFrame(self, count): + for i in range(count): + if self._frames.empty(): + frames = self._silenceFrame + else: + frames = self._frames.get_nowait() + self.transport.write(frames) + + def feed(self, frame): + self._frames.put_nowait(frame) + + def eof(self): + self.transport.closeStdin() + + +STREAM_CMD="""tools/gsmstream.sh""" class FRNStream(FRNClient): def __init__(self): - self._frames = Queue() - self._stream = subprocess.Popen(STREAM_CMD, shell=True, - stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - self._streamtimer = LoopingCall.withCount(self.sendStreamFrame) - self._streamtimer.start(0.20) + self._stream = StreamingProtocol() + + def connectionMade(self): + FRNClient.connectionMade(self) + reactor.spawnProcess(self._stream, "bash", ["bash", "-c", STREAM_CMD], os.environ) + + def connectionLost(self, reason): + FRNClient.connectionLost(self, reason) + self._stream.eof() def getClientName(self, client_id): if self.clientsById.has_key(client_id): @@ -35,20 +73,9 @@ class FRNStream(FRNClient): return client_id def audioFrameReceived(self, from_id, frames): - self._frames.put_nowait(frames) + self._stream.feed(frames) self.pong() - def sendStreamFrame(self, count): - for i in range(count): - if self._frames.empty(): - frames = silence_frame - else: - frames = self._frames.get_nowait() - self._stream.stdin.write(frames) - self._stream.stdin.flush() - self._stream.stdout.flush() - self._stream.stderr.flush() - def loginResponse(self, info): log.msg("Login: %s" % info['al']) diff --git a/tools/dummystream.sh b/tools/dummystream.sh new file mode 100755 index 0000000..453671d --- /dev/null +++ b/tools/dummystream.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +logfile=/tmp/stream.log +echo -n "START " >> $logfile +date >> $logfile +cat > /tmp/stream.gsm +echo -n "STOP " >> $logfile +date >> $logfile diff --git a/tools/gsmstream.sh b/tools/gsmstream.sh new file mode 100755 index 0000000..492c19b --- /dev/null +++ b/tools/gsmstream.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +./tools/gsmdecode | ffmpeg -ar 8000 -ac 1 -f s16le -i /dev/stdin http://127.0.0.1:8090/feed.ffm diff --git a/twisted/plugins/frncrosslink.py b/twisted/plugins/frncrosslink.py index 9dc8cf9..997e2c3 100755 --- a/twisted/plugins/frncrosslink.py +++ b/twisted/plugins/frncrosslink.py @@ -59,7 +59,7 @@ class FRNCrosslinkClient(FRNClient): cl.append(" %s%s %s " % ( cType.get(c['bc'], 'G'), ss, - c['on'], + c['on'].replace('<', '<'), )) sm = [cl[i*15:(i+1)*15] for i in range((len(cl)+14)/15)]