Package rats :: Module fudi
[hide private]
[frames] | no frames]

Source Code for Module rats.fudi

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  # 
  4  # The Purity library for Pure Data dynamic patching. 
  5  # 
  6  # Copyright 2009 Alexandre Quessy 
  7  # <alexandre@quessy.net> 
  8  # http://alexandre.quessy.net 
  9  # 
 10  # Purity is free software: you can redistribute it and/or modify 
 11  # it under the terms of the GNU General Public License as published by 
 12  # the Free Software Foundation, either version 3 of the License, or 
 13  # (at your option) any later version. 
 14  # 
 15  # Purity is distributed in the hope that it will be useful, 
 16  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 17  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 18  # GNU General Public License for more details. 
 19  # 
 20  # You should have received a copy of the gnu general public license 
 21  # along with Purity.  If not, see <http://www.gnu.org/licenses/>. 
 22  # 
 23  """ 
 24  FUDI protocol implementation in Python using Twisted. 
 25   
 26  Simple ASCII based protocol from Miller Puckette for Pure Data. 
 27  """ 
 28   
 29  import types 
 30   
 31  from twisted.internet import reactor 
 32  from twisted.internet.protocol import Protocol 
 33  from twisted.internet.protocol import ClientCreator 
 34  from twisted.internet.protocol import Factory 
 35  from twisted.internet.protocol import ClientFactory 
 36  from twisted.protocols import basic 
 37  from twisted.python import log 
 38   
 39  VERBOSE = False 
 40   
41 -def to_fudi(selector, *atoms):
42 """ 43 Converts int, float, string to FUDI atoms string. 44 :param data: list of basic types variables. 45 Public FUDI message converter 46 """ 47 # if VERBOSE: 48 # print "FUDI: to_fudi", selector, atoms 49 txt = str(selector) 50 for atom in atoms: 51 txt = txt + " %s" % (atom) 52 txt = txt + " ;\r\n" 53 return txt
54
55 -class FUDIProtocol(basic.LineReceiver):
56 """ 57 FUDI protocol implementation in Python. 58 59 Simple ASCII based protocol from Miller Puckette for Pure Data. 60 """ 61 #def connectionMade(self): 62 # print "connection made", self.transport# , self.factory 63 64 delimiter = ';' 65
66 - def lineReceived(self, data):
67 if VERBOSE: 68 print "FUDI: data:", data 69 try: 70 message = data.split(";")[0].strip() 71 except KeyError: 72 log.msg("Got a line without trailing semi-colon.") 73 else: 74 if VERBOSE: 75 print "FUDI: message:", message 76 atoms = message.split() 77 if len(atoms) > 0: 78 output = [] 79 selector = atoms[0] 80 for atom in atoms[1:]: 81 atom = atom.strip() 82 if VERBOSE: 83 print "FUDI: > atom:", atom 84 if atom.isdigit(): 85 output.append(int(atom)) 86 else: 87 try: 88 val = float(atom) 89 output.append(atom) 90 except ValueError: 91 output.append(str(atom)) 92 if self.factory.callbacks.has_key(selector): 93 if VERBOSE: 94 print "FUDI: Calling :", selector, output 95 try: 96 self.factory.callbacks[selector](self, *output) 97 except TypeError, e: 98 print "FUDI:lineReceived():", e.message 99 else: 100 #log.msg("Invalid selector %s." % (selector)) 101 print "FUDI: Invalid selector %s." % (selector)
102
103 - def send_message(self, selector, *atoms):
104 """ 105 Converts int, float, string to FUDI atoms and sends them. 106 :param data: list of basic types variables. 107 """ 108 if VERBOSE: 109 print "send_message", selector, atoms 110 txt = to_fudi(selector, *atoms) 111 if VERBOSE: 112 print "FUDI: sending", txt 113 self.transport.write(txt)
114
115 -class FUDIServerFactory(Factory):
116 """ 117 Factory for FUDI receivers. 118 119 You should attach FUDI message callbacks to an instance of this. 120 """ 121 protocol = FUDIProtocol
122 - def __init__(self):
123 self.callbacks = {}
124
125 - def register_message(self, selector, callback):
126 if type(callback) not in (types.FunctionType, types.MethodType): 127 raise TypeError("Callback '%s' is not callable" % repr(callback)) 128 self.callbacks[selector] = callback
129
130 -def create_FUDI_client(host, port, tcp=True):
131 """ 132 Creates a FUDI sender. 133 134 When connected, will call its callbacks with the sender instance. 135 :return: deferred instance 136 """ 137 if tcp: 138 deferred = ClientCreator(reactor, FUDIProtocol).connectTCP(host, port) 139 else: 140 deferred = ClientCreator(reactor, FUDIProtocol).connectUDP(host, port) 141 return deferred
142 143 if __name__ == "__main__": 144 VERBOSE = True 145
146 - def ping(protocol, *args):
147 print "received ping", args 148 reactor.stop()
149
150 - def on_connected(protocol):
151 protocol.send_message("ping", 1, 2.0, "bang") 152 print "sent ping"
153
154 - def on_error(failure):
155 print "Error trying to connect.", failure 156 reactor.stop()
157 158 PORT_NUMBER = 15555 159 160 s = FUDIServerFactory() 161 s.register_message("ping", ping) 162 reactor.listenTCP(PORT_NUMBER, s) 163 164 create_FUDI_client('localhost', PORT_NUMBER).addCallback(on_connected).addErrback(on_error) 165 reactor.run() 166