def __init__(self,
              real_time_mapper=None,
              register_real_time_data=None,
              *a,
              **k):
     super(CompressorDeviceComponent, self).__init__(*a, **k)
     self._input_channel_router, self._input_type_router = self.register_disconnectables(
         [
             mixin(CompressorInputRouterMixin,
                   InputChannelRouter)(song=self.song),
             mixin(CompressorInputRouterMixin,
                   InputTypeRouter)(song=self.song)
         ])
     self._input_router = self.register_disconnectable(
         InputChannelAndPositionRouter(
             input_channel_router=self._input_channel_router,
             input_type_router=self._input_type_router))
     self._type_list = self.register_disconnectable(
         RoutingTypeList(parent_task_group=self._tasks,
                         router=self._input_type_router))
     self._channel_list = self.register_disconnectable(
         RoutingChannelList(
             parent_task_group=self._tasks,
             rt_channel_assigner=RoutingMeterRealTimeChannelAssigner(
                 real_time_mapper=real_time_mapper,
                 register_real_time_data=register_real_time_data,
                 parent=self),
             router=self._input_router))
     self._positions_list = self.register_disconnectable(
         RoutingChannelPositionList(
             input_channel_router=self._input_router))
示例#2
0
 def _init_browse_mode(self):
     self._main_modes.add_mode('browse', [
         self._when_track_is_not_frozen(
             self._enable_stop_mute_solo_as_modifiers,
             partial(self._view_control.show_view, 'Browser'),
             self._browser_back_to_top, self._browser_hotswap_mode,
             self._browser_mode, self._browser_reset_load_memory)
     ],
                               groups=['add_effect', 'add_track', 'browse'],
                               behaviour=mixin(DynamicBehaviourMixin,
                                               CancellableBehaviour)
                               (lambda: not self._browser_hotswap_mode._mode
                                .can_hotswap() and 'add_effect_left'))
     self._main_modes.add_mode(
         'add_effect_right', [
             self._when_track_is_not_frozen(
                 self._enable_stop_mute_solo_as_modifiers,
                 self._browser_back_to_top,
                 LazyComponentMode(self._create_create_device_right))
         ],
         behaviour=mixin(ExcludingBehaviourMixin,
                         CancellableBehaviour)(['add_track', 'browse']),
         groups=['add_effect'])
     self._main_modes.add_mode(
         'add_effect_left', [
             self._when_track_is_not_frozen(
                 self._enable_stop_mute_solo_as_modifiers,
                 self._browser_back_to_top,
                 LazyComponentMode(self._create_create_device_left))
         ],
         behaviour=mixin(ExcludingBehaviourMixin,
                         CancellableBehaviour)(['add_track', 'browse']),
         groups=['add_effect'])
     self._main_modes.add_mode(
         'add_instrument_track', [
             self._enable_stop_mute_solo_as_modifiers,
             self._browser_back_to_top,
             LazyComponentMode(self._create_create_instrument_track)
         ],
         behaviour=mixin(ExcludingBehaviourMixin, AlternativeBehaviour)(
             excluded_groups=['browse', 'add_effect'],
             alternative_mode='add_default_track'),
         groups=['add_track'])
     self._main_modes.add_mode('add_default_track', [
         self._enable_stop_mute_solo_as_modifiers,
         self._browser_back_to_top,
         LazyComponentMode(self._create_create_default_track)
     ],
                               groups=['add_track'])
     self._main_modes.add_effect_right_button.mode_unselected_color = self._main_modes.add_effect_left_button.mode_unselected_color = self._main_modes.add_instrument_track_button.mode_unselected_color = 'DefaultButton.On'
 def auto_arm_restore_behaviour(self, *extra_classes, **extra_params):
     if not self._auto_arm_restore_behaviour:
         self._auto_arm_restore_behaviour = mixin(
             AutoArmRestoreBehaviour, *extra_classes)(auto_arm=self,
                                                      **extra_params)
     else:
         raise not extra_params and not extra_classes or AssertionError
     return self._auto_arm_restore_behaviour
