class MidiControllerTemplate(object): MIDI_MANUFACTURER_ID = None MIDI_DEVICE_ID = None VPOT_MODE_SINGLE_DOT = 0x00 VPOT_MODE_BOOST_CUT = 0x01 VPOT_MODE_WRAP = 0x02 VPOT_MODE_SPREAD = 0x03 _LED_STATUS = {0x00: 'off', 0x01: 'flashing', 0x7F: 'on'} def __init__(self, midi_input_name, midi_output_name, callback_log): self.callback_log = callback_log # LCD has 2 rows with 56 characters each, fill with spaces self._lcd_characters = [' '] * 2 self._lcd_overlay_characters = [' '] * 2 for line in range(2): self._lcd_characters[line] = [' '] * 56 self._lcd_overlay_characters[line] = [' '] * 56 self._show_overlay = [False, False] self._log('Initialising MIDI ports...', True) self._midi_input_name = midi_input_name self._midi_output_name = midi_output_name self.midi = MidiConnection(self.callback_log, self.receive_midi) self.unset_interconnector() self.display_lcd_available = True self.automated_faders_available = True self.display_7seg_available = True self.display_timecode_available = True self.meter_bridge_available = True self.display_7seg_characters = [] for counter in range(4): self.display_7seg_characters.append(' ') self.display_timecode_characters = [] for counter in range(20): self.display_timecode_characters.append(' ') @staticmethod def get_usage_hint(): return '' def _log(self, message, repaint=False): self.callback_log('[Controller Template] ' + message, repaint) # --- initialisation --- def set_interconnector(self, host): self.interconnector = host def unset_interconnector(self): self.interconnector = None def connect(self): self._log('Opening MIDI ports...', True) self.midi.connect(self._midi_input_name, self._midi_output_name) def disconnect(self): self._log('Closing MIDI ports...') self.midi.disconnect() self._log('Disconnected.', True) def go_online(self): self._log('Mackie Host Control went online...', True) def go_offline(self): self._log('Mackie Host Control went offline...', True) # --- abilities of hardware controller --- def has_display_7seg(self): return self.display_7seg_available def has_display_lcd(self): return self.display_lcd_available def has_display_timecode(self): return self.display_timecode_available def has_automated_faders(self): return self.automated_faders_available def has_meter_bridge(self): return self.meter_bridge_available # --- MIDI processing --- def process_midi_input(self): self.midi.process_input_buffer() def receive_midi(self, status, message): message_string = ['status %02X: ' % status] for byte in message: message_string.append('%02X' % byte) self._log(' '.join(message_string)) def send_midi_control_change(self, channel, cc_number, cc_value): self.midi.send_control_change(channel, cc_number, cc_value) def send_midi_sysex(self, data): assert (type(data) == types.ListType) header = [] header.extend(self.MIDI_MANUFACTURER_ID) header.extend(self.MIDI_DEVICE_ID) self.midi.send_sysex(header, data) @staticmethod def get_preferred_midi_input(): return '' @staticmethod def get_preferred_midi_output(): return '' # --- registration of MIDI controls --- def register_control(self, mcu_command, midi_switch, midi_led=None): if midi_led: self.interconnector.register_control( \ mcu_command, midi_switch, midi_led) else: self.interconnector.register_control( \ mcu_command, midi_switch, midi_switch) def withdraw_control(self, midi_switch): self.interconnector.withdraw_control(midi_switch_cc) def withdraw_all_controls(self): self.interconnector.withdraw_all_controls() # --- handling of Mackie Control commands --- def set_lcd(self, position, hex_codes, update=True): for hex_code in hex_codes: # wrap display and determine position position %= 112 (line, pos) = divmod(position, 56) # convert illegal characters to asterisk if (hex_code < 0x20) or (hex_code > 0x7F): self._lcd_characters[line][pos] = '*' else: self._lcd_characters[line][pos] = chr(hex_code) position += 1 if update: self.update_lcd() def set_led(self, internal_id, led_status): pass def set_display_7seg(self, position, character_code): character = self._decode_7seg_character(character_code) position = 23 - (position * 2) self.display_7seg_characters[position - 1] = character[0] self.display_7seg_characters[position] = character[1] string_7seg = ''.join(self.display_7seg_characters) self._log('7 segment display NOT set to "%s".' % string_7seg) def _decode_7seg_character(self, character_code): if character_code >= 0x40: character_code = character_code - 0x40 dot = '.' else: dot = ' ' if character_code < 0x20: return (chr(character_code + 0x40), dot) else: return (chr(character_code), dot) def set_display_timecode(self, position, character_code): character = self._decode_7seg_character(character_code) position = 19 - (position * 2) self.display_timecode_characters[position - 1] = character[0] self.display_timecode_characters[position] = character[1] # please note that the logged timecode is not necessarily # correct: it will only be dumped when the display's last # character has been updated -- there may be other updates # still pending! if position == 19: string_timecode = ''.join(self.display_timecode_characters) self._log('timecode display NOT set to "%s".' % string_timecode) def set_peak_level(self, meter_id, meter_level): if meter_level == 0x0F: self._log('Meter #%d overload NOT cleared.' % meter_id) elif meter_level == 0x0F: self._log('Meter #%d NOT set to overload.' % meter_id) else: self._log('Meter #%d NOT set to %03d%%.' % \ (meter_id, meter_level * 10)) def fader_moved(self, fader_id, fader_position): self._log('Hardware fader #%d NOT moved to position %04d.' % \ (fader_id, fader_position)) def set_vpot_led_ring(self, vpot_id, vpot_center_led, vpot_mode, \ vpot_position): self._log('V-Pot #%d LED ring NOT set to position %02d (mode %d).' % \ (vpot_id, vpot_position, vpot_mode)) def faders_to_minimum(self): self._log('Hardware faders NOT set to minimum.') def all_leds_off(self): self._log('Hardware LEDs NOT set to "off".') # --- LCD and menu handling def update_lcd(self): pass def get_lcd_characters(self, line): line %= 2 if self._show_overlay[line]: return self._lcd_overlay_characters[line] else: return self._lcd_characters[line] def show_menu(self, line, menu_strings): assert (len(menu_strings) == 8) menu_string_temp = '' for menu_string in menu_strings: menu_string_temp += menu_string.center(7)[:7] menu_characters = list(menu_string_temp) self.show_overlay(line, menu_characters) def hide_menu(self, line): self.hide_overlay(line) def show_overlay(self, line, overlay_characters): line %= 2 assert (len(overlay_characters) == 56) self._show_overlay[line] = True self._lcd_overlay_characters[line] = overlay_characters self.update_lcd() def hide_overlay(self, line): line %= 2 self._show_overlay[line] = False self.update_lcd()
class MidiControllerTemplate(object): MIDI_MANUFACTURER_ID = None MIDI_DEVICE_ID = None VPOT_MODE_SINGLE_DOT = 0x00 VPOT_MODE_BOOST_CUT = 0x01 VPOT_MODE_WRAP = 0x02 VPOT_MODE_SPREAD = 0x03 _LED_STATUS = { 0x00: 'off', 0x01: 'flashing', 0x7F: 'on' } def __init__(self, midi_input_name, midi_output_name, callback_log): self.callback_log = callback_log # LCD has 2 rows with 56 characters each, fill with spaces self._lcd_characters = [' '] * 2 self._lcd_overlay_characters = [' '] * 2 for line in range(2): self._lcd_characters[line] = [' '] * 56 self._lcd_overlay_characters[line] = [' '] * 56 self._show_overlay = [False, False] self._log('Initialising MIDI ports...', True) self._midi_input_name = midi_input_name self._midi_output_name = midi_output_name self.midi = MidiConnection(self.callback_log, self.receive_midi) self.unset_interconnector() self.display_lcd_available = True self.automated_faders_available = True self.display_7seg_available = True self.display_timecode_available = True self.meter_bridge_available = True self.display_7seg_characters = [] for counter in range(4): self.display_7seg_characters.append(' ') self.display_timecode_characters = [] for counter in range(20): self.display_timecode_characters.append(' ') @staticmethod def get_usage_hint(): return '' def _log(self, message, repaint=False): self.callback_log('[Controller Template] ' + message, repaint) # --- initialisation --- def set_interconnector(self, host): self.interconnector = host def unset_interconnector(self): self.interconnector = None def connect(self): self._log('Opening MIDI ports...', True) self.midi.connect(self._midi_input_name, self._midi_output_name) def disconnect(self): self._log('Closing MIDI ports...') self.midi.disconnect() self._log('Disconnected.', True) def go_online(self): self._log('Mackie Host Control went online...', True) def go_offline(self): self._log('Mackie Host Control went offline...', True) # --- abilities of hardware controller --- def has_display_7seg(self): return self.display_7seg_available def has_display_lcd(self): return self.display_lcd_available def has_display_timecode(self): return self.display_timecode_available def has_automated_faders(self): return self.automated_faders_available def has_meter_bridge(self): return self.meter_bridge_available # --- MIDI processing --- def process_midi_input(self): self.midi.process_input_buffer() def receive_midi(self, status, message): message_string = ['status %02X: ' % status] for byte in message: message_string.append('%02X' % byte) self._log(' '.join(message_string)) def send_midi_control_change(self, channel, cc_number, cc_value): self.midi.send_control_change(channel, cc_number, cc_value) def send_midi_sysex(self, data): assert(type(data) == types.ListType) header = [] header.extend(self.MIDI_MANUFACTURER_ID) header.extend(self.MIDI_DEVICE_ID) self.midi.send_sysex(header, data) @staticmethod def get_preferred_midi_input(): return '' @staticmethod def get_preferred_midi_output(): return '' # --- registration of MIDI controls --- def register_control(self, mcu_command, midi_switch, midi_led = None): if midi_led: self.interconnector.register_control( \ mcu_command, midi_switch, midi_led) else: self.interconnector.register_control( \ mcu_command, midi_switch, midi_switch) def withdraw_control(self, midi_switch): self.interconnector.withdraw_control(midi_switch_cc) def withdraw_all_controls(self): self.interconnector.withdraw_all_controls() # --- handling of Mackie Control commands --- def set_lcd(self, position, hex_codes, update=True): for hex_code in hex_codes: # wrap display and determine position position %= 112 (line, pos) = divmod(position, 56) # convert illegal characters to asterisk if (hex_code < 0x20) or (hex_code > 0x7F): self._lcd_characters[line][pos] = '*' else: self._lcd_characters[line][pos] = chr(hex_code) position += 1 if update: self.update_lcd() def set_led(self, internal_id, led_status): pass def set_display_7seg(self, position, character_code): character = self._decode_7seg_character(character_code) position = 23 - (position * 2) self.display_7seg_characters[position - 1] = character[0] self.display_7seg_characters[position] = character[1] string_7seg = ''.join(self.display_7seg_characters) self._log('7 segment display NOT set to "%s".' % string_7seg) def _decode_7seg_character(self, character_code): if character_code >= 0x40: character_code = character_code - 0x40 dot = '.' else: dot = ' ' if character_code < 0x20: return (chr(character_code + 0x40), dot) else: return (chr(character_code), dot) def set_display_timecode(self, position, character_code): character = self._decode_7seg_character(character_code) position = 19 - (position * 2) self.display_timecode_characters[position - 1] = character[0] self.display_timecode_characters[position] = character[1] # please note that the logged timecode is not necessarily # correct: it will only be dumped when the display's last # character has been updated -- there may be other updates # still pending! if position == 19: string_timecode = ''.join(self.display_timecode_characters) self._log('timecode display NOT set to "%s".' % string_timecode) def set_peak_level(self, meter_id, meter_level): if meter_level == 0x0F: self._log('Meter #%d overload NOT cleared.' % meter_id) elif meter_level == 0x0F: self._log('Meter #%d NOT set to overload.' % meter_id) else: self._log('Meter #%d NOT set to %03d%%.' % \ (meter_id, meter_level * 10)) def fader_moved(self, fader_id, fader_position): self._log('Hardware fader #%d NOT moved to position %04d.' % \ (fader_id, fader_position)) def set_vpot_led_ring(self, vpot_id, vpot_center_led, vpot_mode, \ vpot_position): self._log('V-Pot #%d LED ring NOT set to position %02d (mode %d).' % \ (vpot_id, vpot_position, vpot_mode)) def faders_to_minimum(self): self._log('Hardware faders NOT set to minimum.') def all_leds_off(self): self._log('Hardware LEDs NOT set to "off".') # --- LCD and menu handling def update_lcd(self): pass def get_lcd_characters(self, line): line %= 2 if self._show_overlay[line]: return self._lcd_overlay_characters[line] else: return self._lcd_characters[line] def show_menu(self, line, menu_strings): assert(len(menu_strings) == 8) menu_string_temp = '' for menu_string in menu_strings: menu_string_temp += menu_string.center(7)[:7] menu_characters = list(menu_string_temp) self.show_overlay(line, menu_characters) def hide_menu(self, line): self.hide_overlay(line) def show_overlay(self, line, overlay_characters): line %= 2 assert(len(overlay_characters) == 56) self._show_overlay[line] = True self._lcd_overlay_characters[line] = overlay_characters self.update_lcd() def hide_overlay(self, line): line %= 2 self._show_overlay[line] = False self.update_lcd()
class MackieHostControl: __module__ = __name__ __doc__ = 'Python wrapper for Mackie Host Control' ASSUME_SUCCESSFUL_CONNECTION = 'Assume successful connection' CHALLENGE_RESPONSE = 'Challenge / Response' WAIT_FOR_MIDI_DATA = 'Wait for MIDI data' SWITCH_RELEASED = 0 SWITCH_PRESSED = 1 SWITCH_PRESSED_RELEASED = 2 VPOT_CLOCKWISE = 0 VPOT_COUNTER_CLOCKWISE = 1 _LED_SWITCH_CHANNEL_RECORD_READY = 0x00 _LED_SWITCH_CHANNEL_SOLO = 0x08 _LED_SWITCH_CHANNEL_MUTE = 0x10 _LED_SWITCH_CHANNEL_SELECT = 0x18 _LED_SWITCH_CHANNEL_VSELECT = 0x20 _LED_SWITCH_ASSIGNMENT_TRACK = 0x28 _LED_SWITCH_ASSIGNMENT_SEND = 0x29 _LED_SWITCH_ASSIGNMENT_PAN_SURROUND = 0x2A _LED_SWITCH_ASSIGNMENT_PLUG_IN = 0x2B _LED_SWITCH_ASSIGNMENT_EQ = 0x2C _LED_SWITCH_ASSIGNMENT_INSTRUMENT = 0x2D _SWITCH_FADER_BANKS_BANK_LEFT = 0x2E _SWITCH_FADER_BANKS_BANK_RIGHT = 0x2F _SWITCH_FADER_BANKS_CHANNEL_LEFT = 0x30 _SWITCH_FADER_BANKS_CHANNEL_RIGHT = 0x31 _LED_SWITCH_FLIP = 0x32 _LED_SWITCH_GLOBAL_VIEW = 0x33 _SWITCH_NAME_VALUE = 0x34 _SWITCH_SMPTE_BEATS = 0x35 _SWITCH_CHANNEL_FUNCTION = 0x36 _SWITCH_GLOBAL_VIEW_MIDI_TRACKS = 0x3E _SWITCH_GLOBAL_VIEW_INPUTS = 0x3F _SWITCH_GLOBAL_VIEW_AUDIO_TRACKS = 0x40 _SWITCH_GLOBAL_VIEW_AUDIO_INSTRUMENTS = 0x41 _SWITCH_GLOBAL_VIEW_AUX = 0x42 _SWITCH_GLOBAL_VIEW_BUSSES = 0x43 _SWITCH_GLOBAL_VIEW_OUTPUTS = 0x44 _SWITCH_GLOBAL_VIEW_USER = 0x45 _SWITCH_SHIFT = 0x46 _SWITCH_OPTION = 0x47 _SWITCH_CONTROL = 0x48 _SWITCH_COMMAND_ALT = 0x49 _LED_SWITCH_AUTOMATION_READ_OFF = 0x4A _LED_SWITCH_AUTOMATION_WRITE = 0x4B _LED_SWITCH_AUTOMATION_TRIM = 0x4C _LED_SWITCH_AUTOMATION_TOUCH = 0x4D _LED_SWITCH_AUTOMATION_LATCH = 0x4E _LED_SWITCH_GROUP = 0x4F _LED_SWITCH_UTILITIES_SAVE = 0x50 _LED_SWITCH_UTILITIES_UNDO = 0x51 _SWITCH_UTILITIES_CANCEL = 0x52 _SWITCH_UTILITIES_ENTER = 0x53 _LED_SWITCH_MARKER = 0x54 _LED_SWITCH_NUDGE = 0x55 _LED_SWITCH_CYCLE = 0x56 _LED_SWITCH_DROP = 0x57 _LED_SWITCH_REPLACE = 0x58 _LED_SWITCH_CLICK = 0x59 _LED_SWITCH_SOLO = 0x5A _LED_SWITCH_REWIND = 0x5B _LED_SWITCH_FAST_FORWARD = 0x5C _LED_SWITCH_STOP = 0x5D _LED_SWITCH_PLAY = 0x5E _LED_SWITCH_RECORD = 0x5F _SWITCH_CURSOR_UP = 0x60 _SWITCH_CURSOR_DOWN = 0x61 _SWITCH_CURSOR_LEFT = 0x62 _SWITCH_CURSOR_RIGHT = 0x63 _LED_SWITCH_ZOOM = 0x64 _LED_SWITCH_SCRUB = 0x65 _SWITCH_USER_SWITCH_A = 0x66 _SWITCH_USER_SWITCH_B = 0x67 _SWITCH_CHANNEL_FADER_TOUCH = 0x68 _SWITCH_MASTER_FADER_TOUCH = 0x70 _LED_SMPTE = 0x71 _LED_BEATS = 0x72 _LED_RUDE_SOLO = 0x73 _LED_RELAY_CLICK = 0x76 def __init__(self, mcu_model_id, mcu_connection, version_number, \ midi_input_name, midi_output_name, callback_log): self._callback_log = callback_log self._log('Initialising MIDI ports...', True) self._midi_input_name = midi_input_name self._midi_output_name = midi_output_name self._midi = MidiConnection(callback_log, self.receive_midi) self._midi_channel = 0 self.unset_hardware_controller() self._offline = True # Mackie Control model IDs: # * 0x10: Logic Control # * 0x11: Logic Control XT # * 0x14: Mackie Control # * 0x15: Mackie Control XT self._mcu_model_id = mcu_model_id # define connection type (among others, challenge-response) self._mcu_connection = mcu_connection serial_number = '_pyMCU_' self._serial_number_bytes = [] for char in serial_number: self._serial_number_bytes.append(ord(char)) challenge = 'test' self._challenge_bytes = [] for char in challenge: self._challenge_bytes.append(ord(char)) self._response_bytes = self._calculate_reponse_from_challenge( \ self._challenge_bytes) # make sure that the version number consists of exactly 5 # characters version_number = version_number.ljust(5)[0:5] self._version_number_bytes = [] for char in version_number: self._version_number_bytes.append(ord(char)) def _log(self, message, repaint=False): self._callback_log('[Mackie Host Control ] ' + message, repaint) # --- initialisation --- def set_hardware_controller(self, controller): self._hardware_controller = controller self._display_lcd_available = \ self._hardware_controller.has_display_lcd() self._automated_faders_available = \ self._hardware_controller.has_automated_faders() self._display_7seg_available = \ self._hardware_controller.has_display_7seg() self._display_timecode_available = \ self._hardware_controller.has_display_timecode() self._meter_bridge_available = \ self._hardware_controller.has_meter_bridge() def unset_hardware_controller(self): self._hardware_controller = None self._display_lcd_available = False self._automated_faders_available = False self._display_7seg_available = False self._display_timecode_available = False self._meter_bridge_available = False def connect(self): self._log('Opening MIDI ports...') self._midi.connect(self._midi_input_name, self._midi_output_name) if self._mcu_connection == self.CHALLENGE_RESPONSE: self._log('Sending "Host Connection Query"...', True) sysex_message = [0x01] sysex_message.extend(self._serial_number_bytes) sysex_message.extend(self._challenge_bytes) self.send_midi_sysex(sysex_message) return else: # let's make sure the MIDI input buffer is empty self._midi.process_input_buffer(use_callback=False) if self._mcu_connection == self.WAIT_FOR_MIDI_DATA: self._log('Waiting for MIDI input from host...', True) # wait for some MIDI input from the host (all data are # left in the MIDI input buffer!) while self._midi.buffer_is_empty(): time.sleep(0.1) self.go_online() def disconnect(self): self._log('Disconnecting...', True) self.go_offline() self._log('Closing MIDI ports...', True) self._midi.disconnect() def go_online(self): self._offline = False if self._hardware_controller: self._hardware_controller.go_online() self._log('Online.', True) def go_offline(self): self._offline = True if self._hardware_controller: self._hardware_controller.go_offline() if self._mcu_connection == self.CHALLENGE_RESPONSE: self._log('Sending "Host Connection Error"...') sysex_message = [0x04] sysex_message.extend(self._serial_number_bytes) self.send_midi_sysex(sysex_message) self._log('Offline.', True) def is_offline(self): return self._offline def _calculate_reponse_from_challenge(self, challenge_bytes): response_bytes = [] response_bytes.append( \ 0x7F & (challenge_bytes[0] + (challenge_bytes[1] ^ 0x0A) - \ challenge_bytes[3])) response_bytes.append( \ 0x7F & ((challenge_bytes[2] >> 4) ^ \ (challenge_bytes[0] + challenge_bytes[3]))) response_bytes.append( \ 0x7F & (challenge_bytes[3] - (challenge_bytes[2] << 2) ^ \ (challenge_bytes[0] | challenge_bytes[1]))) response_bytes.append( \ 0x7F & (challenge_bytes[1] - challenge_bytes[2] + \ (0xF0 ^ (challenge_bytes[3] << 4)))) return response_bytes # --- static methods --- @staticmethod def get_mcu_model_from_id(id): if id == 0x10: return 'Logic Control' elif id == 0x11: return 'Logic Control XT' elif id == 0x14: return 'Mackie Control' elif id == 0x15: return 'Mackie Control XT' else: return None @staticmethod def get_mcu_id_from_model(model): if model == 'Logic Control': return 0x10 elif model == 'Logic Control XT': return 0x11 elif model == 'Mackie Control': return 0x14 elif model == 'Mackie Control XT': return 0x15 else: return None @staticmethod def get_preferred_mcu_model(): return 'Mackie Control' @staticmethod def get_preferred_mcu_model_id(): return MackieHostControl.get_mcu_id_from_model( \ MackieHostControl.get_preferred_mcu_model()) @staticmethod def get_preferred_midi_input(): if os.name == 'nt': return 'In From MIDI Yoke: 2' else: return 'mcu' @staticmethod def get_preferred_midi_output(): if os.name == 'nt': return 'Out To MIDI Yoke: 1' else: return 'mcu' # --- MIDI processing --- def process_midi_input(self): self._midi.process_input_buffer() def receive_midi(self, status, message): if status == MidiConnection.SYSTEM_MESSAGE and message[0:5] == \ [0xF0, 0x00, 0x00, 0x66, self._mcu_model_id]: if message[5:] == [0x00, 0xF7]: self._log('Received "Device Query".') self._log('Sending "Host Connection Query"...', True) sysex_message = [0x01] sysex_message.extend(self._serial_number_bytes) sysex_message.extend(self._challenge_bytes) self.send_midi_sysex(sysex_message) return elif message[5] == 0x02: self._log('Received "Host Connection Reply".') if (message[6:13] == self._serial_number_bytes) and \ (message[13:17] == self._response_bytes): self._log('Sending "Host Connection Confirmation"...', \ True) sysex_message = [0x03] sysex_message.extend(self._serial_number_bytes) self.send_midi_sysex(sysex_message) self.go_online() else: self._log('Sending "Host Connection Error"...') sysex_message = [0x04] sysex_message.extend(self._serial_number_bytes) self.send_midi_sysex(sysex_message) self._log('Sending "Host Connection Query"...', True) sysex_message = [0x01] sysex_message.extend(self._serial_number_bytes) sysex_message.extend(self._challenge_bytes) self.send_midi_sysex(sysex_message) return elif message[5:] == [0x13, 0x00, 0x0F7]: self._log('Received "Version Request".') self._log('Sending "Version Reply"...', True) sysex_message = [0x14] sysex_message.extend(self._version_number_bytes) self.send_midi_sysex(sysex_message) return elif message[5:] == [0x0F, 0x7F, 0x0F7]: self._log('Received "Go Offline".', True) self.go_offline() return elif message[5:] == [0x61, 0x0F7]: self._log('Received "Faders To Minimum".', True) self.faders_to_minimum() return elif message[5:] == [0x62, 0x0F7]: self._log('Received "All LEDs Off".', True) self.all_leds_off() return elif message[5:] == [0x63, 0x0F7]: self._log('Received "Reset".', True) self.reset() return # do not make this an "elif" clause, otherwise some MIDI SysEx # messages won't get processed! if not self.is_offline(): if status == MidiConnection.SYSTEM_MESSAGE and message[0:5] == \ [0xF0, 0x00, 0x00, 0x66, self._mcu_model_id]: if message[5] == 0x12: if self._display_lcd_available: position = message[6] hex_codes = message[7:-1] self._hardware_controller.set_lcd(position, hex_codes) elif status == MidiConnection.PITCH_WHEEL_CHANGE: if self._automated_faders_available: fader_id = message[0] & 0x0F fader_position = (message[1] + (message[2] << 7)) >> 4 self._hardware_controller.fader_moved( \ fader_id, fader_position) elif status == MidiConnection.NOTE_ON_EVENT: led_id = message[1] led_status = 0 # off if message[2] == 0x7F: led_status = 1 # on elif message[2] == 0x01: led_status = 2 # flashing self._set_led(led_id, led_status) elif (status == MidiConnection.CONTROL_CHANGE) and \ ((message[1] & 0xF0) == 0x30): vpot_id = message[1] & 0x0F vpot_center_led = (message[2] & 0x40) >> 7 vpot_mode = (message[2] & 0x30) >> 4 vpot_position = message[2] & 0x0F self._hardware_controller.set_vpot_led_ring( \ vpot_id, vpot_center_led, vpot_mode, vpot_position) elif (status == MidiConnection.CONTROL_CHANGE) and \ ((message[1] & 0xF0) == 0x40): position = message[1] & 0x0F character_code = message[2] if (position < 10): if self._display_timecode_available: self._hardware_controller.set_display_timecode( \ position, character_code) elif self._display_7seg_available: self._hardware_controller.set_display_7seg( \ position, character_code) elif status == MidiConnection.CHANNEL_PRESSURE: if self._meter_bridge_available: meter_id = (message[1] & 0x70) >> 4 meter_level = message[1] & 0x0F self._hardware_controller.set_peak_level( \ meter_id, meter_level) else: output = 'status %02X: ' % status for byte in message: output += '%02X ' % byte self._log(output.strip()) else: output = 'status %02X: ' % status for byte in message: output += '%02X ' % byte self._log(output.strip()) def send_midi_sysex(self, data): assert(type(data) == types.ListType) header = [0x00, 0x00, 0x66, self._mcu_model_id] # leading 0xF0 and trailing 0xF7 are added by "MidiConnection" # class method self._midi.send_sysex(header, data) # --- commands from hardware control --- def move_vpot(self, vpot_id, direction, number_of_ticks): if self.is_offline(): return vpot_movement = number_of_ticks if direction == self.VPOT_COUNTER_CLOCKWISE: vpot_movement = vpot_movement + 0x40 self._midi.send_control_change( \ self._midi_channel, 0x10 + vpot_id, vpot_movement) def move_vpot_raw(self, vpot_id, vpot_movement): if self.is_offline(): return self._midi.send_control_change( \ self._midi_channel, 0x10 + vpot_id, vpot_movement) def move_fader(self, fader_id, fader_value): if self.is_offline(): return self._midi.send_pitch_wheel_change(fader_id, fader_value) def move_fader_7bit(self, fader_id, fader_value): if self.is_offline(): return self._midi.send_pitch_wheel_change_7bit(fader_id, fader_value) def _key_pressed(self, status, switch_id): if self.is_offline(): return if status == self.SWITCH_RELEASED: self._midi.send_note_on(switch_id, 0x00) elif status == self.SWITCH_PRESSED: self._midi.send_note_on(switch_id, 0x7F) elif status == self.SWITCH_PRESSED_RELEASED: self._midi.send_note_on(switch_id, 0x7F) self._midi.send_note_on(switch_id, 0x00) else: self._log( \ 'Illegal key press status 0x%02X on switch 0x%02X detected!' % \ (status, switch_id)) def keypress_record_ready_channel(self, channel, status): # channel: 1 - 8 self._key_pressed( \ status, self._LED_SWITCH_CHANNEL_RECORD_READY + channel - 1) def keypress_record_ready_channel_1(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY) def keypress_record_ready_channel_2(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 1) def keypress_record_ready_channel_3(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 2) def keypress_record_ready_channel_4(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 3) def keypress_record_ready_channel_5(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 4) def keypress_record_ready_channel_6(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 5) def keypress_record_ready_channel_7(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 6) def keypress_record_ready_channel_8(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 7) def keypress_solo_channel(self, channel, status): # channel: 1 - 8 self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + channel - 1) def keypress_solo_channel_1(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO) def keypress_solo_channel_2(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 1) def keypress_solo_channel_3(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 2) def keypress_solo_channel_4(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 3) def keypress_solo_channel_5(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 4) def keypress_solo_channel_6(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 5) def keypress_solo_channel_7(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 6) def keypress_solo_channel_8(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 7) def keypress_mute_channel(self, channel, status): # channel: 1 - 8 self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + channel - 1) def keypress_mute_channel_1(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE) def keypress_mute_channel_2(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 1) def keypress_mute_channel_3(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 2) def keypress_mute_channel_4(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 3) def keypress_mute_channel_5(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 4) def keypress_mute_channel_6(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 5) def keypress_mute_channel_7(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 6) def keypress_mute_channel_8(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 7) def keypress_select_channel(self, channel, status): # channel: 1 - 8 self._key_pressed( \ status, self._LED_SWITCH_CHANNEL_SELECT + channel - 1) def keypress_select_channel_1(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT) def keypress_select_channel_2(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 1) def keypress_select_channel_3(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 2) def keypress_select_channel_4(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 3) def keypress_select_channel_5(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 4) def keypress_select_channel_6(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 5) def keypress_select_channel_7(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 6) def keypress_select_channel_8(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 7) def keypress_vselect_channel(self, channel, status): # channel: 1 - 8 self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + \ channel - 1) def keypress_vselect_channel_1(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT) def keypress_vselect_channel_2(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 1) def keypress_vselect_channel_3(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 2) def keypress_vselect_channel_4(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 3) def keypress_vselect_channel_5(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 4) def keypress_vselect_channel_6(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 5) def keypress_vselect_channel_7(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 6) def keypress_vselect_channel_8(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 7) def keypress_function_channel(self, channel, status): # channel: 1 - 8 self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + channel - 1) def keypress_function_channel_1(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION) def keypress_function_channel_2(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 1) def keypress_function_channel_3(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 2) def keypress_function_channel_4(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 3) def keypress_function_channel_5(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 4) def keypress_function_channel_6(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 5) def keypress_function_channel_7(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 6) def keypress_function_channel_8(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 7) def keypress_assignment_track(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_TRACK) def keypress_assignment_send(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_SEND) def keypress_assignment_pan_surround(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_PAN_SURROUND) def keypress_assignment_plug_in(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_PLUG_IN) def keypress_assignment_eq(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_EQ) def keypress_assignment_instrument(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_INSTRUMENT) def keypress_fader_banks_bank_left(self, status): self._key_pressed(status, self._SWITCH_FADER_BANKS_BANK_LEFT) def keypress_fader_banks_bank_right(self, status): self._key_pressed(status, self._SWITCH_FADER_BANKS_BANK_RIGHT) def keypress_fader_banks_channel_left(self, status): self._key_pressed(status, self._SWITCH_FADER_BANKS_CHANNEL_LEFT) def keypress_fader_banks_channel_right(self, status): self._key_pressed(status, self._SWITCH_FADER_BANKS_CHANNEL_RIGHT) def keypress_flip(self, status): self._key_pressed(status, self._LED_SWITCH_FLIP) def keypress_global_view(self, status): self._key_pressed(status, self._LED_SWITCH_GLOBAL_VIEW) def keypress_name_value(self, status): self._key_pressed(status, self._SWITCH_NAME_VALUE) def keypress_smpte_beats(self, status): self._key_pressed(status, self._SWITCH_SMPTE_BEATS) def keypress_global_view_midi_tracks(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_MIDI_TRACKS) def keypress_global_view_inputs(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_INPUTS) def keypress_global_view_audio_tracks(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_AUDIO_TRACKS) def keypress_global_view_audio_instruments(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_AUDIO_INSTRUMENTS) def keypress_global_view_aux(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_AUX) def keypress_global_view_busses(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_BUSSES) def keypress_global_view_outputs(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_OUTPUTS) def keypress_global_view_user(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_USER) def keypress_shift(self, status): self._key_pressed(status, self._SWITCH_SHIFT) def keypress_option(self, status): self._key_pressed(status, self._SWITCH_OPTION) def keypress_control(self, status): self._key_pressed(status, self._SWITCH_CONTROL) def keypress_command_alt(self, status): self._key_pressed(status, self._SWITCH_COMMAND_ALT) def keypress_automation_read_off(self, status): self._key_pressed(status, self._LED_SWITCH_AUTOMATION_READ_OFF) def keypress_automation_write(self, status): self._key_pressed(status, self._LED_SWITCH_AUTOMATION_WRITE) def keypress_automation_trim(self, status): self._key_pressed(status, self._LED_SWITCH_AUTOMATION_TRIM) def keypress_automation_touch(self, status): self._key_pressed(status, self._LED_SWITCH_AUTOMATION_TOUCH) def keypress_automation_latch(self, status): self._key_pressed(status, self._LED_SWITCH_AUTOMATION_LATCH) def keypress_group(self, status): self._key_pressed(status, self._LED_SWITCH_GROUP) def keypress_utilities_save(self, status): self._key_pressed(status, self._LED_SWITCH_UTILITIES_SAVE) def keypress_utilities_undo(self, status): self._key_pressed(status, self._LED_SWITCH_UTILITIES_UNDO) def keypress_utilities_cancel(self, status): self._key_pressed(status, self._SWITCH_UTILITIES_CANCEL) def keypress_utilities_enter(self, status): self._key_pressed(status, self._SWITCH_UTILITIES_ENTER) def keypress_marker(self, status): self._key_pressed(status, self._LED_SWITCH_MARKER) def keypress_nudge(self, status): self._key_pressed(status, self._LED_SWITCH_NUDGE) def keypress_cycle(self, status): self._key_pressed(status, self._LED_SWITCH_CYCLE) def keypress_drop(self, status): self._key_pressed(status, self._LED_SWITCH_DROP) def keypress_replace(self, status): self._key_pressed(status, self._LED_SWITCH_REPLACE) def keypress_click(self, status): self._key_pressed(status, self._LED_SWITCH_CLICK) def keypress_solo(self, status): self._key_pressed(status, self._LED_SWITCH_SOLO) def keypress_rewind(self, status): self._key_pressed(status, self._LED_SWITCH_REWIND) def keypress_fast_forward(self, status): self._key_pressed(status, self._LED_SWITCH_FAST_FORWARD) def keypress_stop(self, status): self._key_pressed(status, self._LED_SWITCH_STOP) def keypress_play(self, status): self._key_pressed(status, self._LED_SWITCH_PLAY) def keypress_record(self, status): self._key_pressed(status, self._LED_SWITCH_RECORD) def keypress_cursor_up(self, status): self._key_pressed(status, self._SWITCH_CURSOR_UP) def keypress_cursor_down(self, status): self._key_pressed(status, self._SWITCH_CURSOR_DOWN) def keypress_cursor_left(self, status): self._key_pressed(status, self._SWITCH_CURSOR_LEFT) def keypress_cursor_right(self, status): self._key_pressed(status, self._SWITCH_CURSOR_RIGHT) def keypress_zoom(self, status): self._key_pressed(status, self._LED_SWITCH_ZOOM) def keypress_scrub(self, status): self._key_pressed(status, self._LED_SWITCH_SCRUB) def keypress_user_switch(self, switch_number, status): # switch_number: 1 - 2 if switch_number == 1: self._key_pressed(status, self._SWITCH_USER_SWITCH_A) else: self._key_pressed(status, self._SWITCH_USER_SWITCH_B) def keypress_user_switch_1(self, status): self._key_pressed(status, self._SWITCH_USER_SWITCH_A) def keypress_user_switch_2(self, status): self._key_pressed(status, self._SWITCH_USER_SWITCH_B) def keypress_fader_touch_channel(self, channel, status): # channel: 1 - 8 self._key_pressed( \ status, self._SWITCH_CHANNEL_FADER_TOUCH + channel - 1) def keypress_fader_touch_channel_1(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH) def keypress_fader_touch_channel_2(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 1) def keypress_fader_touch_channel_3(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 2) def keypress_fader_touch_channel_4(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 3) def keypress_fader_touch_channel_5(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 4) def keypress_fader_touch_channel_6(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 5) def keypress_fader_touch_channel_7(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 6) def keypress_fader_touch_channel_8(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 7) def keypress_fader_touch_master(self, status): self._key_pressed(status, self._SWITCH_MASTER_FADER_TOUCH) # --- commands from Mackie Control host --- def _set_led(self, id, status): if self.is_offline(): return selector = { self._LED_SWITCH_CHANNEL_RECORD_READY: \ 'self._hardware_controller.set_led_channel_record_ready(0, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 1: \ 'self._hardware_controller.set_led_channel_record_ready(1, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 2: \ 'self._hardware_controller.set_led_channel_record_ready(2, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 3: \ 'self._hardware_controller.set_led_channel_record_ready(3, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 4: \ 'self._hardware_controller.set_led_channel_record_ready(4, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 5: \ 'self._hardware_controller.set_led_channel_record_ready(5, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 6: \ 'self._hardware_controller.set_led_channel_record_ready(6, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 7: \ 'self._hardware_controller.set_led_channel_record_ready(7, status)', self._LED_SWITCH_CHANNEL_SOLO: \ 'self._hardware_controller.set_led_channel_solo(0, status)', self._LED_SWITCH_CHANNEL_SOLO + 1: \ 'self._hardware_controller.set_led_channel_solo(1, status)', self._LED_SWITCH_CHANNEL_SOLO + 2: \ 'self._hardware_controller.set_led_channel_solo(2, status)', self._LED_SWITCH_CHANNEL_SOLO + 3: \ 'self._hardware_controller.set_led_channel_solo(3, status)', self._LED_SWITCH_CHANNEL_SOLO + 4: \ 'self._hardware_controller.set_led_channel_solo(4, status)', self._LED_SWITCH_CHANNEL_SOLO + 5: \ 'self._hardware_controller.set_led_channel_solo(5, status)', self._LED_SWITCH_CHANNEL_SOLO + 6: \ 'self._hardware_controller.set_led_channel_solo(6, status)', self._LED_SWITCH_CHANNEL_SOLO + 7: \ 'self._hardware_controller.set_led_channel_solo(7, status)', self._LED_SWITCH_CHANNEL_MUTE: \ 'self._hardware_controller.set_led_channel_mute(0, status)', self._LED_SWITCH_CHANNEL_MUTE + 1: \ 'self._hardware_controller.set_led_channel_mute(1, status)', self._LED_SWITCH_CHANNEL_MUTE + 2: \ 'self._hardware_controller.set_led_channel_mute(2, status)', self._LED_SWITCH_CHANNEL_MUTE + 3: \ 'self._hardware_controller.set_led_channel_mute(3, status)', self._LED_SWITCH_CHANNEL_MUTE + 4: \ 'self._hardware_controller.set_led_channel_mute(4, status)', self._LED_SWITCH_CHANNEL_MUTE + 5: \ 'self._hardware_controller.set_led_channel_mute(5, status)', self._LED_SWITCH_CHANNEL_MUTE + 6: \ 'self._hardware_controller.set_led_channel_mute(6, status)', self._LED_SWITCH_CHANNEL_MUTE + 7: \ 'self._hardware_controller.set_led_channel_mute(7, status)', self._LED_SWITCH_CHANNEL_SELECT: \ 'self._hardware_controller.set_led_channel_select(0, status)', self._LED_SWITCH_CHANNEL_SELECT + 1: \ 'self._hardware_controller.set_led_channel_select(1, status)', self._LED_SWITCH_CHANNEL_SELECT + 2: \ 'self._hardware_controller.set_led_channel_select(2, status)', self._LED_SWITCH_CHANNEL_SELECT + 3: \ 'self._hardware_controller.set_led_channel_select(3, status)', self._LED_SWITCH_CHANNEL_SELECT + 4: \ 'self._hardware_controller.set_led_channel_select(4, status)', self._LED_SWITCH_CHANNEL_SELECT + 5: \ 'self._hardware_controller.set_led_channel_select(5, status)', self._LED_SWITCH_CHANNEL_SELECT + 6: \ 'self._hardware_controller.set_led_channel_select(6, status)', self._LED_SWITCH_CHANNEL_SELECT + 7: \ 'self._hardware_controller.set_led_channel_select(7, status)', self._LED_SWITCH_CHANNEL_VSELECT: \ 'self._hardware_controller.set_led_channel_vselect(0, status)', self._LED_SWITCH_CHANNEL_VSELECT + 1: \ 'self._hardware_controller.set_led_channel_vselect(1, status)', self._LED_SWITCH_CHANNEL_VSELECT + 2: \ 'self._hardware_controller.set_led_channel_vselect(2, status)', self._LED_SWITCH_CHANNEL_VSELECT + 3: \ 'self._hardware_controller.set_led_channel_vselect(3, status)', self._LED_SWITCH_CHANNEL_VSELECT + 4: \ 'self._hardware_controller.set_led_channel_vselect(4, status)', self._LED_SWITCH_CHANNEL_VSELECT + 5: \ 'self._hardware_controller.set_led_channel_vselect(5, status)', self._LED_SWITCH_CHANNEL_VSELECT + 6: \ 'self._hardware_controller.set_led_channel_vselect(6, status)', self._LED_SWITCH_CHANNEL_VSELECT + 7: \ 'self._hardware_controller.set_led_channel_vselect(7, status)', self._LED_SWITCH_ASSIGNMENT_TRACK: \ 'self._hardware_controller.set_led_assignment_track(status)', self._LED_SWITCH_ASSIGNMENT_SEND: \ 'self._hardware_controller.set_led_assignment_send(status)', self._LED_SWITCH_ASSIGNMENT_PAN_SURROUND: \ 'self._hardware_controller.set_led_assignment_pan_surround(status)', self._LED_SWITCH_ASSIGNMENT_PLUG_IN: \ 'self._hardware_controller.set_led_assignment_plug_in(status)', self._LED_SWITCH_ASSIGNMENT_EQ: \ 'self._hardware_controller.set_led_assignment_eq(status)', self._LED_SWITCH_ASSIGNMENT_INSTRUMENT: \ 'self._hardware_controller.set_led_assignment_instrument(status)', self._LED_SWITCH_FLIP: \ 'self._hardware_controller.set_led_flip(status)', self._LED_SWITCH_GLOBAL_VIEW: \ 'self._hardware_controller.set_led_global_view(status)', self._LED_SWITCH_AUTOMATION_READ_OFF: \ 'self._hardware_controller.set_led_automation_read_off(status)', self._LED_SWITCH_AUTOMATION_WRITE: \ 'self._hardware_controller.set_led_automation_write(status)', self._LED_SWITCH_AUTOMATION_TRIM: \ 'self._hardware_controller.set_led_automation_trim(status)', self._LED_SWITCH_AUTOMATION_TOUCH: \ 'self._hardware_controller.set_led_automation_touch(status)', self._LED_SWITCH_AUTOMATION_LATCH: \ 'self._hardware_controller.set_led_automation_latch(status)', self._LED_SWITCH_GROUP: \ 'self._hardware_controller.set_led_group(status)', self._LED_SWITCH_UTILITIES_SAVE: \ 'self._hardware_controller.set_led_utilities_save(status)', self._LED_SWITCH_UTILITIES_UNDO: \ 'self._hardware_controller.set_led_utilities_undo(status)', self._LED_SWITCH_MARKER: \ 'self._hardware_controller.set_led_marker(status)', self._LED_SWITCH_NUDGE: \ 'self._hardware_controller.set_led_nudge(status)', self._LED_SWITCH_CYCLE: \ 'self._hardware_controller.set_led_cycle(status)', self._LED_SWITCH_DROP: \ 'self._hardware_controller.set_led_drop(status)', self._LED_SWITCH_REPLACE: \ 'self._hardware_controller.set_led_replace(status)', self._LED_SWITCH_CLICK: \ 'self._hardware_controller.set_led_click(status)', self._LED_SWITCH_SOLO: \ 'self._hardware_controller.set_led_solo(status)', self._LED_SWITCH_REWIND: \ 'self._hardware_controller.set_led_rewind(status)', self._LED_SWITCH_FAST_FORWARD: \ 'self._hardware_controller.set_led_fast_forward(status)', self._LED_SWITCH_STOP: \ 'self._hardware_controller.set_led_stop(status)', self._LED_SWITCH_PLAY: \ 'self._hardware_controller.set_led_play(status)', self._LED_SWITCH_RECORD: \ 'self._hardware_controller.set_led_record(status)', self._LED_SWITCH_ZOOM: \ 'self._hardware_controller.set_led_zoom(status)', self._LED_SWITCH_SCRUB: \ 'self._hardware_controller.set_led_scrub(status)', self._LED_SMPTE: \ 'self._hardware_controller.set_led_smpte(status)', self._LED_BEATS: \ 'self._hardware_controller.set_led_beats(status)', self._LED_RUDE_SOLO: \ 'self._hardware_controller.set_led_rude_solo(status)', self._LED_RELAY_CLICK: \ 'self._hardware_controller.set_led_relay_click(status)' } if id in selector: eval(selector[id]) else: led_status = 'off' if status == 1: status = 'on' elif status == 2: status = 'flashing' self._log('LED 0x%02X NOT implemented (%s).' % (id, led_status)) def faders_to_minimum(self): if self._hardware_controller: self._hardware_controller.faders_to_minimum() def all_leds_off(self): if self._hardware_controller: self._hardware_controller.all_leds_off() def reset(self): self.go_offline()
class MackieHostControl: __module__ = __name__ __doc__ = 'Python wrapper for Mackie Host Control' ASSUME_SUCCESSFUL_CONNECTION = 'Assume successful connection' CHALLENGE_RESPONSE = 'Challenge / Response' WAIT_FOR_MIDI_DATA = 'Wait for MIDI data' SWITCH_RELEASED = 0 SWITCH_PRESSED = 1 SWITCH_PRESSED_RELEASED = 2 VPOT_CLOCKWISE = 0 VPOT_COUNTER_CLOCKWISE = 1 _LED_SWITCH_CHANNEL_RECORD_READY = 0x00 _LED_SWITCH_CHANNEL_SOLO = 0x08 _LED_SWITCH_CHANNEL_MUTE = 0x10 _LED_SWITCH_CHANNEL_SELECT = 0x18 _LED_SWITCH_CHANNEL_VSELECT = 0x20 _LED_SWITCH_ASSIGNMENT_TRACK = 0x28 _LED_SWITCH_ASSIGNMENT_SEND = 0x29 _LED_SWITCH_ASSIGNMENT_PAN_SURROUND = 0x2A _LED_SWITCH_ASSIGNMENT_PLUG_IN = 0x2B _LED_SWITCH_ASSIGNMENT_EQ = 0x2C _LED_SWITCH_ASSIGNMENT_INSTRUMENT = 0x2D _SWITCH_FADER_BANKS_BANK_LEFT = 0x2E _SWITCH_FADER_BANKS_BANK_RIGHT = 0x2F _SWITCH_FADER_BANKS_CHANNEL_LEFT = 0x30 _SWITCH_FADER_BANKS_CHANNEL_RIGHT = 0x31 _LED_SWITCH_FLIP = 0x32 _LED_SWITCH_GLOBAL_VIEW = 0x33 _SWITCH_NAME_VALUE = 0x34 _SWITCH_SMPTE_BEATS = 0x35 _SWITCH_CHANNEL_FUNCTION = 0x36 _SWITCH_GLOBAL_VIEW_MIDI_TRACKS = 0x3E _SWITCH_GLOBAL_VIEW_INPUTS = 0x3F _SWITCH_GLOBAL_VIEW_AUDIO_TRACKS = 0x40 _SWITCH_GLOBAL_VIEW_AUDIO_INSTRUMENTS = 0x41 _SWITCH_GLOBAL_VIEW_AUX = 0x42 _SWITCH_GLOBAL_VIEW_BUSSES = 0x43 _SWITCH_GLOBAL_VIEW_OUTPUTS = 0x44 _SWITCH_GLOBAL_VIEW_USER = 0x45 _SWITCH_SHIFT = 0x46 _SWITCH_OPTION = 0x47 _SWITCH_CONTROL = 0x48 _SWITCH_COMMAND_ALT = 0x49 _LED_SWITCH_AUTOMATION_READ_OFF = 0x4A _LED_SWITCH_AUTOMATION_WRITE = 0x4B _LED_SWITCH_AUTOMATION_TRIM = 0x4C _LED_SWITCH_AUTOMATION_TOUCH = 0x4D _LED_SWITCH_AUTOMATION_LATCH = 0x4E _LED_SWITCH_GROUP = 0x4F _LED_SWITCH_UTILITIES_SAVE = 0x50 _LED_SWITCH_UTILITIES_UNDO = 0x51 _SWITCH_UTILITIES_CANCEL = 0x52 _SWITCH_UTILITIES_ENTER = 0x53 _LED_SWITCH_MARKER = 0x54 _LED_SWITCH_NUDGE = 0x55 _LED_SWITCH_CYCLE = 0x56 _LED_SWITCH_DROP = 0x57 _LED_SWITCH_REPLACE = 0x58 _LED_SWITCH_CLICK = 0x59 _LED_SWITCH_SOLO = 0x5A _LED_SWITCH_REWIND = 0x5B _LED_SWITCH_FAST_FORWARD = 0x5C _LED_SWITCH_STOP = 0x5D _LED_SWITCH_PLAY = 0x5E _LED_SWITCH_RECORD = 0x5F _SWITCH_CURSOR_UP = 0x60 _SWITCH_CURSOR_DOWN = 0x61 _SWITCH_CURSOR_LEFT = 0x62 _SWITCH_CURSOR_RIGHT = 0x63 _LED_SWITCH_ZOOM = 0x64 _LED_SWITCH_SCRUB = 0x65 _SWITCH_USER_SWITCH_A = 0x66 _SWITCH_USER_SWITCH_B = 0x67 _SWITCH_CHANNEL_FADER_TOUCH = 0x68 _SWITCH_MASTER_FADER_TOUCH = 0x70 _LED_SMPTE = 0x71 _LED_BEATS = 0x72 _LED_RUDE_SOLO = 0x73 _LED_RELAY_CLICK = 0x76 def __init__(self, mcu_model_id, mcu_connection, version_number, \ midi_input_name, midi_output_name, callback_log): self._callback_log = callback_log self._log('Initialising MIDI ports...', True) self._midi_input_name = midi_input_name self._midi_output_name = midi_output_name self._midi = MidiConnection(callback_log, self.receive_midi) self._midi_channel = 0 self.unset_hardware_controller() self._offline = True # Mackie Control model IDs: # * 0x10: Logic Control # * 0x11: Logic Control XT # * 0x14: Mackie Control # * 0x15: Mackie Control XT self._mcu_model_id = mcu_model_id # define connection type (among others, challenge-response) self._mcu_connection = mcu_connection serial_number = '_pyMCU_' self._serial_number_bytes = [] for char in serial_number: self._serial_number_bytes.append(ord(char)) challenge = 'test' self._challenge_bytes = [] for char in challenge: self._challenge_bytes.append(ord(char)) self._response_bytes = self._calculate_reponse_from_challenge( \ self._challenge_bytes) # make sure that the version number consists of exactly 5 # characters version_number = version_number.ljust(5)[0:5] self._version_number_bytes = [] for char in version_number: self._version_number_bytes.append(ord(char)) def _log(self, message, repaint=False): self._callback_log('[Mackie Host Control ] ' + message, repaint) # --- initialisation --- def set_hardware_controller(self, controller): self._hardware_controller = controller self._display_lcd_available = \ self._hardware_controller.has_display_lcd() self._automated_faders_available = \ self._hardware_controller.has_automated_faders() self._display_7seg_available = \ self._hardware_controller.has_display_7seg() self._display_timecode_available = \ self._hardware_controller.has_display_timecode() self._meter_bridge_available = \ self._hardware_controller.has_meter_bridge() def unset_hardware_controller(self): self._hardware_controller = None self._display_lcd_available = False self._automated_faders_available = False self._display_7seg_available = False self._display_timecode_available = False self._meter_bridge_available = False def connect(self): self._log('Opening MIDI ports...') self._midi.connect(self._midi_input_name, self._midi_output_name) if self._mcu_connection == self.CHALLENGE_RESPONSE: self._log('Sending "Host Connection Query"...', True) sysex_message = [0x01] sysex_message.extend(self._serial_number_bytes) sysex_message.extend(self._challenge_bytes) self.send_midi_sysex(sysex_message) return else: # let's make sure the MIDI input buffer is empty self._midi.process_input_buffer(use_callback=False) if self._mcu_connection == self.WAIT_FOR_MIDI_DATA: self._log('Waiting for MIDI input from host...', True) # wait for some MIDI input from the host (all data are # left in the MIDI input buffer!) while self._midi.buffer_is_empty(): time.sleep(0.1) self.go_online() def disconnect(self): self._log('Disconnecting...', True) self.go_offline() self._log('Closing MIDI ports...', True) self._midi.disconnect() def go_online(self): self._offline = False if self._hardware_controller: self._hardware_controller.go_online() self._log('Online.', True) def go_offline(self): self._offline = True if self._hardware_controller: self._hardware_controller.go_offline() if self._mcu_connection == self.CHALLENGE_RESPONSE: self._log('Sending "Host Connection Error"...') sysex_message = [0x04] sysex_message.extend(self._serial_number_bytes) self.send_midi_sysex(sysex_message) self._log('Offline.', True) def is_offline(self): return self._offline def _calculate_reponse_from_challenge(self, challenge_bytes): response_bytes = [] response_bytes.append( \ 0x7F & (challenge_bytes[0] + (challenge_bytes[1] ^ 0x0A) - \ challenge_bytes[3])) response_bytes.append( \ 0x7F & ((challenge_bytes[2] >> 4) ^ \ (challenge_bytes[0] + challenge_bytes[3]))) response_bytes.append( \ 0x7F & (challenge_bytes[3] - (challenge_bytes[2] << 2) ^ \ (challenge_bytes[0] | challenge_bytes[1]))) response_bytes.append( \ 0x7F & (challenge_bytes[1] - challenge_bytes[2] + \ (0xF0 ^ (challenge_bytes[3] << 4)))) return response_bytes # --- static methods --- @staticmethod def get_mcu_model_from_id(id): if id == 0x10: return 'Logic Control' elif id == 0x11: return 'Logic Control XT' elif id == 0x14: return 'Mackie Control' elif id == 0x15: return 'Mackie Control XT' else: return None @staticmethod def get_mcu_id_from_model(model): if model == 'Logic Control': return 0x10 elif model == 'Logic Control XT': return 0x11 elif model == 'Mackie Control': return 0x14 elif model == 'Mackie Control XT': return 0x15 else: return None @staticmethod def get_preferred_mcu_model(): return 'Mackie Control' @staticmethod def get_preferred_mcu_model_id(): return MackieHostControl.get_mcu_id_from_model( \ MackieHostControl.get_preferred_mcu_model()) @staticmethod def get_preferred_midi_input(): if os.name == 'nt': return 'In From MIDI Yoke: 2' else: return 'mcu' @staticmethod def get_preferred_midi_output(): if os.name == 'nt': return 'Out To MIDI Yoke: 1' else: return 'mcu' # --- MIDI processing --- def process_midi_input(self): self._midi.process_input_buffer() def receive_midi(self, status, message): if status == MidiConnection.SYSTEM_MESSAGE and message[0:5] == \ [0xF0, 0x00, 0x00, 0x66, self._mcu_model_id]: if message[5:] == [0x00, 0xF7]: self._log('Received "Device Query".') self._log('Sending "Host Connection Query"...', True) sysex_message = [0x01] sysex_message.extend(self._serial_number_bytes) sysex_message.extend(self._challenge_bytes) self.send_midi_sysex(sysex_message) return elif message[5] == 0x02: self._log('Received "Host Connection Reply".') if (message[6:13] == self._serial_number_bytes) and \ (message[13:17] == self._response_bytes): self._log('Sending "Host Connection Confirmation"...', \ True) sysex_message = [0x03] sysex_message.extend(self._serial_number_bytes) self.send_midi_sysex(sysex_message) self.go_online() else: self._log('Sending "Host Connection Error"...') sysex_message = [0x04] sysex_message.extend(self._serial_number_bytes) self.send_midi_sysex(sysex_message) self._log('Sending "Host Connection Query"...', True) sysex_message = [0x01] sysex_message.extend(self._serial_number_bytes) sysex_message.extend(self._challenge_bytes) self.send_midi_sysex(sysex_message) return elif message[5:] == [0x13, 0x00, 0x0F7]: self._log('Received "Version Request".') self._log('Sending "Version Reply"...', True) sysex_message = [0x14] sysex_message.extend(self._version_number_bytes) self.send_midi_sysex(sysex_message) return elif message[5:] == [0x0F, 0x7F, 0x0F7]: self._log('Received "Go Offline".', True) self.go_offline() return elif message[5:] == [0x61, 0x0F7]: self._log('Received "Faders To Minimum".', True) self.faders_to_minimum() return elif message[5:] == [0x62, 0x0F7]: self._log('Received "All LEDs Off".', True) self.all_leds_off() return elif message[5:] == [0x63, 0x0F7]: self._log('Received "Reset".', True) self.reset() return # do not make this an "elif" clause, otherwise some MIDI SysEx # messages won't get processed! if not self.is_offline(): if status == MidiConnection.SYSTEM_MESSAGE and message[0:5] == \ [0xF0, 0x00, 0x00, 0x66, self._mcu_model_id]: if message[5] == 0x12: if self._display_lcd_available: position = message[6] hex_codes = message[7:-1] self._hardware_controller.set_lcd(position, hex_codes) elif status == MidiConnection.PITCH_WHEEL_CHANGE: if self._automated_faders_available: fader_id = message[0] & 0x0F fader_position = (message[1] + (message[2] << 7)) >> 4 self._hardware_controller.fader_moved( \ fader_id, fader_position) elif status == MidiConnection.NOTE_ON_EVENT: led_id = message[1] led_status = 0 # off if message[2] == 0x7F: led_status = 1 # on elif message[2] == 0x01: led_status = 2 # flashing self._set_led(led_id, led_status) elif (status == MidiConnection.CONTROL_CHANGE) and \ ((message[1] & 0xF0) == 0x30): vpot_id = message[1] & 0x0F vpot_center_led = (message[2] & 0x40) >> 7 vpot_mode = (message[2] & 0x30) >> 4 vpot_position = message[2] & 0x0F self._hardware_controller.set_vpot_led_ring( \ vpot_id, vpot_center_led, vpot_mode, vpot_position) elif (status == MidiConnection.CONTROL_CHANGE) and \ ((message[1] & 0xF0) == 0x40): position = message[1] & 0x0F character_code = message[2] if (position < 10): if self._display_timecode_available: self._hardware_controller.set_display_timecode( \ position, character_code) elif self._display_7seg_available: self._hardware_controller.set_display_7seg( \ position, character_code) elif status == MidiConnection.CHANNEL_PRESSURE: if self._meter_bridge_available: meter_id = (message[1] & 0x70) >> 4 meter_level = message[1] & 0x0F self._hardware_controller.set_peak_level( \ meter_id, meter_level) else: output = 'status %02X: ' % status for byte in message: output += '%02X ' % byte self._log(output.strip()) else: output = 'status %02X: ' % status for byte in message: output += '%02X ' % byte self._log(output.strip()) def send_midi_sysex(self, data): assert (type(data) == types.ListType) header = [0x00, 0x00, 0x66, self._mcu_model_id] # leading 0xF0 and trailing 0xF7 are added by "MidiConnection" # class method self._midi.send_sysex(header, data) # --- commands from hardware control --- def move_vpot(self, vpot_id, direction, number_of_ticks): if self.is_offline(): return vpot_movement = number_of_ticks if direction == self.VPOT_COUNTER_CLOCKWISE: vpot_movement = vpot_movement + 0x40 self._midi.send_control_change( \ self._midi_channel, 0x10 + vpot_id, vpot_movement) def move_vpot_raw(self, vpot_id, vpot_movement): if self.is_offline(): return self._midi.send_control_change( \ self._midi_channel, 0x10 + vpot_id, vpot_movement) def move_fader(self, fader_id, fader_value): if self.is_offline(): return self._midi.send_pitch_wheel_change(fader_id, fader_value) def move_fader_7bit(self, fader_id, fader_value): if self.is_offline(): return self._midi.send_pitch_wheel_change_7bit(fader_id, fader_value) def _key_pressed(self, status, switch_id): if self.is_offline(): return if status == self.SWITCH_RELEASED: self._midi.send_note_on(switch_id, 0x00) elif status == self.SWITCH_PRESSED: self._midi.send_note_on(switch_id, 0x7F) elif status == self.SWITCH_PRESSED_RELEASED: self._midi.send_note_on(switch_id, 0x7F) self._midi.send_note_on(switch_id, 0x00) else: self._log( \ 'Illegal key press status 0x%02X on switch 0x%02X detected!' % \ (status, switch_id)) def keypress_record_ready_channel(self, channel, status): # channel: 1 - 8 self._key_pressed( \ status, self._LED_SWITCH_CHANNEL_RECORD_READY + channel - 1) def keypress_record_ready_channel_1(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY) def keypress_record_ready_channel_2(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 1) def keypress_record_ready_channel_3(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 2) def keypress_record_ready_channel_4(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 3) def keypress_record_ready_channel_5(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 4) def keypress_record_ready_channel_6(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 5) def keypress_record_ready_channel_7(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 6) def keypress_record_ready_channel_8(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_RECORD_READY + 7) def keypress_solo_channel(self, channel, status): # channel: 1 - 8 self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + channel - 1) def keypress_solo_channel_1(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO) def keypress_solo_channel_2(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 1) def keypress_solo_channel_3(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 2) def keypress_solo_channel_4(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 3) def keypress_solo_channel_5(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 4) def keypress_solo_channel_6(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 5) def keypress_solo_channel_7(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 6) def keypress_solo_channel_8(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SOLO + 7) def keypress_mute_channel(self, channel, status): # channel: 1 - 8 self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + channel - 1) def keypress_mute_channel_1(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE) def keypress_mute_channel_2(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 1) def keypress_mute_channel_3(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 2) def keypress_mute_channel_4(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 3) def keypress_mute_channel_5(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 4) def keypress_mute_channel_6(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 5) def keypress_mute_channel_7(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 6) def keypress_mute_channel_8(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_MUTE + 7) def keypress_select_channel(self, channel, status): # channel: 1 - 8 self._key_pressed( \ status, self._LED_SWITCH_CHANNEL_SELECT + channel - 1) def keypress_select_channel_1(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT) def keypress_select_channel_2(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 1) def keypress_select_channel_3(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 2) def keypress_select_channel_4(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 3) def keypress_select_channel_5(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 4) def keypress_select_channel_6(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 5) def keypress_select_channel_7(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 6) def keypress_select_channel_8(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_SELECT + 7) def keypress_vselect_channel(self, channel, status): # channel: 1 - 8 self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + \ channel - 1) def keypress_vselect_channel_1(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT) def keypress_vselect_channel_2(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 1) def keypress_vselect_channel_3(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 2) def keypress_vselect_channel_4(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 3) def keypress_vselect_channel_5(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 4) def keypress_vselect_channel_6(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 5) def keypress_vselect_channel_7(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 6) def keypress_vselect_channel_8(self, status): self._key_pressed(status, self._LED_SWITCH_CHANNEL_VSELECT + 7) def keypress_function_channel(self, channel, status): # channel: 1 - 8 self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + channel - 1) def keypress_function_channel_1(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION) def keypress_function_channel_2(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 1) def keypress_function_channel_3(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 2) def keypress_function_channel_4(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 3) def keypress_function_channel_5(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 4) def keypress_function_channel_6(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 5) def keypress_function_channel_7(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 6) def keypress_function_channel_8(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FUNCTION + 7) def keypress_assignment_track(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_TRACK) def keypress_assignment_send(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_SEND) def keypress_assignment_pan_surround(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_PAN_SURROUND) def keypress_assignment_plug_in(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_PLUG_IN) def keypress_assignment_eq(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_EQ) def keypress_assignment_instrument(self, status): self._key_pressed(status, self._LED_SWITCH_ASSIGNMENT_INSTRUMENT) def keypress_fader_banks_bank_left(self, status): self._key_pressed(status, self._SWITCH_FADER_BANKS_BANK_LEFT) def keypress_fader_banks_bank_right(self, status): self._key_pressed(status, self._SWITCH_FADER_BANKS_BANK_RIGHT) def keypress_fader_banks_channel_left(self, status): self._key_pressed(status, self._SWITCH_FADER_BANKS_CHANNEL_LEFT) def keypress_fader_banks_channel_right(self, status): self._key_pressed(status, self._SWITCH_FADER_BANKS_CHANNEL_RIGHT) def keypress_flip(self, status): self._key_pressed(status, self._LED_SWITCH_FLIP) def keypress_global_view(self, status): self._key_pressed(status, self._LED_SWITCH_GLOBAL_VIEW) def keypress_name_value(self, status): self._key_pressed(status, self._SWITCH_NAME_VALUE) def keypress_smpte_beats(self, status): self._key_pressed(status, self._SWITCH_SMPTE_BEATS) def keypress_global_view_midi_tracks(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_MIDI_TRACKS) def keypress_global_view_inputs(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_INPUTS) def keypress_global_view_audio_tracks(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_AUDIO_TRACKS) def keypress_global_view_audio_instruments(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_AUDIO_INSTRUMENTS) def keypress_global_view_aux(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_AUX) def keypress_global_view_busses(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_BUSSES) def keypress_global_view_outputs(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_OUTPUTS) def keypress_global_view_user(self, status): self._key_pressed(status, self._SWITCH_GLOBAL_VIEW_USER) def keypress_shift(self, status): self._key_pressed(status, self._SWITCH_SHIFT) def keypress_option(self, status): self._key_pressed(status, self._SWITCH_OPTION) def keypress_control(self, status): self._key_pressed(status, self._SWITCH_CONTROL) def keypress_command_alt(self, status): self._key_pressed(status, self._SWITCH_COMMAND_ALT) def keypress_automation_read_off(self, status): self._key_pressed(status, self._LED_SWITCH_AUTOMATION_READ_OFF) def keypress_automation_write(self, status): self._key_pressed(status, self._LED_SWITCH_AUTOMATION_WRITE) def keypress_automation_trim(self, status): self._key_pressed(status, self._LED_SWITCH_AUTOMATION_TRIM) def keypress_automation_touch(self, status): self._key_pressed(status, self._LED_SWITCH_AUTOMATION_TOUCH) def keypress_automation_latch(self, status): self._key_pressed(status, self._LED_SWITCH_AUTOMATION_LATCH) def keypress_group(self, status): self._key_pressed(status, self._LED_SWITCH_GROUP) def keypress_utilities_save(self, status): self._key_pressed(status, self._LED_SWITCH_UTILITIES_SAVE) def keypress_utilities_undo(self, status): self._key_pressed(status, self._LED_SWITCH_UTILITIES_UNDO) def keypress_utilities_cancel(self, status): self._key_pressed(status, self._SWITCH_UTILITIES_CANCEL) def keypress_utilities_enter(self, status): self._key_pressed(status, self._SWITCH_UTILITIES_ENTER) def keypress_marker(self, status): self._key_pressed(status, self._LED_SWITCH_MARKER) def keypress_nudge(self, status): self._key_pressed(status, self._LED_SWITCH_NUDGE) def keypress_cycle(self, status): self._key_pressed(status, self._LED_SWITCH_CYCLE) def keypress_drop(self, status): self._key_pressed(status, self._LED_SWITCH_DROP) def keypress_replace(self, status): self._key_pressed(status, self._LED_SWITCH_REPLACE) def keypress_click(self, status): self._key_pressed(status, self._LED_SWITCH_CLICK) def keypress_solo(self, status): self._key_pressed(status, self._LED_SWITCH_SOLO) def keypress_rewind(self, status): self._key_pressed(status, self._LED_SWITCH_REWIND) def keypress_fast_forward(self, status): self._key_pressed(status, self._LED_SWITCH_FAST_FORWARD) def keypress_stop(self, status): self._key_pressed(status, self._LED_SWITCH_STOP) def keypress_play(self, status): self._key_pressed(status, self._LED_SWITCH_PLAY) def keypress_record(self, status): self._key_pressed(status, self._LED_SWITCH_RECORD) def keypress_cursor_up(self, status): self._key_pressed(status, self._SWITCH_CURSOR_UP) def keypress_cursor_down(self, status): self._key_pressed(status, self._SWITCH_CURSOR_DOWN) def keypress_cursor_left(self, status): self._key_pressed(status, self._SWITCH_CURSOR_LEFT) def keypress_cursor_right(self, status): self._key_pressed(status, self._SWITCH_CURSOR_RIGHT) def keypress_zoom(self, status): self._key_pressed(status, self._LED_SWITCH_ZOOM) def keypress_scrub(self, status): self._key_pressed(status, self._LED_SWITCH_SCRUB) def keypress_user_switch(self, switch_number, status): # switch_number: 1 - 2 if switch_number == 1: self._key_pressed(status, self._SWITCH_USER_SWITCH_A) else: self._key_pressed(status, self._SWITCH_USER_SWITCH_B) def keypress_user_switch_1(self, status): self._key_pressed(status, self._SWITCH_USER_SWITCH_A) def keypress_user_switch_2(self, status): self._key_pressed(status, self._SWITCH_USER_SWITCH_B) def keypress_fader_touch_channel(self, channel, status): # channel: 1 - 8 self._key_pressed( \ status, self._SWITCH_CHANNEL_FADER_TOUCH + channel - 1) def keypress_fader_touch_channel_1(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH) def keypress_fader_touch_channel_2(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 1) def keypress_fader_touch_channel_3(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 2) def keypress_fader_touch_channel_4(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 3) def keypress_fader_touch_channel_5(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 4) def keypress_fader_touch_channel_6(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 5) def keypress_fader_touch_channel_7(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 6) def keypress_fader_touch_channel_8(self, status): self._key_pressed(status, self._SWITCH_CHANNEL_FADER_TOUCH + 7) def keypress_fader_touch_master(self, status): self._key_pressed(status, self._SWITCH_MASTER_FADER_TOUCH) # --- commands from Mackie Control host --- def _set_led(self, id, status): if self.is_offline(): return selector = { self._LED_SWITCH_CHANNEL_RECORD_READY: \ 'self._hardware_controller.set_led_channel_record_ready(0, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 1: \ 'self._hardware_controller.set_led_channel_record_ready(1, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 2: \ 'self._hardware_controller.set_led_channel_record_ready(2, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 3: \ 'self._hardware_controller.set_led_channel_record_ready(3, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 4: \ 'self._hardware_controller.set_led_channel_record_ready(4, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 5: \ 'self._hardware_controller.set_led_channel_record_ready(5, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 6: \ 'self._hardware_controller.set_led_channel_record_ready(6, status)', self._LED_SWITCH_CHANNEL_RECORD_READY + 7: \ 'self._hardware_controller.set_led_channel_record_ready(7, status)', self._LED_SWITCH_CHANNEL_SOLO: \ 'self._hardware_controller.set_led_channel_solo(0, status)', self._LED_SWITCH_CHANNEL_SOLO + 1: \ 'self._hardware_controller.set_led_channel_solo(1, status)', self._LED_SWITCH_CHANNEL_SOLO + 2: \ 'self._hardware_controller.set_led_channel_solo(2, status)', self._LED_SWITCH_CHANNEL_SOLO + 3: \ 'self._hardware_controller.set_led_channel_solo(3, status)', self._LED_SWITCH_CHANNEL_SOLO + 4: \ 'self._hardware_controller.set_led_channel_solo(4, status)', self._LED_SWITCH_CHANNEL_SOLO + 5: \ 'self._hardware_controller.set_led_channel_solo(5, status)', self._LED_SWITCH_CHANNEL_SOLO + 6: \ 'self._hardware_controller.set_led_channel_solo(6, status)', self._LED_SWITCH_CHANNEL_SOLO + 7: \ 'self._hardware_controller.set_led_channel_solo(7, status)', self._LED_SWITCH_CHANNEL_MUTE: \ 'self._hardware_controller.set_led_channel_mute(0, status)', self._LED_SWITCH_CHANNEL_MUTE + 1: \ 'self._hardware_controller.set_led_channel_mute(1, status)', self._LED_SWITCH_CHANNEL_MUTE + 2: \ 'self._hardware_controller.set_led_channel_mute(2, status)', self._LED_SWITCH_CHANNEL_MUTE + 3: \ 'self._hardware_controller.set_led_channel_mute(3, status)', self._LED_SWITCH_CHANNEL_MUTE + 4: \ 'self._hardware_controller.set_led_channel_mute(4, status)', self._LED_SWITCH_CHANNEL_MUTE + 5: \ 'self._hardware_controller.set_led_channel_mute(5, status)', self._LED_SWITCH_CHANNEL_MUTE + 6: \ 'self._hardware_controller.set_led_channel_mute(6, status)', self._LED_SWITCH_CHANNEL_MUTE + 7: \ 'self._hardware_controller.set_led_channel_mute(7, status)', self._LED_SWITCH_CHANNEL_SELECT: \ 'self._hardware_controller.set_led_channel_select(0, status)', self._LED_SWITCH_CHANNEL_SELECT + 1: \ 'self._hardware_controller.set_led_channel_select(1, status)', self._LED_SWITCH_CHANNEL_SELECT + 2: \ 'self._hardware_controller.set_led_channel_select(2, status)', self._LED_SWITCH_CHANNEL_SELECT + 3: \ 'self._hardware_controller.set_led_channel_select(3, status)', self._LED_SWITCH_CHANNEL_SELECT + 4: \ 'self._hardware_controller.set_led_channel_select(4, status)', self._LED_SWITCH_CHANNEL_SELECT + 5: \ 'self._hardware_controller.set_led_channel_select(5, status)', self._LED_SWITCH_CHANNEL_SELECT + 6: \ 'self._hardware_controller.set_led_channel_select(6, status)', self._LED_SWITCH_CHANNEL_SELECT + 7: \ 'self._hardware_controller.set_led_channel_select(7, status)', self._LED_SWITCH_CHANNEL_VSELECT: \ 'self._hardware_controller.set_led_channel_vselect(0, status)', self._LED_SWITCH_CHANNEL_VSELECT + 1: \ 'self._hardware_controller.set_led_channel_vselect(1, status)', self._LED_SWITCH_CHANNEL_VSELECT + 2: \ 'self._hardware_controller.set_led_channel_vselect(2, status)', self._LED_SWITCH_CHANNEL_VSELECT + 3: \ 'self._hardware_controller.set_led_channel_vselect(3, status)', self._LED_SWITCH_CHANNEL_VSELECT + 4: \ 'self._hardware_controller.set_led_channel_vselect(4, status)', self._LED_SWITCH_CHANNEL_VSELECT + 5: \ 'self._hardware_controller.set_led_channel_vselect(5, status)', self._LED_SWITCH_CHANNEL_VSELECT + 6: \ 'self._hardware_controller.set_led_channel_vselect(6, status)', self._LED_SWITCH_CHANNEL_VSELECT + 7: \ 'self._hardware_controller.set_led_channel_vselect(7, status)', self._LED_SWITCH_ASSIGNMENT_TRACK: \ 'self._hardware_controller.set_led_assignment_track(status)', self._LED_SWITCH_ASSIGNMENT_SEND: \ 'self._hardware_controller.set_led_assignment_send(status)', self._LED_SWITCH_ASSIGNMENT_PAN_SURROUND: \ 'self._hardware_controller.set_led_assignment_pan_surround(status)', self._LED_SWITCH_ASSIGNMENT_PLUG_IN: \ 'self._hardware_controller.set_led_assignment_plug_in(status)', self._LED_SWITCH_ASSIGNMENT_EQ: \ 'self._hardware_controller.set_led_assignment_eq(status)', self._LED_SWITCH_ASSIGNMENT_INSTRUMENT: \ 'self._hardware_controller.set_led_assignment_instrument(status)', self._LED_SWITCH_FLIP: \ 'self._hardware_controller.set_led_flip(status)', self._LED_SWITCH_GLOBAL_VIEW: \ 'self._hardware_controller.set_led_global_view(status)', self._LED_SWITCH_AUTOMATION_READ_OFF: \ 'self._hardware_controller.set_led_automation_read_off(status)', self._LED_SWITCH_AUTOMATION_WRITE: \ 'self._hardware_controller.set_led_automation_write(status)', self._LED_SWITCH_AUTOMATION_TRIM: \ 'self._hardware_controller.set_led_automation_trim(status)', self._LED_SWITCH_AUTOMATION_TOUCH: \ 'self._hardware_controller.set_led_automation_touch(status)', self._LED_SWITCH_AUTOMATION_LATCH: \ 'self._hardware_controller.set_led_automation_latch(status)', self._LED_SWITCH_GROUP: \ 'self._hardware_controller.set_led_group(status)', self._LED_SWITCH_UTILITIES_SAVE: \ 'self._hardware_controller.set_led_utilities_save(status)', self._LED_SWITCH_UTILITIES_UNDO: \ 'self._hardware_controller.set_led_utilities_undo(status)', self._LED_SWITCH_MARKER: \ 'self._hardware_controller.set_led_marker(status)', self._LED_SWITCH_NUDGE: \ 'self._hardware_controller.set_led_nudge(status)', self._LED_SWITCH_CYCLE: \ 'self._hardware_controller.set_led_cycle(status)', self._LED_SWITCH_DROP: \ 'self._hardware_controller.set_led_drop(status)', self._LED_SWITCH_REPLACE: \ 'self._hardware_controller.set_led_replace(status)', self._LED_SWITCH_CLICK: \ 'self._hardware_controller.set_led_click(status)', self._LED_SWITCH_SOLO: \ 'self._hardware_controller.set_led_solo(status)', self._LED_SWITCH_REWIND: \ 'self._hardware_controller.set_led_rewind(status)', self._LED_SWITCH_FAST_FORWARD: \ 'self._hardware_controller.set_led_fast_forward(status)', self._LED_SWITCH_STOP: \ 'self._hardware_controller.set_led_stop(status)', self._LED_SWITCH_PLAY: \ 'self._hardware_controller.set_led_play(status)', self._LED_SWITCH_RECORD: \ 'self._hardware_controller.set_led_record(status)', self._LED_SWITCH_ZOOM: \ 'self._hardware_controller.set_led_zoom(status)', self._LED_SWITCH_SCRUB: \ 'self._hardware_controller.set_led_scrub(status)', self._LED_SMPTE: \ 'self._hardware_controller.set_led_smpte(status)', self._LED_BEATS: \ 'self._hardware_controller.set_led_beats(status)', self._LED_RUDE_SOLO: \ 'self._hardware_controller.set_led_rude_solo(status)', self._LED_RELAY_CLICK: \ 'self._hardware_controller.set_led_relay_click(status)' } if id in selector: eval(selector[id]) else: led_status = 'off' if status == 1: status = 'on' elif status == 2: status = 'flashing' self._log('LED 0x%02X NOT implemented (%s).' % (id, led_status)) def faders_to_minimum(self): if self._hardware_controller: self._hardware_controller.faders_to_minimum() def all_leds_off(self): if self._hardware_controller: self._hardware_controller.all_leds_off() def reset(self): self.go_offline()