def __init__(self, **kwargs):
     self.comm = kwargs.get('comm')
     BaseIO.BaseIO.__init__(self, **kwargs)
     Config.__init__(self, **kwargs)
     self.register_signal('client_added', 'client_removed', 'unique_address_changed', 'new_master')
     self.discovered_sessions = ChildGroup(name='discovered_sessions', 
                                           child_class=Session, 
                                           ignore_index=True)
     self.app_address = self.GLOBAL_CONFIG.get('app_name', self.get_conf('app_address', 'OSCApp'))
     self.default_root_address = kwargs.get('root_address', '%s-%s' % (self.app_address, socket.gethostname()))
     self.root_address = self.default_root_address
     self.wildcard_address = None
     self.master_priority = int(self.get_conf('master_priority', 10))
     self.GLOBAL_CONFIG['master_priority'] = self.master_priority
     s = self.GLOBAL_CONFIG.get('session_name')
     if s == 'None':
         s = None
     if s is not None:
         self.session_name = s
     else:
         self.session_name = socket.gethostname()
         self.GLOBAL_CONFIG['session_name'] = self.session_name
     self.osc_tree = OSCNode(name=self.app_address, 
                             root_node=True, 
                             transmit_callback=self.on_node_tree_send, 
                             get_client_cb=self.get_client, 
                             get_epoch_offset_cb=self.get_epoch_offset)
     #self.root_node = self.osc_tree.add_child(name=self.app_address)
     self.root_node = self.osc_tree
     #self.epoch_offset = datetime.timedelta()
     #self.epoch_offset = 0.
     self.clock_send_thread = None
     s = kwargs.get('use_unique_addresses', self.get_conf('use_unique_addresses', 'True'))
     flag = not s == 'False'
     
     #self.root_node.addCallback('/clocksync', self.on_master_sent_clocksync)
     #csnode = self.root_node.add_child(name='clocksync')
     #csnode.bind(message_received=self.on_master_sent_clocksync)
     #self.clocksync_node = csnode
     self.ioManager = oscIO(Manager=self)
     self.SessionManager = OSCSessionManager(Manager=self)
     self.SessionManager.bind(client_added=self.on_client_added, 
                              client_removed=self.on_client_removed, 
                              new_master=self.on_new_master)
     self.set_use_unique_address(flag, update_conf=False)
     io = kwargs.get('connection_type', self.get_conf('connection_type', 'Unicast'))
     self.ioManager.build_io(iotype=io, update_conf=False)
     self.ClockSync = ClockSync(osc_parent_node=self.root_node, 
                                clients=self.clients)
     self.ClockSync.bind(offset=self.on_ClockSync_offset_set)
    def __init__(self, **kwargs):
        self.comm = kwargs.get("comm")
        BaseIO.BaseIO.__init__(self, **kwargs)
        Config.__init__(self, **kwargs)
        self.register_signal("client_added", "client_removed", "unique_address_changed", "new_master")
        self.discovered_sessions = ChildGroup(name="discovered_sessions", child_class=Session, ignore_index=True)
        self.app_address = self.GLOBAL_CONFIG.get("app_name", self.get_conf("app_address", "OSCApp"))
        self.default_root_address = kwargs.get("root_address", "%s-%s" % (self.app_address, socket.gethostname()))
        self.root_address = self.default_root_address
        self.wildcard_address = None
        self.master_priority = int(self.get_conf("master_priority", 10))
        self.GLOBAL_CONFIG["master_priority"] = self.master_priority
        s = self.GLOBAL_CONFIG.get("session_name")
        if s == "None":
            s = None
        if s is not None:
            self.session_name = s
        else:
            self.session_name = socket.gethostname()
            self.GLOBAL_CONFIG["session_name"] = self.session_name
        self.osc_tree = OSCNode(
            name=self.app_address,
            root_node=True,
            transmit_callback=self.on_node_tree_send,
            get_client_cb=self.get_client,
            get_epoch_offset_cb=self.get_epoch_offset,
        )
        # self.root_node = self.osc_tree.add_child(name=self.app_address)
        self.root_node = self.osc_tree
        # self.epoch_offset = datetime.timedelta()
        # self.epoch_offset = 0.
        self.clock_send_thread = None
        s = kwargs.get("use_unique_addresses", self.get_conf("use_unique_addresses", "True"))
        flag = not s == "False"

        # self.root_node.addCallback('/clocksync', self.on_master_sent_clocksync)
        # csnode = self.root_node.add_child(name='clocksync')
        # csnode.bind(message_received=self.on_master_sent_clocksync)
        # self.clocksync_node = csnode
        self.ioManager = oscIO(Manager=self)
        self.SessionManager = OSCSessionManager(Manager=self)
        self.SessionManager.bind(
            client_added=self.on_client_added, client_removed=self.on_client_removed, new_master=self.on_new_master
        )
        self.set_use_unique_address(flag, update_conf=False)
        io = kwargs.get("connection_type", self.get_conf("connection_type", "Unicast"))
        self.ioManager.build_io(iotype=io, update_conf=False)
        self.ClockSync = ClockSync(osc_parent_node=self.root_node, clients=self.clients)
        self.ClockSync.bind(offset=self.on_ClockSync_offset_set)
