Example #1
0
class Channel(OSCBaseObject):
    def __init__(self, **kwargs):
        self.channel = kwargs.get('channel')
        kwargs.setdefault('osc_address', str(self.channel + 1))
        super(Channel, self).__init__(**kwargs)
        self.register_signal('event')
        self.notes = ChildGroup(name='note', osc_parent_node=self.osc_node)
        self.controllers = ChildGroup(name='controller', osc_parent_node=self.osc_node)
        for i in range(128):
            n = self.notes.add_child(Note, note=i, channel=self, Index=i)
            n.bind(event=self.on_child_event)
            c = self.controllers.add_child(Controller, controller=i, channel=self)
            c.bind(event=self.on_child_event)
    def unlink(self):
        for n in self.notes.iteritems():
            n.unlink()
        for c in self.controllers.iteritems():
            c.unlink()
        super(Channel, self).unlink()
    def trigger_event(self, **kwargs):
        type = kwargs.get('type')
        attr = type + 's'
        if not hasattr(self, attr):
            return
        obj = getattr(self, attr).get(kwargs.get(type))
        if not obj:
            return
        obj.trigger_event(**kwargs)
    def on_child_event(self, **kwargs):
        kwargs.setdefault('channel', self.channel)
        self.emit('event', **kwargs)
class PageMenu(OSCBaseObject):
    #button_size = dict(w=.2, h=.05)
    def __init__(self, **kwargs):
        self.iOsc = kwargs.get('iOsc')
        self.client = kwargs.get('client')
        self.current_page = None
        kwargs.setdefault('osc_parent_node', self.client.osc_node)
        kwargs.setdefault('osc_address', 'PageMenu')
        kwargs.setdefault('ParentEmissionThread',
                          self.iOsc.ParentEmissionThread)
        super(PageMenu, self).__init__(**kwargs)
        self.x_offset = kwargs.get('x_offset', 0.)
        self.y_offset = kwargs.get('y_offset', 0.)
        #w = self.button_size['w'] * len(PAGES)
        self.button_size = dict(h=.05, w=1. / len(PAGES))
        h = self.button_size['h']
        bounds = [self.x_offset, self.y_offset, 1, h]
        self.topwidget = self.iOsc.add_widget(
            'Label',
            name='PageMenu',
            bounds=bounds,
            osc_parent_node=self.osc_parent_node,
            client=self.client)
        self.btn_topwidget = self.topwidget.add_widget(widgets.Label,
                                                       name='select_buttons',
                                                       bounds=bounds)
        self.menu_buttons = ChildGroup(name='select_buttons',
                                       osc_parent_node=self.osc_node)
        for i, cls in enumerate(PAGES):
            btn = self.btn_topwidget.add_widget(MenuButton,
                                                Index=i,
                                                page_cls=cls,
                                                parent=self)
            self.menu_buttons.add_child(existing_object=btn)
            btn.bind(touch_state=self.on_menu_button_touch_state)

    def unlink(self):
        self.set_current_page(None)
        self.topwidget.remove()
        super(PageMenu, self).unlink()

    def set_current_page(self, cls):
        if self.current_page is not None:
            self.current_page.remove()
            self.current_page = None
        if cls is not None:
            self.current_page = cls(iOsc=self.iOsc,
                                    client=self.client,
                                    y_offset=self.y_offset +
                                    self.button_size['h'] + .01)

    def on_menu_button_touch_state(self, **kwargs):
        btn = kwargs.get('obj')
        state = kwargs.get('value')
        if state:
            self.set_current_page(btn.cls)
            for w in self.menu_buttons.itervalues():
                if w != btn:
                    w.touch_state = False
Example #3
0
class PageMenu(OSCBaseObject):
    #button_size = dict(w=.2, h=.05)
    def __init__(self, **kwargs):
        self.iOsc = kwargs.get('iOsc')
        self.client = kwargs.get('client')
        self.current_page = None
        kwargs.setdefault('osc_parent_node', self.client.osc_node)
        kwargs.setdefault('osc_address', 'PageMenu')
        kwargs.setdefault('ParentEmissionThread', self.iOsc.ParentEmissionThread)
        super(PageMenu, self).__init__(**kwargs)
        self.x_offset = kwargs.get('x_offset', 0.)
        self.y_offset = kwargs.get('y_offset', 0.)
        #w = self.button_size['w'] * len(PAGES)
        self.button_size = dict(h=.05, w=1./len(PAGES))
        h = self.button_size['h']
        bounds = [self.x_offset, self.y_offset, 1, h]
        self.topwidget = self.iOsc.add_widget('Label', 
                                              name='PageMenu', 
                                              bounds=bounds, 
                                              osc_parent_node=self.osc_parent_node, 
                                              client=self.client)
        self.btn_topwidget = self.topwidget.add_widget(widgets.Label, name='select_buttons', bounds=bounds)
        self.menu_buttons = ChildGroup(name='select_buttons', osc_parent_node=self.osc_node)
        for i, cls in enumerate(PAGES):
            btn = self.btn_topwidget.add_widget(MenuButton, Index=i, page_cls=cls, parent=self)
            self.menu_buttons.add_child(existing_object=btn)
            btn.bind(touch_state=self.on_menu_button_touch_state)
            
    def unlink(self):
        self.set_current_page(None)
        self.topwidget.remove()
        super(PageMenu, self).unlink()
        
    def set_current_page(self, cls):
        if self.current_page is not None:
            self.current_page.remove()
            self.current_page = None
        if cls is not None:
            self.current_page = cls(iOsc=self.iOsc, client=self.client, y_offset=self.y_offset + self.button_size['h'] + .01)
            
    def on_menu_button_touch_state(self, **kwargs):
        btn = kwargs.get('obj')
        state = kwargs.get('value')
        if state:
            self.set_current_page(btn.cls)
            for w in self.menu_buttons.itervalues():
                if w != btn:
                    w.touch_state = False