示例#4
0
def create_text_display_line(v_position):
    display = mixin(CachingControlElement, ConfigurablePhysicalDisplayElement)(v_position=v_position, width_in_chars=DISPLAY_LINE_WIDTH, num_segments=NUM_DISPLAY_LINE_SEGMENTS, name=('Text_Display_{}').format(v_position))
    display.set_message_parts(sysex.SET_PROPERTY_MSG_HEADER, (
     sysex.SYSEX_END_BYTE,))
    for index in xrange(NUM_DISPLAY_LINE_SEGMENTS):
        display.segment(index).set_position_identifier((index,))

    return display
示例#5
0
 def auto_arm_restore_behaviour(self, *extra_classes, **extra_params):
     if not self._auto_arm_restore_behaviour:
         self._auto_arm_restore_behaviour = mixin(
             AutoArmRestoreBehaviour, *extra_classes)(auto_arm=self,
                                                      **extra_params)
     else:
         pass
     return self._auto_arm_restore_behaviour
示例#6
0
def create_selection_field(h_position, v_position):
    sysex_identifier = sysex.SET_PROPERTY_MSG_HEADER + (
        h_position, sysex.VALUE_PROPERTY_BYTE, v_position)
    return mixin(CachingControlElement, SysexElement)(
        sysex_identifier=sysex_identifier,
        send_message_generator=lambda v: sysex_identifier +
        (v, sysex.SYSEX_END_BYTE),
        default_value=0,
        name=('Selection_Field_{}_{}').format(h_position, v_position))
示例#7
0
def create_display_color_element(h_position, v_position, name, **k):
    sysex_identifier = sysex.SET_PROPERTY_MSG_HEADER + (
        h_position, sysex.COLOR_PROPERTY_BYTE, v_position)
    return mixin(CachingControlElement, ColorSysexElement)(
        sysex_identifier=sysex_identifier,
        send_message_generator=(lambda v: sysex_identifier +
                                (v, sysex.SYSEX_END_BYTE)),
        default_value=0,
        name=name,
        **k)
