def __init__(self, **kwargs): super(ArtnetManager, self).__init__(**kwargs) self.register_signal('new_node', 'del_node') self.comm = kwargs.get('comm') self.hostaddr = BaseIO.detect_usable_address() self.hostname = socket.gethostname() self.hostport = UDP_PORT self.mac_addr = BaseIO.get_mac_address() self.subnet = kwargs.get('subnet', 0) self.artpoll = messages.ArtPoll(TalkToMe=2) self.artpoll_reply = messages.ArtPollReply(IPAddress=self.hostaddr, Port=UDP_PORT, Oem=0xFF, ShortName=self.hostname, LongName=self.hostname, MAC=self.mac_addr, Style=1, NumPorts=4, PortTypes=[0xC0]*4, Swin=[1, 2, 3, 4]) #Swout=[1, 2, 3, 4]) self.Nodes = {} self.NodesByUniverse = {} self.NodePortInfo = {'InputPorts':{}, 'OutputPorts':{}} for i, style in self.artpoll_reply.Fields['Style'].codes.iteritems(): self.Nodes[style] = {} self.Universes = {} self.ds_universes = {} self.artnet_io = ArtnetIO(hostaddr=PRIMARY_ADDR, hostport=UDP_PORT, manager=self) self.poller = None if getattr(self.comm, 'MainController', None): self.on_comm_MainController_set() else: self.comm.bind(MainController_set=self.on_comm_MainController_set)
class ArtnetManager(BaseIO.BaseIO): ui_name = 'Artnet' def __init__(self, **kwargs): super(ArtnetManager, self).__init__(**kwargs) self.register_signal('new_node', 'del_node') self.comm = kwargs.get('comm') self.hostaddr = BaseIO.detect_usable_address() self.hostname = socket.gethostname() self.hostport = UDP_PORT self.mac_addr = BaseIO.get_mac_address() self.subnet = kwargs.get('subnet', 0) self.artpoll = messages.ArtPoll(TalkToMe=2) self.artpoll_reply = messages.ArtPollReply(IPAddress=self.hostaddr, Port=UDP_PORT, Oem=0xFF, ShortName=self.hostname, LongName=self.hostname, MAC=self.mac_addr, Style=1, NumPorts=4, PortTypes=[0xC0]*4, Swin=[1, 2, 3, 4]) #Swout=[1, 2, 3, 4]) self.Nodes = {} self.NodesByUniverse = {} self.NodePortInfo = {'InputPorts':{}, 'OutputPorts':{}} for i, style in self.artpoll_reply.Fields['Style'].codes.iteritems(): self.Nodes[style] = {} self.Universes = {} self.ds_universes = {} self.artnet_io = ArtnetIO(hostaddr=PRIMARY_ADDR, hostport=UDP_PORT, manager=self) self.poller = None if getattr(self.comm, 'MainController', None): self.on_comm_MainController_set() else: self.comm.bind(MainController_set=self.on_comm_MainController_set) def unlink(self): self.comm.unbind(self) if type(self.ds_universes) != dict: self.ds_universes.unbind(self) super(ArtnetManager, self).unlink() def on_comm_MainController_set(self, **kwargs): self.ds_universes = self.comm.MainController.DeviceSystem.universes self.update_ds_universes() self.ds_universes.bind(child_added=self.on_ds_universes_child_added, child_removed=self.on_ds_universes_child_removed) def on_ds_universes_child_added(self, **kwargs): obj = kwargs.get('obj') self.update_ds_universes(univ_obj=obj) def on_ds_universes_child_removed(self, **kwargs): obj = kwargs.get('obj') self.detach_universe(univ_obj=obj) def update_ds_universes(self, **kwargs): univ_obj = kwargs.get('univ_obj') if univ_obj is not None: universes = [univ_obj] else: universes = self.ds_universes.values() for univ_obj in universes: sub = univ_obj.Artnet_Subnet univ = univ_obj.Artnet_Universe self.detach_universe(univ_obj=univ_obj) if sub is not None and univ is not None: self.attach_universe(universe_obj=univ_obj, universe_index=univ, subnet=sub) univ_obj.bind(property_changed=self.on_ds_universe_obj_property_changed) def on_ds_universe_obj_property_changed(self, **kwargs): prop = kwargs.get('Property') obj = kwargs.get('obj') if prop.name in ['Artnet_Subnet', 'Artnet_Universe']: self.update_ds_universes(univ_obj=obj) def do_connect(self): if self.connected: self.do_disconnect(blocking=True) self.artnet_io.do_connect() # clslist = [communication.MulticastSender, communication.MulticastReceiver] # for key, cls in zip(['sender', 'receiver'], clslist): # obj = cls(hostaddr=self.hostaddr, hostport=self.hostport, # mcastaddr=PRIMARY_ADDR, mcastport=UDP_PORT, # manager=self) # self.multicast_io[key] = obj # obj.do_connect() self.poller = Poller(manager=self) self.poller.start() #self.poller.stop() self.connected = True self.update_ds_universes() def do_disconnect(self, blocking=False): if self.poller is not None: self.poller.stop(blocking=blocking) self.poller = None #for univ in self.Universes.itervalues(): # univ.stop() for univ_obj in self.ds_universes.itervalues(): self.detach_universe(univ_obj=univ_obj, blocking=blocking) self.artnet_io.do_disconnect(blocking=blocking) # for key in ['sender', 'reciever']: # obj = self.multicast_io.get(key) # if obj: # obj.do_disconnect() # del self.multicast_io[key] self.connected = False def attach_universe(self, **kwargs): ''' :Parameters: universe_obj : universe_index : subnet : ''' kwargs.setdefault('subnet', self.subnet) kwargs.setdefault('manager', self) univ = UniverseThread(**kwargs) self.Universes[(univ.subnet, univ.universe_index)] = univ if self.connected: univ.start() keys = ['subnet', 'universe_index', '_thread_id'] d = dict(zip(keys, [getattr(univ, key) for key in keys])) nodes = self.NodePortInfo['OutputPorts'].get((univ.subnet, univ.universe_index), []) d['nodes'] = [str(n) for n in nodes] self.LOG.info('Artnet attached universe: ', d) def detach_universe(self, **kwargs): univ_obj = kwargs.get('univ_obj') blocking = kwargs.get('blocking', True) univ_obj.unbind(self) univ_obj.unbind(self) key = (univ_obj.Artnet_Subnet, univ_obj.Artnet_Universe) for ukey, uval in self.Universes.iteritems(): if uval.universe_obj == univ_obj: key = ukey univ_thread = self.Universes.get(key) if univ_thread: self.LOG.info('Artnet detach universe: ', key, univ_thread._thread_id) univ_thread.stop(blocking=blocking) del self.Universes[key] def add_node(self, **kwargs): msg = kwargs.get('artpoll_reply') if msg is None: return node = Node(artpoll_reply=msg, manager=self) nid = node.id style = node.style if nid not in self.Nodes[style]: self.Nodes[style][nid] = node #print 'new node: id=%s, style=%s, data=%s' % (node.id, node.style, node.data) #keys = node.Properties.keys() #self.LOG.info('Artnet new node: ', dict(zip(keys, [getattr(node, key) for key in keys]))) self.LOG.info('Artnet new node: ', str(node)) self.update_node_port_info(node=node) node.bind(**dict(zip(['InputPorts', 'OutputPorts'], [self.on_node_io_port_update]*2))) self.emit('new_node', style=style, id=nid, node=node) else: self.Nodes[style][nid].set_data(msg) def update_node_port_info(self, **kwargs): node = kwargs.get('node') if node: if node.style != 'StNode': return nodes = [node] else: nodes = self.Nodes['StNode'].values() for node in nodes: for iokey, iodict in self.NodePortInfo.iteritems(): for i, sub_univ in enumerate(getattr(node, iokey)): if sub_univ is not None: if sub_univ not in iodict: iodict[sub_univ] = set() iodict[sub_univ].add(node) if sub_univ in self.Universes: self.Universes[sub_univ].add_node(node=node, port=i) #print self.NodePortInfo def on_node_io_port_update(self, **kwargs): node = kwargs.get('obj') key = kwargs.get('name') old = kwargs.get('old') value = kwargs.get('value') if node.style != 'StNode': return if old is not None: for i, subuniv in enumerate(old): if value[i] != subuniv: nodeset = self.NodePortInfo[key].get(subuniv, set()) nodeset.discard(node) self.update_node_port_info(node=node) def del_node(self, **kwargs): nstyle = kwargs.get('style') nid = kwargs.get('id') node = kwargs.get('node') if node is not None: nstyle = node.style nid = node.id elif nid is not None: node = self.Nodes.get(nstyle, {}).get(nid) if node is None: return node.unbind(self) node.unlink() del self.Nodes[nstyle][nid] self.emit('del_node', style=nstyle, id=nid, node=node) if nstyle != 'StNode': return for iokey, iodict in self.NodePortInfo.iteritems(): for sub_univ in getattr(node, iokey): if sub_univ is not None: nodeset = iodict.get(sub_univ, set()) nodeset.discard(node) if sub_univ in iodict and not len(nodeset): del iodict[sub_univ] if sub_univ in self.Universes: self.Universes[sub_univ].del_node(node=node) #print self.NodePortInfo def send_dmx(self, **kwargs): if not self.comm.osc_io.isMaster: return seq = kwargs.get('sequence', 0) sub = kwargs.get('subnet', self.subnet) univ = kwargs.get('universe', 1) data = kwargs.get('data') nodes = self.NodePortInfo['OutputPorts'].get((sub, univ)) if not nodes: return clients = [(n.data['IPAddress'], n.data['Port']) for n in nodes] #clients = [None] msg = messages.ArtDmx(Sequence=seq, Universe=(sub * 0x10) + univ, Data=data, Physical=univ) #if len(data) < 512: # print 'dmxlen: msg=%s, data=%s, msglen=%s' % (msg.Fields['Length'].value, len(data), len(msg.get_data()[0])) #print 'sending dmx to univ ', univ self.send_msg(msg=msg, clients=clients) def send_msg(self, **kwargs): msg = kwargs.get('msg') clients = kwargs.get('clients', [None]) s = msg.build_string() for client in clients: self.artnet_io.send(s, client) def parse_message(self, **kwargs): data = kwargs.get('data') client = kwargs.get('client') msg = messages.parse_message(data) if not msg: return #print msg.__class__.__name__, [[f.id, f.value] for f in msg.Fields.indexed_items.values()] if msg.msg_type == 'ArtPoll': self.artnet_io.send(self.artpoll_reply.build_string()) elif msg.msg_type == 'ArtPollReply':# and msg.Fields['MAC'].value != self.mac_addr: self.add_node(artpoll_reply=msg) elif msg.msg_type == 'ArtDmx': #print 'ArtDmx from :', client u = msg.Fields['Universe'].value subuniv = (u / 0x10, u % 0x10) u = self.Universes.get(subuniv) if u is None: return u.merge_dmx_msg(msg=msg, client=client) #print 'artnet gc: ', gc.collect(0) self.collect_garbage()