class Channel(OSCBaseObject):
    def __init__(self, **kwargs):
        self.channel = kwargs.get('channel')
        kwargs.setdefault('osc_address', str(self.channel + 1))
        super(Channel, self).__init__(**kwargs)
        self.register_signal('event')
        self.notes = ChildGroup(name='note', osc_parent_node=self.osc_node)
        self.controllers = ChildGroup(name='controller',
                                      osc_parent_node=self.osc_node)
        for i in range(128):
            n = self.notes.add_child(Note, note=i, channel=self, Index=i)
            n.bind(event=self.on_child_event)
            c = self.controllers.add_child(Controller,
                                           controller=i,
                                           channel=self)
            c.bind(event=self.on_child_event)

    def unlink(self):
        for n in self.notes.iteritems():
            n.unlink()
        for c in self.controllers.iteritems():
            c.unlink()
        super(Channel, self).unlink()

    def trigger_event(self, **kwargs):
        type = kwargs.get('type')
        attr = type + 's'
        if not hasattr(self, attr):
            return
        obj = getattr(self, attr).get(kwargs.get(type))
        if not obj:
            return
        obj.trigger_event(**kwargs)

    def on_child_event(self, **kwargs):
        kwargs.setdefault('channel', self.channel)
        self.emit('event', **kwargs)
class ArtBaseMsg(object):
    _fields = {1:'ID', 2:'OpCode'}
    def __init__(self, **kwargs):
        self.msg_type = kwargs.get('msg_type', self.__class__.__name__)
        cls = self.__class__
        fields = {}
        while cls != ArtBaseMsg:
            fields.update(getattr(cls, '_fields', {}))
            cls = cls.__bases__[0]
        fields.update(ArtBaseMsg._fields)
        self.Fields = ChildGroup(name='Fields')
        for index, key in fields.iteritems():
            fcls = getattr(FieldClasses, key, None)
            if fcls is not None:
                fobj = self.Fields.add_child(fcls, Index=index)
        for i in range(1, self._num_fields + 1):
            current = self.Fields.indexed_items.get(i)
            if current is not None:
                field = current
            else:
                if i <= field.Index + field.expected_length - 1:
                    pass
                else:
                    fobj = self.Fields.add_child(FieldClasses.Dummy, id='Dummy_%s' % (i), Index=i)
                    #print 'added dummyobj: i=%s, current=%s, field=%s' % (i, current, field)
                    
        self.init_msg(**kwargs)
        
        datastr = kwargs.get('from_string')
        if datastr:
            self._parse_success = True
            result = self.from_string(datastr)
            if result is False:
                self._parse_success = False
        else:
            for key, field in self.Fields.iteritems():
                value = getattr(self, key, kwargs.get(key, FIELD_DEFAULTS.get(key)))
                if value is not None:
                    field.value = value
    def init_msg(self, **kwargs):
        pass
    def from_string(self, string):
        if string is None:
            return False
        l, fmt = self.get_data()
        while len(string) < struct.calcsize(fmt):
            before = fmt
            fmt = fmt[:-1]
            #print 'fmt trunc: before=%s, after=%s' % (before, fmt)
        if len(string) > struct.calcsize(fmt):
            string = string[:struct.calcsize(fmt)]
        try:
            values = list(struct.unpack(fmt, string))
        except:
            LOG.warning(self, 'could not unpack', struct.calcsize(fmt), len(string))
            return False
        #print 'from_string: ', values
        for field in self.Fields.indexed_items.itervalues():
            length = field.expected_length
            if length > len(values):
                #print 'not enough data for field: ', field.id
                break
            field.set_data(values[:length])
            #print field.__class__.__name__, values[:length], values
            del values[:length]
        
    def get_data(self):
        l = []
        #print 'getdata: ', self.msg_type
        for field in self.Fields.indexed_items.itervalues():
            data = field.get_data()
            #print field.id, data
            l.extend(data)
            
        fmt = '=%s' % (''.join([type(item).struct_fmt for item in l]))
        return l, fmt
        
    def build_string(self):
        l, fmt = self.get_data()
        return struct.pack(fmt, *l)
        
    def copy(self):
        msg = self.__class__()
        for i, field in self.Fields.indexed_items.iteritems():
            msg.Fields.indexed_items[i].value = field.value
        return msg
        
    def __str__(self):
        keys = sorted(self.Fields.indexed_items.keys())
        fields = ', '.join([str(self.Fields.indexed_items[key]) for key in keys])
        return ': '.join([self.msg_type, fields])
