128 lines
3.5 KiB
Python
Executable File
128 lines
3.5 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
|
|
# See LICENSE.txt for copyright info
|
|
|
|
import subprocess
|
|
from frn.protocol.client import FRNClient, FRNClientFactory
|
|
from frn.user import FRNUser
|
|
from twisted.internet import reactor, task
|
|
from twisted.internet.defer import DeferredList
|
|
from twisted.python import log
|
|
import os, string
|
|
from Queue import Queue
|
|
from twisted.internet.task import LoopingCall
|
|
import fcntl
|
|
|
|
from twisted.internet.protocol import ProcessProtocol
|
|
|
|
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._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):
|
|
return self.clientsById[client_id]['ON']
|
|
else:
|
|
return client_id
|
|
|
|
def audioFrameReceived(self, from_id, frames):
|
|
self._stream.feed(frames)
|
|
self.pong()
|
|
|
|
def loginResponse(self, info):
|
|
log.msg("Login: %s" % info['AL'])
|
|
|
|
def clientsListUpdated(self, clients):
|
|
self.clients = clients
|
|
self.clientsById = dict([(i['ID'], i) for i in clients])
|
|
|
|
|
|
class FRNStreamFactory(FRNClientFactory):
|
|
protocol = FRNStream
|
|
reactor = reactor
|
|
|
|
|
|
if __name__ == '__main__':
|
|
import sys
|
|
from os.path import dirname, join as pjoin
|
|
from ConfigParser import ConfigParser
|
|
|
|
log.startLogging(sys.stderr)
|
|
|
|
basedir = dirname(__file__)
|
|
|
|
acfg = ConfigParser()
|
|
acfg.read(['/etc/grn/accounts.conf',
|
|
pjoin(basedir,'accounts.conf'), 'accounts.conf'])
|
|
|
|
scfg = ConfigParser()
|
|
scfg.read(['/etc/grn/servers.conf',
|
|
pjoin(basedir,'servers.conf'), 'servers.conf'])
|
|
|
|
argc = len(sys.argv)
|
|
if argc >= 3:
|
|
server_name, network_name = sys.argv[2].split(':',1)
|
|
account_cfg = acfg.items(sys.argv[1])+[('network', network_name)]
|
|
server_cfg = scfg.items(server_name)
|
|
server = scfg.get(server_name, 'server')
|
|
port = scfg.getint(server_name, 'port')
|
|
|
|
d = dict(account_cfg)
|
|
user = FRNUser(
|
|
EA=d['email'],
|
|
PW=d['password'], ON=d['operator'],
|
|
BC=d['transmission'], DS=d['description'],
|
|
NN=d['country'], CT=d['city'], NT=d['network'])
|
|
reactor.connectTCP(server, port, FRNStreamFactory(user))
|
|
reactor.run()
|
|
|
|
|
|
# vim: set et ai sw=4 ts=4 sts=4:
|