def interconnector_start_stop(self): if not self._interconnector: self._enable_controls(False) self.button_start_stop.setText('&Stop') self.callback_log('Settings') self.callback_log('========') self.callback_log('MCU emulation: %s' % self._mcu_emulated_model) self.callback_log('Connection: %s' % self._mcu_connection) self.callback_log('MIDI input: %s' % self._mcu_midi_input) self.callback_log('MIDI output: %s' % self._mcu_midi_output) self.callback_log('') self.callback_log('Controller: %s' % self._hardware_controller) self.callback_log('MIDI input: %s' % \ self._controller_midi_input) self.callback_log('MIDI output: %s' % \ self._controller_midi_output) self.callback_log('') self.callback_log('MIDI latency: %s ms' % self._midi_latency) self.callback_log('') self.callback_log('') if configuration.has_changed(): self.callback_log('Saving configuration file ...') configuration.save_configuration() self.callback_log('Starting MCU emulation...') self.callback_log('', True) # the "interconnector" is the brain of this application -- it # interconnects Mackie Control Host and MIDI controller while # handling the complete MIDI translation between those two self._interconnector = McuInterconnector( \ self, \ self._mcu_model_id, \ self._mcu_connection, \ self._mcu_midi_input, \ self._mcu_midi_output, \ self._hardware_controller_class, \ self._controller_midi_input, \ self._controller_midi_output, \ self.callback_log) self._interconnector.connect() self._timer.start() else: self._enable_controls(True) self.button_start_stop.setText('&Start') self._interconnector_stop()
def interconnector_start_stop(self): if not self._interconnector: self._enable_controls(False) self.button_start_stop.setText('&Stop') self.callback_log('Settings') self.callback_log('========') self.callback_log('MCU emulation: %s' % self._mcu_emulated_model) self.callback_log('Connection: %s' % self._mcu_connection) self.callback_log('MIDI input: %s' % self._mcu_midi_input) self.callback_log('MIDI output: %s' % self._mcu_midi_output) self.callback_log('') self.callback_log('Controller: %s' % self._hardware_controller) self.callback_log('MIDI input: %s' % \ self._controller_midi_input) self.callback_log('MIDI output: %s' % \ self._controller_midi_output) self.callback_log('') self.callback_log('MIDI latency: %s ms' % self._midi_latency) self.callback_log('') self.callback_log('') if configuration.has_changed(): self.callback_log('Saving configuration file ...') configuration.save_configuration() self.callback_log('Starting MCU emulation...') self.callback_log('', True) # the "interconnector" is the brain of this application -- it # interconnects Mackie Control Host and MIDI controller while # handling the complete MIDI translation between those two self._interconnector = McuInterconnector( \ self, \ self._mcu_model_id, \ self._mcu_connection, \ self._mcu_midi_input, \ self._mcu_midi_output, \ self._hardware_controller_class, \ self._controller_midi_input, \ self._controller_midi_output, \ self.callback_log) self._interconnector.connect() self._timer.start() else: self._enable_controls(True) self.button_start_stop.setText('&Start') self._interconnector_stop()
class PythonMcu(QFrame): def __init__(self, parent=None): super(PythonMcu, self).__init__(parent) font = QFont() font.setStyleHint(QFont.TypeWriter, QFont.PreferAntialias) char_format = QTextCharFormat() char_format.setFontFamily(font.defaultFamily()) text_width = QFontMetrics(char_format.font()).width('*') * 80 # must be defined before starting the logger! self._edit_logger = QPlainTextEdit() self._edit_logger.setReadOnly(True) self._edit_logger.setCurrentCharFormat(char_format) self._edit_logger.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self._edit_logger.setFixedWidth(text_width) # must be defined before reading the configuration file! self._edit_usage_hint = QPlainTextEdit() self._edit_usage_hint.setReadOnly(True) self._edit_usage_hint.setCurrentCharFormat(char_format) self.callback_log('') self.callback_log(configuration.get_full_description()) self.callback_log('') self.callback_log('') self.callback_log('Version numbers') self.callback_log('===============') self.callback_log('Python: %s (%s)' % ( \ platform.python_version(), platform.python_implementation())) self.callback_log('PySide: %s' % PySide.__version__) self.callback_log('pygame: %s' % pygame.version.ver) self.callback_log('') self.callback_log('') # auto-scroll log window by setting cursor to end of document self._edit_logger.moveCursor(QTextCursor.End, QTextCursor.MoveAnchor) self._read_configuration() self._timer = None self._interconnector = None icon = self.style().standardIcon(QStyle.SP_TitleBarMenuButton) self.setWindowIcon(icon) mcu_model_ids = ['Logic Control', 'Logic Control XT', \ 'Mackie Control', 'Mackie Control XT'] hardware_controllers = [ \ 'Novation ZeRO SL MkII', \ 'Novation ZeRO SL MkII (MIDI)' ] # get version number of "Python MCU" version = configuration.get_application_information('version') self.setWindowTitle(configuration.get_version(True)) # create layouts and add widgets self.layout = QHBoxLayout() self.setLayout(self.layout) self.layout_2 = QVBoxLayout() self.layout.addLayout(self.layout_2) self.frame_mcu = QFrame() self.frame_mcu.setFrameStyle(QFrame.Box) self.frame_mcu.setFrameShadow(QFrame.Sunken) self.layout_2.addWidget(self.frame_mcu) self.grid_layout_mcu = QGridLayout() self.frame_mcu.setLayout(self.grid_layout_mcu) self.frame_controller = QFrame() self.frame_controller.setFrameStyle(QFrame.Box) self.frame_controller.setFrameShadow(QFrame.Sunken) self.layout_2.addWidget(self.frame_controller) self.grid_layout_controller = QGridLayout() self.frame_controller.setLayout(self.grid_layout_controller) self._combo_mcu_model_id = self._create_combo_box( \ self.grid_layout_mcu, self._mcu_emulated_model, \ 'Emulation:', mcu_model_ids) connection_types = [MackieHostControl.ASSUME_SUCCESSFUL_CONNECTION, \ MackieHostControl.CHALLENGE_RESPONSE, \ MackieHostControl.WAIT_FOR_MIDI_DATA] self._combo_mcu_connection = self._create_combo_box( \ self.grid_layout_mcu, self._mcu_connection, \ 'Connection:', connection_types) self._combo_mcu_midi_input = self._create_combo_box( \ self.grid_layout_mcu, self._mcu_midi_input, \ 'MIDI In:', MidiConnection.get_midi_inputs()) self._combo_mcu_midi_output = self._create_combo_box( \ self.grid_layout_mcu, self._mcu_midi_output, \ 'MIDI Out:', MidiConnection.get_midi_outputs()) self._combo_hardware_controller = self._create_combo_box( \ self.grid_layout_controller, self._hardware_controller, \ 'Controller:', hardware_controllers) self._combo_controller_midi_input = self._create_combo_box( \ self.grid_layout_controller, self._controller_midi_input, \ 'MIDI In:', MidiConnection.get_midi_inputs()) self._combo_controller_midi_output = self._create_combo_box( \ self.grid_layout_controller, self._controller_midi_output, \ 'MIDI Out:', MidiConnection.get_midi_outputs()) self.grid_layout_controller.addWidget( \ self._edit_usage_hint, self.grid_layout_controller.rowCount(), \ 0, 1, 2) self.layout.addWidget(self._edit_logger) self.bottom_layout = QHBoxLayout() self.layout_2.addLayout(self.bottom_layout) self.button_start_stop = QPushButton('&Start') self.bottom_layout.addWidget(self.button_start_stop) self.button_start_stop.setDefault(True) self.button_start_stop.setFocus() self.button_start_stop.clicked.connect(self.interconnector_start_stop) self.button_close = QPushButton('&Close') self.bottom_layout.addWidget(self.button_close) self.button_close.clicked.connect(self.close_application) self.button_about = QPushButton('A&bout') self.bottom_layout.addWidget(self.button_about) self.button_about.clicked.connect(self.display_about) self._enable_controls(True) self._timer = QTimer(self) self._timer.setInterval(int(self._midi_latency)) self._timer.timeout.connect(self.process_midi_input) def _read_configuration(self): # initialise defaults for MCU and hardware controller mcu_emulated_model_default = MackieHostControl.get_preferred_mcu_model() hardware_controller_default = 'Novation ZeRO SL MkII' midi_latency_default = '1' # retrieve user configuration for MCU and hardware controller self._mcu_emulated_model = configuration.get_option( \ 'Python MCU', 'mcu_emulated_model', mcu_emulated_model_default) self._hardware_controller = configuration.get_option( \ 'Python MCU', 'controller_hardware', hardware_controller_default) self._midi_latency = configuration.get_option( \ 'Python MCU', 'midi_latency', midi_latency_default) # calculate MCU model ID from its name self._mcu_model_id = MackieHostControl.get_mcu_id_from_model( \ self._mcu_emulated_model) # Logic Control units use MCU challenge-response by default, ... if self._mcu_model_id in [0x10, 0x11]: mcu_connection_default = MackieHostControl.CHALLENGE_RESPONSE # whereas Mackie Control Units don't seem to use it else: mcu_connection_default = MackieHostControl.WAIT_FOR_MIDI_DATA self._mcu_connection = configuration.get_option( \ 'Python MCU', 'mcu_connection', mcu_connection_default) # get preferred MIDI ports for hardware controller (controller_midi_input_default, controller_midi_output_default) = \ self._initialise_hardware_controller() # initialise MIDI port defaults for MCU and hardware # controller mcu_midi_input_default = \ MackieHostControl.get_preferred_midi_input() mcu_midi_output_default = \ MackieHostControl.get_preferred_midi_output() # retrieve user configuration for MCU's MIDI ports self._mcu_midi_input = configuration.get_option( \ 'Python MCU', 'mcu_midi_input', \ mcu_midi_input_default) self._mcu_midi_output = configuration.get_option( \ 'Python MCU', 'mcu_midi_output', \ mcu_midi_output_default) # retrieve user configuration for hardware controller's MIDI # ports self._controller_midi_input = configuration.get_option( \ 'Python MCU', 'controller_midi_input', \ controller_midi_input_default) self._controller_midi_output = configuration.get_option( \ 'Python MCU', 'controller_midi_output', \ controller_midi_output_default) def _create_combo_box(self, layout, selection, label_text, choices): row = layout.rowCount() label = QLabel(None) label.setText(label_text) layout.addWidget(label, row, 0) widget = QComboBox() layout.addWidget(widget, row, 1) choices.sort() widget.addItems(choices) current_index = widget.findText(selection) widget.setCurrentIndex(current_index) widget.currentIndexChanged.connect(self.combobox_item_selected) return widget def _enable_controls(self, state): self.frame_mcu.setEnabled(state) self.frame_controller.setEnabled(state) def _initialise_hardware_controller(self): # the hardware controller's class name is simply the # controller's manufacturer and name with all spaces converted # to underscores and all brackets removed self._hardware_controller_class = \ self._hardware_controller.replace(' ', '_') self._hardware_controller_class = \ self._hardware_controller_class.replace('(', '').replace(')', '') self._hardware_controller_class = \ self._hardware_controller_class.replace('[', '').replace(']', '') self._hardware_controller_class = \ self._hardware_controller_class.replace('{', '').replace('}', '') # get hardware controller's preferred MIDI ports eval_controller_midi_input = \ '{0!s}.{0!s}.get_preferred_midi_input()'.format( \ self._hardware_controller_class) eval_controller_midi_output = \ '{0!s}.{0!s}.get_preferred_midi_output()'.format( \ self._hardware_controller_class) controller_midi_input_default = eval(eval_controller_midi_input) controller_midi_output_default = eval(eval_controller_midi_output) # show controller's usage hint usage_hint = '{0!s}.{0!s}.get_usage_hint()'.format( \ self._hardware_controller_class) self._edit_usage_hint.setPlainText(eval(usage_hint)) return (controller_midi_input_default, controller_midi_output_default) def callback_log(self, message, repaint=False): if repaint: self._edit_logger.repaint() print message self._edit_logger.appendPlainText(message) def combobox_item_selected(self, ignore_this): widget = self.sender() selected_text = widget.currentText() if widget == self._combo_mcu_model_id: self._mcu_emulated_model = selected_text configuration.set_option( \ 'Python MCU', 'mcu_emulated_model', \ self._mcu_emulated_model) if self._mcu_emulated_model.startswith('Logic'): current_index = self._combo_mcu_connection.findText( \ MackieHostControl.CHALLENGE_RESPONSE) self._combo_mcu_connection.setCurrentIndex(current_index) else: current_index = self._combo_mcu_connection.findText( \ MackieHostControl.WAIT_FOR_MIDI_DATA) self._combo_mcu_connection.setCurrentIndex(current_index) elif widget == self._combo_mcu_midi_input: self._mcu_midi_input = selected_text configuration.set_option( \ 'Python MCU', 'mcu_midi_input', \ self._mcu_midi_input) elif widget == self._combo_mcu_midi_output: self._mcu_midi_output = selected_text configuration.set_option( \ 'Python MCU', 'mcu_midi_output', \ self._mcu_midi_output) elif widget == self._combo_hardware_controller: self._hardware_controller = selected_text configuration.set_option( \ 'Python MCU', 'controller_hardware', \ self._hardware_controller) # get preferred MIDI ports for hardware controller (controller_midi_input_default, controller_midi_output_default) = \ self._initialise_hardware_controller() # update hardware controller's MIDI ports in GUI current_index = self._combo_controller_midi_input.findText( \ controller_midi_input_default) self._combo_controller_midi_input.setCurrentIndex(current_index) current_index = self._combo_controller_midi_output.findText( \ controller_midi_output_default) self._combo_controller_midi_output.setCurrentIndex(current_index) elif widget == self._combo_controller_midi_input: self._controller_midi_input = selected_text configuration.set_option( \ 'Python MCU', 'controller_midi_input', \ self._controller_midi_input) elif widget == self._combo_controller_midi_output: self._controller_midi_output = selected_text configuration.set_option( \ 'Python MCU', 'controller_midi_output', \ self._controller_midi_output) elif widget == self._combo_mcu_connection: self._mcu_connection = selected_text configuration.set_option( \ 'Python MCU', 'mcu_connection', \ self._mcu_connection) else: self.callback_log('QComboBox not handled ("%s").' % selected_text) def process_midi_input(self): self._interconnector.process_midi_input() def display_about(self): AboutDialog(self).show() def interconnector_start_stop(self): if not self._interconnector: self._enable_controls(False) self.button_start_stop.setText('&Stop') self.callback_log('Settings') self.callback_log('========') self.callback_log('MCU emulation: %s' % self._mcu_emulated_model) self.callback_log('Connection: %s' % self._mcu_connection) self.callback_log('MIDI input: %s' % self._mcu_midi_input) self.callback_log('MIDI output: %s' % self._mcu_midi_output) self.callback_log('') self.callback_log('Controller: %s' % self._hardware_controller) self.callback_log('MIDI input: %s' % \ self._controller_midi_input) self.callback_log('MIDI output: %s' % \ self._controller_midi_output) self.callback_log('') self.callback_log('MIDI latency: %s ms' % self._midi_latency) self.callback_log('') self.callback_log('') if configuration.has_changed(): self.callback_log('Saving configuration file ...') configuration.save_configuration() self.callback_log('Starting MCU emulation...') self.callback_log('', True) # the "interconnector" is the brain of this application -- it # interconnects Mackie Control Host and MIDI controller while # handling the complete MIDI translation between those two self._interconnector = McuInterconnector( \ self, \ self._mcu_model_id, \ self._mcu_connection, \ self._mcu_midi_input, \ self._mcu_midi_output, \ self._hardware_controller_class, \ self._controller_midi_input, \ self._controller_midi_output, \ self.callback_log) self._interconnector.connect() self._timer.start() else: self._enable_controls(True) self.button_start_stop.setText('&Start') self._interconnector_stop() def _interconnector_stop(self): self._timer.stop() self.callback_log('') self.callback_log('Stopping MCU emulation...') self.callback_log('') self._interconnector.disconnect() self._interconnector = None self.callback_log('', True) def close_application(self): self.close() def closeEvent(self, event): if self._interconnector: self._interconnector_stop() self.callback_log('Exiting application...') self.callback_log('', True)
class PythonMcu(QFrame): def __init__(self, parent=None): super(PythonMcu, self).__init__(parent) font = QFont() font.setStyleHint(QFont.TypeWriter, QFont.PreferAntialias) char_format = QTextCharFormat() char_format.setFontFamily(font.defaultFamily()) text_width = QFontMetrics(char_format.font()).width('*') * 80 # must be defined before starting the logger! self._edit_logger = QPlainTextEdit() self._edit_logger.setReadOnly(True) self._edit_logger.setCurrentCharFormat(char_format) self._edit_logger.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self._edit_logger.setFixedWidth(text_width) # must be defined before reading the configuration file! self._edit_usage_hint = QPlainTextEdit() self._edit_usage_hint.setReadOnly(True) self._edit_usage_hint.setCurrentCharFormat(char_format) self.callback_log('') self.callback_log(configuration.get_full_description()) self.callback_log('') self.callback_log('') self.callback_log('Version numbers') self.callback_log('===============') self.callback_log('Python: %s (%s)' % ( \ platform.python_version(), platform.python_implementation())) self.callback_log('PySide: %s' % PySide.__version__) self.callback_log('pygame: %s' % pygame.version.ver) self.callback_log('') self.callback_log('') # auto-scroll log window by setting cursor to end of document self._edit_logger.moveCursor(QTextCursor.End, QTextCursor.MoveAnchor) self._read_configuration() self._timer = None self._interconnector = None icon = self.style().standardIcon(QStyle.SP_TitleBarMenuButton) self.setWindowIcon(icon) mcu_model_ids = ['Logic Control', 'Logic Control XT', \ 'Mackie Control', 'Mackie Control XT'] hardware_controllers = [ \ 'Novation ZeRO SL MkII', \ 'Novation ZeRO SL MkII (MIDI)' ] # get version number of "Python MCU" version = configuration.get_application_information('version') self.setWindowTitle(configuration.get_version(True)) # create layouts and add widgets self.layout = QHBoxLayout() self.setLayout(self.layout) self.layout_2 = QVBoxLayout() self.layout.addLayout(self.layout_2) self.frame_mcu = QFrame() self.frame_mcu.setFrameStyle(QFrame.Box) self.frame_mcu.setFrameShadow(QFrame.Sunken) self.layout_2.addWidget(self.frame_mcu) self.grid_layout_mcu = QGridLayout() self.frame_mcu.setLayout(self.grid_layout_mcu) self.frame_controller = QFrame() self.frame_controller.setFrameStyle(QFrame.Box) self.frame_controller.setFrameShadow(QFrame.Sunken) self.layout_2.addWidget(self.frame_controller) self.grid_layout_controller = QGridLayout() self.frame_controller.setLayout(self.grid_layout_controller) self._combo_mcu_model_id = self._create_combo_box( \ self.grid_layout_mcu, self._mcu_emulated_model, \ 'Emulation:', mcu_model_ids) connection_types = [MackieHostControl.ASSUME_SUCCESSFUL_CONNECTION, \ MackieHostControl.CHALLENGE_RESPONSE, \ MackieHostControl.WAIT_FOR_MIDI_DATA] self._combo_mcu_connection = self._create_combo_box( \ self.grid_layout_mcu, self._mcu_connection, \ 'Connection:', connection_types) self._combo_mcu_midi_input = self._create_combo_box( \ self.grid_layout_mcu, self._mcu_midi_input, \ 'MIDI In:', MidiConnection.get_midi_inputs()) self._combo_mcu_midi_output = self._create_combo_box( \ self.grid_layout_mcu, self._mcu_midi_output, \ 'MIDI Out:', MidiConnection.get_midi_outputs()) self._combo_hardware_controller = self._create_combo_box( \ self.grid_layout_controller, self._hardware_controller, \ 'Controller:', hardware_controllers) self._combo_controller_midi_input = self._create_combo_box( \ self.grid_layout_controller, self._controller_midi_input, \ 'MIDI In:', MidiConnection.get_midi_inputs()) self._combo_controller_midi_output = self._create_combo_box( \ self.grid_layout_controller, self._controller_midi_output, \ 'MIDI Out:', MidiConnection.get_midi_outputs()) self.grid_layout_controller.addWidget( \ self._edit_usage_hint, self.grid_layout_controller.rowCount(), \ 0, 1, 2) self.layout.addWidget(self._edit_logger) self.bottom_layout = QHBoxLayout() self.layout_2.addLayout(self.bottom_layout) self.button_start_stop = QPushButton('&Start') self.bottom_layout.addWidget(self.button_start_stop) self.button_start_stop.setDefault(True) self.button_start_stop.setFocus() self.button_start_stop.clicked.connect(self.interconnector_start_stop) self.button_close = QPushButton('&Close') self.bottom_layout.addWidget(self.button_close) self.button_close.clicked.connect(self.close_application) self.button_about = QPushButton('A&bout') self.bottom_layout.addWidget(self.button_about) self.button_about.clicked.connect(self.display_about) self._enable_controls(True) self._timer = QTimer(self) self._timer.setInterval(int(self._midi_latency)) self._timer.timeout.connect(self.process_midi_input) def _read_configuration(self): # initialise defaults for MCU and hardware controller mcu_emulated_model_default = MackieHostControl.get_preferred_mcu_model( ) hardware_controller_default = 'Novation ZeRO SL MkII' midi_latency_default = '1' # retrieve user configuration for MCU and hardware controller self._mcu_emulated_model = configuration.get_option( \ 'Python MCU', 'mcu_emulated_model', mcu_emulated_model_default) self._hardware_controller = configuration.get_option( \ 'Python MCU', 'controller_hardware', hardware_controller_default) self._midi_latency = configuration.get_option( \ 'Python MCU', 'midi_latency', midi_latency_default) # calculate MCU model ID from its name self._mcu_model_id = MackieHostControl.get_mcu_id_from_model( \ self._mcu_emulated_model) # Logic Control units use MCU challenge-response by default, ... if self._mcu_model_id in [0x10, 0x11]: mcu_connection_default = MackieHostControl.CHALLENGE_RESPONSE # whereas Mackie Control Units don't seem to use it else: mcu_connection_default = MackieHostControl.WAIT_FOR_MIDI_DATA self._mcu_connection = configuration.get_option( \ 'Python MCU', 'mcu_connection', mcu_connection_default) # get preferred MIDI ports for hardware controller (controller_midi_input_default, controller_midi_output_default) = \ self._initialise_hardware_controller() # initialise MIDI port defaults for MCU and hardware # controller mcu_midi_input_default = \ MackieHostControl.get_preferred_midi_input() mcu_midi_output_default = \ MackieHostControl.get_preferred_midi_output() # retrieve user configuration for MCU's MIDI ports self._mcu_midi_input = configuration.get_option( \ 'Python MCU', 'mcu_midi_input', \ mcu_midi_input_default) self._mcu_midi_output = configuration.get_option( \ 'Python MCU', 'mcu_midi_output', \ mcu_midi_output_default) # retrieve user configuration for hardware controller's MIDI # ports self._controller_midi_input = configuration.get_option( \ 'Python MCU', 'controller_midi_input', \ controller_midi_input_default) self._controller_midi_output = configuration.get_option( \ 'Python MCU', 'controller_midi_output', \ controller_midi_output_default) def _create_combo_box(self, layout, selection, label_text, choices): row = layout.rowCount() label = QLabel(None) label.setText(label_text) layout.addWidget(label, row, 0) widget = QComboBox() layout.addWidget(widget, row, 1) choices.sort() widget.addItems(choices) current_index = widget.findText(selection) widget.setCurrentIndex(current_index) widget.currentIndexChanged.connect(self.combobox_item_selected) return widget def _enable_controls(self, state): self.frame_mcu.setEnabled(state) self.frame_controller.setEnabled(state) def _initialise_hardware_controller(self): # the hardware controller's class name is simply the # controller's manufacturer and name with all spaces converted # to underscores and all brackets removed self._hardware_controller_class = \ self._hardware_controller.replace(' ', '_') self._hardware_controller_class = \ self._hardware_controller_class.replace('(', '').replace(')', '') self._hardware_controller_class = \ self._hardware_controller_class.replace('[', '').replace(']', '') self._hardware_controller_class = \ self._hardware_controller_class.replace('{', '').replace('}', '') # get hardware controller's preferred MIDI ports eval_controller_midi_input = \ '{0!s}.{0!s}.get_preferred_midi_input()'.format( \ self._hardware_controller_class) eval_controller_midi_output = \ '{0!s}.{0!s}.get_preferred_midi_output()'.format( \ self._hardware_controller_class) controller_midi_input_default = eval(eval_controller_midi_input) controller_midi_output_default = eval(eval_controller_midi_output) # show controller's usage hint usage_hint = '{0!s}.{0!s}.get_usage_hint()'.format( \ self._hardware_controller_class) self._edit_usage_hint.setPlainText(eval(usage_hint)) return (controller_midi_input_default, controller_midi_output_default) def callback_log(self, message, repaint=False): if repaint: self._edit_logger.repaint() print message self._edit_logger.appendPlainText(message) def combobox_item_selected(self, ignore_this): widget = self.sender() selected_text = widget.currentText() if widget == self._combo_mcu_model_id: self._mcu_emulated_model = selected_text configuration.set_option( \ 'Python MCU', 'mcu_emulated_model', \ self._mcu_emulated_model) if self._mcu_emulated_model.startswith('Logic'): current_index = self._combo_mcu_connection.findText( \ MackieHostControl.CHALLENGE_RESPONSE) self._combo_mcu_connection.setCurrentIndex(current_index) else: current_index = self._combo_mcu_connection.findText( \ MackieHostControl.WAIT_FOR_MIDI_DATA) self._combo_mcu_connection.setCurrentIndex(current_index) elif widget == self._combo_mcu_midi_input: self._mcu_midi_input = selected_text configuration.set_option( \ 'Python MCU', 'mcu_midi_input', \ self._mcu_midi_input) elif widget == self._combo_mcu_midi_output: self._mcu_midi_output = selected_text configuration.set_option( \ 'Python MCU', 'mcu_midi_output', \ self._mcu_midi_output) elif widget == self._combo_hardware_controller: self._hardware_controller = selected_text configuration.set_option( \ 'Python MCU', 'controller_hardware', \ self._hardware_controller) # get preferred MIDI ports for hardware controller (controller_midi_input_default, controller_midi_output_default) = \ self._initialise_hardware_controller() # update hardware controller's MIDI ports in GUI current_index = self._combo_controller_midi_input.findText( \ controller_midi_input_default) self._combo_controller_midi_input.setCurrentIndex(current_index) current_index = self._combo_controller_midi_output.findText( \ controller_midi_output_default) self._combo_controller_midi_output.setCurrentIndex(current_index) elif widget == self._combo_controller_midi_input: self._controller_midi_input = selected_text configuration.set_option( \ 'Python MCU', 'controller_midi_input', \ self._controller_midi_input) elif widget == self._combo_controller_midi_output: self._controller_midi_output = selected_text configuration.set_option( \ 'Python MCU', 'controller_midi_output', \ self._controller_midi_output) elif widget == self._combo_mcu_connection: self._mcu_connection = selected_text configuration.set_option( \ 'Python MCU', 'mcu_connection', \ self._mcu_connection) else: self.callback_log('QComboBox not handled ("%s").' % selected_text) def process_midi_input(self): self._interconnector.process_midi_input() def display_about(self): AboutDialog(self).show() def interconnector_start_stop(self): if not self._interconnector: self._enable_controls(False) self.button_start_stop.setText('&Stop') self.callback_log('Settings') self.callback_log('========') self.callback_log('MCU emulation: %s' % self._mcu_emulated_model) self.callback_log('Connection: %s' % self._mcu_connection) self.callback_log('MIDI input: %s' % self._mcu_midi_input) self.callback_log('MIDI output: %s' % self._mcu_midi_output) self.callback_log('') self.callback_log('Controller: %s' % self._hardware_controller) self.callback_log('MIDI input: %s' % \ self._controller_midi_input) self.callback_log('MIDI output: %s' % \ self._controller_midi_output) self.callback_log('') self.callback_log('MIDI latency: %s ms' % self._midi_latency) self.callback_log('') self.callback_log('') if configuration.has_changed(): self.callback_log('Saving configuration file ...') configuration.save_configuration() self.callback_log('Starting MCU emulation...') self.callback_log('', True) # the "interconnector" is the brain of this application -- it # interconnects Mackie Control Host and MIDI controller while # handling the complete MIDI translation between those two self._interconnector = McuInterconnector( \ self, \ self._mcu_model_id, \ self._mcu_connection, \ self._mcu_midi_input, \ self._mcu_midi_output, \ self._hardware_controller_class, \ self._controller_midi_input, \ self._controller_midi_output, \ self.callback_log) self._interconnector.connect() self._timer.start() else: self._enable_controls(True) self.button_start_stop.setText('&Start') self._interconnector_stop() def _interconnector_stop(self): self._timer.stop() self.callback_log('') self.callback_log('Stopping MCU emulation...') self.callback_log('') self._interconnector.disconnect() self._interconnector = None self.callback_log('', True) def close_application(self): self.close() def closeEvent(self, event): if self._interconnector: self._interconnector_stop() self.callback_log('Exiting application...') self.callback_log('', True)