示例#8
0
    def __init__(self, *a, **k):
        super(Elements, self).__init__(*a, **k)
        self.display_up_button = create_button(81, 'Display_Up_Button')
        self.display_down_button = create_button(82, 'Display_Down_Button')
        self.up_button = create_button(85, 'Up_Button')
        self.down_button = create_button(86, 'Down_Button')
        self.mixer_up_button = create_button(87, 'Mixer_Up_Button')
        self.mixer_down_button = create_button(88, 'Mixer_Down_Button')
        self.grid_button = create_button(89, 'Grid_Button')
        self.options_button = create_button(90, 'Options_Button')
        self.shift_button = create_button(91,
                                          'Shift_Button',
                                          resource_type=PrioritizedResource)
        self.duplicate_button = create_button(92, 'Duplicate_Button')
        self.clear_button = create_button(93, 'Clear_Button')
        self.track_left_button = create_button(102, 'Track_Left_Button')
        self.track_right_button = create_button(103, 'Track_Right_Button')
        self.rw_button = create_button(112, 'RW_Button')
        self.ff_button = create_button(113, 'FF_Button')
        self.stop_button = create_button(114, 'Stop_Button')
        self.play_button = create_button(115, 'Play_Button')
        self.loop_button = create_button(116, 'Loop_Button')
        self.record_button = create_button(117, 'Record_Button')

        def with_shift(button):
            return ComboElement(control=button,
                                modifier=self.shift_button,
                                name=('{}_With_Shift').format(button.name))

        self.up_button_with_shift = with_shift(self.up_button)
        self.down_button_with_shift = with_shift(self.down_button)
        self.record_button_with_shift = with_shift(self.record_button)
        self.play_button_with_shift = with_shift(self.play_button)
        self.track_left_button_with_shift = with_shift(self.track_left_button)
        self.track_right_button_with_shift = with_shift(
            self.track_right_button)
        self.duplicate_button_with_shift = with_shift(self.duplicate_button)
        pads_raw = [[
            create_button(offset + col_index,
                          ('Pad_{}_{}').format(col_index, row_index),
                          msg_type=MIDI_NOTE_TYPE)
            for col_index in xrange(SESSION_WIDTH)
        ] for row_index, offset in enumerate((96, 112))]
        self.pads = ButtonMatrixElement(rows=pads_raw, name='Pads')
        self.pads_quadratic = ButtonMatrixElement(rows=[
            pads_raw[0][4:], pads_raw[1][4:], pads_raw[0][:4], pads_raw[1][:4]
        ],
                                                  name='Pads_Quadratic')
        self.pads_flattened = ButtonMatrixElement(
            rows=[pads_raw[0] + pads_raw[1]], name='Pads_Flattened')
        self.shifted_pad_row_1 = ButtonMatrixElement(
            rows=[[with_shift(control) for control in pads_raw[1]]],
            name='Pad_Row_1_With_Shift')
        scene_launch_buttons_raw = [
            create_button(83 + row_index,
                          name=('Scene_Launch_Button_{}').format(row_index))
            for row_index in xrange(SESSION_HEIGHT)
        ]
        self.scene_launch_buttons = ButtonMatrixElement(
            rows=[scene_launch_buttons_raw], name='Scene_Launch_Buttons')
        self.shifted_scene_launch_button_1 = with_shift(
            scene_launch_buttons_raw[1])
        sliders = [
            SpecialFeedbackChannelSliderElement(
                MIDI_CC_TYPE,
                DEFAULT_CHANNEL,
                41 + index,
                name=('Slider_{}').format(index))
            for index in xrange(SESSION_WIDTH)
        ]
        for slider in sliders:
            slider.set_feedback_delay(1)

        self.sliders = ButtonMatrixElement(rows=[sliders], name='Sliders')
        self.slider_leds = ButtonMatrixElement(rows=[[
            create_rgb_led(index + 54, ('Slider_LED_{}').format(index))
            for index in xrange(8)
        ]],
                                               name='Slider_LEDs')
        self.mixer_soft_button_row_0 = ButtonMatrixElement(
            rows=[[
                create_button(identifier,
                              ('Mixer_Soft_Button_{}_0').format(col_index))
                for col_index, identifier in enumerate(
                    xrange(59, 59 + SESSION_WIDTH))
            ]],
            name='Mixer_Soft_Button_Row_0')
        self.mixer_soft_button_row_1 = ButtonMatrixElement(
            rows=[[
                create_button(identifier,
                              ('Mixer_Soft_Button_{}_1').format(col_index))
                for col_index, identifier in enumerate(
                    xrange(59 + SESSION_WIDTH, 59 + SESSION_WIDTH * 2))
            ]],
            name='Mixer_Soft_Button_Row_1')
        self.message_display = SpecialPhysicalDisplayElement(
            width_in_chars=38,
            num_segments=NUM_MESSAGE_SEGMENTS,
            name='Message_Display')
        self.message_display.set_message_parts(sysex.SHOW_MESSAGE_MSG_HEADER,
                                               (sysex.SYSEX_END_BYTE, ))
        self.center_display_1 = mixin(CachingControlElement,
                                      ConfigurablePhysicalDisplayElement)(
                                          v_position=0,
                                          width_in_chars=9,
                                          name='Center_Display_1')
        self.center_display_2 = mixin(CachingControlElement,
                                      ConfigurablePhysicalDisplayElement)(
                                          v_position=1,
                                          width_in_chars=9,
                                          name='Center_Display_2')
        self.mixer_display_1 = mixin(CachingControlElement,
                                     ConfigurablePhysicalDisplayElement)(
                                         v_position=2,
                                         width_in_chars=9,
                                         name='Mixer_Button_Display_1')
        self.mixer_display_2 = mixin(CachingControlElement,
                                     ConfigurablePhysicalDisplayElement)(
                                         v_position=3,
                                         width_in_chars=9,
                                         name='Mixer_Button_Display_2')
        for display in (self.center_display_1, self.center_display_2,
                        self.mixer_display_1, self.mixer_display_2):
            display.set_message_parts(sysex.SET_PROPERTY_MSG_HEADER,
                                      (sysex.SYSEX_END_BYTE, ))
            display.segment(0).set_position_identifier((8, ))

        self.center_color_field = create_display_color_element(
            8, 0, 'Center_Color_Field')
        self.mixer_color_field_1 = create_display_color_element(
            8, 1, 'Mixer_Color_Field_1')
        self.mixer_color_field_2 = create_display_color_element(
            8, 2, 'Mixer_Color_Field_2')
        self.select_buttons_raw = [
            create_button(51 + index, ('Select_Button_{}').format(index))
            for index in xrange(8)
        ]
        self.select_buttons = ButtonMatrixElement(
            rows=[self.select_buttons_raw], name='Select_Buttons')
        self.select_buttons_with_shift_raw = [
            with_shift(button) for button in self.select_buttons_raw
        ]
        self.display_layout_switch = SysexElement(
            name='Display_Layout_Switch',
            send_message_generator=lambda v: sysex.
            SET_SCREEN_LAYOUT_MESSAGE_HEADER + (v, sysex.SYSEX_END_BYTE),
            default_value=sysex.EMPTY_SCREEN_LAYOUT_BYTE,
            optimized=True)
        self.text_display_line_0 = create_text_display_line(0)
        self.text_display_line_1 = create_text_display_line(1)
        self.text_display_line_2 = create_text_display_line(2)
        self.text_display_line_3 = create_text_display_line(3)
        self.text_display_line_5 = create_text_display_line(5)
        self.text_display_line_3_with_shift = with_shift(
            self.text_display_line_3)
        self.text_display_line_5_with_shift = with_shift(
            self.text_display_line_5)
        self.text_display_lines = [
            self.text_display_line_0, self.text_display_line_1,
            self.text_display_line_2, self.text_display_line_3,
            self.text_display_line_5
        ]
        color_field_line_0_raw, self.color_field_line_0 = create_display_color_element_line(
            0)
        color_field_line_1_raw, _ = create_display_color_element_line(1)
        self.color_field_line_2_raw, self.color_field_line_2 = create_display_color_element_line(
            2)
        self.color_field_lines_0_1_flattened = ButtonMatrixElement(
            rows=[color_field_line_0_raw + color_field_line_1_raw],
            name='Color_Field_Lines_0_1_Flattened')
        self.color_field_line_2_with_shift = ButtonMatrixElement(
            rows=[[
                with_shift(color_field)
                for color_field in self.color_field_line_2_raw
            ]],
            name='Color_Field_Line_2_With_Shift')
        selection_field_line_0_raw, _ = create_selection_field_line(0)
        self.selection_field_line_1_raw, self.selection_field_line_1 = create_selection_field_line(
            1)
        self.selection_field_line_2_raw, self.selection_field_line_2 = create_selection_field_line(
            2)
        self.selection_field_lines_0_1_flattened = ButtonMatrixElement(
            rows=[
                selection_field_line_0_raw + self.selection_field_line_1_raw
            ],
            name='Selection_Field_Lines_0_1_Flattened')
        self.selection_field_line_1_with_shift = ButtonMatrixElement(
            rows=[[
                with_shift(field) for field in self.selection_field_line_1_raw
            ]],
            name='Selection_Field_Line_1_With_Shift')
        self.selection_field_line_2_with_shift = ButtonMatrixElement(
            rows=[[
                with_shift(field) for field in self.selection_field_line_2_raw
            ]],
            name='Selection_Field_Line_2_With_Shift')
        encoders = [
            EncoderElement(
                MIDI_CC_TYPE,
                DEFAULT_CHANNEL,
                21 + index,
                map_mode=Live.MidiMap.MapMode.relative_smooth_two_compliment,
                name=('Encoder_{}').format(index)) for index in xrange(8)
        ]
        for encoder in encoders:
            encoder.set_feedback_delay(1)

        self.encoders = ButtonMatrixElement(rows=[encoders], name='Encoders')
        self.encoder_color_fields = ButtonMatrixElement(
            rows=[[
                create_display_color_element(
                    index, 1, ('Encoder_Color_Field_{}').format(index))
                for index in xrange(8)
            ]],
            name='Encoder_Color_Fields')
示例#9
0
def footswitch_row_control(*a, **k):
    c = mixin(FootswitchRowControl, FootswitchControl)
    return c(FootswitchControl, *a, **k)
 def _init_browse_mode(self):
     self._main_modes.add_mode('browse', [self._when_track_is_not_frozen(self._enable_stop_mute_solo_as_modifiers, partial(self._view_control.show_view, 'Browser'), self._browser_back_to_top, self._browser_hotswap_mode, self._browser_mode, self._browser_reset_load_memory)], groups=['add_effect', 'add_track', 'browse'], behaviour=mixin(DynamicBehaviourMixin, CancellableBehaviour)(lambda : not self._browser_hotswap_mode._mode.can_hotswap() and 'add_effect_left'))
     self._main_modes.add_mode('add_effect_right', [self._when_track_is_not_frozen(self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyComponentMode(self._create_create_device_right))], behaviour=mixin(ExcludingBehaviourMixin, CancellableBehaviour)(['add_track', 'browse']), groups=['add_effect'])
     self._main_modes.add_mode('add_effect_left', [self._when_track_is_not_frozen(self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyComponentMode(self._create_create_device_left))], behaviour=mixin(ExcludingBehaviourMixin, CancellableBehaviour)(['add_track', 'browse']), groups=['add_effect'])
     self._main_modes.add_mode('add_instrument_track', [self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyComponentMode(self._create_create_instrument_track)], behaviour=mixin(ExcludingBehaviourMixin, AlternativeBehaviour)(excluded_groups=['browse', 'add_effect'], alternative_mode='add_default_track'), groups=['add_track'])
     self._main_modes.add_mode('add_default_track', [self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyComponentMode(self._create_create_default_track)], groups=['add_track'])
     self._main_modes.add_effect_right_button.mode_unselected_color = self._main_modes.add_effect_left_button.mode_unselected_color = self._main_modes.add_instrument_track_button.mode_unselected_color = 'DefaultButton.On'
示例#11
0
class Launchpad_X(InstrumentControlMixin, NovationBase):
    model_family_code = ids.LP_X_FAMILY_CODE
    element_class = Elements
    channel_strip_class = ChannelStripComponent
    session_recording_class = mixin(SessionRecordingMixin,
                                    SessionRecordingComponent)
    track_recording_class = mixin(SessionRecordingMixin,
                                  TrackRecordingComponent)
    target_track_class = ArmedTargetTrackComponent
    skin = skin

    def __init__(self, *a, **k):
        self._last_layout_byte = sysex.SESSION_LAYOUT_BYTE
        (super(Launchpad_X, self).__init__)(*a, **k)

    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_byte)
        self._target_track_changed()
        self._drum_group_changed()
        self.set_feedback_channels(
            [DRUM_FEEDBACK_CHANNEL, SCALE_FEEDBACK_CHANNEL])
        super(Launchpad_X, self).on_identified(midi_bytes)

    def _create_components(self):
        super(Launchpad_X, self)._create_components()
        self._background = BackgroundComponent(name='Background',
                                               add_nop_listeners=True)
        self._session_layout_mode = partial(
            self._elements.layout_switch.send_value, sysex.SESSION_LAYOUT_BYTE)
        self._create_recording_modes()
        self._create_mixer_modes()
        self._create_session_modes()
        self._create_note_modes()
        self._create_main_modes()
        self._mixer.set_send_controls = nop
        self._Launchpad_X__on_layout_switch_value.subject = self._elements.layout_switch

    def _create_mixer_modes(self):
        self._mixer_modes = ModesComponent(
            name='Mixer_Modes',
            is_enabled=False,
            enable_skinning=True,
            layer=Layer(
                volume_button=(self._elements.scene_launch_buttons_raw[0]),
                pan_button=(self._elements.scene_launch_buttons_raw[1]),
                send_a_button=(self._elements.scene_launch_buttons_raw[2]),
                send_b_button=(self._elements.scene_launch_buttons_raw[3]),
                stop_button=(self._elements.scene_launch_buttons_raw[4]),
                mute_button=(self._elements.scene_launch_buttons_raw[5]),
                solo_button=(self._elements.scene_launch_buttons_raw[6]),
                arm_button=(self._elements.scene_launch_buttons_raw[7])))
        bottom_row = self._elements.clip_launch_matrix.submatrix[:, 7:8]
        select_none_mode = partial(setattr, self._mixer_modes, 'selected_mode',
                                   'none')
        self._mixer_modes.add_mode('none', self._session_layout_mode)
        button_fader_layout_mode = partial(
            self._elements.layout_switch.send_value, sysex.FADERS_LAYOUT_BYTE)

        def add_fader_mode(name, color, is_pan=False):
            control_dict = {'{}_controls'.format(name): 'button_faders'}
            if is_pan:
                control_dict[
                    'track_color_controls'] = 'button_fader_color_elements'
            else:
                control_dict[
                    'static_color_controls'] = 'button_fader_color_elements'
            self._mixer_modes.add_mode(
                name, (partial(
                    self._elements.button_fader_setup_element.send_value,
                    sysex.FADER_HORIZONTAL_ORIENTATION
                    if is_pan else sysex.FADER_VERTICAL_ORIENTATION,
                    sysex.FADER_BIPOLAR if is_pan else sysex.FADER_UNIPOLAR),
                       partial(self._mixer.set_static_color_value, color),
                       self._clear_send_cache_of_button_fader_color_elements,
                       AddLayerMode(self._mixer, Layer(**control_dict)),
                       button_fader_layout_mode),
                behaviour=ReenterBehaviour(on_reenter=select_none_mode))

        add_fader_mode('volume', Rgb.GREEN.midi_value)
        add_fader_mode('pan', 0, True)
        add_fader_mode('send_a', Rgb.VIOLET.midi_value)
        add_fader_mode('send_b', Rgb.DARK_BLUE.midi_value)
        self._mixer_modes.add_mode(
            'stop', (self._session_layout_mode,
                     AddLayerMode(self._session,
                                  Layer(stop_track_clip_buttons=bottom_row))),
            behaviour=ReenterBehaviour(on_reenter=select_none_mode))
        self._mixer_modes.add_mode(
            'mute',
            (self._session_layout_mode,
             AddLayerMode(self._mixer, Layer(mute_buttons=bottom_row))),
            behaviour=ReenterBehaviour(on_reenter=select_none_mode))
        self._mixer_modes.add_mode(
            'solo',
            (self._session_layout_mode,
             AddLayerMode(self._mixer, Layer(solo_buttons=bottom_row))),
            behaviour=ReenterBehaviour(on_reenter=select_none_mode))
        self._mixer_modes.add_mode(
            'arm', (self._session_layout_mode,
                    AddLayerMode(self._mixer, Layer(arm_buttons=bottom_row))),
            behaviour=ReenterBehaviour(on_reenter=select_none_mode))
        self._mixer_modes.selected_mode = 'none'

    def _clear_send_cache_of_button_fader_color_elements(self):
        for element in self._elements.button_fader_color_elements_raw:
            element.clear_send_cache()

    def _create_session_modes(self):
        self._session_overview = SessionOverviewComponent(
            name='Session_Overview',
            is_enabled=False,
            session_ring=(self._session_ring),
            enable_skinning=True,
            layer=Layer(button_matrix='clip_launch_matrix'))
        self._session_modes = SessionModesComponent(
            name='Session_Modes',
            is_enabled=False,
            layer=Layer(
                cycle_mode_button='session_mode_button',
                mode_button_color_control='session_button_color_element'))
        self._session_modes.add_mode(
            'launch',
            AddLayerMode(self._session,
                         Layer(scene_launch_buttons='scene_launch_buttons')))
        self._session_modes.add_mode(
            'mixer', DelayMode(self._mixer_modes, SESSION_MODES_SWITCH_DELAY))
        (self._session_modes.add_mode(
            'overview',
            (self._session_layout_mode, self._session_overview,
             AddLayerMode(
                 self._session_navigation,
                 Layer(page_up_button='up_button',
                       page_down_button='down_button',
                       page_left_button='left_button',
                       page_right_button='right_button')),
             AddLayerMode(
                 self._background,
                 Layer(scene_launch_buttons='scene_launch_buttons')))), )
        self._session_modes.selected_mode = 'launch'

    def _create_note_modes(self):
        self._drum_group = DrumGroupComponent(
            name='Drum_Group',
            is_enabled=False,
            translation_channel=DRUM_FEEDBACK_CHANNEL,
            layer=Layer(matrix='drum_pads',
                        scroll_up_button='left_button',
                        scroll_down_button='right_button',
                        scroll_page_up_button='up_button',
                        scroll_page_down_button='down_button'))
        self._scale_pad_translator = ConfigurablePlayableComponent(
            SCALE_FEEDBACK_CHANNEL,
            name='Scale_Pads',
            is_enabled=False,
            layer=Layer(matrix='scale_pads'))
        self._note_modes = ModesComponent(name='Note_Modes', is_enabled=False)
        self._note_modes.add_mode(
            'scale', (self._scale_pad_translator,
                      AddLayerMode((self._background),
                                   layer=Layer(up_button='up_button',
                                               down_button='down_button',
                                               left_button='left_button',
                                               right_button='right_button'))))
        self._note_modes.add_mode('drum', self._drum_group)
        self._note_modes.selected_mode = 'scale'
        self._Launchpad_X__on_note_mode_changed.subject = self._note_modes

    def _create_main_modes(self):
        self._main_modes = ModesComponent(
            name='Main_Modes',
            is_enabled=False,
            layer=Layer(session_button='session_mode_button',
                        note_button='note_mode_button',
                        custom_button='custom_mode_button'))
        self._main_modes.add_mode('session', (self._session_modes),
                                  behaviour=(ImmediateBehaviour()))
        self._main_modes.add_mode('note', (self._note_modes),
                                  behaviour=(ImmediateBehaviour()))
        self._main_modes.add_mode('custom',
                                  None,
                                  behaviour=(ImmediateBehaviour()))
        self._main_modes.selected_mode = 'session'
        self._main_modes.set_enabled(True)
        self._Launchpad_X__on_main_mode_changed.subject = self._main_modes

    @listens('selected_mode')
    def __on_main_mode_changed(self, mode):
        self._recording_modes.selected_mode = 'track' if mode == 'note' else 'session'
        if mode == 'session':
            self._session_modes.revert_to_main_mode()
        self._update_controlled_track()
        self._elements.layout_switch.enquire_value()

    @listens('selected_mode')
    def __on_note_mode_changed(self, mode):
        if self._note_modes.is_enabled():
            self._update_controlled_track()

    @listens('value')
    def __on_layout_switch_value(self, value):
        self._last_layout_byte = value

    def _drum_group_changed(self):
        drum_group = self._drum_group_finder.drum_group
        drum_groud_valid = liveobj_valid(drum_group)
        self._drum_group.set_drum_group_device(drum_group)
        self._elements.note_layout_switch.send_value(
            sysex.DRUM_LAYOUT_BYTE if drum_groud_valid else sysex.
            SCALE_LAYOUT_BYTE)
        self._note_modes.selected_mode = 'drum' if drum_groud_valid else 'scale'

    def _is_instrument_mode(self):
        return self._main_modes.selected_mode == 'note'

    def _feedback_velocity_changed(self, feedback_velocity):
        self._elements.scale_feedback_switch.send_value(feedback_velocity)
 def auto_arm_restore_behaviour(self, *extra_classes, **extra_params):
     if not self._auto_arm_restore_behaviour:
         self._auto_arm_restore_behaviour = mixin(AutoArmRestoreBehaviour, *extra_classes)(auto_arm=self, **extra_params)
     else:
         raise not extra_params and not extra_classes or AssertionError
     return self._auto_arm_restore_behaviour