Example #6
0
class Pipeline(Bin):
    _Properties = {'pipeline_state':dict(default='null')}
    base_class = 'Pipeline'
    def __init__(self, **kwargs):
        self.bin_data = kwargs.get('bin_data', [])
        if len(self.bin_data):
            kwargs['simple_links'] = False
        super(Pipeline, self).__init__(**kwargs)
        
        statekeys = ['NULL', 'PAUSED', 'PLAYING', 'READY', 'VOID_PENDING']
        gststates = [int(getattr(self._gst_module, '_'.join(['STATE', key]))) for key in statekeys]
        self.gst_state_map = dict(zip(gststates, [key.lower() for key in statekeys]))
        
        self.Bins = ChildGroup(name='Bins', child_class=Bin)
        for bindata in self.bin_data:
            if isinstance(bindata, Bin):
                bindata = {'existing_object':bindata}
            self.add_bin(**bindata)
        self.link_bins()
            
        bus = self._pipeline.get_bus()
        bus.add_signal_watch()
        bus.connect('message', self.on_bus_message)
        self.bind(pipeline_state=self.on_pipeline_state)
        
    def on_pipeline_state(self, **kwargs):
        #print kwargs
        pass
        
    def init_instance(self, **kwargs):
        self._pipeline = self._gst_module.Pipeline(self.name)
        self.elem_container = self._pipeline
        
    def add_bin(self, **kwargs):
        bin = self.Bins.add_child(**kwargs)
        self.elem_container.add(bin.elem_container)
        
    def link_bins(self):
        if len(self.Bins) < 2:
            return
        for index, bin in self.Bins.indexed_items.iteritems():
            nextbin = self.Bins.indexed_items.get(index+1)
            if nextbin is None:
                continue
            #print index, bin.name, nextbin.name
            try:
                bin.elem_container.link(nextbin.elem_container)
            except:
                print 'could not link %s with %s' % (bin.name, nextbin.name)
                continue
                
#            for i, src in enumerate(bin.GhostPads['src']):
#                if len(nextbin.GhostPads['sink']) <= i - 1:
#                    print src.get_name(), ' linking to ', nextbin.GhostPads['sink'][i].get_name()
#                    src.link(nextbin.GhostPads['sink'][i])
                
        
    def on_bus_message(self, bus, message):
        self.pipeline_state = self.gst_state_map.get(int(self._pipeline.get_state()[1]))
        #print 'bus message: ', self.pipeline_state, self._pipeline.get_state()
        
    def start(self):
        self._pipeline.set_state(self._gst_module.STATE_PLAYING)
    def stop(self):
        self._pipeline.set_state(self._gst_module.STATE_NULL)
        self.pipeline_state = 'null'
