Package toon :: Module puredata
[hide private]
[frames] | no frames]

Source Code for Module toon.puredata

  1  #!/usr/bin/env python 
  2  """ 
  3  Communication with Pure Data.  
  4  start also the pd patch. 
  5  """ 
  6  import pprint 
  7  import sys 
  8   
  9  from twisted.internet import reactor 
 10  from twisted.internet.error import CannotListenError 
 11   
 12  from rats import fudi  
 13   
14 -class PureDataController(object):
15 """ 16 Toonloop API for Pure Data FUDI network messages. 17 18 /frame/add 19 /frame/remove 20 /clip/select <int> 21 /ping 22 /pong 23 24 Restricted / dangerous ones : 25 26 /config/set <string> <any> 27 /call <string> ... 28 /quit 29 """
30 - def __init__(self, **kwargs):
31 self.receive_port = 15555 32 self.send_port = 17777 33 self.send_host = "localhost" # TODO: send to many subscribers. 34 self.receiver = None 35 self.sender = None 36 self.verbose = True 37 self.app = None 38 self.try_again_delay = 30 39 self.try_again = True 40 self.manhole_enable = True 41 self.__dict__.update(**kwargs) 42 self._init_receiver() 43 self._init_sender()
44
45 - def _init_receiver(self):
46 if self.verbose: 47 print("starting FUDI server on port" + str(self.receive_port)) 48 self.receiver = fudi.FUDIServerFactory() 49 self.receiver.register_message("/ping", self.ping) 50 self.receiver.register_message("/pong", self.pong) 51 self.receiver.register_message("/frame/add", self.frame_add) 52 self.receiver.register_message("/frame/remove", self.frame_remove) 53 self.receiver.register_message("/clip/select", self.frame_remove) 54 self.receiver.register_message("/option/group", self.set_option_in_group) 55 if self.manhole_enable: 56 self.receiver.register_message("/call", self.call) 57 self.receiver.register_message("/config/set", self.config_set) 58 self.receiver.register_message("/quit", self.quit) 59 try: 60 reactor.listenTCP(self.receive_port, self.receiver) 61 except CannotListenError, e: 62 print e.message 63 raise 64 self.receiver = None 65 return self.receiver
66
67 - def _init_sender(self):
68 deferred = fudi.create_FUDI_client(self.send_host, self.send_port) 69 deferred.addCallback(self._on_connected) 70 deferred.addErrback(self._on_error) 71 return deferred
72
73 - def _on_connected(self, sender):
74 if self.verbose: 75 print "pd: Connected !" 76 print "pd: sender:", sender 77 print "pd: receiver:", self.receiver 78 self.sender = sender 79 self.sender.send_message("/ping", 1, 2.0, "bang") 80 if self.verbose: 81 print " sent ping"
82
83 - def _on_error(self, failure):
84 print 'FUDI server unavailable:', self.send_host, self.send_port 85 # print "FUDI sender:", failure.getErrorMessage() 86 if self.try_again: 87 reactor.callLater(self.try_again_delay, self._init_sender)
88
89 - def _send_message(self, selector, *args):
90 # TODO: if cannot send, delete send and raise Error 91 if self.sender is None: 92 print "pd: Cannot send. Sender is None" 93 else: 94 try: 95 self.sender.send_message(selector, *args) 96 except Exception, e: 97 print e.message
98 # --------------- FUDI Message Callbacks : ----------
99 - def ping(self, receiver, *args):
100 """ 101 Answers /pong to /ping 102 /ping 103 """ 104 if self.verbose: 105 print "pd: received ping", args 106 response = list(args) 107 if self.verbose: 108 print "pd: will send", "pong", response 109 self._send_message("pong", *response)
110
111 - def pong(self, receiver, *args):
112 """ 113 Receives Pong. 114 /pong 115 """ 116 if self.verbose: 117 print "pd: received pong", args
118
119 - def config_set(self, receiver, *args):
120 """ 121 Sets an configuration option. 122 /options/set <name> <value> 123 """ 124 if self.verbose: 125 print "pd: config_set", args 126 if self.app is not None: 127 try: 128 k = args[0] 129 v = args[1] 130 kind = self.app.config.set(k, v) 131 print " set %s = %s (%s)" % (k, k, kind) 132 except Exception, e: 133 print e.message
134
135 - def frame_add(self, receiver, *args):
136 """ 137 Grabs a frame. 138 /frame/add 139 """ 140 if self.verbose: 141 print "pd: /frame/add", args 142 if self.app is not None: 143 try: 144 self.app.frame_add() 145 except Exception, e: 146 print e.message
147
148 - def set_option_in_group(self, receiver, *args):
149 if self.verbose: 150 print "pd: /option/group", args 151 if self.app is not None: 152 try: 153 group = args[0] 154 key = args[1] 155 value = args[2] 156 if len(args) == 5: 157 value = "%s,%s,%s" % (args[2], args[3], args[4]) 158 self.app.set_option_in_group(group, key, value) 159 except IndexError, e: 160 print("IndexError: %s" % (e.message)) 161 except Exception, e: 162 print("Error setting option from group %s" % (e.message))
163
164 - def frame_remove(self, receiver, *args):
165 """ 166 removes a frame. 167 /frame/remove 168 """ 169 if self.verbose: 170 print "pd: /frame/remove", args 171 if self.app is not None: 172 try: 173 self.app.frame_remove() 174 except Exception, e: 175 print e.message
176
177 - def clip_select(self, receiver, *args):
178 """ 179 Select a clip by number. 180 181 /clip select <index> 182 index=0 183 """ 184 if self.verbose: 185 print "pd: /clip/select", args 186 if self.app is not None: 187 try: 188 self.app.clip_select(int(args[0])) 189 except Exception, e: 190 print e.message 191
192 - def call(self, receiver, *args):
193 """ 194 Wraps any method from the APP. 195 196 Warning : protect this port ! 197 Do not use this FUDI protocol when network is not secure. 198 199 The pound sign (#) is replaced by commas 200 201 call <method> <args...> 202 """ 203 if self.app is None: 204 print 'ERROR: puredata.app is None' 205 else: 206 try: 207 method = getattr(self.app, args[0]) 208 actual_args = list(args[1:]) 209 #for i in range(len(actual_args)): 210 # actual_args[i] = str(actual_args[i]).replace("#", ",") 211 if self.verbose: 212 print ' puredata.%s(%s)' % (args[0], str(actual_args)), method 213 method(*args[1:]) 214 except Exception, e: 215 print "ERROR @ puredata.call:", e.message 216 print sys.exc_info()
217
218 - def quit(self, receiver, *args):
219 """ 220 Quits the application. 221 222 Warning : protect this port ! 223 Do not use this FUDI protocol when network is not secure. 224 225 /quit 226 """ 227 if self.verbose: 228 print "pd: received quit", args 229 if self.app is not None: 230 self.app.quit() 231 else: 232 reactor.stop()
233
234 -def start(**kwargs):
235 """ 236 Factory for the Toonloop FUDI service. 237 238 **kwargs 239 """ 240 fudi.VERBOSE = True 241 print("Starting PureData service.") 242 pprint.pprint(kwargs) 243 pd = PureDataController(**kwargs) 244 return pd 245 246 if __name__ == '__main__': 247 fudi.VERBOSE = True 248 pd = PureDataController() 249 reactor.callLater(15, pd._init_sender) 250 reactor.run() 251