class OSCManager(BaseIO.BaseIO, Config):
    _confsection = 'OSC'
    _Properties = {'app_address':dict(type=str), 
                   'master_priority':dict(default=10), 
                   'session_name':dict(type=str), 
                   'ring_master':dict(type=str), 
                   'epoch_offset':dict(default=0.)}
    def __init__(self, **kwargs):
        self.comm = kwargs.get('comm')
        BaseIO.BaseIO.__init__(self, **kwargs)
        Config.__init__(self, **kwargs)
        self.register_signal('client_added', 'client_removed', 'unique_address_changed', 'new_master')
        self.discovered_sessions = ChildGroup(name='discovered_sessions', 
                                              child_class=Session, 
                                              ignore_index=True)
        self.app_address = self.GLOBAL_CONFIG.get('app_name', self.get_conf('app_address', 'OSCApp'))
        self.default_root_address = kwargs.get('root_address', '%s-%s' % (self.app_address, socket.gethostname()))
        self.root_address = self.default_root_address
        self.wildcard_address = None
        self.master_priority = int(self.get_conf('master_priority', 10))
        self.GLOBAL_CONFIG['master_priority'] = self.master_priority
        s = self.GLOBAL_CONFIG.get('session_name')
        if s == 'None':
            s = None
        if s is not None:
            self.session_name = s
        else:
            self.session_name = socket.gethostname()
            self.GLOBAL_CONFIG['session_name'] = self.session_name
        self.osc_tree = OSCNode(name=self.app_address, 
                                root_node=True, 
                                transmit_callback=self.on_node_tree_send, 
                                get_client_cb=self.get_client, 
                                get_epoch_offset_cb=self.get_epoch_offset)
        #self.root_node = self.osc_tree.add_child(name=self.app_address)
        self.root_node = self.osc_tree
        #self.epoch_offset = datetime.timedelta()
        #self.epoch_offset = 0.
        self.clock_send_thread = None
        s = kwargs.get('use_unique_addresses', self.get_conf('use_unique_addresses', 'True'))
        flag = not s == 'False'
        
        #self.root_node.addCallback('/clocksync', self.on_master_sent_clocksync)
        #csnode = self.root_node.add_child(name='clocksync')
        #csnode.bind(message_received=self.on_master_sent_clocksync)
        #self.clocksync_node = csnode
        self.ioManager = oscIO(Manager=self)
        self.SessionManager = OSCSessionManager(Manager=self)
        self.SessionManager.bind(client_added=self.on_client_added, 
                                 client_removed=self.on_client_removed, 
                                 new_master=self.on_new_master)
        self.set_use_unique_address(flag, update_conf=False)
        io = kwargs.get('connection_type', self.get_conf('connection_type', 'Unicast'))
        self.ioManager.build_io(iotype=io, update_conf=False)
        self.ClockSync = ClockSync(osc_parent_node=self.root_node, 
                                   clients=self.clients)
        self.ClockSync.bind(offset=self.on_ClockSync_offset_set)
        
    @property
    def oscMaster(self):
        return self.SessionManager.oscMaster
    @property
    def isMaster(self):
        return self.SessionManager.isMaster
    @property
    def isRingMaster(self):
        return self.SessionManager.isRingMaster
    @property
    def clients(self):
        return self.SessionManager.clients
    @property
    def local_client(self):
        return self.SessionManager.local_client
        
    def get_epoch_offset(self):
        return self.epoch_offset
        
    def do_connect(self, **kwargs):
        self.SessionManager.do_connect()
        self.ioManager.do_connect(**kwargs)
        self.connected = True
        
    def do_disconnect(self, **kwargs):
        #self.stop_clock_send_thread(blocking=True)
        self.ClockSync.isMaster = False
        self.ioManager.do_disconnect(**kwargs)
        self.SessionManager.do_disconnect(**kwargs)
        self.connected = False
        
    def shutdown(self):
        self.do_disconnect(blocking=True)
        self.osc_tree.unlink_all(direction='down', blocking=True)
        
        
    def set_use_unique_address(self, flag, update_conf=True):
        self.use_unique_address = flag
        if update_conf:
            self.update_conf(use_unique_addresses=flag)
        self.set_address_vars()
        self.emit('unique_address_changed', state=flag)
    
    def set_address_vars(self):
        return
        if self.ioManager.iotype == 'Multicast' or self.use_unique_address:
            self.root_address = self.default_root_address
            #self.SessionManager.add_client_name(None, update_conf=False)
        else:
            self.root_address = self.app_address
            self.root_node.name = self.root_address
            
    def update_wildcards(self):
        return
        #if self.wildcard_address:
        #    self.osc_tree._wildcardNodes.discard(self.wildcard_address)
        #    self.osc_tree._wildcardNodes.discard('{null}')
        names = []
        for c in self.clients.itervalues():
            if not c.isLocalhost:
                names.append(c.osc_name)
        if names:
            s = '{%s}' % (','.join(names))
            self.wildcard_address = s
            self.root_node.name = s
            #self.osc_tree._wildcardNodes.add(s)
            #print 'wildcard = ', s
            #print 'root_node = ', s
            #print 'wcnodes = ', self.osc_tree._wildcardNodes
        
    def get_client(self, **kwargs):
        hostaddr = kwargs.get('hostaddr')[0]
        #print hostaddr, self.clients_by_address
        return self.SessionManager.clients_by_address.get(hostaddr)
        
    def on_node_tree_send(self, **kwargs):
        clients = kwargs.get('clients')
        client_name = kwargs.get('client')
        element = kwargs.get('element')
