def add_control(self, control): """Add a control to this board.""" LOGGER.debug('VirtualMIDI::add_control() -- Adding %s control to %s', control, self._serial) if control.identifier in self._controls: LOGGER.warning('VirtualMIDI::add_control() -- Overwriting control %s', control.identifier) self._controls[control.identifier] = control self._control_map['name'][control.name] = control self._control_map['description'][control.description] = control
def notify(self, signal, control, *args, **kwargs): # pylint: disable=W0221 """Notify this object of an event.""" LOGGER.info('Adapter::notify(%s, %s, %s, %s)', signal, control, args, kwargs) try: for callback in self._callback_map[control][signal]: callback(control) except KeyError as key_err: LOGGER.warning('Adapter::notify() failed to find key %s in %s', key_err, self._callback_map)
def on_change(self, value): """Call to change the state of the button.""" if value == self._state_on: self.pressed() elif value == self._state_off: self.released() else: LOGGER.warning('<%s>[%s] got UNKNOWN State value: %s', type(self).__name__, self.name, value) self.state = Button.State.UNKNOWN
def __call__(self, event, data=None): message, deltatime = event channel, control_identifier, value = message LOGGER.debug( 'Received event on control %d | value=%d | deltatime=%d | channel=%s', control_identifier, value, deltatime, channel) control = self.get_control(control_identifier) if isinstance(control, Control): control.on_change(value)
def _setup_board_config(self, serial=None, controls=None, **kwargs):# pylint: disable=unused-argument self._serial = serial LOGGER.info('Configuring VirtualMIDI: %s', serial) for control_type in controls.get('types', []): control_params = control_type.copy() control_type_class = utils.attempt_import(control_params['type'], _myvars=vars()) del control_params['type'] for control in controls.get(control_type['name']): this_control_params = control_params.copy() this_control_params.update(control) ctrl = Control.create_control(control_type_class, **this_control_params) self.add_control(ctrl)
def initialize(self): """Setup and configure the publisher.""" if self._topic and self._message_type: LOGGER.info('<%s>[%s] -- Creating ROS.Publisher(%s, %s)', type(self).__name__, self.name, self._topic, self._message_type) self._publisher = rospy.Publisher(self._topic, self._message_type, queue_size=self._queue_size) else: LOGGER.warning( '<%s>[%s] -- Must specify topic and message type! (%s, %s)', type(self).__name__, self.name, self._topic, self._message_type) self._publisher = None
def _setup_config(self, config=None, name=None, adapters=None, controls=None, **kwargs):# pylint: disable=unused-argument self._user_config_description = name if isinstance(config, str): config = utils.load_from_file(config) if not isinstance(config, dict): raise TypeError('MIDI board config file not specified.') self._setup_board_config(**config) for adapter_type in adapters: adapter_params = adapter_type.copy() adapter_type_class = utils.attempt_import(adapter_params['type'], _myvars=vars()) del adapter_params['type'] adapter = Adapter.create_adapter(adapter_type_class, **adapter_params) self.add_adapter(adapter) for control_type in controls: for control in controls.get(control_type): try: self._configure_control(control) except KeyError as key_err: LOGGER.warning('VirtualMIDI::_setup_user_config() -- Malformed control; requires key: %s', key_err) except AttributeError as att_err: LOGGER.warning('VirtualMIDI::_setup_user_config() -- Unknown callback: %s', att_err)
def _configure_control(self, control_data): control = self._controls.get(control_data['identifier'], None) if not control: control_type = control_data['type'] control_type_class = utils.attempt_import(control_type, _myvars=vars()) control = Control.create_control(control_type_class, **control_data) self.add_control(control) LOGGER.warning('VirtualMIDI::_configure_control() -- Control.identifier %s not found. ' 'This control is created virtually..', control_data['identifier']) for key in control.properties: try: old_key = getattr(control, key) setattr(control, key, control_data[key]) if old_key in self._control_map[key]: del self._control_map[key][old_key] self._control_map[key][control_data[key]] = control except KeyError: pass for signal_name in control_data['signals']: signal = control_data['signals'][signal_name] self._configure_control_signal(control, signal_name, signal) return True
def initialize(port): """Connect to the midi board.""" global MIDI_IN, MIDI_OUT, MIDI_PORT_NAME MIDI_PORT_NAME = port if not MIDI_IN.is_port_open(): try: ports = MIDI_IN.get_ports() if port in ports: port_number = ports.index(port) MIDI_IN.open_port(port_number) MIDI_OUT.open_port(port_number) LOGGER.info('Successfully connected to board') else: LOGGER.warning('Failed to connect to board') return False except rtmidi.RtMidiError as midi_error: LOGGER.warning('Unable to connect to MIDI board\n\t%s', midi_error) return False return True
def _configure_control_signal(self, control, signal_name, signal): if isinstance(signal, list): for a_signal in signal: self._configure_control_signal(control, signal_name, a_signal) return True if not isinstance(signal, str): LOGGER.warning('VirtualMIDI::_configure_control_signal() -- Bad yaml data: signal data must be string or list of strings.') return False adapter_name, callback_name = signal.split('.') if 'this' in adapter_name: adapter = control else: adapter = self._adapters.get(adapter_name) if not adapter: LOGGER.warning('VirtualMIDI::_configure_control_signal() -- Unknown adapter: %s', adapter_name) return False callback = getattr(adapter, callback_name) signal = getattr(type(control), signal_name) if not signal: LOGGER.warning('VirtualMIDI::_configure_control_signal() -- Unknown signal: %s', signal_name) return False self.connect(control, signal, adapter, callback) return True
def _publish(self, msg): LOGGER.debug('<%s>[%s] -- publish(%s)', type(self).__name__, self.name, msg) if isinstance(self._publisher, rospy.Publisher): if isinstance(msg, self._message_type): self._publisher.publish(msg)
def connect(control, signal, adapter, callback): """Connect a control::signal to an adapter::callback for notification.""" LOGGER.info('VirtualMIDI::connect %s::%s <--> %s::%s', control, signal, adapter, callback.__name__) control.add_observer(adapter, signal, callback) adapter.set_callback(control, signal, callback)
def add_adapter(self, adapter): """Add a control to this board.""" LOGGER.debug('VirtualMIDI::add_adapter() -- Adding %s adapter to %s', adapter, self._serial) if adapter.name in self._adapters: LOGGER.warning('VirtualMIDI::add_adapter() -- Overwriting adapter %s', adapter.name) self._adapters[adapter.name] = adapter
def finalize(self, *args, **kwargs): """Cleanup the object and shutdown.""" LOGGER.info('Observer::finalize(%s, %s)', args, kwargs)
def notify(self, *args, **kwargs): """Update the object with new information.""" LOGGER.info('Observer::notify(%s, %s)', args, kwargs)