class Tweaker(ControlSurface): __module__ = __name__ __doc__ = " MonOhmod companion controller script " def __init__(self, c_instance): """everything except the '_on_selected_track_changed' override and 'disconnect' runs from here""" ControlSurface.__init__(self, c_instance) with self.component_guard(): self._update_linked_device_selection = None self._tweaker_version = '0.4' self.log_message("--------------= Tweaker Mixer " + str(self._tweaker_version) + " log opened =--------------") self._update_linked_device_selection = None self._setup_mixer_control() self._setup_session_control() """script initialization methods""" def _setup_controls(self): is_momentary = True self._grid = [None for index in range(8)] for column in range(8): self._grid[column] = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, column + (row * 8), 'Grid_' + str(column) + '_' + str(row), self) for row in range(4)] self._button = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_BUTTONS[index], 'Button_' + str(index), self) for index in range(len(TWEAKER_BUTTONS))] self._nav = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_NAVS[index], 'Nav_' + str(index), self) for index in range(len(TWEAKER_NAVS))] self._encoder_buttons = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_ENCODER_BUTTONS[index], 'Encoder_Button_' + str(index), self) for index in range(len(TWEAKER_ENCODER_BUTTONS))] self._dial = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_DIALS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_DIALS))] self._fader = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_FADERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_FADERS))] self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute) self._encoder = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_ENCODERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_ENCODERS))] self._pad = [FlashingButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, TWEAKER_PADS[index], 'Pad_' + str(index), self) for index in range(len(TWEAKER_PADS))] self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' for row in range(4): button_row = [] for column in range(7): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_mixer_control(self): is_momentary = True self._num_tracks = (2) #A mixer is one-dimensional; self._mixer = MixerComponent(2, 0, False, True) self._mixer.name = 'Mixer' self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer) self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) def _setup_session_control(self): is_momentary = True num_tracks = 2 num_scenes = 3 self._session = SessionComponent(num_tracks, num_scenes) self._session.name = "Session" self._session.set_offsets(0, 0) self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) """general functionality""" def allow_updates(self, allow_updates): for component in self.components: component.set_allow_update(int(allow_updates!=0)) def disconnect(self): """clean things up on disconnect""" if self._session._is_linked(): self._session._unlink() self.log_message("--------------= Tweaker Mixer " + str(self._tweaker_version) + " log closed =--------------") #Create entry in log file ControlSurface.disconnect(self) return None def connect_script_instances(self, instanciated_scripts): link = False for s in instanciated_scripts: if '_tweaker_version' in dir(s): if s._tweaker_version == self._tweaker_version: link = True if not s is self: s._linked_session = self._session #break if link is True: if not self._session._is_linked(): #self._session.set_offsets(0, 0) self._session._link() def _mixer_tracks_to_use(self, mixer): def tracks_to_use(): return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) return tracks_to_use # a
class Codec(ControlSurface): __module__ = __name__ __doc__ = " MonoCode controller script " def __init__(self, c_instance, *a, **k): super(Codec, self).__init__(c_instance, *a, **k) self._monomod_version = 'b995' self._version_check = 'b995' self._host_name = 'Codec' self._color_type = 'Monochrome' self._link_mixer = LINK_MIXER self._hosts = [] self._linked_script = None self._local_ring_control = True self._last_device = None self._device_list = [None, None, None, None] self._device_select_buttons = None self._last_device_component = None self._timer = 0 self._touched = 0 self._locked = False self.flash_status = 1 self._shift_button = None self._shift_pressed = 0 self._shift_pressed_timer = 0 self._shift_thresh = SHIFT_THRESH self._use_device_selector = USE_DEVICE_SELECTOR self._device_selection_follows_track_selection=FOLLOW with self.component_guard(): #self.local_ring_control(True) #self.set_absolute_mode(True) self._setup_controls() self._setup_monobridge() self._setup_device_controls() self._setup_special_device_control() self._device.append(self._special_device) #necessary for device browsing to work with special device self._setup_device_chooser() self._setup_mixer_controls() self._setup_monomod() self._setup_modes() self._setup_device_selector() self._setup_send_reset() self._setup_default_buttons() self.set_local_ring_control(1) self.song().view.add_selected_track_listener(self._update_selected_device) self._initialize_code() #self._shift_mode.set_mode(0) #self._monomod_mode.set_mode(0) self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Codec ' + str(self._monomod_version) + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>') self.show_message('Codec Control Surface Loaded') self.request_rebuild_midi_map() """script initialization methods""" def _initialize_code(self): self._send_midi(factoryreset) self._send_midi(btn_channels) self._send_midi(enc_channels) def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_controls(self): is_momentary = True self._livid = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self) self._dial = [None for index in range(8)] for column in range(8): self._dial[column] = [None for index in range(4)] for row in range(4): self._dial[column][row] = CodecEncoderElement(MIDI_CC_TYPE, CHANNEL, CODE_DIALS[row][column], Live.MidiMap.MapMode.absolute, 'Dial_' + str(column) + '_' + str(row), (column + (row*8)), self) #CODE_DIALS[row][column] self._button = [None for index in range(8)] for column in range(8): self._button[column] = [None for index in range(4)] for row in range(4): self._button[column][row] = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_BUTTONS[row][column], 'Button_' + str(column) + '_' + str(row), self) self._column_button = [None for index in range(8)] for index in range(8): self._column_button[index] = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_COLUMN_BUTTONS[index], 'Column_Button_' + str(index), self) self._row_button = [None for index in range(4)] for index in range(4): self._row_button[index] = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_ROW_BUTTONS[index], 'Row_Button_' + str(index), self) self._dial_matrix = EncoderMatrixElement(self) self._dial_matrix.name = 'Encoder_Matrix' for row in range(4): dial_row = tuple([self._dial[column][row] for column in range(8)]) self._dial_matrix.add_row(dial_row) self._button_matrix = ButtonMatrixElement() self._button_matrix.name = 'Button_Matrix' for row in range(4): button_row = [self._button[column][row] for column in range(8)] button_row.append(self._row_button[row]) self._button_matrix.add_row(tuple(button_row)) self._button_matrix.add_row(tuple(self._column_button + [self._livid])) def _setup_modes(self): self._monomod_mode = MonomodModeComponent(self._mod_mode_update, self) self._monomod_mode.name = 'Monomod_Mode' self.set_shift_button(self._livid) self._shift_mode = ShiftModeComponent(self._shift_update, self) self._shift_mode.name = 'Shift_Mode' self._shift_mode.set_mode_buttons(tuple([self._row_button[0], self._row_button[1], self._row_button[2], self._row_button[3]])) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_monomod(self): self._host = CodecMonomodComponent(self) self._host.name = 'Monomod_Host' self._host._set_dial_matrix(self._dial_matrix, self._button_matrix) self.hosts = [self._host] encs = [] for row in range(4): for col in range(8): encs.append(self._dial[col][row]) self._host._set_parameter_controls(encs) def _setup_mixer_controls(self): is_momentary = True self._num_tracks = (8) self._session = SessionComponent(self._num_tracks, 0) self._session.name = 'Session' self._mixer = MixerComponent(self._num_tracks, 0, False, False) self._mixer.name = 'Mixer' self._mixer._next_track_value = self._mixer_next_track_value(self._mixer) self._mixer._prev_track_value = self._mixer_prev_track_value(self._mixer) self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) #for index in range(8): #use the bottom row of encoders for volume, so add 24 to offset the index # self._mixer.channel_strip(index).set_volume_control(self._dial[index+24]) for index in range(8): self._mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) self._mixer.channel_strip(index)._invert_mute_feedback = True self._mixer.channel_strip(index)._mute_value = self._channelstrip_mute_value(self._mixer.channel_strip(index)) self._mixer.channel_strip(index)._solo_value = self._channelstrip_solo_value(self._mixer.channel_strip(index)) #mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index])) self.song().view.selected_track = self._mixer.channel_strip(0)._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error self._session.set_mixer(self._mixer) def _setup_device_controls(self): self._device = [None for index in range(4)] for index in range(4): self._device[index] = CodecDeviceComponent(self) self._device[index].name = 'CodecDevice_Component_' + str(index) device_param_controls = [] for control in range(8): device_param_controls.append(self._dial[control][index]) self._device[index].set_on_off_button(self._button[1][index]) self._device[index].set_lock_button(self._button[2][index]) self._device[index].set_bank_nav_buttons(self._button[4][index], self._button[5][index]) self._device[index].set_nav_buttons(self._button[6][index], self._button[7][index]) self._device[index].set_parameter_controls(tuple(device_param_controls)) self.set_device_component(self._device[0]) self._last_device_component = self._device[0] def _setup_special_device_control(self): self._special_device = SpecialCodecDeviceComponent(self) self._special_device.name = 'SpecialCodecDeviceComponent' self._special_device.set_on_off_button(self._button[1][0]) self._special_device.set_lock_button(self._button[2][0]) self._special_device.set_bank_nav_buttons(self._button[4][0], self._button[5][0]) self._special_device.set_nav_buttons(self._button[6][0], self._button[7][0]) device_param_controls = [] for row in range(4): for column in range(8): device_param_controls.append(self._dial[column][row]) self._special_device.set_parameter_controls(tuple(device_param_controls)) def _setup_device_chooser(self): self._selected_device = self._device[0] self._last_selected_device = self._device[0] self._device_select_buttons = [self._button[0][index] for index in range(4)] for button in self._device_select_buttons: button.add_value_listener(self._device_select_value, True) def _setup_device_selector(self): self._device_selector = CodecDeviceSelectorComponent(self, 'c', self._device + [self._special_device]) self._device_selector.name = 'Device_Selector' self._device_selector.set_mode_buttons(self._column_button) #self._device_selector.set_mode_toggle(self._livid) def _setup_send_reset(self): self._send_reset = CodecResetSendsComponent(self) self._send_reset.set_buttons(self._button) def _setup_default_buttons(self): self._value_default = ParameterDefaultComponent(self) buttons = [] dials = [] for column in self._button: for button in column: buttons.append(button) for column in self._dial: for dial in column: dials.append(dial) self._value_default.set_buttons(buttons) self._value_default.set_dials(dials) """multiple device support""" def _device_select_value(self, value, sender): #self.log_message('device_select_value ' + str(value) + ' ' + str(self._device_select_buttons.index(sender))) if not self._shift_pressed: if sender.is_momentary or value > 0: if self._shift_mode._mode_index == 2: self.set_device_component(self._device[self._device_select_buttons.index(sender)]) self._last_device_component = self._device_component if self._device_component != None and isinstance(self._device_component._device, Live.Device.Device): if self._device_component.find_track(self._device_component._device) == self.song().view.selected_track: self._device_component.display_device() """livid double press mechanism""" def set_shift_button(self, button): assert ((button == None) or (isinstance(button, MonoButtonElement))) if self._shift_button != None: self._shift_button.remove_value_listener(self._shift_value) self._shift_button = button if self._shift_button != None: self._shift_button.add_value_listener(self._shift_value) def _shift_value(self, value): self._shift_pressed = int(value != 0) if self._shift_pressed > 0: self._send_midi(SLOWENCODER) if (self._shift_pressed_timer + self._shift_thresh) > self._timer: #if(self._host.is_enabled() != True) self.log_message('mod mode: ' + str(abs(self._monomod_mode._mode_index - 1))) self._monomod_mode.set_mode(max(0, min(1, abs(self._monomod_mode._mode_index - 1)))) #else: # self._monomod_mode.set_mode(0) self._shift_pressed_timer = self._timer % 256 else: self._send_midi(NORMALENCODER) def _mod_mode_update(self): if(self._monomod_mode._mode_index == 0): self._host._set_shift_button(None) self._host.set_enabled(False) self._dial_matrix.reset() self._shift_mode.set_enabled(True) self._shift_update() self.request_rebuild_midi_map() self._livid.turn_off() elif(self._monomod_mode._mode_index == 1): self._shift_mode.set_enabled(False) self._deassign_all() self._dial_matrix.reset() self._button_matrix.reset() self._livid.turn_on() if not self._host._active_client == None: self._host.set_enabled(True) self._host._set_shift_button(self._livid) else: self._assign_alternate_mappings(1) self.request_rebuild_midi_map() """Mode Functions""" def _shift_update(self): if(self._shift_mode.is_enabled()): with self.component_guard(): self.allow_updates(False) #if(not self._in_build_midi_map): # self.set_suppress_rebuild_requests(True) self._deassign_all() if(self._shift_mode._mode_index is 0): self._assign_volume() elif(self._shift_mode._mode_index is 1): self._assign_sends() elif(self._shift_mode._mode_index is 2): self._assign_devices() elif(self._shift_mode._mode_index is 3): self._assign_special_device() for index in range(self._shift_mode.number_of_modes()): if index == self._shift_mode._mode_index: self._shift_mode._modes_buttons[index].turn_on() else: self._shift_mode._modes_buttons[index].turn_off() self.allow_updates(True) #self.set_suppress_rebuild_requests(False) self.request_rebuild_midi_map() def _deassign_all(self): self._assign_alternate_mappings(0) self._device_selector.set_enabled(False) for index in range(8): self._mixer.channel_strip(index).set_volume_control(None) self._mixer.channel_strip(index).set_pan_control(None) self._mixer.channel_strip(index).set_send_controls(tuple([None, None, None, None])) for index in range(4): self._device[index].set_enabled(False) self._device[index]._parameter_controls = None #self._device_navigator[index].set_enabled(False) self._special_device.set_enabled(False) self._special_device._parameter_controls = None self._device_selector.set_enabled(False) self._deassign_buttons() for control in self.controls: control.reset() self.request_rebuild_midi_map() def _deassign_buttons(self): for index in range(8): self._mixer.channel_strip(index).set_select_button(None) self._mixer.channel_strip(index).set_solo_button(None) self._mixer.channel_strip(index).set_mute_button(None) self._mixer.set_select_buttons(None, None) self._send_reset.set_enabled(False) def _assign_volume(self): for index in range(8): self._mixer.channel_strip(index).set_volume_control(self._dial[index][3]) self._mixer.channel_strip(index).set_pan_control(self._dial[index][2]) self._mixer.channel_strip(index).set_send_controls(tuple([self._dial[index][0], self._dial[index][1]])) self._mixer.channel_strip(index).set_select_button(self._column_button[index]) self._mixer.channel_strip(index).set_solo_button(self._button[index][2]) self._mixer.channel_strip(index).set_mute_button(self._button[index][3]) self._mixer.set_select_buttons(self._button[7][0], self._button[6][0]) def _assign_sends(self): for index in range(8): self._mixer.channel_strip(index).set_send_controls(tuple([self._dial[index][0], self._dial[index][1], self._dial[index][2], self._dial[index][3]])) self._mixer.channel_strip(index).set_select_button(self._column_button[index]) self._send_reset.set_enabled(True) def _assign_devices(self): self.set_device_component(self._last_device_component) self._device_select_value(1, self._device_select_buttons[self._device.index(self._device_component)]) for index in range(4): device_param_controls = [] for control in range(8): device_param_controls.append(self._dial[control][index]) self._device[index].set_parameter_controls(tuple(device_param_controls)) self._device[index].set_enabled(True) self._device_selector.set_enabled(self._use_device_selector) if not self._use_device_selector: for index in range(8): self._mixer.channel_strip(index).set_select_button(self._column_button[index]) def _assign_special_device(self): self.set_device_component(self._special_device) device_param_controls = [] for row in range(4): for column in range(8): device_param_controls.append(self._dial[column][row]) self._special_device.set_parameter_controls(tuple(device_param_controls)) self._special_device.set_enabled(True) self._device_selector.set_enabled(self._use_device_selector) if not self._use_device_selector: for index in range(8): self._mixer.channel_strip(index).set_select_button(self._column_button[index]) def _assign_alternate_mappings(self, chan): for column in self._dial: for control in column: control.set_channel(chan) control.set_enabled(chan is 0) for column in self._button: for control in column: control.set_channel(chan) control.set_enabled(chan is 0) for control in self._column_button: control.set_channel(chan) control.set_enabled(chan is 0) for control in self._row_button: control.set_channel(chan) control.set_enabled(chan is 0) """general functionality""" def disconnect(self): """clean things up on disconnect""" if not self._shift_button is None: if self._shift_button.value_has_listener(self._shift_value): self._shift_button.remove_value_listener(self._shift_value) for button in self._device_select_buttons: if button.value_has_listener(self._device_select_value): button.remove_value_listener(self._device_select_value) if self._session._is_linked(): self._session._unlink() self.song().view.remove_selected_track_listener(self._update_selected_device) """for cs in self._control_surfaces(): for host in self._hosts: self.log_message('installed: ' + str(cs) + ' vs. ' + str(host)) if str(type(cs)) == str(type(host)): self.log_message('disconnecting: ' + str(type(cs))) cs.disconnect(cs)""" #self._host._set_parameter_controls(None) self._hosts = [] if self._linked_script != None: self._linked_script._update_linked_device_selection = None self._linked_script = None #self._disconnect_notifier.set_mode(0) self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Codec log closed >>>>>>>>>>>>>>>>>>>>>>>>>') ControlSurface.disconnect(self) return None def connect_script_instances(self, instanciated_scripts): found = False for s in instanciated_scripts: if '_codec_version' in dir(s): if s._codec_version == self._version_check: if s._host_name == ('MonOhm'): self.log_message('found codec version ' + str(s._codec_version) + ' in script ' + str(s._host_name)) found = True self._linked_script = s self._linked_script._update_linked_device_selection = self._update_linked_device_selection if not self._session._is_linked() and self._link_mixer is True: self._session.set_offsets(LINK_OFFSET[0], LINK_OFFSET[1]) self._session._link() else: self.log_message('version mismatch: Monomod version ' + str(self._version_check) + ' vs. Host version ' + str(s._codec_version)) if found == False: for s in instanciated_scripts: if '_codec_version' in dir(s): if s._codec_version == self._version_check: if s._host_name == 'BlockMod': self.log_message('found codec version ' + str(s._codec_version) + ' in script ' + str(s._host_name)) self._linked_script = s self._linked_script._update_linked_device_selection = self._update_linked_device_selection if not self._session._is_linked() and self._link_mixer is True: self._session.set_offsets(LINK_OFFSET[0], LINK_OFFSET[1]) self._session._link() else: self.log_message('version mismatch: Monomod version ' + str(self._version_check) + ' vs. Host version ' + str(s._codec_version)) #self.log_message('hosts: ' + str(self._hosts))""" def update_display(self): ControlSurface.update_display(self) #since we are overriding this from the inherited method, we need to call the original routine as well self._timer = (self._timer + 1) % 256 if(self._timer == 0): self._shift_pressed_timer = -12 if(self._local_ring_control is False): self.send_ring_leds() self.flash() def handle_sysex(self, midi_bytes): #self._send_midi(tuple([240, 00, 01, 97, 04, 15, 01, 247])) #response = [long(0),long(0)] #self.log_message(response) pass def flash(self): if(self.flash_status > 0): for control in self.controls: if isinstance(control, MonoButtonElement): control.flash(self._timer) def send_ring_leds(self): leds = [240, 0, 1, 97, 4, 31] for column in range(8): for row in range(4): wheel = self._dial[column][row] bytes = wheel._get_ring() leds.append(bytes[0]) leds.append(int(bytes[1]) + int(bytes[2])) #if(row == 1 and column == 0): # self.log_message(str(leds) + ' ' + str(bytes[0]) + ' ' + str(bytes[1]) + ' ' + str(bytes[2])) leds.append(247) self._send_midi(tuple(leds)) def set_absolute_mode(self, val = 1): self._absolute_mode = (val!=0) if self._absolute_mode is True: self._send_midi(tuple([240, 0, 1, 97, 4, 17, 0, 0, 0, 0, 0, 0, 0, 0, 247])) else: self._send_midi(tuple([240, 0, 1, 97, 4, 17, 127, 127, 127, 127, 127, 127, 127, 127, 247])) def set_local_ring_control(self, val = 1): self._local_ring_control = (val!=0) if(self._local_ring_control is True): #self._send_midi(tuple([240, 0, 1, 97, 4, 32, 0, 247])) self._send_midi(tuple([240, 0, 1, 97, 4, 8, 72, 247])) else: #self._send_midi(tuple([240, 0, 1, 97, 4, 32, 1, 247])) self._send_midi(tuple([240, 0, 1, 97, 4, 8, 64, 247])) def device_follows_track(self, val): self._device_selection_follows_track_selection = (val == 1) return self """m4l bridge""" def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return ret def notification_to_bridge(self, name, value, sender): if(isinstance(sender, CodecEncoderElement)): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if not self._host.is_enabled(): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched +=1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip() is True: clip_names.append(clip_slot._clip_slot)##.clip.name) return clip_slot._clip_slot ##self.log_message(str(clip_slot._clip_slot.clip.name)) return clip_names """overrides""" def allow_updates(self, allow_updates): for component in self.components: component.set_allow_update(int(allow_updates!=0)) def set_device_component(self, device_component): if self._device_component != None: self._device_component._lock_callback = None assert (device_component != None) assert isinstance(device_component, DeviceComponent) self._device_component = device_component self._device_component._lock_callback = self._toggle_lock #old: self._device_component.set_lock_callback(self._toggle_lock) if self._device_select_buttons != None: for button in self._device_select_buttons: button.send_value(self._device_select_buttons.index(button) == self._device.index(self._device_component)) self._update_device_selection() return None def _update_selected_device(self): if self._device_selection_follows_track_selection is True: self._update_device_selection() return None def _update_linked_device_selection(self, device): #self.log_message('codec received ' + str(device.name)) if self._device_component != None and device != None: if not self._device_component.is_locked(): self._device_component.set_device(device) def _get_num_tracks(self): return self.num_tracks def _update_device_selection(self): #self.log_message('_update_device_selection') if self._device_component != None: if not self._device_component.is_locked(): track = self.song().view.selected_track device_to_select = track.view.selected_device if ((device_to_select == None) and (len(track.devices) > 0)): device_to_select = track.devices[0] if (device_to_select != None): self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) def _channelstrip_mute_value(self, channelstrip): def _mute_value(value): if not self._shift_pressed: self.log_message('shift not pressed') ChannelStripComponent._mute_value(channelstrip, value) return _mute_value def _channelstrip_solo_value(self, channelstrip): def _solo_value(value): if not self._shift_pressed: ChannelStripComponent._solo_value(channelstrip, value) return _solo_value def _mixer_next_track_value(self, mixer): def _next_track_value(value): if not self._shift_pressed: MixerComponent._next_track_value(mixer, value) return _next_track_value def _mixer_prev_track_value(self, mixer): def _prev_track_value(value): if not self._shift_pressed: MixerComponent._prev_track_value(mixer, value) return _prev_track_value
class Codec(ControlSurface): __module__ = __name__ __doc__ = " MonoCode controller script " def __init__(self, c_instance): """everything except the '_on_selected_track_CHANNELged' override and 'disconnect' runs from here""" ControlSurface.__init__(self, c_instance) self.set_suppress_rebuild_requests( True ) # Turn off rebuild MIDI map until after we're done setting up self._monomod_version = 'b995' self._version_check = 'b995' self._host_name = 'Codec' self._color_type = 'Monochrome' self._link_mixer = LINK_MIXER self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Codec ' + str(self._monomod_version) + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>') self._hosts = [] self._linked_script = None self._local_ring_control = True self.set_local_ring_control(1) self._setup_controls() self._last_device = None self._device_list = [None, None, None, None] self._device_select_buttons = None self._last_device_component = None self._timer = 0 self._touched = 0 self._locked = False self.flash_status = 1 self._shift_button = None self._shift_pressed = 0 self._shift_pressed_timer = 0 self._shift_thresh = SHIFT_THRESH self._use_device_selector = USE_DEVICE_SELECTOR self._device_selection_follows_track_selection = FOLLOW self.set_suppress_rebuild_requests( False) #Turn rebuild back on, now that we're done setting up self.song().view.add_selected_track_listener( self._update_selected_device) self.show_message('Codec Control Surface Loaded') #self.local_ring_control(True) #self.set_absolute_mode(True) self._setup_monobridge() self._setup_device_controls() self._setup_special_device_control() self._device.append( self._special_device ) #necessary for device browsing to work with special device self._setup_device_chooser() self._setup_mixer_controls() self._setup_monomod() self._setup_modes() self._setup_device_selector() self._setup_send_reset() self._setup_default_buttons() self._initialize_code() self.request_rebuild_midi_map() #Monomodular.create_instance(c_instance) #self._setup_disconnect() """script initialization methods""" def _initialize_code(self): self._send_midi(factoryreset) self._send_midi(btn_channels) self._send_midi(enc_channels) #pass def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_controls(self): is_momentary = True self._livid = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self) self._dial = [None for index in range(8)] for column in range(8): self._dial[column] = [None for index in range(4)] for row in range(4): self._dial[column][row] = CodecEncoderElement( MIDI_CC_TYPE, CHANNEL, CODE_DIALS[row][column], Live.MidiMap.MapMode.absolute, 'Dial_' + str(column) + '_' + str(row), (column + (row * 8)), self) #CODE_DIALS[row][column] self._button = [None for index in range(8)] for column in range(8): self._button[column] = [None for index in range(4)] for row in range(4): self._button[column][row] = FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_BUTTONS[row][column], 'Button_' + str(column) + '_' + str(row), self) self._column_button = [None for index in range(8)] for index in range(8): self._column_button[index] = FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_COLUMN_BUTTONS[index], 'Column_Button_' + str(index), self) self._row_button = [None for index in range(4)] for index in range(4): self._row_button[index] = FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_ROW_BUTTONS[index], 'Row_Button_' + str(index), self) self._dial_matrix = EncoderMatrixElement(self) self._dial_matrix.name = 'Encoder_Matrix' for row in range(4): dial_row = tuple([self._dial[column][row] for column in range(8)]) self._dial_matrix.add_row(dial_row) self._button_matrix = ButtonMatrixElement() self._button_matrix.name = 'Button_Matrix' for row in range(4): button_row = [self._button[column][row] for column in range(8)] button_row.append(self._row_button[row]) self._button_matrix.add_row(tuple(button_row)) self._button_matrix.add_row(tuple(self._column_button + [self._livid])) def _setup_modes(self): self._monomod_mode = MonomodModeComponent(self) self._monomod_mode.name = 'Monomod_Mode' self._monomod_mode.update = self._mod_mode_update #self._monomod_mode.set_mode_toggle(self._livid) self.set_shift_button(self._livid) self._shift_mode = ShiftModeComponent(self, self._shift_update) self._shift_mode.name = 'Shift_Mode' self._shift_mode.set_mode_buttons( tuple([ self._row_button[0], self._row_button[1], self._row_button[2], self._row_button[3] ])) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_monomod(self): self._host = MonomodComponent(self) self._host.name = 'Monomod_Host' self._host._set_dial_matrix(self._dial_matrix, self._button_matrix) self.hosts = [self._host] encs = [] for row in range(4): for col in range(8): encs.append(self._dial[col][row]) self._host._set_parameter_controls(encs) def _setup_mixer_controls(self): is_momentary = True self._num_tracks = (8) self._session = SessionComponent(self._num_tracks, 0) self._session.name = 'Session' self._mixer = MixerComponent(self._num_tracks, 0, False, False) self._mixer.name = 'Mixer' self._mixer._next_track_value = self._mixer_next_track_value( self._mixer) self._mixer._prev_track_value = self._mixer_prev_track_value( self._mixer) self._mixer.set_track_offset( 0) #Sets start point for mixer strip (offset from left) #for index in range(8): #use the bottom row of encoders for volume, so add 24 to offset the index # self._mixer.channel_strip(index).set_volume_control(self._dial[index+24]) for index in range(8): self._mixer.channel_strip( index).name = 'Mixer_ChannelStrip_' + str(index) self._mixer.channel_strip(index)._invert_mute_feedback = True self._mixer.channel_strip( index)._mute_value = self._channelstrip_mute_value( self._mixer.channel_strip(index)) self._mixer.channel_strip( index)._solo_value = self._channelstrip_solo_value( self._mixer.channel_strip(index)) #mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index])) self.song().view.selected_track = self._mixer.channel_strip( 0 )._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error self._session.set_mixer(self._mixer) def _setup_device_controls(self): self._device = [None for index in range(4)] for index in range(4): self._device[index] = CodecDeviceComponent(self) self._device[index].name = 'CodecDevice_Component_' + str(index) device_param_controls = [] for control in range(8): device_param_controls.append(self._dial[control][index]) self._device[index].set_on_off_button(self._button[1][index]) self._device[index].set_lock_button(self._button[2][index]) self._device[index].set_bank_nav_buttons(self._button[4][index], self._button[5][index]) self._device[index].set_nav_buttons(self._button[6][index], self._button[7][index]) self._device[index].set_parameter_controls( tuple(device_param_controls)) self.set_device_component(self._device[0]) self._last_device_component = self._device[0] def _setup_special_device_control(self): self._special_device = SpecialCodecDeviceComponent(self) self._special_device.name = 'SpecialCodecDeviceComponent' self._special_device.set_on_off_button(self._button[1][0]) self._special_device.set_lock_button(self._button[2][0]) self._special_device.set_bank_nav_buttons(self._button[4][0], self._button[5][0]) self._special_device.set_nav_buttons(self._button[6][0], self._button[7][0]) device_param_controls = [] for row in range(4): for column in range(8): device_param_controls.append(self._dial[column][row]) self._special_device.set_parameter_controls( tuple(device_param_controls)) def _setup_device_chooser(self): self._selected_device = self._device[0] self._last_selected_device = self._device[0] self._device_select_buttons = [ self._button[0][index] for index in range(4) ] for button in self._device_select_buttons: button.add_value_listener(self._device_select_value, True) def _setup_device_selector(self): self._device_selector = CodecDeviceSelectorComponent( self, 'c', self._device + [self._special_device]) self._device_selector.name = 'Device_Selector' self._device_selector.set_mode_buttons(self._column_button) #self._device_selector.set_mode_toggle(self._livid) def _setup_send_reset(self): self._send_reset = CodecResetSendsComponent(self) self._send_reset.set_buttons(self._button) def _setup_default_buttons(self): self._value_default = ParameterDefaultComponent(self) buttons = [] dials = [] for column in self._button: for button in column: buttons.append(button) for column in self._dial: for dial in column: dials.append(dial) self._value_default.set_buttons(buttons) self._value_default.set_dials(dials) """multiple device support""" def _device_select_value(self, value, sender): #self.log_message('device_select_value ' + str(value) + ' ' + str(self._device_select_buttons.index(sender))) if not self._shift_pressed: if sender.is_momentary or value > 0: if self._shift_mode._mode_index == 2: self.set_device_component(self._device[ self._device_select_buttons.index(sender)]) self._last_device_component = self._device_component if self._device_component != None and isinstance( self._device_component._device, Live.Device.Device): if self._device_component.find_track( self._device_component._device) == self.song( ).view.selected_track: self._device_component.display_device() """livid double press mechanism""" def set_shift_button(self, button): assert ((button == None) or (isinstance(button, FlashingButtonElement))) if self._shift_button != None: self._shift_button.remove_value_listener(self._shift_value) self._shift_button = button if self._shift_button != None: self._shift_button.add_value_listener(self._shift_value) def _shift_value(self, value): self._shift_pressed = int(value != 0) if self._shift_pressed > 0: self._send_midi(SLOWENCODER) if (self._shift_pressed_timer + self._shift_thresh) > self._timer: #if(self._host.is_enabled() != True) self._monomod_mode.set_mode( abs(self._monomod_mode._mode_index - 1)) #else: # self._monomod_mode.set_mode(0) self._shift_pressed_timer = self._timer % 256 else: self._send_midi(NORMALENCODER) def _mod_mode_update(self): if (self._monomod_mode._mode_index == 0): self._host._set_shift_button(None) self._host.set_enabled(False) self._dial_matrix.reset() self._shift_mode.set_enabled(True) self._shift_update() self.request_rebuild_midi_map() self._livid.turn_off() elif (self._monomod_mode._mode_index == 1): self._shift_mode.set_enabled(False) self._deassign_all() self._dial_matrix.reset() self._button_matrix.reset() self._livid.turn_on() if not self._host._active_client == None: self._host.set_enabled(True) self._host._set_shift_button(self._livid) else: self._assign_alternate_mappings(1) self.request_rebuild_midi_map() """Mode Functions""" def _shift_update(self): if (self._shift_mode.is_enabled()): self.allow_updates(False) if (not self._in_build_midi_map): self.set_suppress_rebuild_requests(True) self._deassign_all() if (self._shift_mode._mode_index is 0): self._assign_volume() elif (self._shift_mode._mode_index is 1): self._assign_sends() elif (self._shift_mode._mode_index is 2): self._assign_devices() elif (self._shift_mode._mode_index is 3): self._assign_special_device() for index in range(self._shift_mode.number_of_modes()): if index == self._shift_mode._mode_index: self._shift_mode._modes_buttons[index].turn_on() else: self._shift_mode._modes_buttons[index].turn_off() self.allow_updates(True) self.set_suppress_rebuild_requests(False) self.request_rebuild_midi_map() def _deassign_all(self): self._assign_alternate_mappings(0) self._device_selector.set_enabled(False) for index in range(8): self._mixer.channel_strip(index).set_volume_control(None) self._mixer.channel_strip(index).set_pan_control(None) self._mixer.channel_strip(index).set_send_controls( tuple([None, None, None, None])) for index in range(4): self._device[index].set_enabled(False) self._device[index]._parameter_controls = None #self._device_navigator[index].set_enabled(False) self._special_device.set_enabled(False) self._special_device._parameter_controls = None self._device_selector.set_enabled(False) self._deassign_buttons() for control in self.controls: control.reset() self.request_rebuild_midi_map() def _deassign_buttons(self): for index in range(8): self._mixer.channel_strip(index).set_select_button(None) self._mixer.channel_strip(index).set_solo_button(None) self._mixer.channel_strip(index).set_mute_button(None) self._mixer.set_select_buttons(None, None) self._send_reset.set_enabled(False) def _assign_volume(self): for index in range(8): self._mixer.channel_strip(index).set_volume_control( self._dial[index][3]) self._mixer.channel_strip(index).set_pan_control( self._dial[index][2]) self._mixer.channel_strip(index).set_send_controls( tuple([self._dial[index][0], self._dial[index][1]])) self._mixer.channel_strip(index).set_select_button( self._column_button[index]) self._mixer.channel_strip(index).set_solo_button( self._button[index][2]) self._mixer.channel_strip(index).set_mute_button( self._button[index][3]) self._mixer.set_select_buttons(self._button[7][0], self._button[6][0]) def _assign_sends(self): for index in range(8): self._mixer.channel_strip(index).set_send_controls( tuple([ self._dial[index][0], self._dial[index][1], self._dial[index][2], self._dial[index][3] ])) self._mixer.channel_strip(index).set_select_button( self._column_button[index]) self._send_reset.set_enabled(True) def _assign_devices(self): self.set_device_component(self._last_device_component) self._device_select_value( 1, self._device_select_buttons[self._device.index( self._device_component)]) for index in range(4): device_param_controls = [] for control in range(8): device_param_controls.append(self._dial[control][index]) self._device[index].set_parameter_controls( tuple(device_param_controls)) self._device[index].set_enabled(True) self._device_selector.set_enabled(self._use_device_selector) if not self._use_device_selector: for index in range(8): self._mixer.channel_strip(index).set_select_button( self._column_button[index]) def _assign_special_device(self): self.set_device_component(self._special_device) device_param_controls = [] for row in range(4): for column in range(8): device_param_controls.append(self._dial[column][row]) self._special_device.set_parameter_controls( tuple(device_param_controls)) self._special_device.set_enabled(True) self._device_selector.set_enabled(self._use_device_selector) if not self._use_device_selector: for index in range(8): self._mixer.channel_strip(index).set_select_button( self._column_button[index]) def _assign_alternate_mappings(self, chan): for column in self._dial: for control in column: control.set_channel(chan) control.set_enabled(chan is 0) for column in self._button: for control in column: control.set_channel(chan) control.set_enabled(chan is 0) for control in self._column_button: control.set_channel(chan) control.set_enabled(chan is 0) for control in self._row_button: control.set_channel(chan) control.set_enabled(chan is 0) """general functionality""" def disconnect(self): """clean things up on disconnect""" if not self._shift_button is None: if self._shift_button.value_has_listener(self._shift_value): self._shift_button.remove_value_listener(self._shift_value) for button in self._device_select_buttons: if button.value_has_listener(self._device_select_value): button.remove_value_listener(self._device_select_value) if self._session._is_linked(): self._session._unlink() self.song().view.remove_selected_track_listener( self._update_selected_device) """for cs in self._control_surfaces(): for host in self._hosts: self.log_message('installed: ' + str(cs) + ' vs. ' + str(host)) if str(type(cs)) == str(type(host)): self.log_message('disconnecting: ' + str(type(cs))) cs.disconnect(cs)""" #self._host._set_parameter_controls(None) self._hosts = [] if self._linked_script != None: self._linked_script._update_linked_device_selection = None self._linked_script = None #self._disconnect_notifier.set_mode(0) self.log_message( '<<<<<<<<<<<<<<<<<<<<<<<<< Codec log closed >>>>>>>>>>>>>>>>>>>>>>>>>' ) ControlSurface.disconnect(self) return None def connect_script_instances(self, instanciated_scripts): found = False for s in instanciated_scripts: if '_codec_version' in dir(s): if s._codec_version == self._version_check: if s._host_name == ('MonOhm'): self.log_message('found codec version ' + str(s._codec_version) + ' in script ' + str(s._host_name)) found = True self._linked_script = s self._linked_script._update_linked_device_selection = self._update_linked_device_selection if not self._session._is_linked( ) and self._link_mixer is True: self._session.set_offsets(LINK_OFFSET[0], LINK_OFFSET[1]) self._session._link() else: self.log_message('version mismatch: Monomod version ' + str(self._version_check) + ' vs. Host version ' + str(s._codec_version)) if found == False: for s in instanciated_scripts: if '_codec_version' in dir(s): if s._codec_version == self._version_check: if s._host_name == 'BlockMod': self.log_message('found codec version ' + str(s._codec_version) + ' in script ' + str(s._host_name)) self._linked_script = s self._linked_script._update_linked_device_selection = self._update_linked_device_selection if not self._session._is_linked( ) and self._link_mixer is True: self._session.set_offsets(LINK_OFFSET[0], LINK_OFFSET[1]) self._session._link() else: self.log_message('version mismatch: Monomod version ' + str(self._version_check) + ' vs. Host version ' + str(s._codec_version)) #self.log_message('hosts: ' + str(self._hosts))""" def update_display(self): ControlSurface.update_display( self ) #since we are overriding this from the inherited method, we need to call the original routine as well self._timer = (self._timer + 1) % 256 if (self._timer == 0): self._shift_pressed_timer = -12 if (self._local_ring_control is False): self.send_ring_leds() self.flash() def handle_sysex(self, midi_bytes): #self._send_midi(tuple([240, 00, 01, 97, 04, 15, 01, 247])) #response = [long(0),long(0)] #self.log_message(response) pass def flash(self): if (self.flash_status > 0): for control in self.controls: if isinstance(control, FlashingButtonElement): control.flash(self._timer) def send_ring_leds(self): leds = [240, 0, 1, 97, 4, 31] for column in range(8): for row in range(4): wheel = self._dial[column][row] bytes = wheel._get_ring() leds.append(bytes[0]) leds.append(int(bytes[1]) + int(bytes[2])) #if(row == 1 and column == 0): # self.log_message(str(leds) + ' ' + str(bytes[0]) + ' ' + str(bytes[1]) + ' ' + str(bytes[2])) leds.append(247) self._send_midi(tuple(leds)) def set_absolute_mode(self, val=1): self._absolute_mode = (val != 0) if self._absolute_mode is True: self._send_midi( tuple([240, 0, 1, 97, 4, 17, 0, 0, 0, 0, 0, 0, 0, 0, 247])) else: self._send_midi( tuple([ 240, 0, 1, 97, 4, 17, 127, 127, 127, 127, 127, 127, 127, 127, 247 ])) def set_local_ring_control(self, val=1): self._local_ring_control = (val != 0) if (self._local_ring_control is True): #self._send_midi(tuple([240, 0, 1, 97, 4, 32, 0, 247])) self._send_midi(tuple([240, 0, 1, 97, 4, 8, 72, 247])) else: #self._send_midi(tuple([240, 0, 1, 97, 4, 32, 1, 247])) self._send_midi(tuple([240, 0, 1, 97, 4, 8, 64, 247])) def device_follows_track(self, val): self._device_selection_follows_track_selection = (val == 1) return self """m4l bridge""" def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center( (NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return ret def notification_to_bridge(self, name, value, sender): if (isinstance(sender, CodecEncoderElement)): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if not self._host.is_enabled(): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched += 1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip() is True: clip_names.append(clip_slot._clip_slot) ##.clip.name) return clip_slot._clip_slot ##self.log_message(str(clip_slot._clip_slot.clip.name)) return clip_names """overrides""" def allow_updates(self, allow_updates): for component in self.components: component.set_allow_update(int(allow_updates != 0)) def set_device_component(self, device_component): if self._device_component != None: self._device_component._lock_callback = None assert (device_component != None) assert isinstance(device_component, DeviceComponent) self._device_component = device_component self._device_component._lock_callback = self._toggle_lock #old: self._device_component.set_lock_callback(self._toggle_lock) if self._device_select_buttons != None: for button in self._device_select_buttons: button.send_value( self._device_select_buttons.index(button) == self._device.index(self._device_component)) self._update_device_selection() return None def _update_selected_device(self): if self._device_selection_follows_track_selection is True: self._update_device_selection() return None def _update_linked_device_selection(self, device): #self.log_message('codec received ' + str(device.name)) if self._device_component != None and device != None: if not self._device_component.is_locked(): self._device_component.set_device(device) def _get_num_tracks(self): return self.num_tracks def _update_device_selection(self): #new method: code to verify #self.log_message('_update_device_selection') if self._device_component != None: if not self._device_component.is_locked(): track = self.song().view.selected_track device_to_select = track.view.selected_device if ((device_to_select == None) and (len(track.devices) > 0)): device_to_select = track.devices[0] if (device_to_select != None): self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) def _channelstrip_mute_value(self, channelstrip): def _mute_value(value): if not self._shift_pressed: self.log_message('shift not pressed') ChannelStripComponent._mute_value(channelstrip, value) return _mute_value def _channelstrip_solo_value(self, channelstrip): def _solo_value(value): if not self._shift_pressed: ChannelStripComponent._solo_value(channelstrip, value) return _solo_value def _mixer_next_track_value(self, mixer): def _next_track_value(value): if not self._shift_pressed: MixerComponent._next_track_value(mixer, value) return _next_track_value def _mixer_prev_track_value(self, mixer): def _prev_track_value(value): if not self._shift_pressed: MixerComponent._prev_track_value(mixer, value) return _prev_track_value
class Tweaker(ControlSurface): __module__ = __name__ __doc__ = " MonOhmod companion controller script " def __init__(self, c_instance): """everything except the '_on_selected_track_changed' override and 'disconnect' runs from here""" ControlSurface.__init__(self, c_instance) with self.component_guard(): self._update_linked_device_selection = None self._tweaker_version = "0.4" self.log_message( "--------------= Tweaker Mixer " + str(self._tweaker_version) + " log opened =--------------" ) self._update_linked_device_selection = None self._setup_mixer_control() self._setup_session_control() """script initialization methods""" def _setup_controls(self): is_momentary = True self._grid = [None for index in range(8)] for column in range(8): self._grid[column] = [ FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, column + (row * 8), "Grid_" + str(column) + "_" + str(row), self, ) for row in range(4) ] self._button = [ FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_BUTTONS[index], "Button_" + str(index), self ) for index in range(len(TWEAKER_BUTTONS)) ] self._nav = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_NAVS[index], "Nav_" + str(index), self) for index in range(len(TWEAKER_NAVS)) ] self._encoder_buttons = [ FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_ENCODER_BUTTONS[index], "Encoder_Button_" + str(index), self, ) for index in range(len(TWEAKER_ENCODER_BUTTONS)) ] self._dial = [ EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_DIALS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_DIALS)) ] self._fader = [ EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_FADERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_FADERS)) ] self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute) self._encoder = [ EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_ENCODERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_ENCODERS)) ] self._pad = [ FlashingButtonElement( not is_momentary, MIDI_CC_TYPE, CHANNEL, TWEAKER_PADS[index], "Pad_" + str(index), self ) for index in range(len(TWEAKER_PADS)) ] self._matrix = ButtonMatrixElement() self._matrix.name = "Matrix" for row in range(4): button_row = [] for column in range(7): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = "Transport" def _setup_mixer_control(self): is_momentary = True self._num_tracks = 2 # A mixer is one-dimensional; self._mixer = MixerComponent(2, 0, False, True) self._mixer.name = "Mixer" self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer) self._mixer.set_track_offset(0) # Sets start point for mixer strip (offset from left) def _setup_session_control(self): is_momentary = True num_tracks = 2 num_scenes = 3 self._session = SessionComponent(num_tracks, num_scenes) self._session.name = "Session" self._session.set_offsets(0, 0) self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) """general functionality""" def allow_updates(self, allow_updates): for component in self.components: component.set_allow_update(int(allow_updates != 0)) def disconnect(self): """clean things up on disconnect""" if self._session._is_linked(): self._session._unlink() self.log_message( "--------------= Tweaker Mixer " + str(self._tweaker_version) + " log closed =--------------" ) # Create entry in log file ControlSurface.disconnect(self) return None def connect_script_instances(self, instanciated_scripts): link = False for s in instanciated_scripts: if "_tweaker_version" in dir(s): if s._tweaker_version == self._tweaker_version: link = True if not s is self: s._linked_session = self._session # break if link is True: if not self._session._is_linked(): # self._session.set_offsets(0, 0) self._session._link() def _mixer_tracks_to_use(self, mixer): def tracks_to_use(): return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) return tracks_to_use
class midi_twister_110(ControlSurface): def __init__(self, c_instance): super(midi_twister_110, self).__init__(c_instance) with self.component_guard(): global active_mode active_mode = "_mode1" self._set_active_mode() self.show_message("Modified by XXPW") def _mode1(self): self.show_message("_mode1 is active") # mixer global mixer num_tracks = 32 num_returns = 7 self.mixer = MixerComponent(num_tracks, num_returns) self.mixer.set_track_offset(0) self.song().view.selected_track = self.mixer.channel_strip(0)._track # sends send0_controls = ( SliderElement(MIDI_CC_TYPE, 0, 32), SliderElement(MIDI_CC_TYPE, 0, 36), SliderElement(MIDI_CC_TYPE, 0, 40), None, None, None, None, None, ) self.mixer.channel_strip(0).set_send_controls(tuple(send0_controls)) self.mixer.channel_strip(0).set_volume_control( SliderElement(MIDI_CC_TYPE, 0, 44)) send1_controls = ( SliderElement(MIDI_CC_TYPE, 0, 33), SliderElement(MIDI_CC_TYPE, 0, 37), SliderElement(MIDI_CC_TYPE, 0, 41), None, None, None, None, None, ) self.mixer.channel_strip(1).set_send_controls(tuple(send1_controls)) self.mixer.channel_strip(1).set_volume_control( SliderElement(MIDI_CC_TYPE, 0, 45)) send2_controls = ( SliderElement(MIDI_CC_TYPE, 0, 34), SliderElement(MIDI_CC_TYPE, 0, 38), SliderElement(MIDI_CC_TYPE, 0, 42), None, None, None, None, None, ) self.mixer.channel_strip(2).set_send_controls(tuple(send2_controls)) self.mixer.channel_strip(2).set_volume_control( SliderElement(MIDI_CC_TYPE, 0, 46)) send3_controls = ( SliderElement(MIDI_CC_TYPE, 0, 35), SliderElement(MIDI_CC_TYPE, 0, 39), SliderElement(MIDI_CC_TYPE, 0, 43), None, None, None, None, None, ) self.mixer.channel_strip(3).set_send_controls(tuple(send3_controls)) self.mixer.channel_strip(3).set_volume_control( SliderElement(MIDI_CC_TYPE, 0, 47)) # session global _session num_tracks = 4 num_scenes = 3 session_buttons = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] self._pads = [ ButtonElement(1, MIDI_CC_TYPE, 1, session_buttons[index]) for index in range(num_tracks * num_scenes) ] self._grid = ButtonMatrixElement(rows=[ self._pads[(index * num_tracks):(index * num_tracks) + num_tracks] for index in range(num_scenes) ]) self._session = SessionComponent(num_tracks, num_scenes) self._session.set_clip_launch_buttons(self._grid) self.set_highlighting_session_component(self._session) # session track stop stop_track_buttons = [12, 13, 14, 15] self._track_stop_buttons = [ ButtonElement(1, MIDI_CC_TYPE, 1, stop_track_buttons[index]) for index in range(num_tracks) ] self._session.set_stop_track_clip_buttons( tuple(self._track_stop_buttons)) # session navigation self.session_left = ButtonElement(1, MIDI_CC_TYPE, 3, 8) self._session.set_page_left_button(self.session_left) self.session_left.add_value_listener(self._reload_active_devices, identify_sender=False) self.session_right = ButtonElement(1, MIDI_CC_TYPE, 3, 11) self._session.set_page_right_button(self.session_right) self.session_right.add_value_listener(self._reload_active_devices, identify_sender=False) self.session_up = ButtonElement(1, MIDI_CC_TYPE, 3, 10) self._session.set_page_up_button(self.session_up) self.session_up.add_value_listener(self._reload_active_devices, identify_sender=False) self.session_down = ButtonElement(1, MIDI_CC_TYPE, 3, 13) self._session.set_page_down_button(self.session_down) self.session_down.add_value_listener(self._reload_active_devices, identify_sender=False) self._session._link() self._session.set_mixer(self.mixer) #self._session.set_mixer(self.mixer) self._mode1_devices() self.add_device_listeners() # button: next device self.next_device = ButtonElement(0, MIDI_CC_TYPE, 1, 25) self.next_device.add_value_listener(self._next_device_value, identify_sender=False) # button: prev device self.previous_device = ButtonElement(1, MIDI_CC_TYPE, 1, 24) self.previous_device.add_value_listener(self._prev_device_value, identify_sender=False) # transport global transport self.transport = TransportComponent() self.transport.name = 'Transport' loop_button = ButtonElement(1, MIDI_CC_TYPE, 1, 50) loop_button.name = 'loop_button' self.transport.set_loop_button(loop_button) stop_button = ButtonElement(1, MIDI_CC_TYPE, 1, 49) stop_button.name = 'stop_button' self.transport.set_stop_button(stop_button) play_button = ButtonElement(1, MIDI_CC_TYPE, 1, 48) play_button.name = 'play_button' self.transport.set_play_button(play_button) # button: track navigation right self.track_navigation_right = ButtonElement(1, MIDI_CC_TYPE, 3, 17) self.track_navigation_right.add_value_listener( self._track_navigation_right_track_nav, identify_sender=False) # button: track navigation left self.track_navigation_left = ButtonElement(1, MIDI_CC_TYPE, 3, 14) self.track_navigation_left.add_value_listener( self._track_navigation_left_track_nav, identify_sender=False) def _remove_mode1(self): # mixer global mixer self._remove_mode1_devices() self.remove_device_listeners() send0_controls = ( None, None, None, None, None, None, None, None, ) self.mixer.channel_strip(0).set_send_controls(tuple(send0_controls)) send1_controls = ( None, None, None, None, None, None, None, None, ) self.mixer.channel_strip(1).set_send_controls(tuple(send1_controls)) send2_controls = ( None, None, None, None, None, None, None, None, ) self.mixer.channel_strip(2).set_send_controls(tuple(send2_controls)) send3_controls = ( None, None, None, None, None, None, None, None, ) self.mixer.channel_strip(3).set_send_controls(tuple(send3_controls)) # session global _session self._session.set_clip_launch_buttons(None) self.set_highlighting_session_component(None) self._session.set_mixer(None) self._session.set_stop_all_clips_button(None) # session track stop self._track_stop_buttons = None self._session.set_stop_track_clip_buttons(None) # session scene launch self._scene_launch_buttons = None self._session.set_scene_launch_buttons(None) # session navigation self.session_left.remove_value_listener(self._reload_active_devices) self._session.set_page_left_button(None) self.session_right.remove_value_listener(self._reload_active_devices) self._session.set_page_right_button(None) self.session_up.remove_value_listener(self._reload_active_devices) self._session.set_page_up_button(None) self.session_down.remove_value_listener(self._reload_active_devices) self._session.set_page_down_button(None) self._session = None self.next_device.remove_value_listener(self._next_device_value) self.next_device = None self.previous_device.remove_value_listener(self._prev_device_value) self.previous_device = None # transport global transport self.transport.set_loop_button(None) self.transport.set_stop_button(None) self.transport.set_play_button(None) self.transport = None self.track_navigation_right.remove_value_listener( self._track_navigation_right_track_nav) self.track_navigation_right = None self.track_navigation_left.remove_value_listener( self._track_navigation_left_track_nav) self.track_navigation_left = None def _mode1_devices(self): global mixer global _session # device self.mixer.selected_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, 0, 28)) self.mixer.selected_strip().set_pan_control( SliderElement(MIDI_CC_TYPE, 0, 29)) self.mixer.selected_strip().set_mute_button( ButtonElement(1, MIDI_CC_TYPE, 1, 28)) self.mixer.selected_strip().set_solo_button( ButtonElement(1, MIDI_CC_TYPE, 1, 29)) if (len(self.mixer.selected_strip()._track.devices) > 0): global device_tracktype_selected__chain_number_selected self.device_tracktype_selected__chain_number_selected = DeviceComponent( ) device_controls = ( SliderElement(MIDI_CC_TYPE, 0, 16), SliderElement(MIDI_CC_TYPE, 0, 17), SliderElement(MIDI_CC_TYPE, 0, 18), SliderElement(MIDI_CC_TYPE, 0, 19), SliderElement(MIDI_CC_TYPE, 0, 20), SliderElement(MIDI_CC_TYPE, 0, 21), SliderElement(MIDI_CC_TYPE, 0, 22), SliderElement(MIDI_CC_TYPE, 0, 23), ) self.device_tracktype_selected__chain_number_selected.set_parameter_controls( tuple(device_controls)) self.set_device_component( self.device_tracktype_selected__chain_number_selected) self.device_tracktype_selected__chain_number_selected.set_on_off_button( ButtonElement(1, MIDI_CC_TYPE, 1, 26)) self.device_tracktype_selected__chain_number_selected.set_bank_nav_buttons( ButtonElement(0, MIDI_CC_TYPE, 1, 31), ButtonElement(1, MIDI_CC_TYPE, 1, 33)) def _remove_mode1_devices(self): global mixer global _session # device if (hasattr(self, 'device_tracktype_selected__chain_number_selected')): global device_tracktype_selected__chain_number_selected device_controls = ( None, None, None, None, None, None, None, None, ) self.device_tracktype_selected__chain_number_selected.set_parameter_controls( tuple(device_controls)) self.device_tracktype_selected__chain_number_selected.set_on_off_button( None) self.device_tracktype_selected__chain_number_selected.set_bank_nav_buttons( None, None) self.set_device_component( self.device_tracktype_selected__chain_number_selected) def add_device_listeners(self): global mixer num_of_tracks = len(self.song().tracks) value = "add device listener" for index in range(num_of_tracks): self.song().tracks[index].add_devices_listener( self._reload_active_devices) def remove_device_listeners(self): global mixer num_of_tracks = len(self.song().tracks) value = "remove device listener" for index in range(num_of_tracks): self.song().tracks[index].remove_devices_listener( self._reload_active_devices) def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) self._display_reset_delay = 0 value = "selected track changed" self._reload_active_devices(value) def _reload_active_devices(self, value=None): self._remove_active_devices() self._set_active_devices() def _set_active_devices(self): global active_mode # activate mode if (active_mode == "_mode1") and (hasattr(self, '_mode1_devices')): self._mode1_devices() def _remove_active_devices(self): global active_mode # remove activate mode if (active_mode == "_mode1") and (hasattr(self, '_mode1_devices')): self._remove_mode1_devices() def _next_device_value(self, value): if value > 0: self._device = self.song().view.selected_track.view.selected_device if self._device is not None: self.song().view.select_device( self.song().view.selected_track.devices[ self.selected_device_idx() + 1]) def _prev_device_value(self, value): if value > 0: self._device = self.song().view.selected_track.view.selected_device if self._device is not None: self.song().view.select_device( self.song().view.selected_track.devices[ self.selected_device_idx() - 1]) def selected_device_idx(self): self._device = self.song().view.selected_track.view.selected_device return self.tuple_index(self.song().view.selected_track.devices, self._device) def _track_navigation_right_track_nav(self, value): if value > 0: self.song().view.selected_track = self.song().tracks[ self.selected_track_idx() + 1] def _track_navigation_left_track_nav(self, value): if value > 0: self.song().view.selected_track = self.song().tracks[ self.selected_track_idx() - 1] def selected_track_idx(self): return self.tuple_index(self.song().tracks, self.song().view.selected_track) def _set_active_mode(self): global active_mode # activate mode if active_mode == "_mode1": self._mode1() def _remove_active_mode(self): global active_mode # remove activate mode if active_mode == "_mode1": self._remove_mode1() def _activate_mode1(self, value): global active_mode if value > 0: self._remove_active_mode() active_mode = "_mode1" self._set_active_mode() def _activate_shift_mode1(self, value): global active_mode if value > 0: self._remove_active_mode() self._mode1() else: self._remove_mode1() self._set_active_mode() def tuple_index(self, tuple, obj): for i in xrange(0, len(tuple)): if (tuple[i] == obj): return i return (False) def disconnect(self): super(midi_twister_110, self).disconnect()
class Tweaker(ControlSurface): __module__ = __name__ __doc__ = " Tweaker control surface script " def __init__(self, c_instance, *a, **k): super(Tweaker, self).__init__(c_instance, *a, **k) with self.component_guard(): self._update_linked_device_selection = None self._tweaker_version_check = '0.3' self.log_message("--------------= Tweaker Session " + str(self._tweaker_version_check) + " log opened =--------------") self._timer = 0 self.flash_status = 1 self._last_selected_strip_number = 0 self._device_selection_follows_track_selection = False #self._pad_translations = PAD_TRANSLATION self._linked_session = None self._mixer_offset = 0 self._nav_lock = True self._setup_controls() self._setup_transport_control() self._setup_device_control() self._setup_mixer_control() self._setup_session_control() self._setup_crossfader() self._setup_modes() self._setup_pads() self._setup_navigation_lock() self._setup_arrange_session_toggle() #self.assign_main_configuration() #self.request_rebuild_midi_map() #self._mixer._reassign_tracks() #this is to update rebuild the cf_assign closure, otherwise the colors aren't correct #self.schedule_message(30, self._detect_devices) self.show_message('Tweaker Control Surface Loaded') self.show_message('Tweaker Control Surface Loaded') #self._shift_value(0) #this updates the pads so that they transmit to Live on the assigned PAD_CHANNEL...also, lights shift button self.assign_main_configuration() #self.schedule_message(2, self._shift_value, 0) self.schedule_message(3, self._mixer._reassign_tracks) """script initialization methods""" def _setup_controls(self): is_momentary = True self._grid = [None for index in range(8)] for column in range(8): self._grid[column] = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, column + (row * 8) + 1, 'Grid_' + str(column) + '_' + str(row), self) for row in range(4)] self._button = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_BUTTONS[index], 'Button_' + str(index), self) for index in range(len(TWEAKER_BUTTONS))] self._nav = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_NAVS[index], 'Nav_' + str(index), self) for index in range(len(TWEAKER_NAVS))] self._encoder_button = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_ENCODER_BUTTONS[index], 'Encoder_Button_' + str(index), self) for index in range(len(TWEAKER_ENCODER_BUTTONS))] self._dial = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_DIALS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_DIALS))] self._fader = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_FADERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_FADERS))] self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute) self._encoder = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_ENCODERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_ENCODERS))] self._pad = [TweakerMonoButtonElement(False, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_PADS[index], 'Pad_' + str(index), self) for index in range(len(TWEAKER_PADS))] for index in range(4): self._pad[index].set_enabled(False) self._pad[index].set_channel(PAD_CHANNEL) self._pad[index].set_identifier(index + 4) self._pad[index+4].set_enabled(False) self._pad[index+4].set_channel(PAD_CHANNEL) self._pad[index+4].set_identifier(index) self._pad_pressure = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_PAD_PRESSURES[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_PADS))] for index in range(8): self._pad_pressure[index]._last_sent = 0 self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' for row in range(4): button_row = [] for column in range(7): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) self._send_midi(tuple([240,0,1,106,01,07,21,21,247])) #set all pots to walk mode self._send_midi(tuple([240, 0, 1, 106, 1, 6, 127 , 127, 25, 0, 15, 0, 9, PAD_SENSITIVITY, 247])) #set pads to sensitivity set in Map file def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_mixer_control(self): is_momentary = True self._num_tracks = (2) #A mixer is one-dimensional; self._mixer = MixerComponent(2, 0, False, False) self._mixer.name = 'Mixer' self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer) self._device_navigator = [None for index in range(2)] self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(2): self._mixer.channel_strip(index).set_volume_control(self._fader[index]) self._mixer.channel_strip(index)._on_cf_assign_changed = self._channelstrip_on_cf_assign_changed(self._mixer.channel_strip(index)) self._mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) #mixer.track_filter(index).name = 'Mixer_TrackFilter_' + str(index) self._mixer.channel_strip(index)._invert_mute_feedback = True self._mixer.channel_strip(index)._device_component = self._device[index] self._mixer.channel_strip(index).update = self._channelstrip_update(self._mixer.channel_strip(index)) self._mixer.channel_strip(index)._select_value = self._channelstrip_select_value(self._mixer.channel_strip(index), index) self._device_navigator[index] = DetailViewControllerComponent(self, self._mixer.channel_strip(index)) self._device_navigator[index].name = 'Device_Navigator_'+str(index) self._mixer.channel_strip(0).set_track = self._channelstrip_set_track(self._mixer.channel_strip(0), self._channelstrip1_cb) self._mixer.channel_strip(1).set_track = self._channelstrip_set_track(self._mixer.channel_strip(1), self._channelstrip2_cb) self.song().view.selected_track = self._mixer.channel_strip(0)._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error #self._mixer._reassign_tracks() def _setup_session_control(self): is_momentary = True num_tracks = NUM_TRACKS num_scenes = NUM_SCENES self._session = SessionComponent(num_tracks, num_scenes) self._session.name = "Session" self._session.set_offsets(0, 0) self._session.set_stop_track_clip_value(STOP_CLIP) self._scene = [None for index in range(3)] for row in range(num_scenes): self._scene[row] = self._session.scene(row) self._scene[row].name = 'Scene_' + str(row) for column in range(num_tracks): clip_slot = self._scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_' + str(row) clip_slot.set_triggered_to_play_value(CLIP_TRG_PLAY) clip_slot.set_triggered_to_record_value(CLIP_TRG_REC) clip_slot.set_stopped_value(CLIP_STOP) clip_slot.set_started_value(CLIP_STARTED) clip_slot.set_recording_value(CLIP_RECORDING) self._session._stop_track_value = self._session_stop_track_value(self._session) self._session._on_fired_slot_index_changed = self._session_on_fired_slot_index_changed(self._session) self._session._change_offsets = self._session_change_offsets(self._session) self._session.update = self._session_update(self._session) #self._session.add_offset_listener(self._update_navigation_view) self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) self._session_zoom = SessionZoomingComponent(self._session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_stopped_value(ZOOM_STOPPED) self._session_zoom.set_playing_value(ZOOM_PLAYING) self._session_zoom.set_selected_value(ZOOM_SELECTED) #self._session_zoom.set_enabled(True) def _setup_device_control(self): self._device = [None for index in range(2)] for index in range(2): self._device[index] = DeviceComponent() self._device[index].name = 'Device_Component_'+str(index) self._device[index].set_enabled(True) self._device[index]._number_of_parameter_banks = self._device_number_of_parameter_banks(self._device[index]) self._device[index]._assign_parameters = self._device_assign_parameters(self._device[index]) self._device[index]._device_banks = DEVICE_DICT self._device[index]._device_best_banks = DEVICE_BOB_DICT self._device[index]._device_bank_names = BANK_NAME_DICT def _setup_crossfader(self): self._mixer.set_crossfader_control(self._crossfader) def _setup_modes(self): self._pad_offset = PadOffsetComponent(self) self._pad_offset._set_protected_mode_index(0) self._pad_offset.set_enabled(False) def _setup_pads(self): for pad in self._pad_pressure: pad.add_value_listener(self._light_pad, True) def _setup_navigation_lock(self): if(self._encoder_button[0].value_has_listener(self._nav_lock_value)): self._encoder_button[0].remove_value_listener(self._nav_lock_value) self._encoder_button[0].add_value_listener(self._nav_lock_value) def _setup_arrange_session_toggle(self): if(self._nav[1].value_has_listener(self._arrange_session_value)): self._nav[1].remove_value_listener(self._arrange_session_value) self._nav[1].add_value_listener(self._arrange_session_value) """configuration methods""" def assign_main_configuration(self): for column in range(7): for row in range(3): self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row]) self._session.set_stop_track_clip_buttons(tuple([self._grid[index][3] for index in range(7)])) for row in range(3): self._scene[row].set_launch_button(self._grid[7][row]) self._device[0].set_parameter_controls(tuple([self._encoder[index+1] for index in range(3)])) self._device[0].set_enabled(True) self._device[1].set_parameter_controls(tuple([self._encoder[index+4] for index in range(3)])) self._device[1].set_enabled(True) for track in range(2): self._mixer.channel_strip(track).set_volume_control(self._fader[track]) self._mixer.channel_strip(track).set_solo_button(self._button[track*3]) self._button[track*3].set_on_off_values(SOLO, 0) self._mixer.channel_strip(track).set_arm_button(self._button[1 + (track*3)]) self._button[1 + (track*3)].set_on_off_values(ARM, 0) self._mixer.channel_strip(track).set_crossfade_toggle(self._button[2 + (track*3)]) self._mixer.master_strip().set_volume_control(self._dial[1]) self._mixer.set_prehear_volume_control(self._dial[0]) self._session.set_track_bank_buttons(self._nav[4], self._nav[3]) self._session.set_scene_bank_buttons(self._nav[2], self._nav[0]) self._session_zoom.set_zoom_button(self._grid[7][3]) self._session_zoom.set_nav_buttons(self._nav[0], self._nav[2], self._nav[3], self._nav[4]) self._session_zoom.set_button_matrix(self._matrix) self._device[0].set_on_off_button(self._encoder_button[1]) self._device_navigator[0].set_device_nav_buttons(self._encoder_button[2], self._encoder_button[3]) self._device[1].set_on_off_button(self._encoder_button[4]) self._device_navigator[1].set_device_nav_buttons(self._encoder_button[5], self._encoder_button[6]) for track in range(2): self._update_device(self._mixer.channel_strip(track)) #self._device.set_bank_nav_buttons(self._menu[0], self._menu[3]) self.assign_track_selector(self._encoder[0]) #for index in range(8): # self._pad[index].send_value(1, True) # self._pad[index].set_channel(1) # self._pad[index].set_identifier(index) # self._pad[index].set_enabled(False) #this has to happen for translate to work if not self._grid[7][3].value_has_listener(self._shift_value): self._grid[7][3].add_value_listener(self._shift_value) self._grid[7][3].send_value(127, True) self.request_rebuild_midi_map() """Tweaker custom methods""" def _shift_value(self, value): self._pad_offset.set_enabled(value>0) if value > 0: self._update_navigation_view() for pad in self._pad: pad.use_default_message() pad.set_enabled(True) self._pad_offset.set_mode_buttons(tuple(self._pad)) self.schedule_message(1, self._pad_offset.update) if self._session.is_enabled(): #self._update_navigation_view() #self.schedule_message(1, self._update_navigation_veiw) self._update_navigation_view() self._grid[7][3].send_value(SHIFT_ON) for track in range(2): self._mixer.channel_strip(track).set_crossfade_toggle(None) self._mixer.channel_strip(track).set_select_button(self._button[2 + (track*3)]) else: self._pad_offset.set_mode_buttons(None) for index in range(4): self._pad[index].set_enabled(False) self._pad[index].set_channel(PAD_CHANNEL) self._pad[index].set_identifier(index + 4 + (self._pad_offset._mode_index * 8)) self._pad[index+4].set_enabled(False) self._pad[index+4].set_channel(PAD_CHANNEL) self._pad[index+4].set_identifier(index + (self._pad_offset._mode_index * 8)) self._grid[7][3].send_value(SHIFT_OFF) for track in range(2): self._mixer.channel_strip(track).set_select_button(None) self._mixer.channel_strip(track).set_crossfade_toggle(self._button[2 + (track*3)]) def assign_track_selector(self, encoder): assert isinstance(encoder, EncoderElement) if not encoder.value_has_listener(self._track_selector_value): encoder.add_value_listener(self._track_selector_value) def deassign_track_selector(self, encoder): if encoder.value_has_listener(self._track_selector_value): encoder.remove_value_listener(self._track_selector_value) def _nav_lock_value(self, value): if value > 0: if self._nav_lock: self._mixer_offset = self._mixer_offset + self._session._track_offset self._mixer.set_track_offset(self._mixer_offset) else: if self._mixer_offset in range(self._session._track_offset, self._session._track_offset + 5): self._mixer_offset = self._mixer_offset - self._session._track_offset elif self._mixer_offset < self._session._track_offset: self._mixer_offset = 0 else: self._mixer_offset = min(self._session._track_offset+5, len(self._session.tracks_to_use())-2) self._mixer.set_track_offset(self._session._track_offset + self._mixer_offset) self._nav_lock = not self._nav_lock self._session.update() def _arrange_session_value(self, value): if value > 0: if (self.application().view.is_view_visible('Arranger')): self.application().view.show_view('Session') else: self.application().view.show_view('Arranger') def _track_selector_value(self, value): if(value is 1): if self._nav_lock: self._mixer_offset = min(self._mixer_offset + 1, min(NUM_TRACKS - 2, len(self._session.tracks_to_use())-self._session._track_offset-2)) else: self._mixer_offset = min(self._mixer_offset + 1, len(self._session.tracks_to_use())-2) elif(value is 127): self._mixer_offset = max(self._mixer_offset - 1, 0) if self._nav_lock: self._mixer.set_track_offset(self._session._track_offset + self._mixer_offset) #self._session.set_offsets(self._session._track_offset) ?? else: self._mixer.set_track_offset(self._mixer_offset) self._session.update() if self._mixer.channel_strip(self._last_selected_strip_number)._track != None: self.song().view.selected_track = self._mixer.channel_strip(self._last_selected_strip_number)._track if self._linked_session != None: if self._linked_session._is_linked(): self._linked_session._unlink() self._linked_session.set_offsets(self._mixer._track_offset, self._linked_session._scene_offset) self._linked_session._link() def _update_navigation_view(self): dif = self._mixer._track_offset - self._session._track_offset for index in range(7): #if (index + self._session._track_offset) in range(len(self._session.tracks_to_use())): if (index + self._session._track_offset) in range(0, len(self.song().visible_tracks)): self._grid[index][3].send_value(NAV_COLORS[int(index in range(dif, dif + 2))], True) elif (index + self._session._track_offset) in range(len(self.song().visible_tracks), len(self._session.tracks_to_use())): self._grid[index][3].send_value(RETURN_NAV_COLORS[int(index in range(dif, dif + 2))], True) else: self._grid[index][3].send_value(0, True) self._send_midi(tuple([240,0,1,106,01,07,21,21,247])) #set all pots to walk mode def _update_device(self, channelstrip): for control in channelstrip._device_component._parameter_controls: control.send_value(0, True) if channelstrip._device_component._on_off_button != None: channelstrip._device_component._on_off_button.turn_off() if not channelstrip._track is None: if not channelstrip._device_component._device in channelstrip._track.devices: track = channelstrip._track device_to_select = track.view.selected_device if (device_to_select == None) and (len(track.devices) > 0): device_to_select = track.devices[0] elif channelstrip._device_component and not type(channelstrip._device_component) is type(None): channelstrip._device_component.set_device(device_to_select) else: channelstrip._device_component.set_device(None) else: pass else: channelstrip._device_component.set_device(None) channelstrip._device_component._on_on_off_changed() def _light_pad(self, value, sender): if not self._pad_offset.is_enabled(): if value > sender._last_sent: if self._pad[self._pad_pressure.index(sender)]._last_sent_value < 1: self._pad[self._pad_pressure.index(sender)].send_value(127, True) else: self._pad[self._pad_pressure.index(sender)].send_value(0, True) sender._last_sent = value """called on timer""" def update_display(self): super(Tweaker, self).update_display() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if(self.flash_status > 0): for control in self.controls: if isinstance(control, TweakerMonoButtonElement): control.flash(self._timer) """m4l bridge""" def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' return ret def notification_to_bridge(self, name, value, sender): if(isinstance(sender, MonoEncoderElement2)): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if(self._shift_mode._mode_index < 2): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched +=1 def check_touch(self): if(self._shift_mode._mode_index < 2): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def handle_sysex(self, midi_bytes): pass """general functionality""" def disconnect(self): """clean things up on disconnect""" #self._update_linked_device_selection = None if self._session.offset_has_listener(self._update_navigation_view): self._session.remove_offset_listener(self._update_navigation_view) if(self._nav[1].value_has_listener(self._arrange_session_value)): self._nav[1].remove_value_listener(self._arrange_session_value) if(self._encoder_button[0].value_has_listener(self._nav_lock_value)): self._encoder_button[0].remove_value_listener(self._nav_lock_value) for pad in self._pad_pressure: if pad.value_has_listener(self._light_pad): pad.remove_value_listener(self._light_pad) if self._grid[7][3].value_has_listener(self._shift_value): self._grid[7][3].remove_value_listener(self._shift_value) if self._session._is_linked(): self._session._unlink() self.deassign_track_selector(self._encoder[0]) self.log_message("--------------= Tweaker Session " + str(self._tweaker_version_check) + " log closed =--------------") #Create entry in log file super(Tweaker, self).disconnect() return None def _get_num_tracks(self): return self.num_tracks def _on_selected_track_changed(self): super(Tweaker, self)._on_selected_track_changed() if self._session.is_enabled(): self._session.update() for index in range(2): self._update_device(self._mixer.channel_strip(index)) self._mixer.on_selected_track_changed() def connect_script_instances(self, instanciated_scripts): link = False for s in instanciated_scripts: if '_tweaker_version' in dir(s): if s._tweaker_version == self._tweaker_version_check: link = True break if link == True: if not self._session._is_linked(): self._session._link() """SessionComponent overrides""" def _session_update(self, session): def _update(): SessionComponent.update(session) if session.is_enabled(): self._update_navigation_view() return _update def _session_change_offsets(self, session): def _change_offsets(track_increment, scene_increment): offsets_changed = (track_increment != 0) or (scene_increment != 0) if offsets_changed: session._track_offset += track_increment session._scene_offset += scene_increment assert (session._track_offset >= 0) assert (session._scene_offset >= 0) if (session._mixer != None): if(self._nav_lock): if (session.track_offset() + self._mixer_offset) > (len(session.tracks_to_use())-2): self._mixer_offset = max(len(session.tracks_to_use()) - session._track_offset - 2, 0) session._mixer.set_track_offset(max(0, session.track_offset() + self._mixer_offset)) session._reassign_tracks() if offsets_changed: session._reassign_scenes() # this is replaced by notify_offset() in Live9 #for callback in session._offset_callbacks: # this is replaced by notify_offset() in Live9 # callback() session.notify_offset() self._update_navigation_view() if self._mixer.channel_strip(self._last_selected_strip_number)._track != None: self.song().view.selected_track = self._mixer.channel_strip(self._last_selected_strip_number)._track if ((session.width() > 0) and (session.height() > 0)): session._do_show_highlight() return _change_offsets def _session_on_fired_slot_index_changed(self, session): def _on_fired_slot_index_changed(index): tracks_to_use = tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) track_index = index + session.track_offset() if session.is_enabled() and session._stop_track_clip_buttons != None: if index < len(session._stop_track_clip_buttons): button = session._stop_track_clip_buttons[index] if button != None: if(track_index < len(tracks_to_use)) and (tracks_to_use[track_index].clip_slots) and (tracks_to_use[track_index].fired_slot_index == -2): button.send_value(session._stop_track_clip_value) #elif index in range(len(session.tracks_to_use())): # dif = self._mixer._track_offset - self._session._track_offset # button.send_value(NAV_COLORS[int(index in range(dif, dif + 2))], True) #else: # button.turn_off() else: self._update_navigation_view() return _on_fired_slot_index_changed def _session_stop_track_value(self, session): def _stop_track_value(value, sender): assert (session._stop_track_clip_buttons != None) assert (list(session._stop_track_clip_buttons).count(sender) == 1) assert (value in range(128)) if session.is_enabled(): if ((value is not 0) or (not sender.is_momentary())): tracks = session.tracks_to_use() track_index = (list(session._stop_track_clip_buttons).index(sender) + session.track_offset()) if (track_index in range(len(tracks))) and (tracks[track_index] in session.song().tracks): tracks[track_index].stop_all_clips() sender.send_value(3, True) self.schedule_message(10, self._update_navigation_view) return _stop_track_value """ChannelStripComponent overrides""" def _channelstrip_update(self, channelstrip): def _update(): ChannelStripComponent.update(channelstrip) self._update_device(channelstrip) return _update def _channelstrip_set_track(self, channelstrip, cb): def _set_track(track): assert ((track == None) or isinstance(track, Live.Track.Track)) if channelstrip._track != None and isinstance(channelstrip._track, Live.Track.Track): if channelstrip._track.devices_has_listener(cb): channelstrip._track.remove_devices_listener(cb) if (track != None): track.add_devices_listener(cb) ChannelStripComponent.set_track(channelstrip, track) return _set_track def _channelstrip_select_value(self, channelstrip, index): def _select_value(value): ChannelStripComponent._select_value(channelstrip, value) self._last_selected_strip_number = index return _select_value def _channelstrip_on_cf_assign_changed(self, channel_strip): def _on_cf_assign_changed(): if (channel_strip.is_enabled() and (channel_strip._crossfade_toggle != None)): if (channel_strip._track != None) and (channel_strip._track in chain(self.song().tracks, self.song().return_tracks)): if channel_strip._track.mixer_device.crossfade_assign == 1: #modified channel_strip._crossfade_toggle.turn_off() elif channel_strip._track.mixer_device.crossfade_assign == 0: channel_strip._crossfade_toggle.send_value(CROSSFADE_A) else: channel_strip._crossfade_toggle.send_value(CROSSFADE_B) return _on_cf_assign_changed def _channelstrip1_cb(self): self._on_selected_track_changed() def _channelstrip2_cb(self): self._on_selected_track_changed() """MixerComponent overrides""" def _mixer_tracks_to_use(self, mixer): def tracks_to_use(): return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) return tracks_to_use """SessionComponent overrides""" def _device_number_of_parameter_banks(self, device): def _number_of_parameter_banks(): return number_of_parameter_banks(device._device) #added return _number_of_parameter_banks def _device_assign_parameters(self, device): def _assign_parameters(): assert device.is_enabled() assert (device._device != None) assert (device._parameter_controls != None) device._bank_name = ('Bank ' + str(device._bank_index + 1)) #added if (device._device.class_name in device._device_banks.keys()): #modified assert (device._device.class_name in device._device_best_banks.keys()) banks = device._device_banks[device._device.class_name] bank = None if (not device._is_banking_enabled()): banks = device._device_best_banks[device._device.class_name] device._bank_name = 'Best of Parameters' #added if (len(banks) > device._bank_index): bank = banks[device._bank_index] if device._is_banking_enabled(): #added if device._device.class_name in device._device_bank_names.keys(): #added device._bank_name[device._bank_index] = device._device_bank_names[device._device.class_name] #added *recheck assert ((bank == None) or (len(bank) >= len(device._parameter_controls))) for index in range(len(device._parameter_controls)): parameter = None if (bank != None): parameter = get_parameter_by_name(device._device, bank[index]) if (parameter != None): device._parameter_controls[index].connect_to(parameter) else: device._parameter_controls[index].release_parameter() else: parameters = device._device_parameters_to_map() num_controls = len(device._parameter_controls) index = (device._bank_index * num_controls) for control in device._parameter_controls: if (index < len(parameters)): control.connect_to(parameters[index]) else: control.release_parameter() index += 1 return _assign_parameters
class Faderfox(OptimizedControlSurface): __module__ = __name__ __doc__ = " Monomodular controller script for PO10 " def __init__(self, *a, **k): super(Faderfox, self).__init__(*a, **k) self._version_check = '1.0' self._host_name = 'Faderfox' self._color_type = 'Monochrome' self._rgb = 0 self._timer = 0 self._touched = 0 self.flash_status = 1 self._skin = Skin(FaderfoxColors) self._main_modes = None with self.component_guard(): self._setup_monobridge() self._setup_controls() self._setup_session() self._setup_device_control() self._setup_device_selector() self._setup_modes() self._device_selector.select_device(DEFAULT_DEVICE_INDEX) self._on_device_changed.subject = self.song() self.set_feedback_channels(range(14, 15)) #self._main_modes.selected_mode = 'MixMode' self.schedule_message(1, self._open_log) self._session.set_enabled(True) def _open_log(self): self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) + " " + str(self._version_check) + " log opened =>>>>>>>>>>>>>>>>>>>") self.show_message(str(self._host_name) + ' Control Surface Loaded') def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_controls(self): is_momentary = True self._button = [ MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, FADERFOX_BUTTONS[index], name='Button_' + str(index), script=self, skin=self._skin, color_map=COLOR_MAP) for index in range(4) ] self._encoder = [ CodecEncoderElement(MIDI_CC_TYPE, CHANNEL, FADERFOX_ENCODERS[index], Live.MidiMap.MapMode.absolute, 'Encoder_' + str(index), FADERFOX_ENCODERS[index], self) for index in range(4) ] self._encoder_matrix = ButtonMatrixElement(name='Encoder_Matrix', rows=[self._encoder]) self._button_matrix = ButtonMatrixElement(name='Button_Matrix', rows=[self._button[2:]]) def _setup_session(self): self._session = SessionComponent(name='Session_Component', num_tracks=20, num_scenes=1) self._session._scenes[0].layer = Layer(priority=6, launch_button=self._button[0]) self._session.layer = Layer(priority=6, scene_bank_down_button=self._button[1]) self.set_highlighting_session_component(self._session) self._session.set_show_highlight(True) self._session.set_enabled(False) self._session._link() def _setup_device_control(self): self._device = BaseDeviceComponent() self._device.layer = Layer(priority=6, parameter_controls=self._encoder_matrix) self._device.set_enabled(True) def _setup_device_selector(self): self._device_selector = FaderfoxDeviceSelectorComponent(self, self._device, prefix='@d') self._device_selector.layer = Layer(priority=6, matrix=self._button_matrix) self._device_selector.set_enabled(True) def _setup_modes(self): pass def update_display(self): super(Faderfox, self).update_display() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if (self.flash_status > 0): for control in self.controls: if isinstance(control, MonoButtonElement): control.flash(self._timer) @subject_slot('appointed_device') def _on_device_changed(self): debug('appointed device changed, script') def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center( (NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' ret = ret.replace(' ', '_') assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return ret def notification_to_bridge(self, name, value, sender): if (isinstance(sender, (MonoEncoderElement, CodecEncoderElement))): pn = str(self.generate_strip_string(name)) pv = str(self.generate_strip_string(value)) self._monobridge._send(sender.name, 'lcd_name', pn) self._monobridge._send(sender.name, 'lcd_value', pv) def touched(self): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched += 1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def disconnect(self): self._session._unlink() self.log_message("<<<<<<<<<<<<<<<<<<<<<<<<< " + str(self._host_name) + " log closed >>>>>>>>>>>>>>>>>>>>>>>>>") super(Faderfox, self).disconnect() # a