#        timetag = kwargs.get('timetag')
#        if timetag is not None:
#            del kwargs['timetag']
        to_master = kwargs.get('to_master', client_name is None and not self.isMaster)
        if to_master:
            client_name = self.oscMaster
        if clients is None:
            client = self.clients.get(client_name)
            if client is not None:
                clients = [client]
#        address = kwargs.get('address')
#        #root_address = kwargs.get('root_address', self.root_address)
        all_sessions = kwargs.get('all_sessions', False)
#        #address[0] = root_address
#        if not isinstance(address, Address):
#            address = Address(address)
#        #junk, address = address.pop()
#        #address = address.append_right(root_address)
#        
#        #path = '/' + join_address(*address)
#        #if path[-1:] == '/':
#        #    path = path[:-1]
#        args = self.pack_args(kwargs.get('value'))
#        msg = Message(*args, address=address)
#        bundle = Bundle(msg, timetag=timetag)
        
        _sender = self.ioManager._sender
        if _sender is None:
            return
        _sender.preprocess(element)
        if isinstance(element, Bundle):
            messages = element.get_flat_messages()
        else:
            messages = [element]
        if self.ioManager.iotype == 'Multicast':
            #print 'osc_send: ', msg
            _sender._send(element)
            return
        if self.ioManager.iotype != 'Unicast':
            return
            
        if clients is None:
            clients = set()
            for c in self.clients.itervalues():
                if all_sessions:
                    if c.sendAllUpdates:
                        clients.add(c)
                else:
                    if c.sendAllUpdates and c.isSameSession:
                        clients.add(c)
        for c in clients:
            if c.accepts_timetags:
                _sender._send(element, c.hostaddr)
            else:
                for msg in messages:
                    _sender._send(msg, c.hostaddr)
    
    def pack_args(self, value):
        if isinstance(value, list) or isinstance(value, tuple):
            return value
        elif value is None:
            return []
        return [value]
        
    def on_ClockSync_offset_set(self, **kwargs):
        self.epoch_offset = kwargs.get('value')
        
    def start_clock_send_thread(self):
        self.stop_clock_send_thread()
        self.clock_send_thread = ClockSender(osc_node=self.clocksync_node, 
                                             time_method='timestamp', 
                                             clients=self.clients)
        self.clock_send_thread.start()
        
    def stop_clock_send_thread(self, blocking=True):
        if self.clock_send_thread is None:
            return
        self.clock_send_thread.stop(blocking=blocking)
        self.clock_send_thread = None
            
    def on_master_sent_clocksync(self, **kwargs):
        msg = kwargs.get('message')
        value = msg.get_arguments()[0]
        #dt = datetime.datetime.strptime(value, '%Y%m%d %H:%M:%S %f')
        #now = datetime.datetime.fromtimestamp(msg.timestamp)
        now = time.time()
        #print 'msg.timestamp: ', msg.timestamp
        #tsnow = datetime.datetime.fromtimestamp(msg.timestamp)
        #print 'now=%s, tsnow=%s' % (now, tsnow)
        self.epoch_offset = now - value
        #print 'epoch_offset: ', self.epoch_offset
        
    def on_client_added(self, **kwargs):
        self.emit('client_added', **kwargs)
        
    def on_client_removed(self, **kwargs):
        self.emit('client_removed', **kwargs)
        
    def on_new_master(self, **kwargs):
        self.emit('new_master', **kwargs)
