Python - Twisted and PyAudio + Chat
Question: I've been playing around with the Twisted extension and have fooled around
with a chat room sort of system. However I want to expand upon it. As of now
it only support multi-client chats with usernames ect. But I want to try and
use the pyAudio extension to build a sort of VoIP application. I have a
clientFactory and a simple echo protocol in the client and a serverFactory and
protocol on the server. but I'm not entirely sure how to build off of this.
What would be the best way to go about doing something like this?

Code to help if you need it client.py:

    
    
    import wx
    from twisted.internet import wxreactor
    wxreactor.install()
    
    # import twisted reactor
    import sys
    from twisted.internet import reactor, protocol, task
    from twisted.protocols import basic
    
    
    class ChatFrame(wx.Frame):
    
        def __init__(self):
            wx.Frame.__init__(self, parent=None, title="WhiteNOISE")
            self.protocol = None  # twisted Protocol
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            self.text = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY)
            self.ctrl = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER, size=(300, 25))
    
            sizer.Add(self.text, 5, wx.EXPAND)
            sizer.Add(self.ctrl, 0, wx.EXPAND)
            self.SetSizer(sizer)
            self.ctrl.Bind(wx.EVT_TEXT_ENTER, self.send)
    
    
        def send(self, evt):
            self.protocol.sendLine(str(self.ctrl.GetValue()))
            self.ctrl.SetValue("")
    
    
    class DataForwardingProtocol(basic.LineReceiver):
        def __init__(self):
            self.output = None
    
        def dataReceived(self, data):
            gui = self.factory.gui
    
            gui.protocol = self
            if gui:
                val = gui.text.GetValue()
                gui.text.SetValue(val + data)
                gui.text.SetInsertionPointEnd()
    
        def connectionMade(self):
            self.output = self.factory.gui.text  # redirect Twisted's output
    
    
    class ChatFactory(protocol.ClientFactory):
        def __init__(self, gui):
            self.gui = gui
            self.protocol = DataForwardingProtocol
    
        def clientConnectionLost(self, transport, reason):
            reactor.stop()
    
        def clientConnectionFailed(self, transport, reason):
            reactor.stop()
    
    
    if __name__ == '__main__':
        app = wx.App(False)
        frame = ChatFrame()
        frame.Show()
        reactor.registerWxApp(app)
        reactor.connectTCP("192.168.1.115", 5001, ChatFactory(frame))
        reactor.run()
    

server.py:

    
    
    from twisted.internet import reactor, protocol
    from twisted.protocols import basic
    import time
    
    def t():
        return "["+ time.strftime("%H:%M:%S") +"] "
    
    class EchoProtocol(basic.LineReceiver):
        name = "Unnamed"
    
        def connectionMade(self):
        #on client connection made
        self.sendLine("WhiteNOISE")
            self.sendLine("Enter A Username Below...")
            self.sendLine("")
            self.count = 0
            self.factory.clients.append(self)
            print t() + "+ Connection from: "+ self.transport.getPeer().host
    
        def connectionLost(self, reason):
        #on client connection lost
            self.sendMsg("- %s left." % self.name)
            print t() + "- Connection lost: "+ self.name
            self.factory.clients.remove(self)
    
        def lineReceived(self, line):
        #actions to do on message recive
            if line == '/quit':
        #close client connection
                self.sendLine("Goodbye.")
                self.transport.loseConnection()
                return
            elif line == "/userlist":
        #send user list to single client, the one who requested it
                self.chatters()
                return
        elif line.startswith("/me"):
        #send an action formatted message
            self.sendLine("**" + self.name + ": " + line.replace("/me",""))
            return
        elif line == "/?":
            self.sendLine("Commands: /? /me /userlist /quit")
            return
            if not self.count:
                self.username(line)
            else:
                self.sendMsg(self.name +": " + line)
    
        def username(self, line):
        #check if username already in use
            for x in self.factory.clients:
                if x.name == line:
                    self.sendLine("This username is taken; please choose another")
                    return
    
            self.name = line
            self.chatters()
            self.sendLine("You have been connected!")
            self.sendLine("")
            self.count += 1
            self.sendMsg("+ %s joined." % self.name)
            print '%s~ %s connected as: %s' % (t(), self.transport.getPeer().host, self.name)
    
        def chatters(self):
            x = len(self.factory.clients) - 1
            s = 'is' if x == 1 else 'are'
            p = 'person' if x == 1 else 'people'
            self.sendLine("There %s %i other %s connected:" % (s, x, p) )
    
            for client in self.factory.clients:
                if client is not self:
                    self.sendLine(client.name)
            self.sendLine("")
    
        def sendMsg(self, message):
        #send message to all clients
            for client in self.factory.clients:
                client.sendLine(t() + message)
    
    
    class EchoServerFactory(protocol.ServerFactory):
        protocol  = EchoProtocol
        clients = []
    
    if __name__ == "__main__":
        reactor.listenTCP(5001, EchoServerFactory())
        reactor.run()
    


Answer: Take a look at [Divmod Sine](http://bazaar.launchpad.net/~divmod-
dev/divmod.org/trunk/files/head:/Sine/), a SIP application server. The basic
idea is that you need an additional network server in your application that
will support the VoIP parts of the application.