class OSCSessionManager(BaseIO.BaseIO, Config):
    _confsection = 'OSC'
    _Properties = {'oscMaster':dict(type=str)}
    def __init__(self, **kwargs):
        self.Manager = kwargs.get('Manager')
        self.ioManager = self.Manager.ioManager
        self.comm = self.Manager.comm
        self.root_node = self.Manager.root_node
        self.osc_tree = self.Manager.osc_tree
        BaseIO.BaseIO.__init__(self, **kwargs)
        Config.__init__(self, **kwargs)
        self.register_signal('client_added', 'client_removed', 'new_master')
        #self.oscMaster = None
        self.bind(oscMaster=self._on_oscMaster_set)
        self.set_master_timeout = None
        self.master_takeover_timer = None
        self.check_master_attempts = None
        self.local_client = None
        self.clients = ChildGroup(name='clients', 
                                  osc_address='CLIENTS', 
                                  osc_parent_node=self.root_node, 
                                  child_class=Client, 
                                  ignore_index=True)
        self.clients_by_address = {}
        #self.root_node.addCallback('/getMaster', self.on_master_requested_by_osc)
        #self.root_node.addCallback('/setMaster', self.on_master_set_by_osc)
        #self.getMasterNode = self.root_node.add_child(name='getMaster')
        #self.getMasterNode.bind(message_received=self.on_master_requested_by_osc)
        #self.setMasterNode = self.root_node.add_child(name='setMaster')
        #self.setMasterNode.bind(message_received=self.on_master_set_by_osc)
        self.GLOBAL_CONFIG.bind(update=self.on_GLOBAL_CONFIG_update)
        if self.GLOBAL_CONFIG.get('osc_use_discovery', True):
            self.comm.ServiceConnector.connect('new_host', self.on_host_discovered)
            self.comm.ServiceConnector.connect('remove_host', self.on_host_removed)
        
        self.Manager.bind(master_priority=self._on_master_priority_set, 
                          session_name=self._on_session_name_set, 
                          ring_master=self._on_ring_master_set)
    
    @property
    def root_address(self):
        return self.Manager.root_address
    @property
    def local_name(self):
        if not self.local_client:
            return '-'.join([self.GLOBAL_CONFIG.get('app_name'), socket.gethostname()])
        return self.local_client.name
    @property
    def isMaster(self):
        return self.oscMaster == self.local_name
    @property
    def isRingMaster(self):
        return self.Manager.ring_master == self.local_name
    @property
    def master_priority(self):
        return self.Manager.master_priority
    @master_priority.setter
    def master_priority(self, value):
        self.Manager.master_priority = value
    @property
    def discovered_sessions(self):
        return self.Manager.discovered_sessions
    @property
    def session_name(self):
        return self.Manager.session_name
    @session_name.setter
    def session_name(self, value):
        self.Manager.session_name = value
        
    def determine_ring_master(self):
        masters = {}
        for session in self.discovered_sessions.itervalues():
            m = session.master
            if m is None:
                continue
            #key = int(''.join([s.rjust(3, '0') for s in m.address.split('.')]))
            key = ip_to_int(m.address)
            masters[key] = m
        if not len(masters):
            return False
        master = masters[min(masters.keys())]
        if master.name != self.Manager.ring_master:
            self.Manager.ring_master = master.name
        return master
        
    def do_connect(self):
        serv = self.comm.ServiceConnector.add_service(**self.build_zeroconf_data())
        self.comm.ServiceConnector.add_listener(stype='_osc._udp')
        self.connected = True
        self.check_for_master()
        
    def do_disconnect(self, **kwargs):
        self.set_master(False)
        self.connected = False
        
    def add_to_session(self, **kwargs):
        ''' Adds a Client obj to a Session object which will handle
        master determination, etc.  If the Session does not exist,
        one is created.
        '''
        name = kwargs.get('name')
        if name is None:
            return
        client = kwargs.get('client')
        clients = kwargs.get('clients', [])
        if client is not None:
            clients.append(client)
        sessions = self.discovered_sessions
        session = sessions.get(name)
        if session:
            for c in clients:
                session.add_member(c)
        else:
            prebind = dict(master=self.on_session_master_set, 
                           members_update=self.on_session_members_update)
            session = sessions.add_child(name=name, members=clients, prebind=prebind)
            
    def remove_from_session(self, **kwargs):
        ''' Removes a Client object (or objects) from a Session object,
        if it exists.
        '''
        name = kwargs.get('name')
        client = kwargs.get('client')
        clients = kwargs.get('clients', [])
        if client is not None:
            clients.append(client)
        sessions = self.discovered_sessions
        session = sessions.get(name)
        if not session:
            return
        for c in clients:
            session.del_member(c)
        
    def add_client(self, **kwargs):
        kwargs.setdefault('port', self.ioManager.hostdata['sendport'])
        kwargs.setdefault('app_address', self.Manager.app_address)
        #kwargs['osc_parent_node'] = self.client_osc_node
        if socket.gethostname() in kwargs.get('name', ''):
            kwargs['isLocalhost'] = True
            #kwargs['master_priority'] = self.master_priority
        client = self.clients.add_child(**kwargs)
        self.clients_by_address[client.address] = client
        if client.isLocalhost:
            self.local_client = client
            #client.master_priority = self.master_priority
            #print 'local_client session: ', client.session_name
        self.add_to_session(name=client.session_name, client=client)
        client.bind(property_changed=self.on_client_obj_property_changed)
        #if client.session_name is not None:
        #    self.discovered_sessions.add(client.session_name)
        self.Manager.update_wildcards()
        #if self.check_master_attempts is None:
        #    self.check_for_master(client=client.name)
        propkeys = client.Properties.keys()
        self.LOG.info('add_client:', dict(zip(propkeys, [client.Properties[key].value for key in propkeys])))
        keys = ['name', 'address', 'port']
        s_kwargs = dict(zip(keys, [getattr(client, key) for key in keys]))
        s_kwargs.update({'client':client})
        self.emit('client_added', **s_kwargs)
        
    def remove_client(self, **kwargs):
        name = kwargs.get('name')
        client = self.clients.get(name)
        if client is None:
            return
        #self.remove_client_name(name, update_conf=False)
        #self.remove_client_address(addr, update_conf=False)
        client.unbind(self)
        self.clients.del_child(client)
        self.Manager.update_wildcards()
        self.LOG.info('remove_client:', name)
        self.emit('client_removed', name=name, client=client)
        if client.session_name is not None:
            self.remove_from_session(name=client.session_name, client=client)
    
    def on_session_master_set(self, **kwargs):
        session = kwargs.get('obj')
        value = kwargs.get('value')
        self.determine_ring_master()
        if session.name != self.session_name:
            return
        if session.master is None:
            m = self.determine_next_master()
            if m == self.local_client:
                self.set_master()
        if session.master.name == self.oscMaster:
            return
        if session.master != self.local_client:
            self.set_master(session.master.name)
            
    def on_session_members_update(self, **kwargs):
        session = kwargs.get('obj')
        mode = kwargs.get('mode')
        if mode == 'remove':
            if not len(session.members):
                session.unbind(self)
                self.discovered_sessions.del_child(session)
            
    def on_client_obj_property_changed(self, **kwargs):
        prop = kwargs.get('Property')
        old = kwargs.get('old')
        value = kwargs.get('value')
        client = kwargs.get('obj')
        if prop.name == 'isRingMaster' and value is True:
            if self.Manager.ring_master != client.name:
                self.Manager.ring_master = client.name
        elif prop.name == 'session_name' and value is not None:
            self.add_to_session(name=value, client=client)
            
    def build_zeroconf_data(self):
        d = dict(name=self.local_name, 
                 stype='_osc._udp', 
                 port=self.Manager.ioManager.hostdata['recvport'])
        txt = {'app_name':self.GLOBAL_CONFIG['app_name']}
        #session = self.GLOBAL_CONFIG.get('session_name')
        #if session:
        #    txt['session_name'] = session
        d['text'] = txt
        return d
        
    def build_curly_wildcard(self, l):
        return '{%s}' % (','.join(list(l)))
        
    def _on_master_priority_set(self, **kwargs):
        value = kwargs.get('value')
        #if self.local_client is not None:
        #    self.local_client.master_priority = value
        self.GLOBAL_CONFIG['master_priority'] = value
        self.update_conf(master_priority=value)
        #data = self.build_zeroconf_data()
        #self.comm.ServiceConnector.update_service(**data)
        
    def _on_session_name_set(self, **kwargs):
        value = kwargs.get('value')
        #if self.local_client is not None:
        #    self.local_client.session_name = value
        #    self.local_client.isMaster = False
        
        #data = self.build_zeroconf_data()
        #self.comm.ServiceConnector.update_service(**data)
        #self.select_new_master()
        if self.local_client is not None:
            self.add_to_session(name=value, client=self.local_client)
            #self.local_client.session_name = value
            master = self.discovered_sessions[value].master
            if master is not None:
                master = master.name
            self.set_master(master)
        self.GLOBAL_CONFIG['session_name'] = value
        
    def on_GLOBAL_CONFIG_update(self, **kwargs):
        keys = kwargs.get('keys')
        if not keys:
            keys = [kwargs.get('key')]
        for key in ['master_priority', 'session_name']:
            if key not in keys:
                continue
            value = self.GLOBAL_CONFIG.get(key)
            if value != getattr(self, key):
                setattr(self, key, value)
        
    def on_host_discovered(self, **kwargs):
        host = kwargs.get('host')
        if '.' not in host.address:
            return
        c_kwargs = host.hostdata.copy()
        c_kwargs.update({'discovered':True})
        self.add_client(**c_kwargs)
        
    def on_host_removed(self, **kwargs):
        self.LOG.info('remove:', kwargs)
        id = kwargs.get('id')
        self.remove_client(name=id)
        
    def check_for_master(self, **kwargs):
        if self.connected and not self.isMaster:
            name = kwargs.get('name')
            #if self.check_master_attempts is None:
            #    self.check_master_attempts = 0
            #self.cancel_check_master_timer()
            self.set_master_timeout = threading.Timer(10.0, self.on_check_master_timeout)
            self.set_master_timeout.start()
            #new_kwargs = {}#{'address':'getMaster'}
            #if name:
            #    new_kwargs.update({'client':name})
            #element = self.getMasterNode.send_message(value=self.session_name, 
            #                                          all_sessions=True, 
            #                                          timetag=-1)
            #print 'sent getmaster: ', [str(element)]
            
    def on_check_master_timeout(self):
        self.set_master()
        return
        self.check_master_attempts += 1
        if self.check_master_attempts == 3:
            self.check_master_attempts = None
            self.set_master()
        else:
            self.check_for_master()
        
    def set_master(self, name=None):
        self.cancel_check_master_timer()
        if self.master_takeover_timer:
            self.master_takeover_timer.cancel()
        if name is None:
            s = self.local_name
        elif name is False:
            s = None
        else:
            s = name
        if s != self.oscMaster:
            self.oscMaster = s
            if self.oscMaster is None:
                return
            lc = self.local_client
            if self.isMaster:
                if lc is not None:
                    lc.isMaster = True
            else:
                if lc is not None:
                    lc.isMaster = False
                m = self.determine_next_master()
                if m and m.isLocalhost and name is not False:
                    self.LOG.info('master takeover in 10 seconds...')
                    t = threading.Timer(10.0, self.on_master_takeover_timeout)
                    self.master_takeover_timer = t
                    t.start()
        self.LOG.info('master = ', self.oscMaster)
        self.determine_ring_master()
        self.emit('new_master', master=self.oscMaster, master_is_local=self.isMaster)
        
    def on_master_takeover_timeout(self):
        self.LOG.info('master takeover timer complete')
        self.master_takeover_timer = None
        m = self.determine_next_master()
        if not m:
            return
        if not self.isMaster and m.isLocalhost:
            self.set_master()
            
    def cancel_check_master_timer(self):
        if self.set_master_timeout and self.set_master_timeout.isAlive():
            self.set_master_timeout.cancel()
            self.set_master_timeout = None
            
    def determine_next_master(self):
        session = self.discovered_sessions[self.session_name]
        d = {}
        for c in session.members.itervalues():
            key = c.master_priority
            if key is None:
                continue
            if not (c.isSlave or c.isMaster or c.isLocalhost):
                continue
            if key in d and ip_to_int(c.address) > ip_to_int(d[key].address):
                continue
            d[key] = c
        self.LOG.info('clients by priority: ', d)
        if not len(d):
            return None
        return d[min(d)]
        
    def old_determine_next_master(self):
        d = {}
        for client in self.clients.itervalues():
            if not client.isSameSession:
                continue
            key = client.master_priority
            if key is not None and (client.isSlave or client.isMaster or client.isLocalhost):
                if key in d:
                    if d[key].name < client.name:
                        d[key] = client
                else:
                    d[key] = client
        self.LOG.info('clients by priority: ', d)
        if not len(d):
            return None
        return d[min(d)]
        
    def _on_ring_master_set(self, **kwargs):
        value = kwargs.get('value')
        self.LOG.info('RINGMASTER: ', value)
        self.local_client.isRingMaster = value == self.local_name
        self.Manager.ClockSync.isMaster = self.isRingMaster
            
    def _on_oscMaster_set(self, **kwargs):
        self.root_node.oscMaster = self.isMaster
