No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

stream.py 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
  5. # See LICENSE.txt for copyright info
  6. import subprocess
  7. from frn.protocol.client import FRNClient, FRNClientFactory
  8. from frn.user import FRNUser
  9. from twisted.internet import reactor, task
  10. from twisted.internet.defer import DeferredList
  11. from twisted.python import log
  12. import os, string
  13. from Queue import Queue
  14. from twisted.internet.task import LoopingCall
  15. import fcntl
  16. from twisted.internet.protocol import ProcessProtocol
  17. class StreamingProtocol(ProcessProtocol):
  18. _silenceFrame = open("sounds/silence-gsm.gsm", "rb").read()
  19. def __init__(self):
  20. self._frames = Queue()
  21. self._streamTimer = LoopingCall.withCount(self.sendStreamFrame)
  22. def connectionMade(self):
  23. log.msg("Streaming process started")
  24. self._streamTimer.start(0.20)
  25. def inConnectionLost(self):
  26. log.msg("connection lost")
  27. self._streamTimer.stop()
  28. def processExited(self, status):
  29. log.msg("Streaming process exited (%s)" % str(status))
  30. def sendStreamFrame(self, count):
  31. for i in range(count):
  32. if self._frames.empty():
  33. frames = self._silenceFrame
  34. else:
  35. frames = self._frames.get_nowait()
  36. self.transport.write(frames)
  37. def feed(self, frame):
  38. self._frames.put_nowait(frame)
  39. def eof(self):
  40. self.transport.closeStdin()
  41. STREAM_CMD="""tools/gsmstream.sh"""
  42. class FRNStream(FRNClient):
  43. def __init__(self):
  44. self._stream = StreamingProtocol()
  45. def connectionMade(self):
  46. FRNClient.connectionMade(self)
  47. reactor.spawnProcess(self._stream, "bash", ["bash", "-c", STREAM_CMD], os.environ)
  48. def connectionLost(self, reason):
  49. FRNClient.connectionLost(self, reason)
  50. self._stream.eof()
  51. def getClientName(self, client_id):
  52. if self.clientsById.has_key(client_id):
  53. return self.clientsById[client_id]['ON']
  54. else:
  55. return client_id
  56. def audioFrameReceived(self, from_id, frames):
  57. self._stream.feed(frames)
  58. self.pong()
  59. def loginResponse(self, info):
  60. log.msg("Login: %s" % info['AL'])
  61. def clientsListUpdated(self, clients):
  62. self.clients = clients
  63. self.clientsById = dict([(i['ID'], i) for i in clients])
  64. class FRNStreamFactory(FRNClientFactory):
  65. protocol = FRNStream
  66. reactor = reactor
  67. if __name__ == '__main__':
  68. import sys
  69. from os.path import dirname, join as pjoin
  70. from ConfigParser import ConfigParser
  71. log.startLogging(sys.stderr)
  72. basedir = dirname(__file__)
  73. acfg = ConfigParser()
  74. acfg.read(['/etc/grn/accounts.conf',
  75. pjoin(basedir,'accounts.conf'), 'accounts.conf'])
  76. scfg = ConfigParser()
  77. scfg.read(['/etc/grn/servers.conf',
  78. pjoin(basedir,'servers.conf'), 'servers.conf'])
  79. argc = len(sys.argv)
  80. if argc >= 3:
  81. server_name, network_name = sys.argv[2].split(':',1)
  82. account_cfg = acfg.items(sys.argv[1])+[('network', network_name)]
  83. server_cfg = scfg.items(server_name)
  84. server = scfg.get(server_name, 'server')
  85. port = scfg.getint(server_name, 'port')
  86. d = dict(account_cfg)
  87. user = FRNUser(
  88. EA=d['email'],
  89. PW=d['password'], ON=d['operator'],
  90. BC=d['transmission'], DS=d['description'],
  91. NN=d['country'], CT=d['city'], NT=d['network'])
  92. reactor.connectTCP(server, port, FRNStreamFactory(user))
  93. reactor.run()
  94. # vim: set et ai sw=4 ts=4 sts=4: