Exemple #1
0
class ATOMSQ(ControlSurface):
    def __init__(self, *a, **k):
        super(ATOMSQ, self).__init__(*a, **k)
        with self.component_guard():
            self._elements = Elements()
            with inject(element_container=const(self._elements)).everywhere():
                self._create_background()
                self._create_transport()
                self._create_undo()
                self._create_view_toggle()
                self._create_device_parameters()
                self._create_translating_background()
                self._create_device_navigation()
                self._create_launch_and_stop()
                self._create_session()
                self._create_mixer()
                self._create_view_control()
                self._create_button_labels()
                self._create_record_modes()
                self._create_lower_pad_modes()
                self._create_main_modes()
        self.__on_main_view_changed.subject = self.application.view

    def disconnect(self):
        super(ATOMSQ, self).disconnect()
        self._send_midi(midi.NATIVE_MODE_OFF_MESSAGE)

    def port_settings_changed(self):
        self._send_midi(midi.NATIVE_MODE_ON_MESSAGE)
        if self._main_modes.selected_mode == b'instrument':
            self.schedule_message(
                1, self._elements.upper_firmware_toggle_switch.send_value, 1)
        if self._main_modes.selected_mode != b'song':
            self.schedule_message(
                1, self._elements.lower_firmware_toggle_switch.send_value, 1)
        super(ATOMSQ, self).port_settings_changed()

    def _create_background(self):
        self._background = BackgroundComponent(
            name=b'Background',
            is_enabled=False,
            add_nop_listeners=True,
            layer=Layer(**{name: name
                           for name in BANK_BUTTON_NAMES}))
        self._background.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(
            name=b'Transport',
            is_enabled=False,
            layer=Layer(scroll_encoder=b'display_encoder',
                        play_button=b'play_button',
                        loop_button=b'play_button_with_shift',
                        stop_button=b'stop_button',
                        metronome_button=b'click_button',
                        capture_midi_button=b'record_button_with_shift',
                        prev_cue_button=b'display_left_button',
                        next_cue_button=b'display_right_button',
                        shift_button=b'shift_button'))
        self._transport.set_enabled(True)

    def _create_undo(self):
        self._undo = UndoRedoComponent(
            name=b'Undo',
            is_enabled=False,
            layer=Layer(undo_button=b'stop_button_with_shift'))
        self._undo.set_enabled(True)

    def _create_view_toggle(self):
        self._view_toggle = ViewToggleComponent(
            name=b'View_Toggle',
            is_enabled=False,
            layer=Layer(main_view_toggle_button=b'bank_a_button',
                        browser_view_toggle_button=b'bank_b_button',
                        detail_view_toggle_button=b'bank_d_button',
                        clip_view_toggle_button=b'bank_h_button'))

    def _create_device_parameters(self):
        self._device_parameters = SimpleDeviceParameterComponent(
            name=b'Device_Parameters',
            device_bank_registry=self._device_bank_registry,
            toggle_lock=self.toggle_lock,
            layer=Layer(device_name_display=b'device_name_display'),
            is_enabled=False)
        self._device_parameters.set_enabled(True)

    def _create_translating_background(self):
        self._translating_background = TranslatingBackgroundComponent(
            name=b'Translating_Background',
            is_enabled=False,
            add_nop_listeners=True,
            layer=Layer(encoders=b'encoders',
                        channel_selection_buttons=b'display_buttons'))

    def _create_device_navigation(self):
        self._device_navigation = SimpleDeviceNavigationComponent(
            name=b'Device_Navigation',
            is_enabled=False,
            layer=Layer(prev_button=b'display_buttons_raw[1]',
                        next_button=b'display_buttons_raw[2]'))

    def _create_launch_and_stop(self):
        self._launch_and_stop = LaunchAndStopComponent(
            name=b'Launch_And_Stop',
            is_enabled=False,
            layer=Layer(clip_launch_button=b'display_buttons_raw[3]',
                        scene_launch_button=b'display_buttons_raw[4]',
                        track_stop_button=b'display_buttons_raw[5]'))

    def _create_session(self):
        self._session_ring = SessionRingComponent(name=b'Session_Ring',
                                                  num_tracks=SESSION_WIDTH,
                                                  num_scenes=SESSION_HEIGHT)
        self._session = SessionComponent(
            name=b'Session',
            is_enabled=False,
            session_ring=self._session_ring,
            layer=Layer(clip_launch_buttons=b'upper_pads'))
        self._session_navigation = SessionNavigationComponent(
            name=b'Session_Navigation',
            is_enabled=False,
            session_ring=self._session_ring,
            layer=Layer(up_button=b'up_button_with_shift',
                        down_button=b'down_button_with_shift'))
        self._session_navigation.set_enabled(True)

    def _create_mixer(self):
        self._mixer = MixerComponent(
            name=b'Mixer',
            auto_name=True,
            tracks_provider=self._session_ring,
            track_assigner=SimpleTrackAssigner(),
            channel_strip_component_type=ChannelStripComponent)
        self._mixer.selected_strip().layer = Layer(
            track_name_display=b'track_name_display')
        self._mixer.set_enabled(True)

    def _create_view_control(self):
        self._view_control = NotifyingViewControlComponent(
            name=b'View_Control',
            is_enabled=False,
            track_provider=self._session_ring,
            enable_skinning=False,
            layer=Layer(next_track_button=b'right_button',
                        prev_track_button=b'left_button',
                        next_scene_button=b'down_button',
                        prev_scene_button=b'up_button'))
        self._view_control.set_enabled(True)
        self._session_ring_selection_linking = self.register_disconnectable(
            SessionRingSelectionLinking(
                session_ring=self._session_ring,
                selection_changed_notifier=self._view_control))

    def _create_button_labels(self):
        self._button_labels = ButtonLabelsComponent(
            is_enabled=False,
            layer=Layer(display_lines=b'button_label_display_matrix'))
        self._button_labels.set_enabled(True)

    def _create_record_modes(self):
        self._session_record = SessionRecordingComponent(
            name=b'Session_Record',
            is_enabled=False,
            layer=Layer(record_button=b'record_button'))
        self._record_modes = ModesComponent(name=b'Record_Modes')
        self._record_modes.add_mode(b'session',
                                    EnablingMode(self._session_record))
        self._record_modes.add_mode(
            b'arrange',
            AddLayerMode(self._transport,
                         layer=Layer(record_button=b'record_button')))
        self.__on_main_view_changed()

    def _create_lower_pad_modes(self):
        self._lower_pad_modes = ModesComponent(
            name=b'Lower_Pad_Modes',
            is_enabled=False,
            layer=Layer(cycle_mode_button=b'minus_button'))
        self._lower_pad_modes.add_mode(
            b'select',
            AddLayerMode(self._mixer,
                         Layer(track_select_buttons=b'lower_pads')),
            cycle_mode_button_color=b'Session.StopClipDisabled')
        self._lower_pad_modes.add_mode(
            b'stop',
            AddLayerMode(self._session,
                         Layer(stop_track_clip_buttons=b'lower_pads')),
            cycle_mode_button_color=b'Session.StopClip')
        self._lower_pad_modes.selected_mode = b'select'

    def _create_main_modes(self):
        self._main_modes = ModesComponent(
            name=b'Main_Modes',
            is_enabled=False,
            layer=Layer(song_button=b'song_mode_button',
                        instrument_button=b'instrument_mode_button',
                        editor_button=b'editor_mode_button',
                        user_button=b'user_mode_button'))
        device_params_mode = AddLayerMode(
            self._device_parameters, Layer(parameter_controls=b'encoders'))
        enable_lower_fw_functions = partial(
            self._elements.lower_firmware_toggle_switch.send_value, 1)
        disable_upper_fw_functions = partial(
            self._elements.upper_firmware_toggle_switch.send_value, 0)
        self._main_modes.add_mode(
            b'song',
            (partial(self._elements.lower_firmware_toggle_switch.send_value,
                     0), disable_upper_fw_functions,
             self._elements.display_buttons.reset, self._view_toggle,
             self._launch_and_stop, self._session, self._lower_pad_modes,
             AddLayerMode(self._session.scene(0),
                          Layer(launch_button=b'plus_button')),
             AddLayerMode(
                 self._mixer.selected_strip(),
                 Layer(volume_control=b'encoders_raw[0]',
                       pan_control=b'encoders_raw[1]',
                       send_controls=self._elements.encoders.submatrix[2:, :],
                       solo_button=b'display_buttons_raw[0]',
                       mute_button=b'display_buttons_raw[1]',
                       arm_button=b'display_buttons_raw[2]')),
             AddLayerMode(self._mixer,
                          Layer(crossfader_control=b'touch_strip'))))
        self._main_modes.add_mode(
            b'instrument',
            (enable_lower_fw_functions,
             partial(self._elements.upper_firmware_toggle_switch.send_value,
                     1), device_params_mode))
        self._main_modes.add_mode(
            b'editor',
            (enable_lower_fw_functions, disable_upper_fw_functions,
             device_params_mode, self._device_navigation,
             AddLayerMode(
                 self._device_parameters,
                 Layer(device_lock_button=b'display_buttons_raw[0]',
                       device_on_off_button=b'display_buttons_raw[3]',
                       prev_bank_button=b'display_buttons_raw[4]',
                       next_bank_button=b'display_buttons_raw[5]'))))
        self._main_modes.add_mode(
            b'user', (enable_lower_fw_functions, disable_upper_fw_functions,
                      self._translating_background))
        self._main_modes.selected_mode = b'instrument'
        self._main_modes.set_enabled(True)
        self.__on_main_modes_changed.subject = self._main_modes

    @listens(b'selected_mode')
    def __on_main_modes_changed(self, mode):
        self._button_labels.show_button_labels_for_mode(mode)
        self._elements.track_name_display.clear_send_cache()
        self._elements.device_name_display.clear_send_cache()

    @listens(b'is_view_visible', b'Session')
    def __on_main_view_changed(self):
        if self.application.view.is_view_visible(b'Session'):
            self._record_modes.selected_mode = b'session'
        else:
            self._record_modes.selected_mode = b'arrange'
class Oxygen_Pro(IdentifiableControlSurface):
    session_height = 2
    session_width = 8
    live_mode_byte = midi.LIVE_MODE_BYTE
    pad_ids = ((40, 41, 42, 43, 48, 49, 50, 51), (36, 37, 38, 39, 44, 45, 46, 47))
    device_parameter_component = SimpleDeviceParameterComponent
    has_session_component = True

    def __init__(self, *a, **k):
        (super(Oxygen_Pro, self).__init__)(a, product_id_bytes=midi.M_AUDIO_MANUFACTURER_ID + (0, ), **k)
        self._last_selected_knob_mode = 'device'
        with self.component_guard():
            self._elements = Elements(self.session_height, self.session_width, self.pad_ids)
            with inject(element_container=(const(self._elements))).everywhere():
                self._create_background()
                self._create_transport()
                self._create_undo_redo()
                self._create_session()
                self._create_mixer()
                self._create_device_parameters()
                self._create_record_modes()
                self._create_button_modes()
                self._create_knob_modes()
                self._create_takeover_modes()
        self._Oxygen_Pro__on_main_view_changed.subject = self.application.view

    def on_identified(self, response_bytes):
        self._elements.firmware_mode_switch.send_value(self.live_mode_byte)
        self._elements.control_mode_switch.send_value(midi.RECORD_MODE_BYTE)
        self._elements.control_mode_switch.send_value(midi.DEVICE_MODE_BYTE)
        self._elements.led_control_switch.send_value(midi.LED_ENABLE_BYTE)
        self._elements.led_mode_switch.send_value(midi.SOFTWARE_CONTROL_BYTE)
        self._button_modes.selected_mode = 'arm'
        self._knob_modes.selected_mode = 'device'
        if self.has_session_component:
            self._session_ring.set_enabled(True)
        super(Oxygen_Pro, self).on_identified(response_bytes)

    def port_settings_changed(self):
        if self.has_session_component:
            self._session_ring.set_enabled(False)
        super(Oxygen_Pro, self).port_settings_changed()

    def _create_background(self):
        self._background = BackgroundComponent(name='Background',
          is_enabled=False,
          add_nop_listeners=True,
          layer=Layer(shift_button='shift_button'))
        self._background.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(name='Transport',
          is_enabled=False,
          layer=Layer(loop_button='loop_button',
          stop_button='stop_button',
          play_button='play_button',
          metronome_button='metronome_button',
          seek_forward_button='fastforward_button',
          seek_backward_button='rewind_button'))
        self._transport.set_enabled(True)

    def _create_undo_redo(self):
        self._undo_redo = UndoRedoComponent(name='Undo_Redo',
          is_enabled=False,
          layer=Layer(undo_button='back_button'))
        self._undo_redo.set_enabled(True)

    def _create_session(self):
        self._session_ring = SessionRingComponent(name='Session_Ring',
          is_enabled=False,
          num_tracks=(self.session_width),
          num_scenes=(self.session_height))
        if self.has_session_component:
            self._session = SessionComponent(name='Session',
              is_enabled=False,
              session_ring=(self._session_ring),
              layer=Layer(clip_launch_buttons='pads',
              scene_launch_buttons='scene_launch_buttons',
              selected_scene_launch_button='encoder_push_button',
              scene_encoder='encoder_with_encoder_push'))
            self._session.set_enabled(True)
        self._session_navigation = SessionNavigationComponent(name='Session_Navigation',
          is_enabled=False,
          session_ring=(self._session_ring),
          layer=Layer(left_button='bank_left_button',
          right_button='bank_right_button',
          scene_encoder='encoder'))
        self._session_navigation.set_enabled(True)

    def _create_mixer(self):
        self._mixer = MixerComponent(name='Mixer',
          is_enabled=False,
          auto_name=True,
          channel_strip_component_type=ChannelStripComponent,
          tracks_provider=(self._session_ring),
          track_assigner=(SimpleTrackAssigner()),
          layer=Layer(volume_controls='faders'))
        self._mixer.master_strip().set_volume_control(self._elements.master_fader)
        self._mixer.set_enabled(True)

    def _create_device_parameters(self):
        self._device_parameters = self.device_parameter_component(name='Device_Parameters',
          is_enabled=False,
          layer=Layer(parameter_controls='knobs'))

    def _create_record_modes(self):
        self._session_record = SessionRecordingComponent(name='Session_Record',
          is_enabled=False,
          layer=Layer(record_button='record_button'))
        self._record_modes = ModesComponent(name='Record_Modes')
        self._record_modes.add_mode('session', EnablingMode(self._session_record))
        self._record_modes.add_mode('arrange', AddLayerMode((self._transport), layer=Layer(record_button='record_button')))
        self._Oxygen_Pro__on_main_view_changed()

    def _create_button_modes(self):
        self._button_modes = ModesComponent(name='Button_Modes',
          is_enabled=False,
          layer=Layer(off_button='off_mode_button',
          arm_button='arm_mode_button',
          track_select_button='track_select_mode_button',
          mute_button='mute_mode_button',
          solo_button='solo_mode_button'))
        self._button_modes.add_mode('off', None, behaviour=(ImmediateBehaviour()))
        self._button_modes.add_mode('arm',
          AddLayerMode((self._mixer), layer=Layer(arm_buttons='fader_buttons')),
          behaviour=(ImmediateBehaviour()))
        self._button_modes.add_mode('track_select',
          AddLayerMode((self._mixer), layer=Layer(track_select_buttons='fader_buttons')),
          behaviour=(ImmediateBehaviour()))
        self._button_modes.add_mode('mute',
          AddLayerMode((self._mixer), layer=Layer(mute_buttons='fader_buttons')),
          behaviour=(ImmediateBehaviour()))
        self._button_modes.add_mode('solo',
          AddLayerMode((self._mixer), layer=Layer(solo_buttons='fader_buttons')),
          behaviour=(ImmediateBehaviour()))
        self._button_modes.selected_mode = 'arm'
        self._button_modes.set_enabled(True)

    def _create_knob_modes(self):
        self._knob_modes = ModesComponent(name='Knob_Modes',
          is_enabled=False,
          layer=Layer(volume_button='volume_mode_button',
          pan_button='pan_mode_button',
          sends_button='sends_mode_button',
          device_button='device_mode_button'))
        self._knob_modes.add_mode('volume',
          AddLayerMode((self._mixer), layer=Layer(volume_controls='knobs')),
          behaviour=(ImmediateBehaviour()))
        self._knob_modes.add_mode('pan',
          AddLayerMode((self._mixer), layer=Layer(pan_controls='knobs')),
          behaviour=(ImmediateBehaviour()))
        self._knob_modes.add_mode('sends',
          AddLayerMode((self._mixer), layer=Layer(send_controls='knobs')),
          behaviour=ReenterBehaviour(on_reenter=(self._on_reenter_sends_mode)))
        self._knob_modes.add_mode('device',
          (self._device_parameters), behaviour=(self._get_device_mode_behaviour()))
        self._knob_modes.add_mode('takeover', None)
        self._knob_modes.selected_mode = 'device'
        self._Oxygen_Pro__on_knob_mode_changed.subject = self._knob_modes
        self._knob_modes.set_enabled(True)

    def _get_device_mode_behaviour(self):
        return ImmediateBehaviour()

    def _on_reenter_sends_mode(self):
        new_send_index = 1 if self._mixer.send_index == 0 else 0
        if new_send_index in range(self._mixer.num_sends):
            self._mixer.send_index = new_send_index

    def _create_takeover_modes(self):
        self._takeover_modes = ModesComponent(name='Takeover_Modes',
          is_enabled=False,
          layer=Layer(daw_button='daw_mode_button', preset_button='preset_mode_button'))
        self._takeover_modes.add_mode('daw', self._select_knob_mode)
        self._takeover_modes.add_mode('preset', (
         self._select_knob_mode,
         AddLayerMode((self._background),
           layer=Layer(faders='faders', knobs='knobs'))))
        self._takeover_modes.selected_mode = 'daw'
        self._takeover_modes.set_enabled(True)

    def _select_knob_mode(self):
        if self._takeover_modes.selected_mode == 'daw':
            self._knob_modes.selected_mode = self._last_selected_knob_mode
        else:
            self._knob_modes.selected_mode = 'takeover'

    @listens('selected_mode')
    def __on_knob_mode_changed(self, mode):
        if mode != 'takeover':
            self._last_selected_knob_mode = mode

    @listens('is_view_visible', 'Session')
    def __on_main_view_changed(self):
        if self.application.view.is_view_visible('Session'):
            self._record_modes.selected_mode = 'session'
        else:
            self._record_modes.selected_mode = 'arrange'
class Launchpad_Pro_MK3(InstrumentControlMixin, NovationBase):
    model_family_code = ids.LP_PRO_MK3_FAMILY_CODE
    element_class = Elements
    session_class = SessionComponent
    mixer_class = MixerComponent
    channel_strip_class = ChannelStripComponent
    skin = skin
    suppress_layout_switch = False
    track_recording_class = FixedLengthTrackRecordingComponent

    def __init__(self, *a, **k):
        self._layout_to_restore = None
        self._can_restore_layout = False
        self._last_layout_bytes = ids.SESSION_LAYOUT_BYTES
        super(Launchpad_Pro_MK3, self).__init__(*a, **k)

    def disconnect(self):
        super(Launchpad_Pro_MK3, self).disconnect()
        self._auto_arm.set_enabled(False)
        self._elements.scale_feedback_switch.send_value(Rgb.GREEN.midi_value)

    def on_identified(self, midi_bytes):
        self._elements.firmware_mode_switch.send_value(sysex.DAW_MODE_BYTE)
        self._elements.layout_switch.send_value(self._last_layout_bytes)
        self._target_track_changed()
        self._drum_group_changed()
        self.set_feedback_channels(
            [DRUM_FEEDBACK_CHANNEL, SCALE_FEEDBACK_CHANNEL])
        self._setup_faders()
        super(Launchpad_Pro_MK3, self).on_identified(midi_bytes)

    def port_settings_changed(self):
        self._auto_arm.set_enabled(False)
        super(Launchpad_Pro_MK3, self).port_settings_changed()

    def _setup_faders(self):
        for i, fader_mode in enumerate(FADER_MODES):
            orientation, polarity = (
                sysex.FADER_HORIZONTAL_ORIENTATION,
                sysex.FADER_BIPOLAR) if fader_mode == u'pan' else (
                    sysex.FADER_VERTICAL_ORIENTATION, sysex.FADER_UNIPOLAR)
            self._elements.fader_setup_element.send_value(
                i, orientation, polarity)

    def _create_components(self):
        self._fixed_length_setting = FixedLengthSetting()
        self._fixed_length_recording = FixedLengthRecording(
            self.song, self._fixed_length_setting)
        with inject(fixed_length_recording=const(
                self._fixed_length_recording)).everywhere():
            super(Launchpad_Pro_MK3, self)._create_components()
            self._create_recording_modes()
        self._create_session_overview()
        self._create_auto_arm()
        self._create_background()
        self._create_device_navigation()
        self._create_device_parameters()
        self._create_print_to_clip()
        self._create_undo_redo()
        self._create_transport()
        self._create_clip_actions()
        self._create_quantization()
        self._create_fixed_length()
        self._create_drum_group()
        self._create_scale_pad_translator()
        self._create_mixer_modes()
        self._create_session_modes()
        self._create_note_modes()
        self._create_main_modes()
        self.__on_layout_switch_value.subject = self._elements.layout_switch

    def _create_session_overview(self):
        self._session_overview = SessionOverviewComponent(
            name=u'Session_Overview',
            is_enabled=False,
            session_ring=self._session_ring,
            enable_skinning=True,
            layer=Layer(button_matrix=u'clip_launch_matrix'))

    def _create_auto_arm(self):
        self._auto_arm = AutoArmComponent(name=u'Auto_Arm', is_enabled=False)

    def _create_background(self):
        self._background = BackgroundComponent(
            name=u'Background',
            is_enabled=False,
            add_nop_listeners=True,
            layer=Layer(clear_button=u'clear_button',
                        duplicate_button=u'duplicate_button',
                        quantize_button=u'quantize_button',
                        scene_launch_buttons=u'scene_launch_buttons',
                        priority=-1) +
            Layer(
                duplicate_button_with_shift=u'duplicate_button_with_shift',
                track_select_buttons_with_shift=
                u'track_select_buttons_with_shift',
                up_button_with_shift=u'up_button_with_shift',
                down_button_with_shift=u'down_button_with_shift',
                left_button_with_shift=u'left_button_with_shift',
                right_button_with_shift=u'right_button_with_shift',
                double_button=u'duplicate_button_with_shift',
                clear_button_with_shift=u'clear_button_with_shift',
                volume_button_with_shift=u'volume_button_with_shift',
                pan_button_with_shift=u'pan_button_with_shift',
                sends_button_with_shift=u'sends_button_with_shift',
                device_button_with_shift=u'device_button_with_shift',
                stop_clip_button_with_shift=u'stop_clip_button_with_shift',
                fixed_length_button_with_shift=u'fixed_length_button_with_shift'
            ))
        self._background.set_enabled(True)

    def _create_print_to_clip(self):
        self._print_to_clip = PrintToClipComponent(
            name=u'Print_To_Clip',
            is_enabled=False,
            layer=Layer(
                print_to_clip_control=u'print_to_clip_element',
                print_to_clip_enabler=u'print_to_clip_enabler_element'))
        self._print_to_clip.set_enabled(True)

    def _create_undo_redo(self):
        self._undo_redo = UndoRedoComponent(
            name=u'Undo_Redo',
            is_enabled=False,
            layer=Layer(undo_button=u'record_arm_button_with_shift',
                        redo_button=u'mute_button_with_shift'))
        self._undo_redo.undo_button.color = u'Action.Undo'
        self._undo_redo.undo_button.pressed_color = u'Action.UndoPressed'
        self._undo_redo.redo_button.color = u'Action.Redo'
        self._undo_redo.redo_button.pressed_color = u'Action.RedoPressed'
        self._undo_redo.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(
            name=u'Transport',
            is_enabled=False,
            layer=Layer(play_button=u'play_button',
                        continue_playing_button=u'play_button_with_shift',
                        metronome_button=u'solo_button_with_shift',
                        capture_midi_button=u'record_button_with_shift',
                        tap_tempo_button=u'sends_button_with_shift'))
        self._transport.tap_tempo_button.color = u'Transport.TapTempo'
        self._transport.set_enabled(True)

    def _create_clip_actions(self):
        self._clip_actions = ClipActionsComponent(
            name=u'Clip_Actions',
            is_enabled=False,
            layer=Layer(duplicate_button=u'duplicate_button',
                        quantize_button=u'quantize_button',
                        double_loop_button=u'duplicate_button_with_shift'))

    def _create_quantization(self):
        self._quantization = QuantizationComponent(
            name=u'Quantization',
            is_enabled=False,
            layer=Layer(
                quantization_toggle_button=u'quantize_button_with_shift'))
        self._quantization.set_enabled(True)
        ClipActionsComponent.quantization_component = self._quantization
        ClipSlotComponent.quantization_component = self._quantization

    def _create_fixed_length(self):
        self._fixed_length = FixedLengthComponent(
            fixed_length_setting=self._fixed_length_setting,
            name=u'Fixed_Length',
            is_enabled=False,
            layer=Layer(fixed_length_button=u'fixed_length_button'))
        self._fixed_length.settings_component.layer = Layer(
            length_option_buttons=u'track_select_buttons')
        self._fixed_length.set_enabled(True)

    def _create_drum_group(self):
        self._drum_group = DrumGroupComponent(
            self._clip_actions,
            name=u'Drum_Group',
            is_enabled=False,
            translation_channel=DRUM_FEEDBACK_CHANNEL,
            layer=Layer(matrix=u'drum_pads'))
        self._drum_group.set_enabled(True)

    def _create_device_parameters(self):
        self._device_parameters = SimpleDeviceParameterComponent(
            name=u'Device_Parameters',
            is_enabled=False,
            device_bank_registry=self._device_bank_registry,
            layer=Layer(
                parameter_controls=u'device_button_faders',
                static_color_controls=u'device_button_fader_color_elements',
                stop_fader_control=u'stop_fader_element'),
            static_color_value=Rgb.DARK_BLUE.midi_value)
        self._device_parameters.set_enabled(True)

    def _create_device_navigation(self):
        self._device_navigation = SimpleDeviceNavigationComponent(
            name=u'Device_Navigation')

    def _create_scale_pad_translator(self):
        self._scale_pad_translator = ConfigurablePlayableComponent(
            SCALE_FEEDBACK_CHANNEL,
            name=u'Scale_Pads',
            is_enabled=False,
            layer=Layer(matrix=u'scale_pads'))
        self._scale_pad_translator.set_enabled(True)

    def _create_mixer_modes(self):
        self._mixer_modes = ModesComponent(
            name=u'Mixer_Modes',
            is_enabled=False,
            enable_skinning=True,
            layer=Layer(arm_button=u'record_arm_button',
                        mute_button=u'mute_button',
                        solo_button=u'solo_button',
                        volume_button=u'volume_button',
                        pan_button=u'pan_button',
                        sends_button=u'sends_button',
                        device_button=u'device_button',
                        stop_button=u'stop_clip_button'))
        self._mixer.layer = Layer(volume_controls=u'volume_button_faders',
                                  pan_controls=u'pan_button_faders',
                                  send_controls=u'sends_button_faders')
        reselect_track_select_mode = partial(setattr, self._mixer_modes,
                                             u'selected_mode', u'track_select')

        def restore_main_layout():
            if self._can_restore_layout and self._layout_to_restore:
                self._elements.layout_switch.send_value(
                    self._layout_to_restore)

        def add_track_select_button_mode(name,
                                         control=None,
                                         component=self._mixer):
            control_key = control if control else u'{}_buttons'.format(name)
            control_dict = {control_key: u'track_select_buttons'}
            self._mixer_modes.add_mode(
                name, (AddLayerMode(component, Layer(**control_dict)),
                       DelayMode(restore_main_layout, delay=0.1)),
                behaviour=ReenterBehaviour(
                    on_reenter=reselect_track_select_mode))

        add_track_select_button_mode(u'track_select')
        add_track_select_button_mode(u'arm')
        add_track_select_button_mode(u'mute')
        add_track_select_button_mode(u'solo')
        add_track_select_button_mode(u'stop',
                                     control=u'stop_track_clip_buttons',
                                     component=self._session)

        def switch_to_fader_layout(bank):
            fader_layout_bytes = (ids.FADER_LAYOUT_BYTE, bank, 0)
            self._elements.layout_switch.send_value(fader_layout_bytes)

        def add_fader_mode(name, bank, add_layer_mode, static_color=None):
            self._mixer_modes.add_mode(
                name,
                (add_layer_mode,
                 AddLayerMode(
                     self._mixer,
                     Layer(track_select_buttons=u'track_select_buttons')),
                 partial(self._mixer._update_send_control_colors),
                 partial(self._mixer.set_static_color_value,
                         static_color), partial(switch_to_fader_layout, bank)),
                behaviour=ReenterBehaviour(
                    on_reenter=reselect_track_select_mode))

        add_fader_mode(
            u'volume',
            0,
            AddLayerMode(
                self._mixer,
                Layer(
                    static_color_controls=u'volume_button_fader_color_elements'
                )),
            static_color=Rgb.GREEN.midi_value)
        add_fader_mode(
            u'pan', 1,
            AddLayerMode(
                self._mixer,
                Layer(
                    track_color_controls=u'pan_button_fader_color_elements')))
        add_fader_mode(
            u'sends', 2,
            AddLayerMode(
                self._mixer,
                Layer(send_select_buttons=u'scene_launch_buttons',
                      return_track_color_controls=
                      u'sends_button_fader_color_elements',
                      stop_fader_control=u'stop_fader_element')))
        add_fader_mode(
            u'device', 3,
            (AddLayerMode(
                self._background,
                Layer(up_button=u'up_button', down_button=u'down_button')),
             AddLayerMode(
                 self._device_navigation,
                 Layer(prev_button=u'left_button',
                       next_button=u'right_button')),
             AddLayerMode(self._device_parameters,
                          Layer(bank_select_buttons=u'scene_launch_buttons'))))
        self._mixer_modes.selected_mode = u'track_select'
        self._mixer_modes.set_enabled(True)

    def _create_session_modes(self):
        self._session_modes = ModesComponent(
            name=u'Session_Modes',
            is_enabled=False,
            layer=Layer(overview_button=u'session_mode_button'))
        self._session_modes.add_mode(
            u'launch',
            AddLayerMode(
                self._session,
                Layer(managed_select_button=u'shift_button',
                      managed_delete_button=u'clear_button',
                      managed_duplicate_button=u'duplicate_button',
                      managed_quantize_button=u'quantize_button',
                      managed_double_button=u'duplicate_button_with_shift',
                      scene_launch_buttons=u'scene_launch_buttons')))
        self._session_modes.add_mode(
            u'overview', (self._session_overview,
                          AddLayerMode(
                              self._session_navigation,
                              Layer(page_up_button=u'up_button',
                                    page_down_button=u'down_button',
                                    page_left_button=u'left_button',
                                    page_right_button=u'right_button'))),
            behaviour=MomentaryBehaviour())
        self._session_modes.selected_mode = u'launch'

    def _create_note_modes(self):
        self._note_modes = ModesComponent(name=u'Note_Modes', is_enabled=False)
        self._note_modes.add_mode(
            u'scale',
            AddLayerMode(self._clip_actions,
                         Layer(delete_button=u'clear_button')))
        self._note_modes.add_mode(
            u'drum',
            AddLayerMode(
                self._drum_group,
                Layer(scroll_up_button=u'left_button',
                      scroll_down_button=u'right_button',
                      scroll_page_up_button=u'up_button',
                      scroll_page_down_button=u'down_button',
                      delete_button=u'clear_button')))

    def _create_main_modes(self):
        self._main_modes = ModesComponent(name=u'Main_Modes', is_enabled=False)
        suppressed_arrow_button_mode = (AddLayerMode(
            self._background,
            Layer(left_button=u'left_button',
                  right_button=u'right_button',
                  up_button=u'up_button',
                  down_button=u'down_button')), )
        self._main_modes.add_mode(u'none', suppressed_arrow_button_mode)
        self._main_modes.add_mode(u'fader', None)
        self._main_modes.add_mode(u'session', self._session_modes)
        self._main_modes.add_mode(u'note',
                                  (self._note_modes, self._clip_actions))
        self._main_modes.add_mode(u'chord', suppressed_arrow_button_mode)
        self._main_modes.selected_mode = u'session'
        self._main_modes.set_enabled(True)
        self.__on_main_mode_changed.subject = self._main_modes

    @listens(u'selected_mode')
    def __on_main_mode_changed(self, mode):
        if mode == u'session':
            self._session_modes.selected_mode = u'launch'
        self._recording_modes.selected_mode = u'session' if mode == u'session' else u'track'
        self._update_controlled_track()
        self._auto_arm.set_enabled(self._is_instrument_mode())

    @listens(u'value')
    def __on_layout_switch_value(self, value):
        self._can_restore_layout = value[0] in LIVE_LAYOUT_BYTES
        if not self._can_restore_layout:
            return
        if value[0] == ids.FADER_LAYOUT_BYTE:
            self._main_modes.selected_mode = u'fader'
        else:
            self._layout_to_restore = value
            if self._mixer_modes.selected_mode in FADER_MODES:
                self._mixer_modes.selected_mode = u'track_select'
            if value in LAYOUT_BYTES_TO_MODE_NAMES_MAP:
                self._main_modes.selected_mode = LAYOUT_BYTES_TO_MODE_NAMES_MAP[
                    value]
            else:
                self._main_modes.selected_mode = u'none'
        self._last_layout_bytes = value

    def _drum_group_changed(self):
        drum_group = self._drum_group_finder.drum_group
        drum_group_valid = liveobj_valid(drum_group)
        self._drum_group.set_drum_group_device(drum_group)
        self._elements.layout_switch.send_value(
            ids.DRUM_LAYOUT_BYTES if drum_group_valid else ids.
            SCALE_LAYOUT_BYTES)
        self._note_modes.selected_mode = u'drum' if drum_group_valid else u'scale'

    def _is_instrument_mode(self):
        return self._main_modes.selected_mode in NOTE_MODE_NAMES

    def _feedback_velocity_changed(self, feedback_velocity):
        self._elements.scale_feedback_switch.send_value(feedback_velocity)
Exemple #4
0
class ATOM(ControlSurface):
    def __init__(self, *a, **k):
        super(ATOM, self).__init__(*a, **k)
        with self.component_guard():
            with inject(skin=const(skin)).everywhere():
                self._elements = Elements()
        with self.component_guard():
            with inject(element_container=const(self._elements)).everywhere():
                self._create_lighting()
                self._create_transport()
                self._create_record_modes()
                self._create_undo()
                self._create_view_toggle()
                self._create_background()
                self._create_session()
                self._create_mixer()
                self._create_encoder_modes()
                self._create_session_navigation_modes()
                self._create_keyboard()
                self._create_drum_group()
                self._create_note_modes()
                self._create_pad_modes()
                self._create_user_assignments_mode()
                self._target_track = ArmedTargetTrackComponent(
                    name=u'Target_Track')
                self.__on_target_track_changed.subject = self._target_track
        self._drum_group_finder = self.register_disconnectable(
            PercussionInstrumentFinder(
                device_parent=self._target_track.target_track))
        self.__on_drum_group_changed.subject = self._drum_group_finder
        self.__on_drum_group_changed()
        self.__on_main_view_changed.subject = self.application.view

    def disconnect(self):
        self._send_midi(midi.NATIVE_MODE_OFF_MESSAGE)
        super(ATOM, self).disconnect()

    def port_settings_changed(self):
        self._send_midi(midi.NATIVE_MODE_ON_MESSAGE)
        super(ATOM, self).port_settings_changed()

    def _create_lighting(self):
        self._lighting = LightingComponent(name=u'Lighting',
                                           is_enabled=False,
                                           layer=Layer(
                                               shift_button=u'shift_button',
                                               zoom_button=u'zoom_button'))
        self._lighting.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(
            name=u'Transport',
            is_enabled=False,
            layer=Layer(play_button=u'play_button',
                        loop_button=u'play_button_with_shift',
                        stop_button=u'stop_button',
                        metronome_button=u'click_button'))
        self._transport.set_enabled(True)

    def _create_record_modes(self):
        self._session_record = SessionRecordingComponent(
            name=u'Session_Record',
            is_enabled=False,
            layer=Layer(record_button=u'record_button'))
        self._record_modes = ModesComponent(name=u'Record_Modes')
        self._record_modes.add_mode(u'session', self._session_record)
        self._record_modes.add_mode(
            u'arrange',
            AddLayerMode(self._transport,
                         layer=Layer(record_button=u'record_button')))
        self.__on_main_view_changed()

    def _create_undo(self):
        self._undo = UndoRedoComponent(
            name=u'Undo',
            is_enabled=False,
            layer=Layer(undo_button=u'stop_button_with_shift'))
        self._undo.set_enabled(True)

    def _create_view_toggle(self):
        self._view_toggle = ViewToggleComponent(
            name=u'View_Toggle',
            is_enabled=False,
            layer=Layer(detail_view_toggle_button=u'show_hide_button',
                        main_view_toggle_button=u'preset_button'))
        self._view_toggle.set_enabled(True)

    def _create_background(self):
        self._background = BackgroundComponent(
            name=u'Background',
            is_enabled=False,
            add_nop_listeners=True,
            layer=Layer(set_loop_button=u'set_loop_button',
                        nudge_button=u'nudge_button',
                        bank_button=u'bank_button'))
        self._background.set_enabled(True)

    def _create_session(self):
        self._session_ring = SessionRingComponent(name=u'Session_Ring',
                                                  num_tracks=SESSION_WIDTH,
                                                  num_scenes=SESSION_HEIGHT)
        self._session = SessionComponent(name=u'Session',
                                         session_ring=self._session_ring)
        self._session_navigation = SessionNavigationComponent(
            name=u'Session_Navigation',
            is_enabled=False,
            session_ring=self._session_ring,
            layer=Layer(left_button=u'left_button',
                        right_button=u'right_button'))
        self._session_navigation.set_enabled(True)
        self._session_overview = SessionOverviewComponent(
            name=u'Session_Overview',
            is_enabled=False,
            session_ring=self._session_ring,
            enable_skinning=True,
            layer=Layer(button_matrix=u'pads_with_zoom'))

    def _create_mixer(self):
        self._mixer = MixerComponent(
            name=u'Mixer',
            auto_name=True,
            tracks_provider=self._session_ring,
            track_assigner=SimpleTrackAssigner(),
            invert_mute_feedback=True,
            channel_strip_component_type=ChannelStripComponent)

    def _create_encoder_modes(self):
        self._encoder_modes = ModesComponent(name=u'Encoder_Modes',
                                             enable_skinning=True)
        self._encoder_modes.add_mode(
            u'volume',
            AddLayerMode(self._mixer, Layer(volume_controls=u'encoders')))
        self._encoder_modes.add_mode(
            u'pan', AddLayerMode(self._mixer, Layer(pan_controls=u'encoders')))
        self._encoder_modes.add_mode(
            u'send_a',
            AddLayerMode(self._mixer, Layer(send_a_controls=u'encoders')))
        self._encoder_modes.add_mode(
            u'send_b',
            AddLayerMode(self._mixer, Layer(send_b_controls=u'encoders')))
        self._encoder_modes.selected_mode = u'volume'

    def _create_session_navigation_modes(self):
        self._session_navigation_modes = ModesComponent(
            name=u'Session_Navigation_Modes',
            is_enabled=False,
            layer=Layer(cycle_mode_button=u'bank_button'))
        self._session_navigation_modes.add_mode(
            u'default',
            AddLayerMode(self._session_navigation,
                         layer=Layer(up_button=u'up_button',
                                     down_button=u'down_button')),
            cycle_mode_button_color=u'DefaultButton.Off')
        self._session_navigation_modes.add_mode(
            u'paged',
            AddLayerMode(self._session_navigation,
                         layer=Layer(page_up_button=u'up_button',
                                     page_down_button=u'down_button',
                                     page_left_button=u'left_button',
                                     page_right_button=u'right_button')),
            cycle_mode_button_color=u'DefaultButton.On')
        self._session_navigation_modes.selected_mode = u'default'

    def _create_keyboard(self):
        self._keyboard = KeyboardComponent(
            midi.KEYBOARD_CHANNEL,
            name=u'Keyboard',
            is_enabled=False,
            layer=Layer(matrix=u'pads',
                        scroll_up_button=u'up_button',
                        scroll_down_button=u'down_button'))

    def _create_drum_group(self):
        self._drum_group = DrumGroupComponent(
            name=u'Drum_Group',
            is_enabled=False,
            translation_channel=midi.DRUM_CHANNEL,
            layer=Layer(matrix=u'pads',
                        scroll_page_up_button=u'up_button',
                        scroll_page_down_button=u'down_button'))

    def _create_note_modes(self):
        self._note_modes = ModesComponent(name=u'Note_Modes', is_enabled=False)
        self._note_modes.add_mode(u'keyboard', self._keyboard)
        self._note_modes.add_mode(u'drum', self._drum_group)
        self._note_modes.selected_mode = u'keyboard'

    def _create_pad_modes(self):
        self._pad_modes = ModesComponent(
            name=u'Pad_Modes',
            is_enabled=False,
            layer=Layer(session_button=u'full_level_button',
                        note_button=u'note_repeat_button',
                        channel_button=u'select_button',
                        encoder_modes_button=u'setup_button'))
        self._pad_modes.add_mode(
            u'session',
            (AddLayerMode(self._background,
                          Layer(unused_pads=u'pads_with_shift')),
             AddLayerMode(
                 self._session,
                 Layer(clip_launch_buttons=u'pads',
                       scene_launch_buttons=self._elements.pads_with_shift.
                       submatrix[3:, :])), self._session_overview,
             self._session_navigation_modes))
        self._pad_modes.add_mode(u'note', self._note_modes)
        self._pad_modes.add_mode(
            u'channel',
            (self._elements.pads.reset,
             AddLayerMode(
                 self._mixer,
                 Layer(
                     arm_buttons=self._elements.pads.submatrix[:, :1],
                     solo_buttons=self._elements.pads.submatrix[:, 1:2],
                     track_select_buttons=self._elements.pads.submatrix[:,
                                                                        2:3])),
             AddLayerMode(
                 self._session,
                 Layer(stop_track_clip_buttons=self._elements.pads.
                       submatrix[:, 3:])), self._session_navigation_modes))
        self._pad_modes.add_mode(
            u'encoder_modes',
            (LayerMode(
                self._encoder_modes,
                Layer(volume_button=self._elements.pads_raw[0][0],
                      pan_button=self._elements.pads_raw[0][1],
                      send_a_button=self._elements.pads_raw[0][2],
                      send_b_button=self._elements.pads_raw[0][3])),
             AddLayerMode(
                 self._background,
                 Layer(unused_pads=self._elements.pads.submatrix[:, 1:]))),
            behaviour=MomentaryBehaviour())
        self._pad_modes.selected_mode = u'session'
        self._pad_modes.set_enabled(True)

    def _create_user_assignments_mode(self):
        self._translating_background = TranslatingBackgroundComponent(
            midi.USER_CHANNEL,
            name=u'Translating_Background',
            is_enabled=False,
            add_nop_listeners=True,
            layer=Layer(note_repeat_button=u'note_repeat_button',
                        full_level_button=u'full_level_button',
                        bank_button=u'bank_button',
                        preset_button=u'preset_button',
                        show_hide_button=u'show_hide_button',
                        nudge_button=u'nudge_button',
                        set_loop_button=u'set_loop_button',
                        setup_button=u'setup_button',
                        up_button=u'up_button',
                        down_button=u'down_button',
                        left_button=u'left_button',
                        right_button=u'right_button',
                        select_button=u'select_button',
                        click_button=u'click_button',
                        record_button=u'record_button',
                        play_button=u'play_button',
                        stop_button=u'stop_button',
                        pads=u'pads',
                        encoders=u'encoders'))
        self._top_level_modes = ModesComponent(
            name=u'Top_Level_Modes',
            is_enabled=False,
            support_momentary_mode_cycling=False,
            layer=Layer(cycle_mode_button=u'editor_button'))
        self._top_level_modes.add_mode(
            u'default',
            self.refresh_state,
            cycle_mode_button_color=u'DefaultButton.Off')
        self._top_level_modes.add_mode(
            u'user',
            self._translating_background,
            cycle_mode_button_color=u'DefaultButton.On')
        self._top_level_modes.selected_mode = u'default'
        self._top_level_modes.set_enabled(True)

    @listens(u'is_view_visible', u'Session')
    def __on_main_view_changed(self):
        if self.application.view.is_view_visible(u'Session'):
            self._record_modes.selected_mode = u'session'
        else:
            self._record_modes.selected_mode = u'arrange'

    @listens(u'target_track')
    def __on_target_track_changed(self):
        self._drum_group_finder.device_parent = self._target_track.target_track

    @listens(u'instrument')
    def __on_drum_group_changed(self):
        drum_group = self._drum_group_finder.drum_group
        self._drum_group.set_drum_group_device(drum_group)
        self._note_modes.selected_mode = u'drum' if liveobj_valid(
            drum_group) else u'keyboard'
class Oxygen_Pro(ControlSurface):
    def __init__(self, *a, **k):
        super(Oxygen_Pro, self).__init__(*a, **k)
        with self.component_guard():
            self._elements = Elements()
            with inject(element_container=const(self._elements)).everywhere():
                self._create_transport()
                self._create_undo_redo()
                self._create_device_parameters()
                self._create_session()
                self._create_mixer()
                self._create_record_modes()
        self.__on_main_view_changed.subject = self.application.view

    def _create_transport(self):
        self._transport = TransportComponent(name=u'Transport',
                                             is_enabled=False,
                                             layer=Layer(
                                                 loop_button=u'loop_button',
                                                 stop_button=u'stop_button',
                                                 play_button=u'play_button'))
        self._transport.set_enabled(True)

    def _create_undo_redo(self):
        self._undo_redo = UndoRedoComponent(
            name=u'Undo_Redo',
            is_enabled=False,
            layer=Layer(undo_button=u'back_button'))
        self._undo_redo.set_enabled(True)

    def _create_device_parameters(self):
        self._device_parameters = SimpleDeviceParameterComponent(
            name=u'Device_Parameters',
            is_enabled=False,
            layer=Layer(parameter_controls=u'knobs'))
        self._device_parameters.set_enabled(True)

    def _create_session(self):
        self._session_ring = SessionRingComponent(name=u'Session_Ring',
                                                  num_tracks=SESSION_WIDTH,
                                                  num_scenes=SESSION_HEIGHT)
        self._session = SessionComponent(
            name=u'Session',
            is_enabled=False,
            session_ring=self._session_ring,
            layer=Layer(clip_launch_buttons=u'pads',
                        scene_launch_buttons=u'scene_launch_buttons',
                        scene_encoder=u'encoder'))
        self._session.selected_scene().set_launch_button(
            self._elements.encoder_push_button)
        self._session.set_enabled(True)
        self._session_navigation = SessionNavigationComponent(
            name=u'Session_Navigation',
            is_enabled=False,
            session_ring=self._session_ring,
            layer=Layer(left_button=u'bank_left_button',
                        right_button=u'bank_right_button'))
        self._session_navigation.set_up_button(self._elements.rewind_button)
        self._session_navigation.set_down_button(
            self._elements.fastforward_button)
        self._session_navigation.set_enabled(True)

    def _create_mixer(self):
        self._mixer = MixerComponent(name=u'Mixer',
                                     is_enabled=False,
                                     auto_name=True,
                                     tracks_provider=self._session_ring,
                                     track_assigner=SimpleTrackAssigner(),
                                     layer=Layer(volume_controls=u'faders',
                                                 arm_buttons=u'fader_buttons'))
        self._mixer.master_strip().set_volume_control(
            self._elements.master_fader)
        self._mixer.set_enabled(True)

    def _create_record_modes(self):
        self._session_record = SessionRecordingComponent(
            name=u'Session_Record',
            is_enabled=False,
            layer=Layer(record_button=u'record_button'))
        self._record_modes = ModesComponent(name=u'Record_Modes')
        self._record_modes.add_mode(u'session',
                                    EnablingMode(self._session_record))
        self._record_modes.add_mode(
            u'arrange',
            AddLayerMode(self._transport,
                         layer=Layer(record_button=u'record_button')))
        self.__on_main_view_changed()

    @listens(u'is_view_visible', u'Session')
    def __on_main_view_changed(self):
        if self.application.view.is_view_visible(u'Session'):
            self._record_modes.selected_mode = u'session'
        else:
            self._record_modes.selected_mode = u'arrange'
Exemple #6
0
class Launchkey_MK3(InstrumentControlMixin, NovationBase):
    element_class = Elements
    session_height = SESSION_HEIGHT
    mixer_class = MixerComponent
    channel_strip_class = ChannelStripComponent
    skin = skin
    suppress_layout_switch = False

    def __init__(self, *a, **k):
        self._is_small_model = False
        self._last_pad_layout_byte = midi.PAD_SESSION_LAYOUT
        self._last_pot_layout_byte = None
        self._last_fader_layout_byte = midi.VOLUME_LAYOUT
        super(Launchkey_MK3, self).__init__(*a, **k)

    def disconnect(self):
        self._elements.pad_layout_switch.send_value(midi.PAD_DRUM_LAYOUT)
        self._auto_arm.set_enabled(False)
        super(Launchkey_MK3, self).disconnect()

    def on_identified(self, midi_bytes):
        if self._last_pot_layout_byte is None:
            self._last_pot_layout_byte = midi.VOLUME_LAYOUT if self._is_small_model else midi.PAN_LAYOUT
            self._pot_modes.selected_mode = u'volume' if self._is_small_model else u'pan'
        self._elements.incontrol_mode_switch.send_value(midi.INCONTROL_ONLINE_VALUE)
        self._elements.pad_layout_switch.send_value(self._last_pad_layout_byte)
        self._elements.pot_layout_switch.send_value(self._last_pot_layout_byte)
        if not self._is_small_model:
            self._elements.fader_layout_switch.send_value(self._last_fader_layout_byte)
        self._target_track_changed()
        self._drum_group_changed()
        self._auto_arm.set_enabled(True)
        self.set_feedback_channels([DRUM_FEEDBACK_CHANNEL])
        super(Launchkey_MK3, self).on_identified(midi_bytes)

    def port_settings_changed(self):
        self._auto_arm.set_enabled(False)
        super(Launchkey_MK3, self).port_settings_changed()

    def _create_components(self):
        super(Launchkey_MK3, self)._create_components()
        self.register_slot(self._elements.incontrol_mode_switch, nop, u'value')
        self._create_auto_arm()
        self._create_background()
        self._create_notification()
        self._create_view_control()
        self._create_transport()
        self._create_recording_modes()
        self._create_undo()
        self._create_quantization()
        self._create_device()
        self._create_drum_group()
        self._pot_modes = self._create_pot_or_fader_modes(u'pot')
        self._create_stop_solo_mute_modes()
        self._create_pad_modes()
        if not self._is_small_model:
            self._fader_modes = self._create_pot_or_fader_modes(u'fader')
            self._setup_master_fader()
            self._create_fader_button_modes()

    def _setup_master_fader(self):
        strip = self._mixer.master_strip()
        strip.set_volume_control(self._elements.master_fader)
        strip.volume_display.set_control_element(self._elements.master_fader_parameter_value_display)
        self._elements.master_fader_parameter_name_display.display_message(u'Master Volume')

    def _create_session_navigation_layer(self):
        return Layer(up_button=u'up_button', down_button=u'down_button')

    def _create_session_layer(self):
        return super(Launchkey_MK3, self)._create_session_layer() + Layer(scene_launch_buttons=u'scene_launch_buttons')

    def _create_auto_arm(self):
        self._auto_arm = AutoArmComponent(name=u'Auto_Arm', is_enabled=False)

    def _create_background(self):
        self._background = BackgroundComponent(name=u'Background', is_enabled=False, add_nop_listeners=True, layer=Layer(secondary_up_button=u'secondary_up_button', secondary_down_button=u'secondary_down_button', device_select_button=u'device_select_button', unused_matrix=self._elements.device_select_matrix.submatrix[:, 1:], pot_parameter_name_displays=u'pot_parameter_name_displays', pot_parameter_value_displays=u'pot_parameter_value_displays', fader_parameter_name_displays=u'fader_parameter_name_displays', fader_parameter_value_displays=u'fader_parameter_value_displays'))
        self._background.set_enabled(True)

    def _create_notification(self):
        self._notification_component = NotificationComponent(name=u'Notifications', is_enabled=False, layer=Layer(display_lines=u'notification_display'))
        self._notification_component.set_enabled(True)

    def _create_view_control(self):
        self._view_control = NotifyingViewControlComponent(name=u'Track_Scroller', is_enabled=False, track_provider=self._session_ring, layer=Layer(prev_track_button=u'left_button', next_track_button=u'right_button'))
        self._view_control.set_enabled(True)
        self._session_ring_selection_linking = self.register_disconnectable(SessionRingSelectionLinking(session_ring=self._session_ring, selection_changed_notifier=self._view_control))

    def _create_transport(self):
        self._transport = TransportComponent(name=u'Transport', is_enabled=False, layer=Layer(play_button=u'play_button', alt_stop_button=u'stop_button', loop_button=u'loop_button', metronome_button=u'click_button', capture_midi_button=u'capture_midi_button'))
        self._transport.set_enabled(True)

    def _create_undo(self):
        self._undo = UndoRedoComponent(name=u'Undo', is_enabled=False, layer=Layer(undo_button=u'undo_button'))
        self._undo.set_enabled(True)

    def _create_quantization(self):
        self._quantization = QuantizationComponent(name=u'Quantization')
        self._clip_actions = ClipActionsComponent(name=u'Clip_Actions', is_enabled=False, layer=Layer(quantize_button=u'quantize_button'))
        self._clip_actions.set_enabled(True)
        ClipActionsComponent.quantization_component = self._quantization

    def _create_device(self):
        self._device = DeviceComponent(name=u'Device', is_enabled=False, show_notification=self._notification_component.show_notification, device_bank_registry=self._device_bank_registry, toggle_lock=self.toggle_lock, use_parameter_banks=True, layer=Layer(device_lock_button=u'device_lock_button'))
        self._device.set_enabled(True)

    def _create_drum_group(self):
        self._drum_group = DrumGroupComponent(name=u'Drum_Group', is_enabled=False, translation_channel=DRUM_FEEDBACK_CHANNEL, layer=Layer(matrix=u'drum_pads', scroll_page_up_button=u'up_button', scroll_page_down_button=u'down_button'))

    def _create_pot_or_fader_modes(self, modes_type_name):
        modes = ModesComponent(name=u'{}_Modes'.format(modes_type_name.title()), is_enabled=False, layer=Layer(mode_selection_control=u'{}_layout_switch'.format(modes_type_name)))
        elements_name = u'{}s'.format(modes_type_name)
        name_displays_element_name = u'{}_parameter_name_displays'.format(modes_type_name)
        value_displays_element_name = u'{}_parameter_value_displays'.format(modes_type_name)

        def add_pot_or_fader_mixer_mode(parameter_name):
            modes.add_mode(parameter_name, (partial(getattr(self._mixer, u'set_{}_parameter_name'.format(modes_type_name)), parameter_name.replace(u'_', u' ').title()), AddLayerMode(self._mixer, Layer(**{u'{}_controls'.format(parameter_name): elements_name,
              u'{}_parameter_name_displays'.format(modes_type_name): name_displays_element_name,
              u'{}_displays'.format(parameter_name): value_displays_element_name}))))

        modes.add_mode(u'dummy', None)
        add_pot_or_fader_mixer_mode(u'volume')
        modes.add_mode(u'device', AddLayerMode(self._device, Layer(parameter_controls=elements_name, parameter_name_displays=name_displays_element_name, parameter_value_displays=value_displays_element_name)))
        if modes_type_name == u'pot':
            add_pot_or_fader_mixer_mode(u'pan')
        else:
            modes.add_mode(u'pan', None)
        add_pot_or_fader_mixer_mode(u'send_a')
        add_pot_or_fader_mixer_mode(u'send_b')
        for i in range(4):
            modes.add_mode(u'custom{}'.format(i), None)

        modes.selected_mode = u'pan' if modes_type_name == u'pot' else u'volume'
        modes.set_enabled(True)
        self.register_slot(modes, getattr(self, u'_on_{}_mode_byte_changed'.format(modes_type_name)), u'mode_byte')
        return modes

    def _create_fader_button_modes(self):
        self._fader_button_modes = ModesComponent(name=u'Fader_Modes', is_enabled=False, support_momentary_mode_cycling=False, layer=Layer(cycle_mode_button=u'fader_button_modes_button'))
        self._fader_button_modes.add_mode(u'arm', AddLayerMode(self._mixer, Layer(arm_buttons=u'fader_buttons')), cycle_mode_button_color=u'DefaultButton.Off')
        self._fader_button_modes.add_mode(u'track_select', AddLayerMode(self._mixer, Layer(track_select_buttons=u'fader_buttons')), cycle_mode_button_color=u'DefaultButton.On')
        self._fader_button_modes.selected_mode = u'arm'
        self._fader_button_modes.set_enabled(True)

    def _create_stop_solo_mute_modes(self):
        self._stop_solo_mute_modes = ModesComponent(name=u'Stop_Solo_Mute_Modes', is_enabled=False, support_momentary_mode_cycling=False)
        lower_matrix_row = self._elements.clip_launch_matrix.submatrix[:, 1:]
        self._stop_solo_mute_modes.add_mode(u'launch', None, cycle_mode_button_color=u'Mode.Launch.On')
        self._stop_solo_mute_modes.add_mode(u'stop', AddLayerMode(self._session, Layer(stop_track_clip_buttons=lower_matrix_row)), cycle_mode_button_color=u'Session.StopClip')
        self._stop_solo_mute_modes.add_mode(u'solo', AddLayerMode(self._mixer, Layer(solo_buttons=lower_matrix_row)), cycle_mode_button_color=u'Mixer.SoloOn')
        self._stop_solo_mute_modes.add_mode(u'mute', AddLayerMode(self._mixer, Layer(mute_buttons=lower_matrix_row)), cycle_mode_button_color=u'Mixer.MuteOff')
        self._stop_solo_mute_modes.selected_mode = u'launch'
        self._stop_solo_mute_modes.set_enabled(True)
        self.__on_stop_solo_mute_mode_changed.subject = self._stop_solo_mute_modes

    def _create_pad_modes(self):
        self._pad_modes = ModesComponent(name=u'Pad_Modes', is_enabled=False, layer=Layer(mode_selection_control=u'pad_layout_switch'))
        suppress_scene_launch_buttons = AddLayerMode(self._background, layer=Layer(scene_launch_buttons=u'scene_launch_buttons'))
        suppress_all_buttons_around_pads = AddLayerMode(self._background, layer=Layer(scene_launch_buttons=u'scene_launch_buttons', up_button=u'up_button', down_button=u'down_button'))
        self._pad_modes.add_mode(u'dummy', suppress_all_buttons_around_pads)
        self._pad_modes.add_mode(u'drum', (suppress_scene_launch_buttons, self._drum_group))
        self._pad_modes.add_mode(u'session', LayerMode(self._stop_solo_mute_modes, layer=Layer(cycle_mode_button=self._elements.scene_launch_buttons_raw[1])))
        for i in range(6):
            self._pad_modes.add_mode(u'custom{}'.format(i), suppress_all_buttons_around_pads)

        upper_matrix_row = self._elements.device_select_matrix.submatrix[:, :1]
        self._pad_modes.add_mode(u'device_select', (suppress_scene_launch_buttons, self._device.show_device_name_and_bank, AddLayerMode(self._device, layer=Layer(bank_select_buttons=upper_matrix_row, prev_button=u'up_button', next_button=u'down_button'))))
        self._pad_modes.selected_mode = u'session'
        self._pad_modes.set_enabled(True)
        self.__on_pad_mode_changed.subject = self._pad_modes
        self.__on_pad_mode_byte_changed.subject = self._pad_modes

    @listens(u'selected_mode')
    def __on_pad_mode_changed(self, mode):
        self._recording_modes.selected_mode = u'track' if mode == u'drum' else u'session'
        self._update_controlled_track()

    @listens(u'selected_mode')
    def __on_stop_solo_mute_mode_changed(self, mode):
        if mode:
            self._notification_component.show_notification(u'Lower Pad Mode', mode.title())

    @listens(u'mode_byte')
    def __on_pad_mode_byte_changed(self, mode_byte):
        self._last_pad_layout_byte = mode_byte

    def _on_pot_mode_byte_changed(self, mode_byte):
        self._last_pot_layout_byte = mode_byte

    def _on_fader_mode_byte_changed(self, mode_byte):
        self._last_fader_layout_byte = mode_byte

    def _drum_group_changed(self):
        self._drum_group.set_drum_group_device(self._drum_group_finder.drum_group)

    def _target_track_changed(self):
        super(Launchkey_MK3, self)._target_track_changed()
        self._notification_component.show_notification(u'Track', self._target_track.target_track.name)

    def _is_instrument_mode(self):
        return self._pad_modes.selected_mode == u'drum'

    def _extract_product_id_bytes(self, midi_bytes):
        u""" Extends standard to deal with each model having a different ID byte, determine
        whether the model is one of the small models and compose the target product ID
        bytes based on the bytes that were received. """
        id_bytes = super(Launchkey_MK3, self)._extract_product_id_bytes(midi_bytes)
        model_id_byte = id_bytes[3]
        if id_bytes[:3] == sysex.NOVATION_MANUFACTURER_ID and model_id_byte in midi.MODEL_ID_BYTES and id_bytes[4:] == midi.MODEL_ID_BYTE_SUFFIX:
            self._is_small_model = model_id_byte in midi.SMALL_MODEL_ID_BYTES
            self._product_id_bytes = sysex.NOVATION_MANUFACTURER_ID + id_bytes[3:]
        return id_bytes