def _create_detail_view_control(self): self._detail_view_toggler = DetailViewCntrlComponent( name='Detail_View_Control', is_enabled=False, layer=Layer( device_clip_toggle_button=self._device_clip_toggle_button, device_nav_left_button=self._detail_left_button, device_nav_right_button=self._detail_right_button))
def _create_view_control(self): self._view_control = DetailViewCntrlComponent( name=u'View_Control', is_enabled=False, layer=Layer(device_nav_left_button=self._prev_device_button, device_nav_right_button=self._next_device_button, device_clip_toggle_button=self._clip_device_button, detail_toggle_button=self._detail_view_button)) self._view_control.device_clip_toggle_button.pressed_color = u'DefaultButton.On'
def _detail_control(self): toggler = DetailViewCntrlComponent( is_enabled=False, layer=Layer( device_nav_left_button=self.control_surface.utility_buttons[4], device_nav_right_button=self.control_surface.utility_buttons[5] )) toggler.device_nav_right_button._set_color('Alt') toggler.device_nav_left_button._set_color('Alt') return toggler
class OP1(ControlSurface): def __init__(self, *args, **kwargs): ControlSurface.__init__(self, *args, **kwargs) self.log_message('__init__()') self.show_message("Version: " + VERSION) # Data for tracking connection attempts self.device_connected = False self.next_retry_delay = 1 self.next_retry_ts = None self.retries_count = 0 self._current_midi_map = None # State of display text self.text_top = '' self.text_bottom = '' # State of display key slots self.display_color_by_slot_num = {} for i in range(NUM_DISPLAY_CLIP_SLOTS): self.display_color_by_slot_num[i] = COLOR_BLACK_BYTES with self.component_guard(): self._build_components() self.init_modes() # # Ableton Helpers # @property def num_tracks(self): return min(NUM_TRACKS, len(self.song().tracks)) @property def num_scenes(self): return min(NUM_SCENES, len(self.song().scenes)) @property def selected_track(self): return self.song().view.selected_track @property def selected_track_num(self): return list(self.song().tracks).index(self.selected_track) @property def selected_scene(self): return self.song().view.selected_scene @property def selected_scene_num(self): return list(self.song().scenes).index(self.selected_scene) @property def selected_clip_slot(self): return self.selected_track.clip_slots[self.selected_scene_num] @property def selected_device(self): return self.selected_track.view.selected_device def get_selected_track_devices(self, class_name): return [ device for device in self.selected_track.devices if device.class_name == class_name ] # # Connected Components # def _with_shift(self, control): return ComboElement(control, modifiers=[self._button_shift]) def _build_components(self): self._buttons = {} for identifier in range(5, 53) + range(64, 68): # We create the shift button in a special way if identifier == OP1_SHIFT_BUTTON: continue # Encoders present as buttons when values are changed button = APCUtils.make_pedal_button(identifier) button.add_value_listener(self.debug_button_handler) self._buttons[identifier] = button # Encoder buttons # See notes below for explanation of exclusion of first button # for identifier in [OP1_ENCODER_2_BUTTON, OP1_ENCODER_3_BUTTON, OP1_ENCODER_4_BUTTON]: # button = APCUtils.make_pedal_button(identifier) # button.add_value_listener(self.debug_button_handler) # APCUtils.make_pedal_button(identifier] = butto) self._notes = {} for identifier in range(OP1_MIN_NOTE, OP1_MAX_NOTE + 1): note = APCUtils.make_button(CHANNEL, identifier) note.add_value_listener(self.debug_note_handler) self._notes[identifier] = note # Buttons self._button_shift = ButtonElement( is_momentary=True, msg_type=MIDI_CC_TYPE, channel=0, identifier=OP1_SHIFT_BUTTON, # Required for modifier buttons resource_type=PrioritizedResource, name='ShiftButton', ) # self._button_shift.add_value_listener(self.on_shift_button) self._button_mode_synth = self._buttons[OP1_MODE_1_BUTTON] self._button_mode_drum = self._buttons[OP1_MODE_2_BUTTON] self._button_mode_tape = self._buttons[OP1_MODE_3_BUTTON] self._button_mode_mixer = self._buttons[OP1_MODE_4_BUTTON] self._button_mode_1 = self._buttons[OP1_T1_BUTTON] self._button_mode_2 = self._buttons[OP1_T2_BUTTON] self._button_mode_3 = self._buttons[OP1_T3_BUTTON] self._button_mode_4 = self._buttons[OP1_T4_BUTTON] self._button_down = self._buttons[OP1_ARROW_DOWN_BUTTON] self._button_up = self._buttons[OP1_ARROW_UP_BUTTON] self._button_left = self._buttons[OP1_LEFT_ARROW] self._button_right = self._buttons[OP1_RIGHT_ARROW] self._button_metronome = self._buttons[OP1_METRONOME_BUTTON] self._button_scissors = self._buttons[OP1_SCISSOR_BUTTON] self._button_ss1 = self._buttons[OP1_SS1_BUTTON] self._button_ss2 = self._buttons[OP1_SS2_BUTTON] self._button_ss3 = self._buttons[OP1_SS3_BUTTON] self._button_ss4 = self._buttons[OP1_SS4_BUTTON] self._button_ss5 = self._buttons[OP1_SS5_BUTTON] self._button_ss6 = self._buttons[OP1_SS6_BUTTON] self._button_ss7 = self._buttons[OP1_SS7_BUTTON] self._button_ss8 = self._buttons[OP1_SS8_BUTTON] self._button_record = self._buttons[OP1_REC_BUTTON] self._button_play = self._buttons[OP1_PLAY_BUTTON] self._button_stop = self._buttons[OP1_STOP_BUTTON] self._button_microphone = self._buttons[OP1_MICROPHONE] self._button_com = self._buttons[OP1_COM] self._button_sequencer = self._buttons[OP1_SEQUENCER] # Encoders self._encoder_1 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_1, ENCODER_MODE) self._encoder_2 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_2, ENCODER_MODE) self._encoder_3 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_3, ENCODER_MODE) self._encoder_4 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_4, ENCODER_MODE) self._unshift_encoder_1 = ShiftEnabledControl(self._encoder_1, self._button_shift, False, self) self._unshift_encoder_2 = ShiftEnabledControl(self._encoder_2, self._button_shift, False, self) self._unshift_encoder_3 = ShiftEnabledControl(self._encoder_3, self._button_shift, False, self) self._unshift_encoder_4 = ShiftEnabledControl(self._encoder_4, self._button_shift, False, self) self._shift_encoder_1 = ShiftEnabledControl(self._encoder_1, self._button_shift, True, self) self._shift_encoder_2 = ShiftEnabledControl(self._encoder_2, self._button_shift, True, self) self._shift_encoder_3 = ShiftEnabledControl(self._encoder_3, self._button_shift, True, self) self._shift_encoder_4 = ShiftEnabledControl(self._encoder_4, self._button_shift, True, self) self._encoder_u01_1 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U01_ENCODER_1, ENCODER_MODE) self._encoder_u01_2 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U01_ENCODER_2, ENCODER_MODE) self._encoder_u01_3 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U01_ENCODER_3, ENCODER_MODE) self._encoder_u01_4 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U01_ENCODER_4, ENCODER_MODE) self._unshift_encoder_u01_1 = ShiftEnabledControl( self._encoder_u01_1, self._button_shift, False, self) self._unshift_encoder_u01_2 = ShiftEnabledControl( self._encoder_u01_2, self._button_shift, False, self) self._unshift_encoder_u01_3 = ShiftEnabledControl( self._encoder_u01_3, self._button_shift, False, self) self._unshift_encoder_u01_4 = ShiftEnabledControl( self._encoder_u01_4, self._button_shift, False, self) self._shift_encoder_u01_1 = ShiftEnabledControl( self._encoder_u01_1, self._button_shift, True, self) self._shift_encoder_u01_2 = ShiftEnabledControl( self._encoder_u01_2, self._button_shift, True, self) self._shift_encoder_u01_3 = ShiftEnabledControl( self._encoder_u01_3, self._button_shift, True, self) self._shift_encoder_u01_4 = ShiftEnabledControl( self._encoder_u01_4, self._button_shift, True, self) self._encoder_u02_1 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U02_ENCODER_1, ENCODER_MODE) self._encoder_u02_2 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U02_ENCODER_2, ENCODER_MODE) self._encoder_u02_3 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U02_ENCODER_3, ENCODER_MODE) self._encoder_u02_4 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U02_ENCODER_4, ENCODER_MODE) # NOTE: encoder_1_button conflicts with encoder_U03_4 self._encoder_button_1 = self._buttons[OP1_ENCODER_1_BUTTON] self._encoder_button_2 = self._buttons[OP1_ENCODER_2_BUTTON] self._encoder_button_3 = self._buttons[OP1_ENCODER_3_BUTTON] self._encoder_button_4 = self._buttons[OP1_ENCODER_4_BUTTON] self._mixer = MixerComponent( num_tracks=NUM_TRACKS, num_returns=2, ) # self._mixer.set_select_buttons( # prev_button=self._button_up, # next_button=self._button_down, # ) # self.map_mixer_controls_for_current_track() def on_down_button(value): if value == BUTTON_ON: self.set_selected_scene(self.scene_offset + 1) def on_up_button(value): if value == BUTTON_ON: self.set_selected_scene(self.scene_offset - 1) self.scene_offset = 0 self.song().view.add_selected_scene_listener( self.selected_scene_changed) self._button_right.add_value_listener(on_down_button) self._button_left.add_value_listener(on_up_button) self._transport = TransportComponent() self._transport.set_metronome_button(self._button_metronome) # # Controls for navigating the bottom detail pane # self._device_navigation = DetailViewCntrlComponent() # Toggle hide/show of bottom detail pane self._device_navigation.set_detail_toggle_button(self._button_ss1) # Toggle between clip detail and effects detail in bottom detail pane self._device_navigation.set_device_clip_toggle_button(self._button_ss2) # Nav left/right in the device chain detail view in bottom pane self._device_navigation.device_nav_left_button.set_control_element( self._button_ss7) self._device_navigation.device_nav_right_button.set_control_element( self._button_ss8) # Clip firing self._notes[OP1_F3_NOTE].add_value_listener(partial( self.clip_fired, 0)) self._notes[OP1_G3_NOTE].add_value_listener(partial( self.clip_fired, 1)) self._notes[OP1_A3_NOTE].add_value_listener(partial( self.clip_fired, 2)) self._notes[OP1_B3_NOTE].add_value_listener(partial( self.clip_fired, 3)) self._notes[OP1_C4_NOTE].add_value_listener(partial( self.clip_fired, 4)) self._notes[OP1_D4_NOTE].add_value_listener(partial( self.clip_fired, 5)) self._notes[OP1_E4_NOTE].add_value_listener(partial( self.clip_fired, 6)) self._notes[OP1_F4_NOTE].add_value_listener(partial( self.clip_fired, 7)) self._button_scissors.add_value_listener(self.selected_clip_deleted) # # Device Controls # # self._device = DeviceComponent( # name='Device_Component', # is_enabled=False, # layer=Layer( # parameter_controls=ButtonMatrixElement(rows=[[ # self._encoder_u01_1, # self._encoder_u01_2, # self._encoder_u01_3, # self._encoder_u01_4, # self._encoder_u02_1, # self._encoder_u02_2, # self._encoder_u02_3, # self._encoder_u02_4, # ]]), # # bank_buttons=ButtonMatrixElement(rows=[[ # # self._encoder_button_1, # # self._encoder_button_2, # # self._encoder_button_3, # # self._encoder_button_4, # # ]]), # bank_prev_button=self._button_ss5, # bank_next_button=self._button_ss6, # on_off_button=self._button_record, # ), # device_selection_follows_track_selection=True # ) # self._device.set_enabled(True) # self.set_device_component(self._device) # # Mode configuration # def init_modes(self): self.tracks_mode = modes.TracksMode(self) self.effects_mode = modes.EffectsMode(self) self.current_mode = None self._button_mode_synth.add_value_listener( partial(self.on_mode_button, self.tracks_mode)) self._button_mode_drum.add_value_listener( partial(self.on_mode_button, self.effects_mode)) # self._button_mode_3.add_value_listener( # partial(self.on_mode_button, )) # self._button_mode_4.add_value_listener( # partial(self.on_mode_button, )) self.set_mode(self.tracks_mode) def set_mode(self, mode): self.log_message('set_mode()') if self.current_mode is not None: self.current_mode.deactivate() self.current_mode = mode self.current_mode.activate() def on_mode_button(self, mode, value): if value: self.set_mode(mode) # # Shift Button Alternative modes # def on_shift_button(self, value): if value == BUTTON_ON: self.log_message('shift on') pass else: self.log_message('shift off') pass # # Scene selection # def selected_scene_changed(self): self.log_message('selected_scene_changed()') self.scene_offset = self.selected_scene_num self.map_clip_controls_for_current_scene() def set_selected_scene(self, scene_offset): scene_offset = max(0, scene_offset) scene_offset = min(scene_offset, self.num_scenes - 1) next_scene = self.song().scenes[scene_offset] next_scene = self.song().view.selected_scene = next_scene self.scene_offset = scene_offset def clear_key_assignments(self): pass def map_clip_controls_for_current_scene(self): for clip_slot in self.selected_scene.clip_slots: pass # # Clip triggers # def clip_fired(self, clip_num, value): if value == NOTE_ON: self.log_message('clip_fired(clip_num=%s, value=%s)' % (clip_num, value)) clip_slot = self.selected_track.clip_slots[clip_num] # if clip_slot.is_playing: # self.log_message('stoping clip') # clip_slot.stop() # else: # self.log_message('firing clip. has_clip=%s has_stop=%s, playing_status=%s' % ( # clip_slot.has_clip, # clip_slot.has_stop_button, # clip_slot.playing_status, # )) # clip_slot.fire() self.log_message( 'firing clip. has_clip=%s has_stop=%s, playing_status=%s' % ( clip_slot.has_clip, clip_slot.has_stop_button, clip_slot.playing_status, )) clip_slot.fire() # Update scene selection to fired clip's row. self.set_selected_scene(clip_num) def selected_clip_deleted(self, value): if value == BUTTON_ON: self.log_message('deleting clip') self.selected_clip_slot.delete_clip() # # Looper triggers # def looper_fired(looper_device): fire_param = [ param for param in looper_device.parameters if param.name == 'State' ] self.log_message(fire_param) # # Refresh handling # def handle_sysex(self, midi_bytes): super(OP1, self).handle_sysex(midi_bytes) if (len(midi_bytes) >= 8 and (midi_bytes[6] == 32) and (midi_bytes[7] == 118)): self.handle_device_connection_success() else: self.log_message("sysex: %s" % (midi_bytes, )) def refresh_state(self): super(OP1, self).refresh_state() self.log_message("refresh_state()") self.retries_count = 0 self.next_retry_ts = None self.next_retry_delay = 1 self.device_connected = False def update_display(self): super(OP1, self).update_display() if not (self.device_connected): if self.next_retry_ts is None or time.time() >= self.next_retry_ts: self.attempt_connection_with_device() return # Render the currently active view self.current_mode.view.render() # # Connection Management # def build_midi_map(self, midi_map_handle): super(OP1, self).build_midi_map(midi_map_handle) # map mixer controls to currently selected track # self.map_mixer_controls_for_current_track() def attempt_connection_with_device(self): self.log_message("Attempting to connect to OP-1... (num_retries: %s)" % self.retries_count) self.retries_count += 1 self.next_retry_ts = time.time() + self.next_retry_delay self.next_retry_delay *= 2 self._send_midi(ID_SEQUENCE) def handle_device_connection_success(self): self.device_connected = True self.retries_count = 0 self.log_message("OP-1 Connected") self._send_midi(ENABLE_SEQUENCE) def disconnect(self): self.log_message("disconnect()") self.retries_count = 0 self.device_connected = False self._send_midi(DISABLE_SEQUENCE) super(OP1, self).disconnect() def suggest_input_port(self): return "OP-1 Midi Device" def suggest_output_port(self): return "OP-1 Midi Device" # # Debug utils # def param_value_updated(self, param): self.log_message('Param update: %s(%s)' % (param.name, param.value)) self.log_message(' value_items: %s' % (list(param.value_items), )) def debug_button_handler(self, value, *args, **kwargs): self.log_message('button: %s' % value) def debug_note_handler(self, value, *args, **kwargs): self.log_message('note: %s' % value) def handle_nonsysex(self, midi_bytes): super(OP1, self).handle_nonsysex(midi_bytes) channel, identifier, value, is_pitchbend = midi_bytes_to_values( midi_bytes) if not is_pitchbend: self.log_message('midi ch:%s value:%s(%s)' % (channel, identifier, value))
def _build_components(self): self._buttons = {} for identifier in range(5, 53) + range(64, 68): # We create the shift button in a special way if identifier == OP1_SHIFT_BUTTON: continue # Encoders present as buttons when values are changed button = APCUtils.make_pedal_button(identifier) button.add_value_listener(self.debug_button_handler) self._buttons[identifier] = button # Encoder buttons # See notes below for explanation of exclusion of first button # for identifier in [OP1_ENCODER_2_BUTTON, OP1_ENCODER_3_BUTTON, OP1_ENCODER_4_BUTTON]: # button = APCUtils.make_pedal_button(identifier) # button.add_value_listener(self.debug_button_handler) # APCUtils.make_pedal_button(identifier] = butto) self._notes = {} for identifier in range(OP1_MIN_NOTE, OP1_MAX_NOTE + 1): note = APCUtils.make_button(CHANNEL, identifier) note.add_value_listener(self.debug_note_handler) self._notes[identifier] = note # Buttons self._button_shift = ButtonElement( is_momentary=True, msg_type=MIDI_CC_TYPE, channel=0, identifier=OP1_SHIFT_BUTTON, # Required for modifier buttons resource_type=PrioritizedResource, name='ShiftButton', ) # self._button_shift.add_value_listener(self.on_shift_button) self._button_mode_synth = self._buttons[OP1_MODE_1_BUTTON] self._button_mode_drum = self._buttons[OP1_MODE_2_BUTTON] self._button_mode_tape = self._buttons[OP1_MODE_3_BUTTON] self._button_mode_mixer = self._buttons[OP1_MODE_4_BUTTON] self._button_mode_1 = self._buttons[OP1_T1_BUTTON] self._button_mode_2 = self._buttons[OP1_T2_BUTTON] self._button_mode_3 = self._buttons[OP1_T3_BUTTON] self._button_mode_4 = self._buttons[OP1_T4_BUTTON] self._button_down = self._buttons[OP1_ARROW_DOWN_BUTTON] self._button_up = self._buttons[OP1_ARROW_UP_BUTTON] self._button_left = self._buttons[OP1_LEFT_ARROW] self._button_right = self._buttons[OP1_RIGHT_ARROW] self._button_metronome = self._buttons[OP1_METRONOME_BUTTON] self._button_scissors = self._buttons[OP1_SCISSOR_BUTTON] self._button_ss1 = self._buttons[OP1_SS1_BUTTON] self._button_ss2 = self._buttons[OP1_SS2_BUTTON] self._button_ss3 = self._buttons[OP1_SS3_BUTTON] self._button_ss4 = self._buttons[OP1_SS4_BUTTON] self._button_ss5 = self._buttons[OP1_SS5_BUTTON] self._button_ss6 = self._buttons[OP1_SS6_BUTTON] self._button_ss7 = self._buttons[OP1_SS7_BUTTON] self._button_ss8 = self._buttons[OP1_SS8_BUTTON] self._button_record = self._buttons[OP1_REC_BUTTON] self._button_play = self._buttons[OP1_PLAY_BUTTON] self._button_stop = self._buttons[OP1_STOP_BUTTON] self._button_microphone = self._buttons[OP1_MICROPHONE] self._button_com = self._buttons[OP1_COM] self._button_sequencer = self._buttons[OP1_SEQUENCER] # Encoders self._encoder_1 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_1, ENCODER_MODE) self._encoder_2 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_2, ENCODER_MODE) self._encoder_3 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_3, ENCODER_MODE) self._encoder_4 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_4, ENCODER_MODE) self._unshift_encoder_1 = ShiftEnabledControl(self._encoder_1, self._button_shift, False, self) self._unshift_encoder_2 = ShiftEnabledControl(self._encoder_2, self._button_shift, False, self) self._unshift_encoder_3 = ShiftEnabledControl(self._encoder_3, self._button_shift, False, self) self._unshift_encoder_4 = ShiftEnabledControl(self._encoder_4, self._button_shift, False, self) self._shift_encoder_1 = ShiftEnabledControl(self._encoder_1, self._button_shift, True, self) self._shift_encoder_2 = ShiftEnabledControl(self._encoder_2, self._button_shift, True, self) self._shift_encoder_3 = ShiftEnabledControl(self._encoder_3, self._button_shift, True, self) self._shift_encoder_4 = ShiftEnabledControl(self._encoder_4, self._button_shift, True, self) self._encoder_u01_1 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U01_ENCODER_1, ENCODER_MODE) self._encoder_u01_2 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U01_ENCODER_2, ENCODER_MODE) self._encoder_u01_3 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U01_ENCODER_3, ENCODER_MODE) self._encoder_u01_4 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U01_ENCODER_4, ENCODER_MODE) self._unshift_encoder_u01_1 = ShiftEnabledControl( self._encoder_u01_1, self._button_shift, False, self) self._unshift_encoder_u01_2 = ShiftEnabledControl( self._encoder_u01_2, self._button_shift, False, self) self._unshift_encoder_u01_3 = ShiftEnabledControl( self._encoder_u01_3, self._button_shift, False, self) self._unshift_encoder_u01_4 = ShiftEnabledControl( self._encoder_u01_4, self._button_shift, False, self) self._shift_encoder_u01_1 = ShiftEnabledControl( self._encoder_u01_1, self._button_shift, True, self) self._shift_encoder_u01_2 = ShiftEnabledControl( self._encoder_u01_2, self._button_shift, True, self) self._shift_encoder_u01_3 = ShiftEnabledControl( self._encoder_u01_3, self._button_shift, True, self) self._shift_encoder_u01_4 = ShiftEnabledControl( self._encoder_u01_4, self._button_shift, True, self) self._encoder_u02_1 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U02_ENCODER_1, ENCODER_MODE) self._encoder_u02_2 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U02_ENCODER_2, ENCODER_MODE) self._encoder_u02_3 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U02_ENCODER_3, ENCODER_MODE) self._encoder_u02_4 = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_U02_ENCODER_4, ENCODER_MODE) # NOTE: encoder_1_button conflicts with encoder_U03_4 self._encoder_button_1 = self._buttons[OP1_ENCODER_1_BUTTON] self._encoder_button_2 = self._buttons[OP1_ENCODER_2_BUTTON] self._encoder_button_3 = self._buttons[OP1_ENCODER_3_BUTTON] self._encoder_button_4 = self._buttons[OP1_ENCODER_4_BUTTON] self._mixer = MixerComponent( num_tracks=NUM_TRACKS, num_returns=2, ) # self._mixer.set_select_buttons( # prev_button=self._button_up, # next_button=self._button_down, # ) # self.map_mixer_controls_for_current_track() def on_down_button(value): if value == BUTTON_ON: self.set_selected_scene(self.scene_offset + 1) def on_up_button(value): if value == BUTTON_ON: self.set_selected_scene(self.scene_offset - 1) self.scene_offset = 0 self.song().view.add_selected_scene_listener( self.selected_scene_changed) self._button_right.add_value_listener(on_down_button) self._button_left.add_value_listener(on_up_button) self._transport = TransportComponent() self._transport.set_metronome_button(self._button_metronome) # # Controls for navigating the bottom detail pane # self._device_navigation = DetailViewCntrlComponent() # Toggle hide/show of bottom detail pane self._device_navigation.set_detail_toggle_button(self._button_ss1) # Toggle between clip detail and effects detail in bottom detail pane self._device_navigation.set_device_clip_toggle_button(self._button_ss2) # Nav left/right in the device chain detail view in bottom pane self._device_navigation.device_nav_left_button.set_control_element( self._button_ss7) self._device_navigation.device_nav_right_button.set_control_element( self._button_ss8) # Clip firing self._notes[OP1_F3_NOTE].add_value_listener(partial( self.clip_fired, 0)) self._notes[OP1_G3_NOTE].add_value_listener(partial( self.clip_fired, 1)) self._notes[OP1_A3_NOTE].add_value_listener(partial( self.clip_fired, 2)) self._notes[OP1_B3_NOTE].add_value_listener(partial( self.clip_fired, 3)) self._notes[OP1_C4_NOTE].add_value_listener(partial( self.clip_fired, 4)) self._notes[OP1_D4_NOTE].add_value_listener(partial( self.clip_fired, 5)) self._notes[OP1_E4_NOTE].add_value_listener(partial( self.clip_fired, 6)) self._notes[OP1_F4_NOTE].add_value_listener(partial( self.clip_fired, 7)) self._button_scissors.add_value_listener(self.selected_clip_deleted)
def _setup_APC_detail_component(self): self._alt_device_navigator = DetailViewCntrlComponent()
class AumTroll_G(AumTroll): def __init__(self, *a, **k): super(AumTroll_G, self).__init__(*a, **k) with self.component_guard(): self._setup_session_recording_component() self._setup_APC_detail_component() self.log_message('Aumtroll G 4') def _setup_session_recording_component(self): self._recorder = SessionRecordingComponent(ClipCreator(), ViewControlComponent()) def _setup_APC_detail_component(self): self._alt_device_navigator = DetailViewCntrlComponent() """the mixer component corresponds and moves with our selection in Live, and allows us to assign physical controls""" """to Live's mixer functions without having to make all the links ourselves""" def _setup_mixer_control(self): is_momentary = True self._num_tracks = (8) #A mixer is one-dimensional; self._mixer = MixerComponent( 8, 2, True, False ) #These values represent the (Number_of_tracks, Number_of_returns, EQ_component, Filter_component) self._mixer.name = 'Mixer' #We name everything that we might want to access in m4l self._mixer.set_track_offset( 0) #Sets start point for mixer strip (offset from left) for index in range(8): #self._mixer.channel_strip(index).set_volume_control(self._fader[index]) #Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it self._mixer.channel_strip( index ).name = 'Mixer_ChannelStrip_' + str( index ) #We also name the individual channel_strip so we can access it self._mixer.track_eq(index).name = 'Mixer_EQ_' + str( index ) #We also name the individual EQ_component so we can access it self._mixer.channel_strip( index )._invert_mute_feedback = True #This makes it so that when a track is muted, the corresponding button is turned off 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._send_reset = ResetSendsComponent( self ) #This creates a custom MonoComponent that allows us to reset all the sends on a track to zero with a single button self._send_reset.name = 'Sends_Reset' #We name it so that we can access it from m4l """the session component represents a grid of buttons that can be used to fire, stop, and navigate clips in the session view""" def _setup_session_control(self): is_momentary = True num_tracks = 8 #we are working with a 4x4 grid, num_scenes = 4 #so the height and width are both set to 4 self._session = SessionComponent( num_tracks, num_scenes ) #we create our SessionComponent with the variables we set above it self._session.name = "Session" #we name it so we can access it in m4l self._session.set_offsets( 0, 0 ) #we set the initial offset to the far left, top of the session grid self._session._track_banking_increment = 4 self._session.set_stop_clip_value( STOP_CLIP[self._rgb] ) #we assign the colors that will be displayed when the stop_clip button is pressed. This value comes from CNTRLR_Map.py, which is imported in the header of our script self._scene = [ None for index in range(4) ] #we create an array to hold the Scene subcomponents so that we can get to them if we need them. for row in range( num_scenes ): #now we'll fill the array with different objects that were created when we called the SessionComponent() module self._scene[row] = self._session.scene( row) #each session row is a SceneComponent self._scene[row].name = 'Scene_' + str( row) #name it so we can access it in m4l for column in range( num_tracks ): #now we'll create holders and names for the contents of each scene clip_slot = self._scene[row].clip_slot( column ) #we use our assignment of the scene above to gain access to the individual clipslots. Here, we are just assigning 'clip_slot' each time as a local variable so we can manipulated it's properties clip_slot.name = str(column) + '_Clip_Slot' + str( row) #name it so that we can acces it in m4l clip_slot.set_triggered_to_play_value( CLIP_TRG_PLAY[self._rgb]) #set its triggered to play color clip_slot.set_triggered_to_record_value( CLIP_TRG_REC[ self._rgb]) #set its triggered to record color clip_slot.set_stopped_value( CLIP_STOP[self._rgb]) #set its stop color clip_slot.set_started_value( CLIP_STARTED[self._rgb]) #set its started color clip_slot.set_recording_value( CLIP_RECORDING[self._rgb]) #set its recording value self._session.set_mixer( self._mixer ) #now we link the MixerComponent we created in _setup_mixer_control() to our session component so that they will follow each other when either is navigated self.set_highlighting_session_component(self._session) self._session_zoom = SessionZoomingComponent( self._session ) #this creates the ZoomingComponent that allows navigation when the shift button is pressed self._session_zoom.name = 'Session_Overview' #name it so we can access it in m4l self._session_zoom.set_stopped_value( ZOOM_STOPPED[self._rgb]) #set the zooms stopped color self._session_zoom.set_playing_value( ZOOM_PLAYING[self._rgb]) #set the zooms playing color self._session_zoom.set_selected_value( ZOOM_SELECTED[self._rgb]) #set the zooms selected color self._session_zoom.set_button_matrix( self._matrix ) #assign the ButtonMatrixElement that we created in _setup_controls() to the zooming component so that we can control it self._session_zoom.set_zoom_button( self._button[31] ) #assign a shift button so that we can switch states between the SessionComponent and the SessionZoomingComponent """this section is used so that we can reassign the color properties of each state. Legacy, from the OhmModes script, to support either RGB or Monochrome""" def _assign_session_colors(self): num_tracks = 8 num_scenes = 4 self._session.set_stop_clip_value(STOP_ALL[self._rgb]) for row in range(num_scenes): for column in range(num_tracks): self._scene[row].clip_slot(column).set_triggered_to_play_value( CLIP_TRG_PLAY[self._rgb]) self._scene[row].clip_slot( column).set_triggered_to_record_value( CLIP_TRG_REC[self._rgb]) self._scene[row].clip_slot(column).set_stopped_value( CLIP_STOP[self._rgb]) self._scene[row].clip_slot(column).set_started_value( CLIP_STARTED[self._rgb]) self._scene[row].clip_slot(column).set_recording_value( CLIP_RECORDING[self._rgb]) self._session_zoom.set_stopped_value(ZOOM_STOPPED[self._rgb]) self._session_zoom.set_playing_value(ZOOM_PLAYING[self._rgb]) self._session_zoom.set_selected_value(ZOOM_SELECTED[self._rgb]) self.refresh_state() def deassign_live_controls(self, *a, **k): for index in range(4): self._encoder[index].send_value(0, True) self._encoder[index].clear_send_cache() self._mixer.channel_strip(index + 4).set_volume_control( None ) #Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it #for the left side of the mixer self._mixer.channel_strip(index + 4).set_solo_button( None) #remove the solo button assignments self._mixer.channel_strip(index + 4).set_arm_button( None) #remove the arm button assignments self._mixer.channel_strip(index + 4).set_mute_button( None) #remove the mute button assignments self._mixer.channel_strip(index + 4).set_select_button( None) #remove the select button assignments #self._alt_device_navigator.set_arrange_session_toggle_button(None) self._alt_device_navigator.set_device_clip_toggle_button(None) self._alt_device_navigator.set_detail_toggle_button(None) self._alt_device_navigator.set_enabled(False) #self._alt_device_navigator.set_shift_button(None) self._transport.set_nudge_buttons(None, None) self._recorder.set_record_button(None) self._recorder.set_re_enable_automation_button(None) super(AumTroll_G, self).deassign_live_controls(*a, **k) def assign_live_controls(self): """the following lines update all of the controls' last_sent properties, so that they forward the next value they receive regardless of whether or not it is the same as the last it recieved""" """we also reset the encoder rings and buttons, since the device component will not update them if it is not locked to a device in Live""" for index in range(16): self._grid[index].force_next_send() for index in range(32): #self._button[index].set_on_off_values(0, 127) self._button[index].send_value(0, True) self._button[index].force_next_send() for index in range(8): self._encoder_button[index + 4].send_value(0, True) self._encoder_button[index + 4].force_next_send() for index in range(12): self._encoder[index].send_value(0, True) self._encoder[index].force_next_send() """here we assign the left side of our mixer's buttons on the lower 32 keys""" if self._monohm is None: with self.component_guard(): for index in range( 4 ): #we set up a recursive loop to assign all four of our track channel strips' controls self._button[index + 16].set_on_value( MUTE[self._rgb]) #set the mute color from the Map.py self._mixer.channel_strip(index).set_mute_button( self._button[index + 16] ) #assign the mute buttons to our mixer channel strips self._button[index + 28].set_on_value( MUTE[self._rgb]) #set the mute color from the Map.py self._mixer.channel_strip(index + 4).set_mute_button( self._button[index + 28] ) #assign the mute buttons to our mixer channel strips self._button[index].set_on_off_values( SELECT[self._rgb], SELECT_OFF[self._rgb]) self._mixer.channel_strip(index).set_select_button( self._button[index] ) #assign the select buttons to our mixer channel strips self._button[index + 12].set_on_off_values( SELECT[self._rgb], SELECT_OFF[ self._rgb]) #set the select color from the Map.py self._mixer.channel_strip(index + 4).set_select_button( self._button[index + 12] ) #assign the select buttons to our mixer channel strips #self._session.set_stop_track_clip_buttons(tuple(self._button[index+4] for index in range(8))) #these last two lines assign the send_reset buttons and the stop_clip buttons for each track for index in range(8): #self._button[index + 4].set_on_off_values(SOLO[self._rgb], SOLO[self._rgb]) #this assigns the custom colors defined in the Map.py file to the stop_clip buttons. They have seperate on/off values, but we assign them both the same value so we can always identify them self._mixer.channel_strip(index).set_solo_button( self._button[index + 4]) #self._button[index + 4].send_value(STOP_CLIP[self._rgb], True) #finally, we send the on/off colors out to turn the LEDs on for the stop clip buttons for index in range( 4 ): #set up a for loop to generate an index for assigning the session nav buttons' colors self._button[index + 20].set_on_off_values( SESSION_NAV[self._rgb], SESSION_NAV_OFF[self._rgb] ) #assign the colors from Map.py to the session nav buttons self._session.set_track_bank_buttons( self._button[21], self._button[20] ) #set the track bank buttons for the Session navigation controls self._session.set_scene_bank_buttons( self._button[23], self._button[22] ) #set the scnee bank buttons for the Session navigation controls """this section assigns the grid to the clip launch functionality of the SessionComponent""" for column in range( 4 ): #we need to set up a double recursion so that we can generate the indexes needed to assign the grid buttons for row in range( 4 ): #the first recursion passes the column index, the second the row index self._scene[row].clip_slot(column).set_launch_button( self._grid[(row * 4) + column] ) #we use the indexes to grab the first the scene and then the clip we assigned above, and then we use them again to define the button held in the grid array that we want to assign to the clip slot from the session component for index in range( 4 ): #set up a for loop to generate an index for assigning the session nav buttons' colors self._button[index + 24].set_on_off_values( SHIFTS[self._rgb], SHIFTS_OFF[self._rgb] ) #assign the colors from Map.py to the session nav buttons self._session.update( ) #tell the Session component to update so that the grid will display the currently selected session region self._session.set_enabled(True) #enable the Session Component self._session_zoom.set_enabled(True) #enable the Session Zoom #self._alt_device_navigator.set_arrange_session_toggle_button(self._encoder_button[4]) self._alt_device_navigator.set_device_clip_toggle_button( self._encoder_button[5]) self._alt_device_navigator.set_detail_toggle_button( self._encoder_button[6]) #self._device_navigator.set_shift_button(self._encoder_button[7]) self._session_zoom.set_zoom_button( self._encoder_button[7] ) #assign the lower right key button to the shift function of the Zoom component self._session.set_scene_bank_buttons(self._button[25], self._button[24]) self._recorder.set_record_button(self._button[27]) self._recorder.set_re_enable_automation_button( self._button[26]) else: for index in range(8): self._mixer2.channel_strip(index).set_volume_control( self._fader[index]) self._mixer2.set_track_offset(TROLL_OFFSET) self._device_selector.set_mode_buttons(self._grid) if not self._shifted: self._assign_monomodular_controls() else: self._assign_shifted_controls() self._device1.set_parameter_controls( tuple([self._knobs[index] for index in range(8)])) self._device2.set_parameter_controls( tuple([self._knobs[index + 12] for index in range(8)])) self._device1.set_enabled(True) self._device2.set_enabled(True) self._find_devices() self._device1.update() self._device2.update() """this section assigns the encoders and encoder buttons""" self._device.set_parameter_controls( tuple([self._encoder[index + 4] for index in range(8)]) ) #assign the encoders from the device component controls - we are doing this here b #self._encoder_button[7].set_on_value(DEVICE_LOCK[self._rgb]) #set the on color for the Device lock encoder button #self._device.set_lock_button(self._encoder_button[7]) #assign encoder button 7 to the device lock control #self._encoder_button[4].set_on_value(DEVICE_ON[self._rgb]) #set the on color for the Device on/off encoder button #self._device.set_on_off_button(self._encoder_button[4]) #assing encoder button 4 to the device on/off control for index in range( 2 ): #setup a recursion to generate indexes so that we can reference the correct controls to assing to the device_navigator functions self._encoder_button[index + 8].set_on_value( DEVICE_NAV[ self._rgb]) #assign the on color for the device navigator self._encoder_button[index + 10].set_on_value( DEVICE_BANK[self._rgb] ) #assign the on color for the device bank controls self._device_navigator.set_nav_buttons( self._encoder_button[10], self._encoder_button[11] ) #set the device navigators controls to encoder buttons 10 and 11 self._device.set_bank_nav_buttons( self._encoder_button[8], self._encoder_button[9] ) #set the device components bank nav controls to encoder buttons 8 and 9 """now we turn on and update some of the components we've just made assignments to""" self._device.set_enabled(True) #enable the Device Component self._device_navigator.set_enabled(True) #enable the Device Navigator self._alt_device_navigator.set_enabled(True) self._device.update( ) #tell the Device component to update its assingments so that it will detect the currently selected device parameters and display them on the encoder rings
class AumTroll_G(AumTroll): def __init__(self, *a, **k): super(AumTroll_G, self).__init__(*a, **k) with self.component_guard(): self._setup_session_recording_component() self._setup_APC_detail_component() self.log_message('Aumtroll G 4') def _setup_session_recording_component(self): self._recorder = SessionRecordingComponent(ClipCreator(), ViewControlComponent()) def _setup_APC_detail_component(self): self._alt_device_navigator = DetailViewCntrlComponent() """the mixer component corresponds and moves with our selection in Live, and allows us to assign physical controls""" """to Live's mixer functions without having to make all the links ourselves""" def _setup_mixer_control(self): is_momentary = True self._num_tracks = (8) #A mixer is one-dimensional; self._mixer = MixerComponent(8, 2, True, False) #These values represent the (Number_of_tracks, Number_of_returns, EQ_component, Filter_component) self._mixer.name = 'Mixer' #We name everything that we might want to access in m4l self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(8): #self._mixer.channel_strip(index).set_volume_control(self._fader[index]) #Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it self._mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) #We also name the individual channel_strip so we can access it self._mixer.track_eq(index).name = 'Mixer_EQ_' + str(index) #We also name the individual EQ_component so we can access it self._mixer.channel_strip(index)._invert_mute_feedback = True #This makes it so that when a track is muted, the corresponding button is turned off 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._send_reset = ResetSendsComponent(self) #This creates a custom MonoComponent that allows us to reset all the sends on a track to zero with a single button self._send_reset.name = 'Sends_Reset' #We name it so that we can access it from m4l """the session component represents a grid of buttons that can be used to fire, stop, and navigate clips in the session view""" def _setup_session_control(self): is_momentary = True num_tracks = 8 #we are working with a 4x4 grid, num_scenes = 4 #so the height and width are both set to 4 self._session = SessionComponent(num_tracks, num_scenes) #we create our SessionComponent with the variables we set above it self._session.name = "Session" #we name it so we can access it in m4l self._session.set_offsets(0, 0) #we set the initial offset to the far left, top of the session grid self._session._track_banking_increment = 4 self._session.set_stop_clip_value(STOP_CLIP[self._rgb]) #we assign the colors that will be displayed when the stop_clip button is pressed. This value comes from CNTRLR_Map.py, which is imported in the header of our script self._scene = [None for index in range(4)] #we create an array to hold the Scene subcomponents so that we can get to them if we need them. for row in range(num_scenes): #now we'll fill the array with different objects that were created when we called the SessionComponent() module self._scene[row] = self._session.scene(row) #each session row is a SceneComponent self._scene[row].name = 'Scene_' + str(row) #name it so we can access it in m4l for column in range(num_tracks): #now we'll create holders and names for the contents of each scene clip_slot = self._scene[row].clip_slot(column) #we use our assignment of the scene above to gain access to the individual clipslots. Here, we are just assigning 'clip_slot' each time as a local variable so we can manipulated it's properties clip_slot.name = str(column) + '_Clip_Slot' + str(row) #name it so that we can acces it in m4l clip_slot.set_triggered_to_play_value(CLIP_TRG_PLAY[self._rgb]) #set its triggered to play color clip_slot.set_triggered_to_record_value(CLIP_TRG_REC[self._rgb])#set its triggered to record color clip_slot.set_stopped_value(CLIP_STOP[self._rgb]) #set its stop color clip_slot.set_started_value(CLIP_STARTED[self._rgb]) #set its started color clip_slot.set_recording_value(CLIP_RECORDING[self._rgb]) #set its recording value self._session.set_mixer(self._mixer) #now we link the MixerComponent we created in _setup_mixer_control() to our session component so that they will follow each other when either is navigated self.set_highlighting_session_component(self._session) self._session_zoom = SessionZoomingComponent(self._session) #this creates the ZoomingComponent that allows navigation when the shift button is pressed self._session_zoom.name = 'Session_Overview' #name it so we can access it in m4l self._session_zoom.set_stopped_value(ZOOM_STOPPED[self._rgb]) #set the zooms stopped color self._session_zoom.set_playing_value(ZOOM_PLAYING[self._rgb]) #set the zooms playing color self._session_zoom.set_selected_value(ZOOM_SELECTED[self._rgb]) #set the zooms selected color self._session_zoom.set_button_matrix(self._matrix) #assign the ButtonMatrixElement that we created in _setup_controls() to the zooming component so that we can control it self._session_zoom.set_zoom_button(self._button[31]) #assign a shift button so that we can switch states between the SessionComponent and the SessionZoomingComponent """this section is used so that we can reassign the color properties of each state. Legacy, from the OhmModes script, to support either RGB or Monochrome""" def _assign_session_colors(self): num_tracks = 8 num_scenes = 4 self._session.set_stop_clip_value(STOP_ALL[self._rgb]) for row in range(num_scenes): for column in range(num_tracks): self._scene[row].clip_slot(column).set_triggered_to_play_value(CLIP_TRG_PLAY[self._rgb]) self._scene[row].clip_slot(column).set_triggered_to_record_value(CLIP_TRG_REC[self._rgb]) self._scene[row].clip_slot(column).set_stopped_value(CLIP_STOP[self._rgb]) self._scene[row].clip_slot(column).set_started_value(CLIP_STARTED[self._rgb]) self._scene[row].clip_slot(column).set_recording_value(CLIP_RECORDING[self._rgb]) self._session_zoom.set_stopped_value(ZOOM_STOPPED[self._rgb]) self._session_zoom.set_playing_value(ZOOM_PLAYING[self._rgb]) self._session_zoom.set_selected_value(ZOOM_SELECTED[self._rgb]) self.refresh_state() def deassign_live_controls(self, *a, **k): for index in range(4): self._encoder[index].send_value(0, True) self._encoder[index].clear_send_cache() self._mixer.channel_strip(index+4).set_volume_control(None) #Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it #for the left side of the mixer self._mixer.channel_strip(index+4).set_solo_button(None) #remove the solo button assignments self._mixer.channel_strip(index+4).set_arm_button(None) #remove the arm button assignments self._mixer.channel_strip(index+4).set_mute_button(None) #remove the mute button assignments self._mixer.channel_strip(index+4).set_select_button(None) #remove the select button assignments #self._alt_device_navigator.set_arrange_session_toggle_button(None) self._alt_device_navigator.set_device_clip_toggle_button(None) self._alt_device_navigator.set_detail_toggle_button(None) self._alt_device_navigator.set_enabled(False) #self._alt_device_navigator.set_shift_button(None) self._transport.set_nudge_buttons(None, None) self._recorder.set_record_button(None) self._recorder.set_re_enable_automation_button(None) super(AumTroll_G, self).deassign_live_controls(*a, **k) def assign_live_controls(self): """the following lines update all of the controls' last_sent properties, so that they forward the next value they receive regardless of whether or not it is the same as the last it recieved""" """we also reset the encoder rings and buttons, since the device component will not update them if it is not locked to a device in Live""" for index in range(16): self._grid[index].force_next_send() for index in range(32): #self._button[index].set_on_off_values(0, 127) self._button[index].send_value(0, True) self._button[index].force_next_send() for index in range(8): self._encoder_button[index+4].send_value(0, True) self._encoder_button[index+4].force_next_send() for index in range(12): self._encoder[index].send_value(0, True) self._encoder[index].force_next_send() """here we assign the left side of our mixer's buttons on the lower 32 keys""" if self._monohm is None: with self.component_guard(): for index in range(4): #we set up a recursive loop to assign all four of our track channel strips' controls self._button[index+16].set_on_value(MUTE[self._rgb]) #set the mute color from the Map.py self._mixer.channel_strip(index).set_mute_button(self._button[index+16]) #assign the mute buttons to our mixer channel strips self._button[index+28].set_on_value(MUTE[self._rgb]) #set the mute color from the Map.py self._mixer.channel_strip(index+4).set_mute_button(self._button[index+28]) #assign the mute buttons to our mixer channel strips self._button[index].set_on_off_values(SELECT[self._rgb], SELECT_OFF[self._rgb]) self._mixer.channel_strip(index).set_select_button(self._button[index]) #assign the select buttons to our mixer channel strips self._button[index+12].set_on_off_values(SELECT[self._rgb], SELECT_OFF[self._rgb]) #set the select color from the Map.py self._mixer.channel_strip(index+4).set_select_button(self._button[index+12]) #assign the select buttons to our mixer channel strips #self._session.set_stop_track_clip_buttons(tuple(self._button[index+4] for index in range(8))) #these last two lines assign the send_reset buttons and the stop_clip buttons for each track for index in range(8): #self._button[index + 4].set_on_off_values(SOLO[self._rgb], SOLO[self._rgb]) #this assigns the custom colors defined in the Map.py file to the stop_clip buttons. They have seperate on/off values, but we assign them both the same value so we can always identify them self._mixer.channel_strip(index).set_solo_button(self._button[index+4]) #self._button[index + 4].send_value(STOP_CLIP[self._rgb], True) #finally, we send the on/off colors out to turn the LEDs on for the stop clip buttons for index in range(4): #set up a for loop to generate an index for assigning the session nav buttons' colors self._button[index + 20].set_on_off_values(SESSION_NAV[self._rgb], SESSION_NAV_OFF[self._rgb]) #assign the colors from Map.py to the session nav buttons self._session.set_track_bank_buttons(self._button[21], self._button[20]) #set the track bank buttons for the Session navigation controls self._session.set_scene_bank_buttons(self._button[23], self._button[22]) #set the scnee bank buttons for the Session navigation controls """this section assigns the grid to the clip launch functionality of the SessionComponent""" for column in range(4): #we need to set up a double recursion so that we can generate the indexes needed to assign the grid buttons for row in range(4): #the first recursion passes the column index, the second the row index self._scene[row].clip_slot(column).set_launch_button(self._grid[(row*4)+column]) #we use the indexes to grab the first the scene and then the clip we assigned above, and then we use them again to define the button held in the grid array that we want to assign to the clip slot from the session component for index in range(4): #set up a for loop to generate an index for assigning the session nav buttons' colors self._button[index + 24].set_on_off_values(SHIFTS[self._rgb], SHIFTS_OFF[self._rgb]) #assign the colors from Map.py to the session nav buttons self._session.update() #tell the Session component to update so that the grid will display the currently selected session region self._session.set_enabled(True) #enable the Session Component self._session_zoom.set_enabled(True) #enable the Session Zoom #self._alt_device_navigator.set_arrange_session_toggle_button(self._encoder_button[4]) self._alt_device_navigator.set_device_clip_toggle_button(self._encoder_button[5]) self._alt_device_navigator.set_detail_toggle_button(self._encoder_button[6]) #self._device_navigator.set_shift_button(self._encoder_button[7]) self._session_zoom.set_zoom_button(self._encoder_button[7]) #assign the lower right key button to the shift function of the Zoom component self._session.set_scene_bank_buttons(self._button[25], self._button[24]) self._recorder.set_record_button(self._button[27]) self._recorder.set_re_enable_automation_button(self._button[26]) else: for index in range(8): self._mixer2.channel_strip(index).set_volume_control(self._fader[index]) self._mixer2.set_track_offset(TROLL_OFFSET) self._device_selector.set_mode_buttons(self._grid) if not self._shifted: self._assign_monomodular_controls() else: self._assign_shifted_controls() self._device1.set_parameter_controls(tuple([self._knobs[index] for index in range(8)])) self._device2.set_parameter_controls(tuple([self._knobs[index+12] for index in range(8)])) self._device1.set_enabled(True) self._device2.set_enabled(True) self._find_devices() self._device1.update() self._device2.update() """this section assigns the encoders and encoder buttons""" self._device.set_parameter_controls(tuple([self._encoder[index+4] for index in range(8)])) #assign the encoders from the device component controls - we are doing this here b #self._encoder_button[7].set_on_value(DEVICE_LOCK[self._rgb]) #set the on color for the Device lock encoder button #self._device.set_lock_button(self._encoder_button[7]) #assign encoder button 7 to the device lock control #self._encoder_button[4].set_on_value(DEVICE_ON[self._rgb]) #set the on color for the Device on/off encoder button #self._device.set_on_off_button(self._encoder_button[4]) #assing encoder button 4 to the device on/off control for index in range(2): #setup a recursion to generate indexes so that we can reference the correct controls to assing to the device_navigator functions self._encoder_button[index + 8].set_on_value(DEVICE_NAV[self._rgb]) #assign the on color for the device navigator self._encoder_button[index + 10].set_on_value(DEVICE_BANK[self._rgb]) #assign the on color for the device bank controls self._device_navigator.set_nav_buttons(self._encoder_button[10], self._encoder_button[11]) #set the device navigators controls to encoder buttons 10 and 11 self._device.set_bank_nav_buttons(self._encoder_button[8], self._encoder_button[9]) #set the device components bank nav controls to encoder buttons 8 and 9 """now we turn on and update some of the components we've just made assignments to""" self._device.set_enabled(True) #enable the Device Component self._device_navigator.set_enabled(True) #enable the Device Navigator self._alt_device_navigator.set_enabled(True) self._device.update() #tell the Device component to update its assingments so that it will detect the currently selected device parameters and display them on the encoder rings