class OSCManager(BaseIO.BaseIO, Config):
    _confsection = "OSC"
    _Properties = {
        "app_address": dict(type=str),
        "master_priority": dict(default=10),
        "session_name": dict(type=str),
        "ring_master": dict(type=str),
        "epoch_offset": dict(default=0.0),
    }

    def __init__(self, **kwargs):
        self.comm = kwargs.get("comm")
        BaseIO.BaseIO.__init__(self, **kwargs)
        Config.__init__(self, **kwargs)
        self.register_signal("client_added", "client_removed", "unique_address_changed", "new_master")
        self.discovered_sessions = ChildGroup(name="discovered_sessions", child_class=Session, ignore_index=True)
        self.app_address = self.GLOBAL_CONFIG.get("app_name", self.get_conf("app_address", "OSCApp"))
        self.default_root_address = kwargs.get("root_address", "%s-%s" % (self.app_address, socket.gethostname()))
        self.root_address = self.default_root_address
        self.wildcard_address = None
        self.master_priority = int(self.get_conf("master_priority", 10))
        self.GLOBAL_CONFIG["master_priority"] = self.master_priority
        s = self.GLOBAL_CONFIG.get("session_name")
        if s == "None":
            s = None
        if s is not None:
            self.session_name = s
        else:
            self.session_name = socket.gethostname()
            self.GLOBAL_CONFIG["session_name"] = self.session_name
        self.osc_tree = OSCNode(
            name=self.app_address,
            root_node=True,
            transmit_callback=self.on_node_tree_send,
            get_client_cb=self.get_client,
            get_epoch_offset_cb=self.get_epoch_offset,
        )
        # self.root_node = self.osc_tree.add_child(name=self.app_address)
        self.root_node = self.osc_tree
        # self.epoch_offset = datetime.timedelta()
        # self.epoch_offset = 0.
        self.clock_send_thread = None
        s = kwargs.get("use_unique_addresses", self.get_conf("use_unique_addresses", "True"))
        flag = not s == "False"

        # self.root_node.addCallback('/clocksync', self.on_master_sent_clocksync)
        # csnode = self.root_node.add_child(name='clocksync')
        # csnode.bind(message_received=self.on_master_sent_clocksync)
        # self.clocksync_node = csnode
        self.ioManager = oscIO(Manager=self)
        self.SessionManager = OSCSessionManager(Manager=self)
        self.SessionManager.bind(
            client_added=self.on_client_added, client_removed=self.on_client_removed, new_master=self.on_new_master
        )
        self.set_use_unique_address(flag, update_conf=False)
        io = kwargs.get("connection_type", self.get_conf("connection_type", "Unicast"))
        self.ioManager.build_io(iotype=io, update_conf=False)
        self.ClockSync = ClockSync(osc_parent_node=self.root_node, clients=self.clients)
        self.ClockSync.bind(offset=self.on_ClockSync_offset_set)

    @property
    def oscMaster(self):
        return self.SessionManager.oscMaster

    @property
    def isMaster(self):
        return self.SessionManager.isMaster

    @property
    def isRingMaster(self):
        return self.SessionManager.isRingMaster

    @property
    def clients(self):
        return self.SessionManager.clients

    @property
    def local_client(self):
        return self.SessionManager.local_client

    def get_epoch_offset(self):
        return self.epoch_offset

    def do_connect(self, **kwargs):
        self.SessionManager.do_connect()
        self.ioManager.do_connect(**kwargs)
        self.connected = True

    def do_disconnect(self, **kwargs):
        # self.stop_clock_send_thread(blocking=True)
        self.ClockSync.isMaster = False
        self.ioManager.do_disconnect(**kwargs)
        self.SessionManager.do_disconnect(**kwargs)
        self.connected = False

    def shutdown(self):
        self.do_disconnect(blocking=True)
        self.osc_tree.unlink_all(direction="down", blocking=True)

    def set_use_unique_address(self, flag, update_conf=True):
        self.use_unique_address = flag
        if update_conf:
            self.update_conf(use_unique_addresses=flag)
        self.set_address_vars()
        self.emit("unique_address_changed", state=flag)

    def set_address_vars(self):
        return
        if self.ioManager.iotype == "Multicast" or self.use_unique_address:
            self.root_address = self.default_root_address
            # self.SessionManager.add_client_name(None, update_conf=False)
        else:
            self.root_address = self.app_address
            self.root_node.name = self.root_address

    def update_wildcards(self):
        return
        # if self.wildcard_address:
        #    self.osc_tree._wildcardNodes.discard(self.wildcard_address)
        #    self.osc_tree._wildcardNodes.discard('{null}')
        names = []
        for c in self.clients.itervalues():
            if not c.isLocalhost:
                names.append(c.osc_name)
        if names:
            s = "{%s}" % (",".join(names))
            self.wildcard_address = s
            self.root_node.name = s
            # self.osc_tree._wildcardNodes.add(s)
            # print 'wildcard = ', s
            # print 'root_node = ', s
            # print 'wcnodes = ', self.osc_tree._wildcardNodes

    def get_client(self, **kwargs):
        hostaddr = kwargs.get("hostaddr")[0]
        # print hostaddr, self.clients_by_address
        return self.SessionManager.clients_by_address.get(hostaddr)

    def on_node_tree_send(self, **kwargs):
        clients = kwargs.get("clients")
        client_name = kwargs.get("client")
        element = kwargs.get("element")
        #        timetag = kwargs.get('timetag')
        #        if timetag is not None:
        #            del kwargs['timetag']
        to_master = kwargs.get("to_master", client_name is None and not self.isMaster)
        if to_master:
            client_name = self.oscMaster
        if clients is None:
            client = self.clients.get(client_name)
            if client is not None:
                clients = [client]
        #        address = kwargs.get('address')
        #        #root_address = kwargs.get('root_address', self.root_address)
        all_sessions = kwargs.get("all_sessions", False)
        #        #address[0] = root_address
        #        if not isinstance(address, Address):
        #            address = Address(address)
        #        #junk, address = address.pop()
        #        #address = address.append_right(root_address)
        #
        #        #path = '/' + join_address(*address)
        #        #if path[-1:] == '/':
        #        #    path = path[:-1]
        #        args = self.pack_args(kwargs.get('value'))
        #        msg = Message(*args, address=address)
        #        bundle = Bundle(msg, timetag=timetag)

        _sender = self.ioManager._sender
        if _sender is None:
            return
        _sender.preprocess(element)
        if isinstance(element, Bundle):
            messages = element.get_flat_messages()
        else:
            messages = [element]
        if self.ioManager.iotype == "Multicast":
            # print 'osc_send: ', msg
            _sender._send(element)
            return
        if self.ioManager.iotype != "Unicast":
            return

        if clients is None:
            clients = set()
            for c in self.clients.itervalues():
                if all_sessions:
                    if c.sendAllUpdates:
                        clients.add(c)
                else:
                    if c.sendAllUpdates and c.isSameSession:
                        clients.add(c)
        for c in clients:
            if c.accepts_timetags:
                _sender._send(element, c.hostaddr)
            else:
                for msg in messages:
                    _sender._send(msg, c.hostaddr)

    def pack_args(self, value):
        if isinstance(value, list) or isinstance(value, tuple):
            return value
        elif value is None:
            return []
        return [value]

    def on_ClockSync_offset_set(self, **kwargs):
        self.epoch_offset = kwargs.get("value")

    def start_clock_send_thread(self):
        self.stop_clock_send_thread()
        self.clock_send_thread = ClockSender(
            osc_node=self.clocksync_node, time_method="timestamp", clients=self.clients
        )
        self.clock_send_thread.start()

    def stop_clock_send_thread(self, blocking=True):
        if self.clock_send_thread is None:
            return
        self.clock_send_thread.stop(blocking=blocking)
        self.clock_send_thread = None

    def on_master_sent_clocksync(self, **kwargs):
        msg = kwargs.get("message")
        value = msg.get_arguments()[0]
        # dt = datetime.datetime.strptime(value, '%Y%m%d %H:%M:%S %f')
        # now = datetime.datetime.fromtimestamp(msg.timestamp)
        now = time.time()
        # print 'msg.timestamp: ', msg.timestamp
        # tsnow = datetime.datetime.fromtimestamp(msg.timestamp)
        # print 'now=%s, tsnow=%s' % (now, tsnow)
        self.epoch_offset = now - value
        # print 'epoch_offset: ', self.epoch_offset

    def on_client_added(self, **kwargs):
        self.emit("client_added", **kwargs)

    def on_client_removed(self, **kwargs):
        self.emit("client_removed", **kwargs)

    def on_new_master(self, **kwargs):
        self.emit("new_master", **kwargs)