Example #8
0
class Bin(gstBase):
    base_class = 'Bin'
    def __init__(self, **kwargs):
        super(Bin, self).__init__(**kwargs)
        if not hasattr(self, 'element_data'):
            self.element_data = kwargs.get('element_data', [])
        self.simple_links = kwargs.get('simple_links', True)
        if self.base_class == 'Bin':
            self._bin = self._gst_module.Bin(self.name)
            self.elem_container = self._bin
            
        self.Elements = ChildGroup(name='Elements', child_class=Element)
        self.unlinked_elements = {}
        self.init_instance(**kwargs)
        self.build_elements()
        self.link_elements()
        if self.base_class == 'Bin':
            self.enable_ghost_pads = set(kwargs.get('enable_ghost_pads', ['src', 'sink']))
            self.build_ghost_pads()
            
    def build_ghost_pads(self):
        padmap = {self._gst_module.PAD_SINK:'sink', 
                  self._gst_module.PAD_SRC:'src'}
        self.GhostPads = {'sink':[], 'src':[]}
        elems = {'sink':self.Elements.indexed_items.values()[0], 
                 'src':self.Elements.indexed_items.values()[-1:][0]}
        for key, elem in elems.iteritems():
            if key not in self.enable_ghost_pads:
                continue
            for p in elem._element.pads():
                direction = padmap.get(p.get_direction())
                if direction != key:
                    continue
                name = ''.join(['Ghost', p.get_name()])
                gpad = self._gst_module.GhostPad(name, p)
                self.elem_container.add_pad(gpad)
                self.GhostPads[key].append(gpad)
                
    def init_instance(self, **kwargs):
        pass
    def build_elements(self):
        for edata in self.element_data:
            if isinstance(edata, Element):
                edata = {'existing_object':edata}
            elif type(edata) == str:
                edata = {'gst_name':edata}
            self.add_element(**edata)
    def link_elements(self):
        if not self.simple_links or len(self.Elements) < 2:
            return
        for i, elem in self.Elements.indexed_items.iteritems():
            nextelem = self.Elements.indexed_items.get(i+1)
            if nextelem is None:
                continue
            try:
                elem._element.link(nextelem._element)
            except:
                sigs = []
                for e in [elem, nextelem]:
                    sigs.append(e._element.connect('pad-added', self.on_element_pad_added, i))
                self.unlinked_elements[i] = ((elem, nextelem), sigs)
    def add_element(self, **kwargs):
        element = self.Elements.add_child(**kwargs)
        self.elem_container.add(element._element)
    def on_element_pad_added(self, element, pad, index):
        if index not in self.unlinked_elements:
            return
        elems, gsignals = self.unlinked_elements.get(index)
        try:
            elems[0]._element.link(elems[1]._element)
            for e, sig in zip(elems, gsignals):
                e.disconnect(sig)
            del self.unlinked_elements[index]
        except:
            return
class Pipeline(Bin):
    _Properties = {'pipeline_state': dict(default='null')}
    base_class = 'Pipeline'

    def __init__(self, **kwargs):
        self.bin_data = kwargs.get('bin_data', [])
        if len(self.bin_data):
            kwargs['simple_links'] = False
        super(Pipeline, self).__init__(**kwargs)

        statekeys = ['NULL', 'PAUSED', 'PLAYING', 'READY', 'VOID_PENDING']
        gststates = [
            int(getattr(self._gst_module, '_'.join(['STATE', key])))
            for key in statekeys
        ]
        self.gst_state_map = dict(
            zip(gststates, [key.lower() for key in statekeys]))

        self.Bins = ChildGroup(name='Bins', child_class=Bin)
        for bindata in self.bin_data:
            if isinstance(bindata, Bin):
                bindata = {'existing_object': bindata}
            self.add_bin(**bindata)
        self.link_bins()

        bus = self._pipeline.get_bus()
        bus.add_signal_watch()
        bus.connect('message', self.on_bus_message)
        self.bind(pipeline_state=self.on_pipeline_state)

    def on_pipeline_state(self, **kwargs):
        #print kwargs
        pass

    def init_instance(self, **kwargs):
        self._pipeline = self._gst_module.Pipeline(self.name)
        self.elem_container = self._pipeline

    def add_bin(self, **kwargs):
        bin = self.Bins.add_child(**kwargs)
        self.elem_container.add(bin.elem_container)

    def link_bins(self):
        if len(self.Bins) < 2:
            return
        for index, bin in self.Bins.indexed_items.iteritems():
            nextbin = self.Bins.indexed_items.get(index + 1)
            if nextbin is None:
                continue
            #print index, bin.name, nextbin.name
            try:
                bin.elem_container.link(nextbin.elem_container)
            except:
                print 'could not link %s with %s' % (bin.name, nextbin.name)
                continue

#            for i, src in enumerate(bin.GhostPads['src']):
#                if len(nextbin.GhostPads['sink']) <= i - 1:
#                    print src.get_name(), ' linking to ', nextbin.GhostPads['sink'][i].get_name()
#                    src.link(nextbin.GhostPads['sink'][i])

    def on_bus_message(self, bus, message):
        self.pipeline_state = self.gst_state_map.get(
            int(self._pipeline.get_state()[1]))
        #print 'bus message: ', self.pipeline_state, self._pipeline.get_state()

    def start(self):
        self._pipeline.set_state(self._gst_module.STATE_PLAYING)

    def stop(self):
        self._pipeline.set_state(self._gst_module.STATE_NULL)
        self.pipeline_state = 'null'
class OSCSessionManager(BaseIO.BaseIO, Config):
    _confsection = "OSC"
    _Properties = {"oscMaster": dict(type=str)}

    def __init__(self, **kwargs):
        self.Manager = kwargs.get("Manager")
        self.ioManager = self.Manager.ioManager
        self.comm = self.Manager.comm
        self.root_node = self.Manager.root_node
        self.osc_tree = self.Manager.osc_tree
        BaseIO.BaseIO.__init__(self, **kwargs)
        Config.__init__(self, **kwargs)
        self.register_signal("client_added", "client_removed", "new_master")
        # self.oscMaster = None
        self.bind(oscMaster=self._on_oscMaster_set)
        self.set_master_timeout = None
        self.master_takeover_timer = None
        self.check_master_attempts = None
        self.local_client = None
        self.clients = ChildGroup(
            name="clients", osc_address="CLIENTS", osc_parent_node=self.root_node, child_class=Client, ignore_index=True
        )
        self.clients_by_address = {}
        # self.root_node.addCallback('/getMaster', self.on_master_requested_by_osc)
        # self.root_node.addCallback('/setMaster', self.on_master_set_by_osc)
        # self.getMasterNode = self.root_node.add_child(name='getMaster')
        # self.getMasterNode.bind(message_received=self.on_master_requested_by_osc)
        # self.setMasterNode = self.root_node.add_child(name='setMaster')
        # self.setMasterNode.bind(message_received=self.on_master_set_by_osc)
        self.GLOBAL_CONFIG.bind(update=self.on_GLOBAL_CONFIG_update)
        if self.GLOBAL_CONFIG.get("osc_use_discovery", True):
            self.comm.ServiceConnector.connect("new_host", self.on_host_discovered)
            self.comm.ServiceConnector.connect("remove_host", self.on_host_removed)

        self.Manager.bind(
            master_priority=self._on_master_priority_set,
            session_name=self._on_session_name_set,
            ring_master=self._on_ring_master_set,
        )

    @property
    def root_address(self):
        return self.Manager.root_address

    @property
    def local_name(self):
        if not self.local_client:
            return "-".join([self.GLOBAL_CONFIG.get("app_name"), socket.gethostname()])
        return self.local_client.name

    @property
    def isMaster(self):
        return self.oscMaster == self.local_name

    @property
    def isRingMaster(self):
        return self.Manager.ring_master == self.local_name

    @property
    def master_priority(self):
        return self.Manager.master_priority

    @master_priority.setter
    def master_priority(self, value):
        self.Manager.master_priority = value

    @property
    def discovered_sessions(self):
        return self.Manager.discovered_sessions

    @property
    def session_name(self):
        return self.Manager.session_name

    @session_name.setter
    def session_name(self, value):
        self.Manager.session_name = value

    def determine_ring_master(self):
        masters = {}
        for session in self.discovered_sessions.itervalues():
            m = session.master
            if m is None:
                continue
            # key = int(''.join([s.rjust(3, '0') for s in m.address.split('.')]))
            key = ip_to_int(m.address)
            masters[key] = m
        if not len(masters):
            return False
        master = masters[min(masters.keys())]
        if master.name != self.Manager.ring_master:
            self.Manager.ring_master = master.name
        return master

    def do_connect(self):
        serv = self.comm.ServiceConnector.add_service(**self.build_zeroconf_data())
        self.comm.ServiceConnector.add_listener(stype="_osc._udp")
        self.connected = True
        self.check_for_master()

    def do_disconnect(self, **kwargs):
        self.set_master(False)
        self.connected = False

    def add_to_session(self, **kwargs):
        """ Adds a Client obj to a Session object which will handle
        master determination, etc.  If the Session does not exist,
        one is created.
        """
        name = kwargs.get("name")
        if name is None:
            return
        client = kwargs.get("client")
        clients = kwargs.get("clients", [])
        if client is not None:
            clients.append(client)
        sessions = self.discovered_sessions
        session = sessions.get(name)
        if session:
            for c in clients:
                session.add_member(c)
        else:
            prebind = dict(master=self.on_session_master_set, members_update=self.on_session_members_update)
            session = sessions.add_child(name=name, members=clients, prebind=prebind)

    def remove_from_session(self, **kwargs):
        """ Removes a Client object (or objects) from a Session object,
        if it exists.
        """
        name = kwargs.get("name")
        client = kwargs.get("client")
        clients = kwargs.get("clients", [])
        if client is not None:
            clients.append(client)
        sessions = self.discovered_sessions
        session = sessions.get(name)
        if not session:
            return
        for c in clients:
            session.del_member(c)

    def add_client(self, **kwargs):
        kwargs.setdefault("port", self.ioManager.hostdata["sendport"])
        kwargs.setdefault("app_address", self.Manager.app_address)
        # kwargs['osc_parent_node'] = self.client_osc_node
        if socket.gethostname() in kwargs.get("name", ""):
            kwargs["isLocalhost"] = True
            # kwargs['master_priority'] = self.master_priority
        client = self.clients.add_child(**kwargs)
        self.clients_by_address[client.address] = client
        if client.isLocalhost:
            self.local_client = client
            # client.master_priority = self.master_priority
            # print 'local_client session: ', client.session_name
        self.add_to_session(name=client.session_name, client=client)
        client.bind(property_changed=self.on_client_obj_property_changed)
        # if client.session_name is not None:
        #    self.discovered_sessions.add(client.session_name)
        self.Manager.update_wildcards()
        # if self.check_master_attempts is None:
        #    self.check_for_master(client=client.name)
        propkeys = client.Properties.keys()
        self.LOG.info("add_client:", dict(zip(propkeys, [client.Properties[key].value for key in propkeys])))
        keys = ["name", "address", "port"]
        s_kwargs = dict(zip(keys, [getattr(client, key) for key in keys]))
        s_kwargs.update({"client": client})
        self.emit("client_added", **s_kwargs)

    def remove_client(self, **kwargs):
        name = kwargs.get("name")
        client = self.clients.get(name)
        if client is None:
            return
        # self.remove_client_name(name, update_conf=False)
        # self.remove_client_address(addr, update_conf=False)
        client.unbind(self)
        self.clients.del_child(client)
        self.Manager.update_wildcards()
        self.LOG.info("remove_client:", name)
        self.emit("client_removed", name=name, client=client)
        if client.session_name is not None:
            self.remove_from_session(name=client.session_name, client=client)

    def on_session_master_set(self, **kwargs):
        session = kwargs.get("obj")
        value = kwargs.get("value")
        self.determine_ring_master()
        if session.name != self.session_name:
            return
        if session.master is None:
            m = self.determine_next_master()
            if m == self.local_client:
                self.set_master()
        if session.master.name == self.oscMaster:
            return
        if session.master != self.local_client:
            self.set_master(session.master.name)

    def on_session_members_update(self, **kwargs):
        session = kwargs.get("obj")
        mode = kwargs.get("mode")
        if mode == "remove":
            if not len(session.members):
                session.unbind(self)
                self.discovered_sessions.del_child(session)

    def on_client_obj_property_changed(self, **kwargs):
        prop = kwargs.get("Property")
        old = kwargs.get("old")
        value = kwargs.get("value")
        client = kwargs.get("obj")
        if prop.name == "isRingMaster" and value is True:
            if self.Manager.ring_master != client.name:
                self.Manager.ring_master = client.name
        elif prop.name == "session_name" and value is not None:
            self.add_to_session(name=value, client=client)

    def build_zeroconf_data(self):
        d = dict(name=self.local_name, stype="_osc._udp", port=self.Manager.ioManager.hostdata["recvport"])
        txt = {"app_name": self.GLOBAL_CONFIG["app_name"]}
        # session = self.GLOBAL_CONFIG.get('session_name')
        # if session:
        #    txt['session_name'] = session
        d["text"] = txt
        return d

    def build_curly_wildcard(self, l):
        return "{%s}" % (",".join(list(l)))

    def _on_master_priority_set(self, **kwargs):
        value = kwargs.get("value")
        # if self.local_client is not None:
        #    self.local_client.master_priority = value
        self.GLOBAL_CONFIG["master_priority"] = value
        self.update_conf(master_priority=value)
        # data = self.build_zeroconf_data()
        # self.comm.ServiceConnector.update_service(**data)

    def _on_session_name_set(self, **kwargs):
        value = kwargs.get("value")
        # if self.local_client is not None:
        #    self.local_client.session_name = value
        #    self.local_client.isMaster = False

        # data = self.build_zeroconf_data()
        # self.comm.ServiceConnector.update_service(**data)
        # self.select_new_master()
        if self.local_client is not None:
            self.add_to_session(name=value, client=self.local_client)
            # self.local_client.session_name = value
            master = self.discovered_sessions[value].master
            if master is not None:
                master = master.name
            self.set_master(master)
        self.GLOBAL_CONFIG["session_name"] = value

    def on_GLOBAL_CONFIG_update(self, **kwargs):
        keys = kwargs.get("keys")
        if not keys:
            keys = [kwargs.get("key")]
        for key in ["master_priority", "session_name"]:
            if key not in keys:
                continue
            value = self.GLOBAL_CONFIG.get(key)
            if value != getattr(self, key):
                setattr(self, key, value)

    def on_host_discovered(self, **kwargs):
        host = kwargs.get("host")
        if "." not in host.address:
            return
        c_kwargs = host.hostdata.copy()
        c_kwargs.update({"discovered": True})
        self.add_client(**c_kwargs)

    def on_host_removed(self, **kwargs):
        self.LOG.info("remove:", kwargs)
        id = kwargs.get("id")
        self.remove_client(name=id)

    def check_for_master(self, **kwargs):
        if self.connected and not self.isMaster:
            name = kwargs.get("name")
            # if self.check_master_attempts is None:
            #    self.check_master_attempts = 0
            # self.cancel_check_master_timer()
            self.set_master_timeout = threading.Timer(10.0, self.on_check_master_timeout)
            self.set_master_timeout.start()
            # new_kwargs = {}#{'address':'getMaster'}
            # if name:
            #    new_kwargs.update({'client':name})
            # element = self.getMasterNode.send_message(value=self.session_name,
            #                                          all_sessions=True,
            #                                          timetag=-1)
            # print 'sent getmaster: ', [str(element)]

    def on_check_master_timeout(self):
        self.set_master()
        return
        self.check_master_attempts += 1
        if self.check_master_attempts == 3:
            self.check_master_attempts = None
            self.set_master()
        else:
            self.check_for_master()

    def set_master(self, name=None):
        self.cancel_check_master_timer()
        if self.master_takeover_timer:
            self.master_takeover_timer.cancel()
        if name is None:
            s = self.local_name
        elif name is False:
            s = None
        else:
            s = name
        if s != self.oscMaster:
            self.oscMaster = s
            if self.oscMaster is None:
                return
            lc = self.local_client
            if self.isMaster:
                if lc is not None:
                    lc.isMaster = True
            else:
                if lc is not None:
                    lc.isMaster = False
                m = self.determine_next_master()
                if m and m.isLocalhost and name is not False:
                    self.LOG.info("master takeover in 10 seconds...")
                    t = threading.Timer(10.0, self.on_master_takeover_timeout)
                    self.master_takeover_timer = t
                    t.start()
        self.LOG.info("master = ", self.oscMaster)
        self.determine_ring_master()
        self.emit("new_master", master=self.oscMaster, master_is_local=self.isMaster)

    def on_master_takeover_timeout(self):
        self.LOG.info("master takeover timer complete")
        self.master_takeover_timer = None
        m = self.determine_next_master()
        if not m:
            return
        if not self.isMaster and m.isLocalhost:
            self.set_master()

    def cancel_check_master_timer(self):
        if self.set_master_timeout and self.set_master_timeout.isAlive():
            self.set_master_timeout.cancel()
            self.set_master_timeout = None

    def determine_next_master(self):
        session = self.discovered_sessions[self.session_name]
        d = {}
        for c in session.members.itervalues():
            key = c.master_priority
            if key is None:
                continue
            if not (c.isSlave or c.isMaster or c.isLocalhost):
                continue
            if key in d and ip_to_int(c.address) > ip_to_int(d[key].address):
                continue
            d[key] = c
        self.LOG.info("clients by priority: ", d)
        if not len(d):
            return None
        return d[min(d)]

    def old_determine_next_master(self):
        d = {}
        for client in self.clients.itervalues():
            if not client.isSameSession:
                continue
            key = client.master_priority
            if key is not None and (client.isSlave or client.isMaster or client.isLocalhost):
                if key in d:
                    if d[key].name < client.name:
                        d[key] = client
                else:
                    d[key] = client
        self.LOG.info("clients by priority: ", d)
        if not len(d):
            return None
        return d[min(d)]

    def _on_ring_master_set(self, **kwargs):
        value = kwargs.get("value")
        self.LOG.info("RINGMASTER: ", value)
        self.local_client.isRingMaster = value == self.local_name
        self.Manager.ClockSync.isMaster = self.isRingMaster

    def _on_oscMaster_set(self, **kwargs):
        self.root_node.oscMaster = self.isMaster