def set_enabled(self, enabled):
     if not enabled:
         self._do_implicit_arm(enabled)
     ControlSurfaceComponent.set_enabled(self, enabled)
     ModesComponent.set_enabled(self._modes, enabled)
     if enabled:
         self._do_implicit_arm(enabled)
class Launchpad_Pro(IdentifiableControlSurface, OptimizedControlSurface):

    def __init__(self, c_instance, *a, **k):
        product_id_bytes = consts.MANUFACTURER_ID + consts.DEVICE_CODE
        super(Launchpad_Pro, self).__init__(c_instance=c_instance, product_id_bytes=product_id_bytes, *a, **k)
        self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143
        with self.component_guard():
            self._skin = make_default_skin()
            with inject(skin=const(self._skin)).everywhere():
                self._midimap = MidiMap()
            self._target_track_component = TargetTrackComponent(name='Target_Track')
            self._create_background()
            self._create_global_component()
            self._last_sent_mode_byte = None
            with inject(layout_setup=const(self._layout_setup), should_arm=const(self._should_arm_track)).everywhere():
                self._create_session()
                self._create_recording()
                self._create_actions()
                self._create_drums()
                self._create_mixer()
                self._create_device()
                self._create_modes()
                self._create_m4l_interface()
            self._on_session_record_changed.subject = self.song()
        self.set_highlighting_session_component(self._session)
        self.set_device_component(self._device)
        self._device_selection_follows_track_selection = True
        self._on_session_record_changed()

    def disconnect(self):
        self._send_midi(consts.TURN_OFF_LEDS)
        self._send_midi(consts.QUIT_MESSAGE)
        super(Launchpad_Pro, self).disconnect()

    def _create_background(self):
        self._modifier_background_component = ModifierBackgroundComponent(name='Background_Component', is_enabled=False, layer=Layer(shift_button=self._midimap['Shift_Button']))
        self._shifted_background = BackgroundComponent(name='No_Op_Shifted_Buttons', is_enabled=False, layer=Layer(click_bitton=self._midimap.with_shift('Click_Button'), delete_button=self._midimap.with_shift('Delete_Button'), duplicate_button=self._midimap.with_shift('Duplicate_Button'), double_button=self._midimap.with_shift('Double_Loop_Button'), session_record_button=self._midimap.with_shift('Session_Record_Button')))

    def _create_global_component(self):
        self._actions_component = ActionsComponent(name='Global_Actions', is_enabled=False, layer=Layer(undo_button=self._midimap['Undo_Button'], redo_button=self._midimap.with_shift('Undo_Button'), metronome_button=self._midimap['Click_Button'], quantization_on_button=self._midimap.with_shift('Quantize_Button')))

    def _create_session(self):
        self._session = SessionComponent(NUM_TRACKS, NUM_SCENES, auto_name=True, is_enabled=False, enable_skinning=True, layer=Layer(track_bank_left_button=self._midimap['Arrow_Left_Button'], track_bank_right_button=self._midimap['Arrow_Right_Button'], scene_bank_up_button=self._midimap['Arrow_Up_Button'], scene_bank_down_button=self._midimap['Arrow_Down_Button']))
        self._session.set_enabled(True)
        self._session.set_rgb_mode(CLIP_COLOR_TABLE, RGB_COLOR_TABLE)
        SpecialClipSlotComponent.quantization_component = self._actions_component
        for scene_index in xrange(NUM_SCENES):
            scene = self._session.scene(scene_index)
            scene.layer = Layer(select_button=self._midimap['Shift_Button'], delete_button=self._midimap['Delete_Button'], duplicate_button=self._midimap['Duplicate_Button'])
            for track_index in xrange(NUM_TRACKS):
                slot = scene.clip_slot(track_index)
                slot.layer = Layer(select_button=self._midimap['Shift_Button'], delete_button=self._midimap['Delete_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_loop_button=self._midimap['Double_Loop_Button'], quantize_button=self._midimap['Quantize_Button'])

        self._session_zoom = SessionZoomingComponent(self._session, name='Session_Overview', is_enabled=True, enable_skinning=True)

    def _create_recording(self):
        self._session_record = SpecialSessionRecordingComponent(self._target_track_component, name='Session_Recording', is_enabled=False, layer=Layer(record_button=self._midimap['Session_Record_Button']))

    def _create_actions(self):
        self._clip_actions_component = ClipActionsComponent(self._target_track_component, name='Clip_Actions', is_enabled=False, layer=Layer(duplicate_button=self._midimap['Duplicate_Button'], double_button=self._midimap['Double_Loop_Button'], quantize_button=self._midimap['Quantize_Button']))
        ClipActionsComponent.quantization_component = self._actions_component

    def _create_drums(self):
        self._drum_group_finder = DrumGroupFinderComponent(self._target_track_component, name='Drum_Group_Finder', is_enabled=False, layer=None)
        self._on_drum_group_changed.subject = self._drum_group_finder
        self._drum_group_finder.set_enabled(True)
        self._drum_group = DrumGroupComponent(self._clip_actions_component, name='Drum_Group_Control', translation_channel=consts.DR_MAP_CHANNEL)
        self._drum_group.set_enabled(True)

    def _create_mixer(self):
        self._mixer = SpecialMixerComponent(NUM_TRACKS, auto_name=True, is_enabled=True, invert_mute_feedback=True)
        self._mixer.name = 'Mixer_Control'
        self._session.set_mixer(self._mixer)

    def _create_device(self):
        self._device = SpecialDeviceComponent(name='Device_Control', is_enabled=False)
        self._device_navigation = DeviceNavigationComponent(name='Device_Navigation')
        self._device_background = BackgroundComponent(name='Device_Background_Component')

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

    def _create_translation(self, comp_name, channel, button_layer, should_enable = True, should_reset = True):
        translation_component = TranslationComponent(name=comp_name, translated_channel=channel, should_enable=should_enable, should_reset=should_reset, is_enabled=False, layer=button_layer)
        setattr(self, '_' + comp_name.lower(), translation_component)
        return translation_component

    def _create_modes(self):
        self._modes = ModesComponent(name='Launchpad_Modes', is_enabled=False)
        self._session_layer_mode = AddLayerMode(self._session, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix'], clip_launch_buttons=self._midimap['Main_Button_Matrix'], delete_button=self._midimap['Delete_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_button=self._midimap['Double_Loop_Button'], quantize_button=self._midimap['Quantize_Button']))
        action_button_background = BackgroundComponent(name='No_Op_Buttons')
        self._action_button_background_layer_mode = LayerMode(action_button_background, Layer(delete_button=self._midimap['Delete_Button'], quantize_button=self._midimap['Quantize_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_button=self._midimap['Double_Loop_Button']))
        self._clip_delete_layer_mode = AddLayerMode(self._clip_actions_component, layer=Layer(delete_button=self._midimap['Delete_Button']))
        self._create_session_zooming_modes()
        self._create_session_mode()
        self._create_note_modes()
        self._create_device_mode()
        self._create_user_mode()
        self._create_record_arm_mode()
        self._create_track_select_mode()
        self._create_mute_mode()
        self._create_solo_mode()
        self._create_volume_mode()
        self._create_pan_mode()
        self._create_sends_mode()
        self._create_stop_clips_mode()
        self._modes.layer = Layer(session_mode_button=self._midimap['Session_Mode_Button'], note_mode_button=self._midimap['Note_Mode_Button'], device_mode_button=self._midimap['Device_Mode_Button'], user_mode_button=self._midimap['User_Mode_Button'], record_arm_mode_button=self._midimap['Record_Arm_Mode_Button'], track_select_mode_button=self._midimap['Track_Select_Mode_Button'], mute_mode_button=self._midimap['Mute_Mode_Button'], solo_mode_button=self._midimap['Solo_Mode_Button'], volume_mode_button=self._midimap['Volume_Mode_Button'], pan_mode_button=self._midimap['Pan_Mode_Button'], sends_mode_button=self._midimap['Sends_Mode_Button'], stop_clip_mode_button=self._midimap['Stop_Clip_Mode_Button'])
        self._modes.selected_mode = 'session_mode'
        self._on_layout_changed.subject = self._modes

    def _create_session_zooming_modes(self):
        session_zoom_layer = Layer(button_matrix=self._midimap['Main_Button_Matrix'], nav_left_button=self._midimap['Arrow_Left_Button'], nav_right_button=self._midimap['Arrow_Right_Button'], nav_up_button=self._midimap['Arrow_Up_Button'], nav_down_button=self._midimap['Arrow_Down_Button'])
        session_zooming_layer_mode = LayerMode(self._session_zoom, session_zoom_layer)
        self._session_zooming_manager = SessionZoomingManagerComponent(self._modes, is_enabled=False)
        session_zooming_button_layer_mode = LayerMode(self._session_zooming_manager, Layer(session_zooming_button=self._midimap['Session_Mode_Button']))
        self._prioritized_session_zooming_button_layer_mode = LayerMode(self._session_zooming_manager, Layer(session_zooming_button=self._midimap['Session_Mode_Button'], priority=1))
        self._session_zooming_background = BackgroundComponent(name='Session_Zooming_Background')
        session_zooming_background_layer_mode = LayerMode(self._session_zooming_background, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix'], delete_button=self._midimap['Delete_Button'], quantize_button=self._midimap['Quantize_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_loop_button=self._midimap['Double_Loop_Button']))
        self._modes.add_mode('session_zooming_mode', [self._session_zooming_manager,
         session_zooming_button_layer_mode,
         session_zooming_layer_mode,
         session_zooming_background_layer_mode])
        self._modes.add_mode('prioritized_session_zooming_mode', [partial(self._layout_switch, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         session_zooming_layer_mode,
         session_zooming_background_layer_mode,
         self.update])

    def _create_session_mode(self):
        self._modes.add_mode('session_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE), self._session_layer_mode, self._session.update_navigation_buttons], behaviour=CancelingReenterBehaviour('session_zooming_mode'))

    def _create_note_modes(self):
        note_mode_matrix_translation = self._create_translation('Note_Mode_Matrix_Translation', consts.CHROM_MAP_CHANNEL, Layer(button_matrix=self._midimap['Main_Button_Matrix'], note_button_matrix=self._midimap['Note_Button_Matrix'], drum_matrix=self._midimap['Drum_Button_Matrix'], mixer_button_matrix=self._midimap['Mixer_Button_Matrix']), should_enable=False)
        note_mode_scene_launch_translation = self._create_translation('Note_Mode_Scene_Launch_Translation', consts.CHROM_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        drum_mode_note_matrix_translation = self._create_translation('Drum_Mode_Note_Button_Translation', 0, Layer(note_button_matrix=self._midimap['Note_Button_Matrix']), should_enable=False, should_reset=False)
        drum_group_layer_mode = LayerMode(self._drum_group, layer=Layer(scroll_up_button=self._midimap['Arrow_Left_Button'], scroll_down_button=self._midimap['Arrow_Right_Button'], scroll_page_up_button=self._midimap['Arrow_Up_Button'], scroll_page_down_button=self._midimap['Arrow_Down_Button'], drum_matrix=self._midimap['Drum_Button_Matrix'], select_button=self._midimap['Shift_Button'], delete_button=self._midimap['Delete_Button']))
        self._note_modes = SpecialModesComponent(name='Note_Modes')
        self._note_modes.add_mode('chromatic_mode', [partial(self._layout_setup, consts.NOTE_LAYOUT_SYSEX_BYTE), self._clip_delete_layer_mode, note_mode_matrix_translation])
        self._note_modes.add_mode('drum_mode', [partial(self._layout_setup, consts.DRUM_LAYOUT_SYSEX_BYTE),
         self._setup_drum_group,
         drum_group_layer_mode,
         drum_mode_note_matrix_translation])
        self._note_modes.add_mode('audio_mode', [partial(self._layout_setup, consts.AUDIO_LAYOUT_SYSEX_BYTE), self._clip_delete_layer_mode])
        self._note_modes.set_enabled(False)
        self._modes.add_mode('note_mode', [note_mode_scene_launch_translation,
         self._note_modes,
         self._select_note_mode,
         self._select_target_track,
         self._clip_actions_component,
         self._show_playing_clip,
         self._set_clip_actions_type], behaviour=ReenterBehaviour(self.toggle_detail_view))
        self._session_record.set_modes_component(self._modes)
        self._session_record.set_note_mode_name('note_mode')

    def _create_device_mode(self):
        device_mode_scene_launch_translation = self._create_translation('Device_Mode_Scene_Launch_Translation', consts.DEVICE_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        device_layer_mode = LayerMode(self._device, layer=Layer(parameter_controls=self._midimap['Slider_Button_Matrix']))
        device_nav_layer_mode = LayerMode(self._device_navigation, layer=Layer(device_nav_left_button=self._midimap['Arrow_Left_Button'], device_nav_right_button=self._midimap['Arrow_Right_Button']))
        device_background_layer_mode = LayerMode(self._device_background, layer=Layer(arrow_up_button=self._midimap['Arrow_Up_Button'], arrow_down_button=self._midimap['Arrow_Down_Button']))
        self._modes.add_mode('device_mode', [partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         self._device,
         device_layer_mode,
         device_nav_layer_mode,
         device_background_layer_mode,
         self._clip_actions_component,
         self._clip_delete_layer_mode,
         device_mode_scene_launch_translation,
         self._show_playing_clip,
         self._set_clip_actions_type], behaviour=ReenterBehaviour(self.toggle_detail_view))

    def _create_user_mode(self):
        self._modes.add_mode('user_mode', [partial(self._layout_setup, consts.USER_LAYOUT_SYSEX_BYTE)])

    def _create_record_arm_mode(self):
        arm_layer_mode = LayerMode(self._mixer, layer=Layer(arm_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('record_arm_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         arm_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_track_select_mode(self):
        track_select_layer_mode = LayerMode(self._mixer, layer=Layer(track_select_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('track_select_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         track_select_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_mute_mode(self):
        mute_layer_mode = LayerMode(self._mixer, layer=Layer(mute_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('mute_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         mute_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_solo_mode(self):
        solo_layer_mode = LayerMode(self._mixer, layer=Layer(solo_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('solo_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         solo_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_volume_mode(self):
        volume_mode_scene_launch_translation = self._create_translation('Volume_Mode_Scene_Launch_Translation', consts.VOLUME_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        volume_layer_mode = LayerMode(self._mixer, layer=Layer(volume_controls=self._midimap['Slider_Button_Matrix']))
        self._modes.add_mode('volume_mode', [partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         volume_layer_mode,
         self._action_button_background_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         volume_mode_scene_launch_translation,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_pan_mode(self):
        pan_mode_scene_launch_translation = self._create_translation('Pan_Mode_Scene_Launch_Translation', consts.PAN_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        pan_layer_mode = LayerMode(self._mixer, layer=Layer(pan_controls=self._midimap['Slider_Button_Matrix']))
        self._modes.add_mode('pan_mode', [partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         pan_layer_mode,
         self._action_button_background_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         pan_mode_scene_launch_translation,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_sends_mode(self):
        send_layer_mode = LayerMode(self._mixer, layer=Layer(send_controls=self._midimap['Slider_Button_Matrix'], send_select_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        self._modes.add_mode('sends_mode', [partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         send_layer_mode,
         self._action_button_background_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_stop_clips_mode(self):
        stop_layer_mode = AddLayerMode(self._session, Layer(stop_track_clip_buttons=self._midimap['Mixer_Button_Matrix'], stop_scene_clip_buttons=self._midimap['Scene_Stop_Button_Matrix'], stop_all_clips_button=self._midimap['Stop_All_Clips_Button']))
        self._modes.add_mode('stop_clip_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         stop_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_m4l_interface(self):
        self._m4l_interface = M4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard, priority=1)
        self.get_control_names = self._m4l_interface.get_control_names
        self.get_control = self._m4l_interface.get_control
        self.grab_control = self._m4l_interface.grab_control
        self.release_control = self._m4l_interface.release_control

    def toggle_detail_view(self):
        view = self.application().view
        if view.is_view_visible('Detail'):
            if view.is_view_visible('Detail/DeviceChain'):
                view.show_view('Detail/Clip')
            else:
                view.show_view('Detail/DeviceChain')

    @subject_slot('drum_group')
    def _on_drum_group_changed(self):
        if self._note_modes.selected_mode == 'drum_mode':
            self._drum_group.set_drum_group_device(self._drum_group_finder.drum_group)
        if self._modes.selected_mode == 'note_mode':
            self._select_note_mode()
        else:
            self.release_controlled_track()
        self._update_note_mode_button(self._drum_group_finder.drum_group is not None)

    def _select_note_mode(self):
        """
        Selects which note mode to use depending on the kind of
        current target track and its device chain.  Will also
        select the target if specified.
        """
        track = self._target_track_component.target_track
        drum_device = self._drum_group_finder.drum_group
        if track is None or track.is_foldable or track in self.song().return_tracks or track == self.song().master_track or track.is_frozen or track.has_audio_input:
            self._note_modes.selected_mode = 'audio_mode'
        elif drum_device:
            self._note_modes.selected_mode = 'drum_mode'
        else:
            self._note_modes.selected_mode = 'chromatic_mode'
        self._modes.update()
        if self._note_modes.selected_mode == 'audio_mode':
            self.release_controlled_track()
        else:
            self.set_controlled_track(self._target_track_component.target_track)

    def _select_target_track(self):
        track = self._target_track_component.target_track
        if track != self.song().view.selected_track:
            self.song().view.selected_track = track

    def _update_note_mode_button(self, focused_track_is_drum_track):
        button = self._midimap['Note_Mode_Button']
        if focused_track_is_drum_track:
            button.default_states = {True: 'Mode.Drum.On',
             False: 'Mode.Drum.Off'}
        else:
            button.default_states = {True: 'Mode.Chromatic.On',
             False: 'Mode.Chromatic.Off'}
        button.reset_state()
        self._modes.update()

    def _show_playing_clip(self):
        track = None
        if self._use_sel_track():
            track = self.song().view.selected_track
        else:
            track = self._target_track_component.target_track
        if track in self.song().tracks:
            slot_index = track.fired_slot_index
            if slot_index < 0:
                slot_index = track.playing_slot_index
            if slot_index >= 0:
                clip_slot = track.clip_slots[slot_index]
                self.song().view.highlighted_clip_slot = clip_slot

    def _set_clip_actions_type(self):
        self._clip_actions_component.use_selected_track(self._use_sel_track())
        self._clip_actions_component.update()

    def _use_sel_track(self):
        return self._modes.selected_mode == 'device_mode'

    def _should_arm_track(self):
        return self._modes.selected_mode == 'record_arm_mode'

    @subject_slot('selected_mode')
    def _on_layout_changed(self, mode):
        if mode == 'note_mode':
            self.set_controlled_track(self._target_track_component.target_track)
        else:
            self.release_controlled_track()
        self._session_record.set_enabled(mode != 'user_mode')

    @subject_slot('session_record')
    def _on_session_record_changed(self):
        status = self.song().session_record
        feedback_color = int(self._skin['Instrument.FeedbackRecord'] if status else self._skin['Instrument.Feedback'])
        self._c_instance.set_feedback_velocity(feedback_color)

    def _clear_send_cache(self):
        with self.component_guard():
            for control in self.controls:
                control.clear_send_cache()

    def _update_global_components(self):
        self._actions_component.update()
        self._session_record.update()
        self._modifier_background_component.update()

    def _layout_setup(self, mode):
        self._layout_switch(mode)
        self._clear_send_cache()
        self._update_global_components()

    def _layout_switch(self, mode):
        prefix = consts.SYSEX_STANDARD_PREFIX + consts.SYSEX_PARAM_BYTE_LAYOUT
        suffix = consts.SYSEX_STANDARD_SUFFIX
        self._send_midi(prefix + mode + suffix)
        self._last_sent_mode_byte = mode

    def _send_identity_request(self):
        self._send_midi(consts.SYSEX_IDENTITY_REQUEST)

    def on_identified(self):
        self._send_challenge()

    def _send_challenge(self):
        challenge_bytes = []
        for index in range(4):
            challenge_bytes.append(self._challenge >> 8 * index & 127)

        challenge = consts.CHALLENGE_PREFIX + tuple(challenge_bytes) + (247,)
        self._send_midi(challenge)

    def _on_handshake_successful(self):
        self._do_send_midi(consts.LIVE_MODE_SWITCH_REQUEST)
        with self.component_guard():
            self._modes.set_enabled(True)
            self._actions_component.set_enabled(True)
            self._session_record.set_enabled(True)
            self._modifier_background_component.set_enabled(True)
            self._shifted_background.set_enabled(True)
            self.release_controlled_track()
            self.set_feedback_channels(consts.FEEDBACK_CHANNELS)
        if self._last_sent_mode_byte is not None:
            self._layout_setup(self._last_sent_mode_byte)
        self.update()

    def _is_challenge_response(self, midi_bytes):
        return len(midi_bytes) == 10 and midi_bytes[:7] == consts.SYSEX_STANDARD_PREFIX + consts.SYSEX_CHALLENGE_RESPONSE_BYTE

    def _is_response_valid(self, midi_bytes):
        response = long(midi_bytes[7])
        response += long(midi_bytes[8] << 8)
        return response == Live.Application.encrypt_challenge2(self._challenge)

    def handle_sysex(self, midi_bytes):
        if len(midi_bytes) < 7:
            pass
        if self._is_challenge_response(midi_bytes) and self._is_response_valid(midi_bytes):
            self._on_handshake_successful()
        elif midi_bytes[6] in (consts.SYSEX_STATUS_BYTE_MODE, consts.SYSEX_STATUS_BYTE_LAYOUT):
            pass
        else:
            super(Launchpad_Pro, self).handle_sysex(midi_bytes)
Example #3
0
File: Cntrlr.py Project: aumhaa/mod
class Cntrlr(ControlSurface):
	__module__ = __name__
	__doc__ = " Monomodular controller script for Livid CNTRLR "


	def __init__(self, *a, **k):
		super(Cntrlr, self).__init__(*a, **k)
		self._version_check = 'b996'
		self._host_name = 'Cntrlr'
		self._color_type = 'OhmRGB'
		self._client = [None for index in range(4)]
		self._active_client = None
		self._rgb = 0
		self._timer = 0
		self._touched = 0
		self.flash_status = 1
		self._skin = Skin(CntrlrColors)
		self._device_selection_follows_track_selection = FOLLOW
		with self.component_guard():
			self._setup_monobridge()
			self._setup_controls()
			self._define_sysex()
			self._setup_transport_control()
			self._setup_autoarm()
			self._setup_session_recording_component()
			self._setup_mixer_control()
			self._setup_send_resets()
			self._setup_session_control()
			self._setup_device_control()
			self._setup_device_selector()
			self._setup_translations()
			self._setup_viewcontrol()
			self._setup_mod()
			self._setup_instrument()
			self._setup_modswitcher()
			self._setup_modes() 
			self._setup_m4l_interface()
			self._on_device_changed.subject = self.song()
			self.set_feedback_channels(range(14, 15))
		self._main_modes.selected_mode = 'MixMode'
		self.schedule_message(1, self._open_log)
	

	def _open_log(self):
		self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) + " " + str(self._version_check) + " log opened =>>>>>>>>>>>>>>>>>>>") 
		self.show_message(str(self._host_name) + ' Control Surface Loaded')
	

	def _setup_monobridge(self):
		self._monobridge = MonoBridgeElement(self)
		self._monobridge.name = 'MonoBridge'
	

	def _setup_controls(self):
		is_momentary = True 
		self._fader = [MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, CNTRLR_FADERS[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self) for index in range(8)]
		self._dial_left = [MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, CNTRLR_KNOBS_LEFT[index], Live.MidiMap.MapMode.absolute, 'Dial_Left_' + str(index), CNTRLR_KNOBS_LEFT[index], self) for index in range(12)]
		self._dial_right = [MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, CNTRLR_KNOBS_RIGHT[index], Live.MidiMap.MapMode.absolute, 'Dial_Right_' + str(index), CNTRLR_KNOBS_RIGHT[index], self) for index in range(12)]
		self._encoder = [CodecEncoderElement(MIDI_CC_TYPE, CHANNEL, CNTRLR_DIALS[index], Live.MidiMap.MapMode.absolute, 'Encoder_' + str(index), CNTRLR_DIALS[index], self) for index in range(12)] 
		self._encoder_button = [MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CNTRLR_DIAL_BUTTONS[index], name = 'Encoder_Button_' + str(index), script = self, skin = self._skin) for index in range(12)]	
		self._grid = [MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CNTRLR_GRID[index], name = 'Grid_' + str(index), script = self, skin = self._skin) for index in range(16)]
		self._button = [MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CNTRLR_BUTTONS[index], name = 'Button_' + str(index), script = self, skin = self._skin) for index in range(32)]
		self._knobs = self._dial_left + self._dial_right

		self._fader_matrix = ButtonMatrixElement(name = 'Fader_Matrix', rows = [self._fader])
		self._matrix = ButtonMatrixElement(name = 'Matrix', rows = [self._grid[index*4:(index*4)+4] for index in range(4)])
		self._knob_left_matrix = ButtonMatrixElement(name = 'Knob_Left_Matrix', rows = [self._dial_left[index*4:(index*4)+4] for index in range(3)])
		self._knob_right_matrix = ButtonMatrixElement(name = 'Knob_Right_Matrix', rows = [self._dial_right[index*4:(index*4)+4] for index in range(3)])
		self._dial_matrix = ButtonMatrixElement(name = 'Dial_Matrix', rows = [self._encoder[index*4:(index*4)+4] for index in range(3)])
		self._dial_button_matrix = ButtonMatrixElement(name = 'Dial_Button_Matrix', rows = [self._encoder_button[index*4:(index*4)+4] for index in range(1,3)])
		self._key_matrix = ButtonMatrixElement(name = 'Key_Matrix', rows = [self._button[0:16], self._button[16:32]])
		
		self._translated_controls = self._fader + self._knobs + self._encoder[4:] + self._grid + self._button
	

	def _define_sysex(self):
		self.encoder_navigation_on = SendSysexMode(script = self, sysex = (240, 0, 1, 97, 8, 17, 15, 0, 0, 0, 0, 0, 0, 0, 247))
		self.encoder_navigation_off = SendSysexMode(script = self, sysex = (240, 0, 1, 97, 8, 17, 0, 0, 0, 0, 0, 0, 0, 0, 247))
	

	def _setup_transport_control(self):
		self._transport = CntrlrTransportComponent() 
		self._transport.name = 'Transport'
		self._transport.layer = Layer(priority = 4,
									play_button = self._button[28],
									record_button = self._button[30],
									stop_button = self._button[29])
	

	def _setup_autoarm(self):
		self._auto_arm = AutoArmComponent(name='Auto_Arm')
		self._auto_arm.can_auto_arm_track = self._can_auto_arm_track
	

	def _setup_session_recording_component(self):
		self._clip_creator = ClipCreator()
		self._clip_creator.name = 'ClipCreator'
		self._recorder = CntrlrSessionRecordingComponent(self._clip_creator, ViewControlComponent()) # is_enabled = False)
		self._recorder.layer = Layer(priority = 4, new_button = self._button[28], record_button = self._button[29], automation_button = self._button[30])
		self._recorder.set_enabled(False)
	

	def _setup_mixer_control(self):
		is_momentary = True
		self._num_tracks = (4)
		self._mixer = MixerComponent(num_tracks = 4, num_returns = 2, name = 'Mixer', auto_name = True, invert_mute_feedback = True)
		self._mixer.set_track_offset(0)
		if self._mixer.channel_strip(0)._track:
			self.song().view.selected_track = self._mixer.channel_strip(0)._track
		self._mixer.main_faders_layer = AddLayerMode(self._mixer, Layer(priority = 4,
											volume_controls = self._fader_matrix.submatrix[:4, :],
											return_controls = self._fader_matrix.submatrix[4:6, :],
											prehear_volume_control = self._fader[6],))
		self._mixer.main_buttons_layer = AddLayerMode(self._mixer, Layer(priority = 4, 
											mute_buttons = self._key_matrix.submatrix[:4, 1:],
											arm_buttons = self._key_matrix.submatrix[4:8, :1],
											solo_buttons = self._key_matrix.submatrix[:4, :1],
											track_select_buttons = self._key_matrix.submatrix[4:8, 1:],))
		self._mixer.stop_layer = AddLayerMode(self._mixer, Layer(priority = 4,
											stop_clip_buttons = self._key_matrix.submatrix[8:12, 1:],))
		self._mixer.main_knobs_layer = AddLayerMode(self._mixer, Layer(priority = 4,
											send_controls = self._knob_left_matrix.submatrix[:, :2],
											pan_controls = self._knob_left_matrix.submatrix[:, 2:],
											eq_gain_controls = self._knob_right_matrix))
		self._mixer.master_fader_layer = AddLayerMode(self._mixer.master_strip(), Layer(priority = 4,
											volume_control = self._fader[7]))
		self._mixer.instrument_buttons_layer = AddLayerMode(self._mixer, Layer(priority = 4,
											mute_buttons = self._key_matrix.submatrix[:4, 1:],
											track_select_buttons = self._key_matrix.submatrix[4:8, 1:],))
		self._mixer.dial_nav_layer = AddLayerMode(self._mixer, Layer(priority = 4,
									track_select_dial = self._encoder[3]))
	

	def _setup_send_resets(self):
		self._send_reset = CntrlrResetSendsComponent(self)
		self._send_reset.name = 'Sends_Reset'
		self._send_reset.layer = Layer(buttons = self._key_matrix.submatrix[8:12, :1])
	

	def _setup_session_control(self):
		self._session = CntrlrSessionComponent(num_tracks = 4, num_scenes = 4, name = 'Session', enable_skinning = True, auto_name = True)
		self._session.set_mixer(self._mixer)
		self.set_highlighting_session_component(self._session)
		self._session.layer = Layer(priority = 4, clip_launch_buttons = self._matrix)
		self._session.nav_layer = AddLayerMode(self._session, Layer(priority = 4,
									scene_bank_down_button = self._button[14],
									scene_bank_up_button = self._button[15],
									track_bank_left_button = self._button[12],
									track_bank_right_button = self._button[13]))
		self._session.dial_nav_layer = AddLayerMode(self._session, Layer(priority = 4,
									scene_select_dial = self._encoder[2]))

		self._session_zoom = SessionZoomingComponent(session = self._session, name = 'Session_Overview', enable_skinning = True)  # is_enabled = False)	 #
		self._session_zoom.buttons_layer = AddLayerMode(self._session_zoom, Layer(priority = 4, button_matrix = self._matrix))

		self._session.set_offsets(0, 0)
	

	def _setup_device_control(self):
		self._device_selection_follows_track_selection = FOLLOW
		self._device = DeviceComponent()
		self._device.name = 'Device_Component'
		self._device._is_banking_enabled = self.device_is_banking_enabled(self._device)
		self.set_device_component(self._device)
		self._device.layer = Layer(priority = 4, parameter_controls = self._dial_matrix.submatrix[:, 1:3], 
											lock_button = self._encoder_button[5],
											on_off_button = self._encoder_button[4],
											bank_prev_button = self._encoder_button[6],
											bank_next_button = self._encoder_button[7])

		self._device_navigator = DeviceNavigator(self._device, self._mixer, self)
		self._device_navigator.name = 'Device_Navigator'
		self._device_navigator.layer = Layer(priority = 4, prev_button = self._encoder_button[8], 
											next_button = self._encoder_button[9], 
											prev_chain_button = self._encoder_button[10], 
											next_chain_button = self._encoder_button[11],)
	

	def _setup_device_selector(self):
		self._device_selector = DeviceSelectorComponent(self)  # is_enabled = False)
		self._device_selector.name = 'Device_Selector'
		self._device_selector.layer = Layer(matrix = self._matrix.submatrix[:, :3])
		self._device_selector.set_enabled(False)
	

	def _setup_translations(self):
		self._translations = TranslationComponent(self._translated_controls, user_channel_offset = 4, channel = 4)	# is_enabled = False)
		self._translations.name = 'TranslationComponent'
		self._translations.layer = Layer(priority = 10,)
		self._translations.selector_layer = AddLayerMode(self._translations, Layer(priority = 10, channel_selector_buttons = self._dial_button_matrix))
		self._translations.set_enabled(False)

		self._optional_translations = CompoundMode(TranslationComponent(controls = self._fader, user_channel_offset = 4, channel = 4, name = 'FaderTranslation', is_enabled = False, layer = Layer(priority = 10)) if FADER_BANKING else None, 
														TranslationComponent(controls = self._knobs, user_channel_offset = 4, channel = 4, name = 'DialTranslation', is_enabled = False, layer = Layer(priority = 10)) if DIAL_BANKING else None)
	

	def _setup_mod(self):
		self.monomodular = get_monomodular(self)
		self.monomodular.name = 'monomodular_switcher'
		self.modhandler = CntrlrModHandler(self) # is_enabled = False)
		self.modhandler.name = 'ModHandler' 
		self.modhandler.set_lock_button(self._encoder_button[1])
		self.modhandler.layer = Layer(priority = 8, cntrlr_encoder_grid = self._dial_matrix,
										cntrlr_encoder_button_grid = self._dial_button_matrix,
										cntrlr_grid = self._matrix,
										cntrlr_keys = self._key_matrix,)
										#parameter_controls = self._dial_matrix)
	

	def _setup_instrument(self):
		self._grid_resolution = self.register_disconnectable(GridResolution())
		self._c_instance.playhead.enabled = True
		self._playhead_element = PlayheadElement(self._c_instance.playhead)
		self._playhead_element.reset()

		self._instrument = CntrlrMonoInstrumentComponent(self, self._skin, grid_resolution = self._grid_resolution, name = 'InstrumentModes') # is_enabled = False)
		#self._instrument.layer = Layer(priority = 10, shift_mode_button = self._button[31])
		self._instrument.shift_button_layer = AddLayerMode(self._instrument, Layer(priority = 5, shift_mode_button = self._button[31]))
		self._instrument.audioloop_layer = LayerMode(self._instrument, Layer(priority = 4, loop_selector_matrix = self._key_matrix.submatrix[:, :1]))
		self._instrument.keypad_shift_layer = AddLayerMode(self._instrument, Layer(priority = 4, 
									scale_up_button = self._button[13], 
									scale_down_button = self._button[12],
									offset_up_button = self._button[11], 
									offset_down_button = self._button[10],
									vertical_offset_up_button = self._button[9],
									vertical_offset_down_button = self._button[8],
									split_button = self._button[14],
									sequencer_button = self._button[15]))
		self._instrument.drumpad_shift_layer = AddLayerMode(self._instrument, Layer(priority = 4, 
									scale_up_button = self._button[13],
									scale_down_button = self._button[12],
									drum_offset_up_button = self._button[11], 
									drum_offset_down_button = self._button[10],
									drumpad_mute_button = self._button[9],
									drumpad_solo_button = self._button[8],
									split_button = self._button[14],
									sequencer_button = self._button[15]))
		self._instrument._keypad.main_layer = LayerMode(self._instrument._keypad, Layer(priority = 4, keypad_matrix = self._matrix))
		self._instrument._keypad.sequencer_layer = LayerMode(self._instrument._keypad, Layer(priority = 4, playhead = self._playhead_element, keypad_matrix = self._matrix, sequencer_matrix = self._key_matrix.submatrix[:,:1]))
		self._instrument._keypad.split_layer = LayerMode(self._instrument._keypad, Layer(priority = 4, keypad_matrix = self._matrix, split_matrix = self._key_matrix.submatrix[:8,:1]))
		self._instrument._keypad.sequencer_shift_layer = LayerMode(self._instrument._keypad, Layer(priority = 4, keypad_matrix = self._matrix, loop_selector_matrix = self._key_matrix.submatrix[:8, :1], quantization_buttons = self._key_matrix.submatrix[:7, 1:], follow_button = self._button[23]))
		self._instrument._drumpad.main_layer = LayerMode(self._instrument._drumpad, Layer(priority = 4, drumpad_matrix = self._matrix))
		self._instrument._drumpad.sequencer_layer = LayerMode(self._instrument._drumpad, Layer(priority = 4, playhead = self._playhead_element, drumpad_matrix = self._matrix, sequencer_matrix = self._key_matrix.submatrix[:,:1]))
		self._instrument._drumpad.split_layer = LayerMode(self._instrument._drumpad, Layer(priority = 4, drumpad_matrix = self._matrix, split_matrix = self._key_matrix.submatrix[:8,:1]))
		self._instrument._drumpad.sequencer_shift_layer = LayerMode(self._instrument._drumpad, Layer(priority = 4, drumpad_matrix = self._matrix, loop_selector_matrix = self._key_matrix.submatrix[:8, :1], quantization_buttons = self._key_matrix.submatrix[:7, 1:], follow_button = self._button[23]))
		self._instrument.set_enabled(False)
	

	def _setup_modswitcher(self):
		self._modswitcher = ModesComponent(name = 'ModSwitcher')  # is_enabled = False)
		#self._modswitcher.add_mode('instrument', [self._optional_translations])
		self._modswitcher.add_mode('mod', [self.modhandler, self._optional_translations])
		self._modswitcher.add_mode('instrument', [self._instrument, self._instrument.shift_button_layer, self._optional_translations])
		self._modswitcher.set_enabled(False)
	

	def _setup_viewcontrol(self):
		self._view_control = ViewControlComponent(name='View_Control')# is_enabled = False)
		self._view_control.main_layer = AddLayerMode(self._view_control, Layer(prev_track_button=self._button[24], 
													next_track_button= self._button[25], 
													next_scene_button=self._button[27], 
													prev_scene_button = self._button[26]))
		#self._view_control.set_enabled(False)
		self._view_control.selector_layer = AddLayerMode(self._view_control, Layer(priority = 8, 
													prev_track_button = self._grid[12], 
													next_track_button = self._grid[13], 
													next_scene_button = self._grid[15], 
													prev_scene_button = self._grid[14]))
	

	def _setup_modes(self):
		main_buttons=CompoundMode(self._mixer.main_buttons_layer, self._mixer.stop_layer, self._transport, self._send_reset, self._session.nav_layer)
		main_buttons_instrument=CompoundMode(self._mixer.main_buttons_layer, self._recorder, self._view_control.main_layer)
		main_faders=CompoundMode(self._mixer.main_faders_layer, self._mixer.master_fader_layer)
		bottom_buttons=CompoundMode(self._mixer.instrument_buttons_layer, self._recorder, self._view_control.main_layer)

		self._instrument._main_modes = ModesComponent(name = 'InstrumentModes')
		self._instrument._main_modes.add_mode('disabled', [main_buttons_instrument, main_faders, self._mixer.main_knobs_layer, self._device, self._session, self._recorder, self._view_control.main_layer, self._send_reset, self._session.nav_layer,])
		self._instrument._main_modes.add_mode('drumpad', [self._instrument._drumpad.main_layer, main_buttons_instrument, self._send_reset, self._session.nav_layer])
		self._instrument._main_modes.add_mode('drumpad_split', [self._instrument._drumpad.split_layer, self._send_reset, self._session.nav_layer])
		self._instrument._main_modes.add_mode('drumpad_sequencer', [self._instrument._drumpad.sequencer_layer, bottom_buttons])
		self._instrument._main_modes.add_mode('drumpad_shifted', [self._instrument._drumpad.main_layer, self._instrument.drumpad_shift_layer, main_buttons_instrument, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('drumpad_split_shifted', [self._instrument._drumpad.split_layer, self._instrument.drumpad_shift_layer, bottom_buttons, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('drumpad_sequencer_shifted', [self._instrument._drumpad.sequencer_shift_layer, self._instrument.drumpad_shift_layer, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('keypad', [self._instrument._keypad.main_layer, main_buttons_instrument, self._send_reset, self._session.nav_layer])
		self._instrument._main_modes.add_mode('keypad_split', [self._instrument._keypad.split_layer, bottom_buttons, self._send_reset, self._session.nav_layer])
		self._instrument._main_modes.add_mode('keypad_sequencer', [self._instrument._keypad.sequencer_layer, bottom_buttons])
		self._instrument._main_modes.add_mode('keypad_shifted', [self._instrument._keypad.main_layer, self._instrument.keypad_shift_layer, main_buttons_instrument, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('keypad_split_shifted', [self._instrument._keypad.split_layer, self._instrument.keypad_shift_layer, bottom_buttons, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('keypad_sequencer_shifted', [self._instrument._keypad.sequencer_shift_layer, self._instrument.keypad_shift_layer, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('audioloop', [self._instrument.audioloop_layer, self._session, bottom_buttons, self._recorder, self._view_control.main_layer])
		self._instrument.register_component(self._instrument._main_modes)
		self._instrument.set_enabled(False)

		self._session_modes = ModesComponent(name = 'SessionModes', is_enabled = False)
		self._session_modes.add_mode('Session', [self._session])
		self._session_modes.add_mode('SessionZoom', [self._session_zoom.buttons_layer], behaviour = BicoloredMomentaryBehaviour(color = 'Session.ZoomOn', off_color = 'Session.ZoomOff'))
		self._session_modes.layer = Layer(priority = 4, SessionZoom_button = self._button[31])
		self._session_modes.selected_mode = 'Session'

		self._main_modes = ModesComponent(name = 'MainModes')
		self._main_modes.add_mode('MixMode', [main_buttons, main_faders, self._mixer.main_knobs_layer, self._device, self._session_modes, self._session.nav_layer,])  # self._session.dial_nav_layer, self._mixer.dial_nav_layer, self.encoder_navigation_on])
		self._main_modes.add_mode('ModSwitcher', [main_faders, self._mixer.main_knobs_layer, self._modswitcher], behaviour = DefaultedBehaviour(default_mode = 'MixMode', color = 'ModeButtons.ModSwitcher', off_color = 'ModeButtons.ModSwitcherDisabled'))
		self._main_modes.add_mode('Translations', [main_faders, self._mixer.main_knobs_layer, self._translations, DelayMode(self._translations.selector_layer)], behaviour = DefaultedBehaviour(default_mode = 'MixMode', color = 'ModeButtons.Translations', off_color = 'ModeButtons.TranslationsDisabled'))
		self._main_modes.add_mode('DeviceSelector', [self._device_selector, main_buttons, main_faders, self._mixer.main_knobs_layer, self._device, self._device_navigator, self._view_control.selector_layer], behaviour = ColoredCancellableBehaviourWithRelease(color = 'ModeButtons.DeviceSelector', off_color = 'ModeButtons.DeviceSelectorDisabled'))
		self._main_modes.layer = Layer(priority = 4, ModSwitcher_button = self._encoder_button[0], Translations_button = self._encoder_button[3], DeviceSelector_button = self._encoder_button[2])
	

	def _setup_m4l_interface(self):
		self._m4l_interface = MonoM4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard, priority = 10)
		self._m4l_interface.name = "M4LInterface"
		self.get_control_names = self._m4l_interface.get_control_names
		self.get_control = self._m4l_interface.get_control
		self.grab_control = self._m4l_interface.grab_control
		self.release_control = self._m4l_interface.release_control
	

	def _can_auto_arm_track(self, track):
		routing = track.current_input_routing
		return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith('Cntrlr Input')
	

	@subject_slot('appointed_device')
	def _on_device_changed(self):
		debug('appointed device changed, script')
		self.schedule_message(2, self._update_modswitcher)
	

	def _on_selected_track_changed(self):
		super(Cntrlr, self)._on_selected_track_changed()
		self.schedule_message(2, self._update_modswitcher)
	

	def _update_modswitcher(self):
		debug('update modswitcher', self.modhandler.active_mod())
		if self.modhandler.active_mod():
			self._modswitcher.selected_mode = 'mod'
		else:
			self._modswitcher.selected_mode = 'instrument'
	

	def reset_controlled_track(self, track = None, *a):
		if not track:
			track = self.song().view.selected_track
		self.set_controlled_track(track)
	

	def set_controlled_track(self, track = None, *a):
		if isinstance(track, Live.Track.Track):
			super(Cntrlr, self).set_controlled_track(track)
		else:
			self.release_controlled_track()
	

	"""called on timer"""
	def update_display(self):
		super(Cntrlr, self).update_display()		#since we are overriding this from the inherited method, we need to call the original routine as well
		self._timer = (self._timer + 1) % 256	#each 100/60ms, increase the self._timer property by one.  Start over at 0 when we hit 256
		self.modhandler.send_ring_leds()	#if local rings are turned off, then we need to send the new values if they've changed			
		self.flash()							#call the flash method below
	

	def flash(self):
		if(self.flash_status > 0):
			for control in self.controls:
				if isinstance(control, MonoButtonElement):
					control.flash(self._timer)		
	

	"""m4l lcd bridge"""
	def generate_strip_string(self, display_string):
		NUM_CHARS_PER_DISPLAY_STRIP = 12
		if (not display_string):
			return (' ' * NUM_CHARS_PER_DISPLAY_STRIP)
		if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))):
			display_string = display_string[:-2]
		if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)):
			for um in [' ',
			 'i',
			 'o',
			 'u',
			 'e',
			 'a']:
				while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)):
					um_pos = display_string.rfind(um, 1)
					display_string = (display_string[:um_pos] + display_string[(um_pos + 1):])
		else:
			display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1))
		ret = u''
		for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)):
			if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)):
				ret += ' '
			else:
				ret += display_string[i]

		ret += ' '
		ret = ret.replace(' ', '_')
		assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
		return ret
	

	def notification_to_bridge(self, name, value, sender):
		if(isinstance(sender, (MonoEncoderElement, CodecEncoderElement))):
			pn = str(self.generate_strip_string(name))
			pv = str(self.generate_strip_string(value))
			self._monobridge._send(sender.name, 'lcd_name', pn)
			self._monobridge._send(sender.name, 'lcd_value', pv)
	

	def touched(self):
		if self._touched is 0:
			self._monobridge._send('touch', 'on')
			self.schedule_message(2, self.check_touch)
		self._touched +=1
	

	def check_touch(self):
		if self._touched > 5:
			self._touched = 5
		elif self._touched > 0:
			self._touched -= 1
		if self._touched is 0:
			self._monobridge._send('touch', 'off')
		else:
			self.schedule_message(2, self.check_touch)
	

	def handle_sysex(self, midi_bytes):
		pass
	

	def disconnect(self):
		self.log_message("<<<<<<<<<<<<<<<<<<<<<<<<< " + str(self._host_name) + " log closed >>>>>>>>>>>>>>>>>>>>>>>>>")
		super(Cntrlr, self).disconnect()
	

	def restart_monomodular(self):
		#debug('restart monomodular')
		self.modhandler.disconnect()
		with self.component_guard():
			self._setup_mod()
	

	def _get_num_tracks(self):
		return self.num_tracks
	

	"""a closure fix for banking when we deassign the bank buttons and still want to change bank indexes"""
	def device_is_banking_enabled(self, device):
		def _is_banking_enabled():
			return True
		return _is_banking_enabled
Example #4
0
class MonoWing(ControlSurface):


	def __init__(self, *a, **k):
		super(MonoWing, self).__init__(*a, **k)
		self._monomod_version = 'b995'
		self._codec_version = 'b996'
		self._cntrlr_version = 'b996'
		self._cntrlr = None
		self._host_name = 'MonoWing'
		self._color_type = 'OhmRGB'
		self.hosts = []
		self._timer = 0
		self.flash_status = 0
		self._touched = 0
		self._last_main_mode = 'looper'
		with self.component_guard():
			self._setup_monobridge()
			self._setup_controls()
			self._setup_looper()
			self._setup_launcher()
			self._setup_device_control()
			self._setup_modes()
		self.schedule_message(1, self._open_log)
		#self._loop_selector.set_enabled(True)
	

	"""script initialization methods"""
	def _open_log(self):
		self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) + " " + str(self._monomod_version) + " log opened =>>>>>>>>>>>>>>>>>>>") 
		self.show_message(str(self._host_name) + ' Control Surface Loaded')
	

	def _setup_monobridge(self):
		self._monobridge = MonoBridgeElement(self)
		self._monobridge.name = 'MonoBridge'
	

	def _setup_controls(self):
		self._pedal = [None for index in range(12)]
		for index in range(9):
			self._pedal[index] = DoublePressElement(MonoButtonElement(True, MIDI_NOTE_TYPE, 0, PEDAL_DEFS[index], 'Pedal_'+str(index), self))
			#is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self
			self._pedal[index].name = 'Pedal_'+str(index)
			self._pedal[index]._report = False
		self._pedal[9] = LoopPedalExpressionElement(self, MIDI_CC_TYPE, 0, 3, Live.MidiMap.MapMode.absolute)
		self._pedal[9].name = 'Pedal_'+str(9)
		self._pedal[9]._report = False
		self._pedal[10] = LoopPedalExpressionElement(self, MIDI_CC_TYPE, 0, 1, Live.MidiMap.MapMode.absolute)
		self._pedal[10].name = 'Pedal_'+str(10)
		self._pedal[10]._report = False
		self._pedal[11] = LoopPedalExpressionElement(self, MIDI_CC_TYPE, 0, 2, Live.MidiMap.MapMode.absolute)
		self._pedal[11].name = 'Pedal_'+str(11)
		self._pedal[11]._report = False
		self._leds = [self._pedal[6], self._pedal[5], self._pedal[4], self._pedal[3]]
		self._side_buttons = [MonoButtonElement(True, MIDI_NOTE_TYPE, 0, SIDE_DEFS[index], 'Side_Button_'+str(index), self) for index in range(4)]
				
		self._select_buttons = ButtonMatrixElement()
		self._select_buttons.name = 'SelectMatrix'
		self._select_buttons.add_row([self._pedal[6], self._pedal[5], self._pedal[4], self._pedal[3]])
		self._doublepress_select_buttons = ButtonMatrixElement()
		self._doublepress_select_buttons.name = 'DoublepressSelectMatrix'
		self._doublepress_select_buttons.add_row([self._pedal[6].double_press, self._pedal[5].double_press, self._pedal[4].double_press, self._pedal[3].double_press])

		self._record_button = self._pedal[1]
		self._mute_button = self._pedal[2]
		self._overdub_button = self._pedal[0]
		self._clear_button = self._pedal[7]
		self._reverse_button = self._pedal[8]
		self._record_button.turn_off()
		self._mute_button.turn_off()
		self._overdub_button.turn_off()
		self._clear_button.turn_off()
		self._reverse_button.turn_off()
	

	def _setup_looper(self):
		self._looper = MonolooperComponent(self._leds, self)
		self._looper.layer = Layer(select_buttons = self._select_buttons, 
									doublepress_select_buttons = self._doublepress_select_buttons,
									overdub_button = self._pedal[2], 
									record_button = self._pedal[1], 
									mute_button = self._pedal[0],
									clear_button = self._pedal[7],
									reverse_button = self._pedal[8],
									expression_pedal = self._pedal[9],)
	

	def _setup_launcher(self):
		self._launcher = LauncherComponent(self._leds, self)
		self._launcher.set_enabled(False)
		self._launcher.layer = Layer(select_buttons = self._select_buttons, 
									doublepress_select_buttons = self._doublepress_select_buttons,
									fire1_button = self._pedal[2], 
									fire2_button = self._pedal[1], 
									fire3_button = self._pedal[0],
									fire4_button = self._pedal[8],
									expression_pedal = self._pedal[9])
	

	def _setup_device_control(self):
		self._device_control = DeviceControlComponent(self._leds, self)
		self._device_control.set_enabled(False)
		self._device_control.layer = Layer(select_buttons = self._select_buttons, 
									doublepress_select_buttons = self._doublepress_select_buttons,
									toggle1_button = self._pedal[2], 
									toggle2_button = self._pedal[1], 
									toggle3_button = self._pedal[0],
									toggle4_button = self._pedal[8],
									expression_pedal = self._pedal[9],
									expression2 = self._pedal[10],
									expression3 = self._pedal[11])
	

	def _setup_modes(self):
		self._button_modes = ModesComponent(name='Button_Modes')
		self._button_modes.add_mode('launcher', self._launcher)
		self._button_modes.add_mode('looper', self._looper)
		self._button_modes.add_mode('device', self._device_control)
		self._button_modes.selected_mode = 'looper'
		self._button_modes.layer = Layer(looper_button = self._side_buttons[0], launcher_button = self._side_buttons[1], device_button = self._side_buttons[2])
		self._button_modes.set_enabled(True)
	

	def receive_led(self, button, value):
		#self.log_message('receive led: ' + str(index) + ' ' + str(value))
		pass
	

	def toggle_mode(self):
		self._button_modes.selected_mode = 'launcher' if self._button_modes.selected_mode is 'looper' else 'looper'
		self._last_main_mode = self._button_modes.selected_mode
		#self.log_message('toggle mode to: ' + str(self._button_modes.selected_mode))
	

	def toggle_device_control(self, x):
		self._button_modes.selected_mode = 'device' if not self._button_modes.selected_mode is 'device' else self._last_main_mode
		if self._button_modes.selected_mode is 'device':
			self._device_control.set_bank(x)
	

	"""called on timer"""
	def update_display(self):
		super(MonoWing, self).update_display()
		self._timer = (self._timer + 1) % 256
		self.flash()
	

	def flash(self):
		if(self.flash_status > 0):
			for control in self.controls:
				if isinstance(control, MonoButtonElement):
					control.flash(self._timer)
Example #5
0
class Roland_A_PRO(ControlSurface):

    def __init__(self, *a, **k):
        super(Roland_A_PRO, self).__init__(*a, **k)
        with self.component_guard():
            self._create_controls()
            self._create_transport()
            self._create_mixer()
            self._create_device()
            self._create_drums()
            self._create_modes()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[ EncoderElement(MIDI_CC_TYPE, 0, identifier, Live.MidiMap.MapMode.absolute, name='Encoder_%d' % index) for index, identifier in enumerate(ENCODER_IDS) ]])
        self._master_encoder = EncoderElement(MIDI_CC_TYPE, 0, 10, Live.MidiMap.MapMode.absolute, name='Master_Encoder')
        self._sliders = ButtonMatrixElement(rows=[[ SliderElement(MIDI_CC_TYPE, 0, identifier, name='Slider_%d' % index) for index, identifier in enumerate(SLIDER_IDS) ]])
        self._master_slider = SliderElement(MIDI_CC_TYPE, 0, 7, name='Master_Slider')
        self._play_button = ButtonElement(True, MIDI_CC_TYPE, 0, 26)
        self._stop_button = ButtonElement(True, MIDI_CC_TYPE, 0, 25)
        self._record_button = ButtonElement(True, MIDI_CC_TYPE, 0, 28)
        self._forward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 24)
        self._backward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 21)
        self._ff_button = ButtonElement(True, MIDI_CC_TYPE, 0, 23)
        self._rw_button = ButtonElement(True, MIDI_CC_TYPE, 0, 22)
        self._device_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 80)
        self._pan_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 81)
        self._send_a_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 82)
        self._send_b_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 83)
        self._pads = ButtonMatrixElement(rows=[ [ ButtonElement(True, MIDI_NOTE_TYPE, 0, identifier) for identifier in row ] for row in PAD_ROWS ])

    def _create_transport(self):
        self._transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=self._play_button, stop_button=self._stop_button, record_button=self._record_button))
        self._transport.set_enabled(True)

    def _create_mixer(self):
        mixer_size = self._sliders.width()
        self._mixer = MixerComponent(mixer_size, name='Mixer', is_enabled=False, layer=Layer(volume_controls=self._sliders, prehear_volume_control=self._master_encoder))
        self._mixer.master_strip().layer = Layer(volume_control=self._master_slider)
        self._mixer.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(device_selection_follows_track_selection=True)
        self._device_navigation = DeviceNavigationComponent()
        self._device.set_enabled(True)
        self._device_navigation.set_enabled(True)
        self.set_device_component(self._device)

    def _create_drums(self):
        self._drums = DrumRackComponent(name='Drum_Rack', is_enabled=False, layer=Layer(pads=self._pads))
        self._drums.set_enabled(True)

    def _create_modes(self):
        self._encoder_modes = ModesComponent()
        device_layer_mode = LayerMode(self._device, Layer(parameter_controls=self._encoders))
        device_navigation_layer_mode = LayerMode(self._device_navigation, Layer(device_nav_right_button=self._forward_button, device_nav_left_button=self._backward_button))
        self._encoder_modes.add_mode('device_mode', [device_layer_mode, device_navigation_layer_mode])
        self._encoder_modes.add_mode('pan_mode', AddLayerMode(self._mixer, Layer(pan_controls=self._encoders, bank_up_button=self._forward_button, bank_down_button=self._backward_button, track_up_button=self._ff_button, track_down_button=self._rw_button)))
        send_layer_mode = AddLayerMode(self._mixer, Layer(send_controls=self._encoders, bank_up_button=self._forward_button, bank_down_button=self._backward_button, track_up_button=self._ff_button, track_down_button=self._rw_button))
        self._encoder_modes.add_mode('send_a_mode', [send_layer_mode, partial(self._set_send_index, 0)])
        self._encoder_modes.add_mode('send_b_mode', [send_layer_mode, partial(self._set_send_index, 1)])
        self._encoder_modes.layer = Layer(device_mode_button=self._device_mode_button, pan_mode_button=self._pan_mode_button, send_a_mode_button=self._send_a_mode_button, send_b_mode_button=self._send_b_mode_button)
        self._encoder_modes.selected_mode = 'device_mode'
        self._encoder_modes.set_enabled(True)

    def _set_send_index(self, index):
        self._mixer.send_index = index
Example #6
0
class Launchkey_MK2(OptimizedControlSurface):
    identity_request_delay = 0.5

    def __init__(self, c_instance, *a, **k):
        super(Launchkey_MK2, self).__init__(c_instance=c_instance, *a, **k)
        self._is_25_key_model = False
        self._is_in_control_on = True
        with self.component_guard():
            self._skin = make_skin()
            with inject(skin=const(self._skin)).everywhere():
                self._create_controls()
        self._request_task = self._tasks.add(Task.sequence(Task.wait(self.identity_request_delay), Task.run(self._send_identity_request)))
        self._request_task.kill()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[ make_encoder(identifier, name='Encoder_%d' % (index,)) for index, identifier in enumerate(xrange(21, 29)) ]])
        self._top_pad_row = ButtonMatrixElement(rows=[[ make_button(identifier, name='Pad_0_%d' % (index,)) for index, identifier in enumerate(xrange(96, 104)) ]])
        self._bottom_pad_row_raw = [ make_button(identifier, name='Pad_1_%d' % (index,)) for index, identifier in enumerate(xrange(112, 120)) ]
        self._bottom_pad_row = ButtonMatrixElement(rows=[self._bottom_pad_row_raw])
        self._top_launch_button = make_button(104, name='Scene_Launch_Button')
        self._bottom_launch_button = make_button(120, name='Stop_All_Clips_Button')
        self._scene_up_button = make_button(112, MIDI_CC_TYPE, name='Scene_Up_Button')
        self._scene_down_button = make_button(113, MIDI_CC_TYPE, name='Scene_Down_Button')
        self._stop_button = make_button(114, MIDI_CC_TYPE, name='Stop_Button')
        self._play_button = make_button(115, MIDI_CC_TYPE, name='Play_Button')
        self._loop_button = make_button(116, MIDI_CC_TYPE, name='Loop_Button')
        self._record_button = make_button(117, MIDI_CC_TYPE, name='Record_Button')
        self._sliders = ButtonMatrixElement(rows=[[ make_slider(identifier, name='Slider_%d' % (index,)) for index, identifier in enumerate(xrange(41, 49)) ]])
        self._master_slider = make_slider(7, name='Master_Slider')
        self._25_key_slider = make_slider(7, name='Slider', channel=0)
        self._mute_buttons_raw = [ make_button(identifier, MIDI_CC_TYPE, name='Mute_Button_%d' % (index,)) for index, identifier in enumerate(xrange(51, 59)) ]
        self._mute_buttons = ButtonMatrixElement(rows=[self._mute_buttons_raw])
        self._master_button = make_button(59, MIDI_CC_TYPE, name='Master_Button')
        self._track_left_button = make_button(102, MIDI_CC_TYPE, name='Track_Left_Button')
        self._track_right_button = make_button(103, MIDI_CC_TYPE, name='Track_Right_Button')
        self._device_mode_button = self._bottom_pad_row_raw[0]
        self._pan_mode_button = self._bottom_pad_row_raw[1]
        self._send_mode_buttons = dict()
        for index in xrange(consts.MAX_SENDS):
            setattr(self, '_send_%d_button' % (index,), self._bottom_pad_row_raw[index + 2])
            self._send_mode_buttons['send_%d_mode_button' % (index,)] = getattr(self, '_send_%d_button' % (index,))

        self._extended_mode_button = make_button(12, name='Dummy_Extended_Mode_Button')
        self._extended_mode_button.add_value_listener(nop)
        self._encoder_incontrol_button = make_button(13, is_momentary=False, name='Encoder_InControl_Button')
        self._encoder_incontrol_button.add_value_listener(nop)
        self._slider_incontrol_button = make_button(14, is_momentary=False, name='Fader_InControl_Button')
        self._slider_incontrol_button.add_value_listener(nop)
        self._pad_incontrol_button = make_button(15, is_momentary=False, name='Pad_InControl_Button')
        self._pad_incontrol_button.add_value_listener(self._update_pads)
        self._encoder_incontrol_button2 = make_button(16, name='Encoder_InControl_Button')
        self._pad_in_control_status_button = make_button(11, name='Dummy_InControl_Button')

    def _create_session(self):
        self._session = SessionComponent(name='Session', is_enabled=False, num_tracks=self._top_pad_row.width(), num_scenes=self._top_pad_row.height(), enable_skinning=True, layer=Layer(clip_launch_buttons=self._top_pad_row, scene_launch_buttons=ButtonMatrixElement(rows=[[self._top_launch_button]]), stop_track_clip_buttons=self._bottom_pad_row, stop_all_clips_button=self._bottom_launch_button))
        self._session.set_rgb_mode(CLIP_COLOR_TABLE, RGB_COLOR_TABLE)
        self._session.set_mixer(self._mixer)
        self._session.set_enabled(True)

    def _setup_navigation(self):
        self._session_navigation = SessionNavigationComponent(is_enabled=False, name='Session_Navigation', layer=Layer(next_track_button=self._track_right_button, prev_track_button=self._track_left_button, next_scene_button=self._scene_down_button, prev_scene_button=self._scene_up_button))
        self._session_navigation.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(is_enabled=False, name='Transport', layer=Layer(play_button=self._play_button, stop_button=self._stop_button, loop_button=self._loop_button, record_button=self._record_button))
        self._transport.set_enabled(True)

    def _create_mixer(self):
        mixer_volume_layer = None
        if self._is_25_key_model:
            mixer_volume_layer = Layer(volume_control=self._25_key_slider)
        else:
            mixer_volume_layer = Layer(volume_controls=self._sliders)
        self._mixer = MixerComponent(is_enabled=False, name='Mixer', num_tracks=self._sliders.width(), layer=mixer_volume_layer)
        if not self._is_25_key_model:
            self._mixer.master_strip().layer = Layer(volume_control=self._master_slider)
        self._mixer.set_enabled(True)
        self._mute_button_modes = ModesComponent()
        mute_mode = AddLayerMode(self._mixer, Layer(mute_buttons=self._mute_buttons))
        solo_mode = AddLayerMode(self._mixer, Layer(solo_buttons=self._mute_buttons))
        self._mute_button_modes.add_mode('mute_mode', mute_mode)
        self._mute_button_modes.add_mode('solo_mode', solo_mode, behaviour=CancellableBehaviour())
        self._mute_button_modes.layer = Layer(solo_mode_button=self._master_button)
        self._mute_button_modes.selected_mode = 'mute_mode'
        self._mute_button_modes.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(name='Device', is_enabled=False, device_selection_follows_track_selection=True)
        self.set_device_component(self._device)
        self._device.set_enabled(True)

    def _create_background(self):
        self._background = BackgroundComponent(name='BackgroundComponent')

    def _create_encoder_modes(self):
        self._encoder_modes = DisablingModesComponent()
        self._encoder_modes.default_behaviour = mixin(SkinableBehaviourMixin, ImmediateBehaviour)()
        device_mode = LayerMode(self._device, Layer(parameter_controls=self._encoders, bank_buttons=self._top_pad_row))
        pan_mode = AddLayerMode(self._mixer, Layer(pan_controls=self._encoders))
        sends_mode = AddLayerMode(self._mixer, Layer(send_controls=self._encoders))
        background_mode = LayerMode(self._background, Layer(bank_buttons=self._top_pad_row))
        self._encoder_modes.add_mode('device_mode', device_mode, is_enabled=True)
        self._encoder_modes.add_mode('pan_mode', [pan_mode, background_mode], is_enabled=True)
        for index in xrange(6):
            self._encoder_modes.add_mode('send_%d_mode' % (index,), [sends_mode, partial(self._set_send_index, index), background_mode], is_enabled=False)

        self._encoder_modes.selected_mode = 'device_mode'
        self._encoder_modes.set_enabled(True)

    def _create_mode_selector(self):
        self._mode_selector = ModesComponent()
        mode_selection = LayerMode(self._encoder_modes, Layer(device_mode_button=self._device_mode_button, pan_mode_button=self._pan_mode_button, **self._send_mode_buttons))
        device_navigation = AddLayerMode(self._device, Layer(device_nav_left_button=self._track_left_button, device_nav_right_button=self._track_right_button))
        self._mode_selector.add_mode('mode_selection', [partial(self._toggle_in_control, True), mode_selection, device_navigation], behaviour=MomentaryBehaviour())
        session_control = AddLayerMode(self._session, Layer(clip_launch_buttons=self._top_pad_row))
        self._mode_selector.add_mode('session_mode', [partial(self._toggle_in_control, False), session_control])
        self._mode_selector.layer = Layer(mode_selection_button=self._encoder_incontrol_button2)

    def _create_in_control_status_listener(self):
        self._in_control_status = InControlStatusComponent(set_is_in_control_on=self._set_is_in_control_on, is_enabled=False, layer=Layer(in_control_status_button=self._pad_in_control_status_button))
        self._in_control_status.set_enabled(True)

    @subject_slot('value')
    def _update_pads(self, value):
        if value:
            self.update()

    @subject_slot('return_tracks')
    def _on_return_tracks_changed(self):
        num_sends = self._mixer.num_sends
        for index in xrange(6):
            self._encoder_modes.set_mode_enabled('send_%d_mode' % (index,), True if index < num_sends else False)

    def _set_send_index(self, index):
        self._mixer.send_index = index

    def _set_is_in_control_on(self, value):
        self._is_in_control_on = value

    def _toggle_in_control(self, value):
        if not self._is_in_control_on:
            self._send_midi(consts.DRUM_IN_CONTROL_ON_MESSAGE if value else consts.DRUM_IN_CONTROL_OFF_MESSAGE)

    def port_settings_changed(self):
        self._disconnect_and_unregister_all_components()
        self._request_task.restart()

    def handle_sysex(self, midi_bytes):
        if self._is_identity_response(midi_bytes):
            product_id_bytes = self._extract_product_id_bytes(midi_bytes)
            if self._is_identity_response_valid(product_id_bytes):
                self._set_model_type(product_id_bytes)
                self._request_task.kill()
                self.on_identified()
            else:
                self.log_message('MIDI device responded with wrong product id (%s).' % (str(product_id_bytes),))
        else:
            super(Launchkey_MK2, self).handle_sysex(midi_bytes)

    def _extract_product_id_bytes(self, midi_bytes):
        return midi_bytes[5:]

    def _is_identity_response(self, midi_bytes):
        return midi_bytes[3:5] == (6, 2)

    def _is_identity_response_valid(self, product_id_bytes):
        return product_id_bytes[:3] == consts.PRODUCT_ID_BYTE_PREFIX and product_id_bytes[3] in consts.PRODUCT_ID_BYTES

    def _set_model_type(self, product_id_bytes):
        self._is_25_key_model = product_id_bytes[3] == consts.LAUNCHKEY_25_ID_BYTE

    def _send_identity_request(self):
        self._send_midi(consts.IDENTITY_REQUEST)

    def on_identified(self):
        self._extended_mode_button.turn_on()
        with self.component_guard():
            self._create_mixer()
            self._create_session()
            self._setup_navigation()
            self._create_transport()
            self._create_device()
            self._create_background()
            self._create_encoder_modes()
            self._create_mode_selector()
            self._create_in_control_status_listener()
            self._on_return_tracks_changed.subject = self.song()
            self._on_return_tracks_changed()
        self._mode_selector.selected_mode = 'session_mode'
        self.update()

    def disconnect(self):
        self._extended_mode_button.turn_off()
        super(Launchkey_MK2, self).disconnect()
Example #7
0
class Launchpad_Pro(IdentifiableControlSurface, OptimizedControlSurface):
    identity_request = consts.SYSEX_IDENTITY_REQUEST

    def __init__(self, c_instance, *a, **k):
        product_id_bytes = consts.MANUFACTURER_ID + consts.DEVICE_CODE
        super(Launchpad_Pro, self).__init__(c_instance=c_instance,
                                            product_id_bytes=product_id_bytes,
                                            *a,
                                            **k)
        self._challenge = Live.Application.get_random_int(
            0, 400000000) & 2139062143
        with self.component_guard():
            self._skin = make_default_skin()
            with inject(skin=const(self._skin)).everywhere():
                self._midimap = MidiMap()
            self._target_track_component = TargetTrackComponent(
                name=u'Target_Track')
            self._create_background()
            self._create_global_component()
            self._last_sent_mode_byte = None
            with inject(layout_setup=const(self._layout_setup),
                        should_arm=const(self._should_arm_track)).everywhere():
                self._create_session()
                self._create_recording()
                self._create_actions()
                self._create_drums()
                self._create_mixer()
                self._create_device()
                self._create_modes()
                self._create_user()
            self._on_session_record_changed.subject = self.song()
        self.set_device_component(self._device)
        self._on_session_record_changed()

    def disconnect(self):
        self._send_midi(consts.TURN_OFF_LEDS)
        self._send_midi(consts.QUIT_MESSAGE)
        super(Launchpad_Pro, self).disconnect()

    def _create_background(self):
        self._modifier_background_component = ModifierBackgroundComponent(
            name=u'Background_Component',
            is_enabled=False,
            layer=Layer(shift_button=self._midimap[u'Shift_Button']))
        self._shifted_background = BackgroundComponent(
            name=u'No_Op_Shifted_Buttons',
            is_enabled=False,
            layer=Layer(
                click_bitton=self._midimap.with_shift(u'Click_Button'),
                delete_button=self._midimap.with_shift(u'Delete_Button'),
                duplicate_button=self._midimap.with_shift(u'Duplicate_Button'),
                double_button=self._midimap.with_shift(u'Double_Loop_Button'),
                session_record_button=self._midimap.with_shift(
                    u'Session_Record_Button')))

    def _create_global_component(self):
        self._actions_component = ActionsComponent(
            name=u'Global_Actions',
            is_enabled=False,
            layer=Layer(undo_button=self._midimap[u'Undo_Button'],
                        redo_button=self._midimap.with_shift(u'Undo_Button'),
                        metronome_button=self._midimap[u'Click_Button'],
                        quantization_on_button=self._midimap.with_shift(
                            u'Quantize_Button')))

    def _create_session(self):
        self._session = SessionComponent(
            NUM_TRACKS,
            NUM_SCENES,
            auto_name=True,
            is_enabled=False,
            enable_skinning=True,
            layer=Layer(
                track_bank_left_button=self._midimap[u'Arrow_Left_Button'],
                track_bank_right_button=self._midimap[u'Arrow_Right_Button'],
                scene_bank_up_button=self._midimap[u'Arrow_Up_Button'],
                scene_bank_down_button=self._midimap[u'Arrow_Down_Button']))
        self._session.set_enabled(True)
        self._session.set_rgb_mode(LIVE_COLORS_TO_MIDI_VALUES, RGB_COLOR_TABLE)
        SpecialClipSlotComponent.quantization_component = self._actions_component
        for scene_index in xrange(NUM_SCENES):
            scene = self._session.scene(scene_index)
            scene.layer = Layer(
                select_button=self._midimap[u'Shift_Button'],
                delete_button=self._midimap[u'Delete_Button'],
                duplicate_button=self._midimap[u'Duplicate_Button'])
            for track_index in xrange(NUM_TRACKS):
                slot = scene.clip_slot(track_index)
                slot.layer = Layer(
                    select_button=self._midimap[u'Shift_Button'],
                    delete_button=self._midimap[u'Delete_Button'],
                    duplicate_button=self._midimap[u'Duplicate_Button'],
                    double_loop_button=self._midimap[u'Double_Loop_Button'],
                    quantize_button=self._midimap[u'Quantize_Button'])

        self._session_zoom = SessionZoomingComponent(self._session,
                                                     name=u'Session_Overview',
                                                     is_enabled=True,
                                                     enable_skinning=True)

    def _create_recording(self):
        self._session_record = SpecialSessionRecordingComponent(
            self._target_track_component,
            name=u'Session_Recording',
            is_enabled=False,
            layer=Layer(record_button=self._midimap[u'Session_Record_Button']))

    def _create_actions(self):
        self._clip_actions_component = ClipActionsComponent(
            self._target_track_component,
            name=u'Clip_Actions',
            is_enabled=False,
            layer=Layer(duplicate_button=self._midimap[u'Duplicate_Button'],
                        double_button=self._midimap[u'Double_Loop_Button'],
                        quantize_button=self._midimap[u'Quantize_Button']))
        ClipActionsComponent.quantization_component = self._actions_component

    def _create_drums(self):
        self._drum_group_finder = DrumGroupFinderComponent(
            self._target_track_component,
            name=u'Drum_Group_Finder',
            is_enabled=False,
            layer=None)
        self._on_drum_group_changed.subject = self._drum_group_finder
        self._drum_group_finder.set_enabled(True)
        self._drum_group = DrumGroupComponent(
            self._clip_actions_component,
            name=u'Drum_Group_Control',
            translation_channel=consts.DR_MAP_CHANNEL)
        self._drum_group.set_enabled(True)

    def _create_mixer(self):
        self._mixer = SpecialMixerComponent(NUM_TRACKS,
                                            auto_name=True,
                                            is_enabled=True,
                                            invert_mute_feedback=True)
        self._mixer.name = u'Mixer_Control'
        self._session.set_mixer(self._mixer)

    def _create_device(self):
        self._device = SpecialDeviceComponent(
            name=u'Device_Control',
            is_enabled=False,
            device_selection_follows_track_selection=True)
        self._device_navigation = DeviceNavigationComponent(
            name=u'Device_Navigation')
        self._device_background = BackgroundComponent(
            name=u'Device_Background_Component')

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

    def _create_translation(self,
                            comp_name,
                            channel,
                            button_layer,
                            should_enable=True,
                            should_reset=True):
        translation_component = TranslationComponent(
            name=comp_name,
            translated_channel=channel,
            should_enable=should_enable,
            should_reset=should_reset,
            is_enabled=False,
            layer=button_layer)
        setattr(self, u'_' + comp_name.lower(), translation_component)
        return translation_component

    def _create_modes(self):
        self._modes = ModesComponent(name=u'Launchpad_Modes', is_enabled=False)
        self._session_layer_mode = AddLayerMode(
            self._session,
            Layer(scene_launch_buttons=self.
                  _midimap[u'Scene_Launch_Button_Matrix'],
                  clip_launch_buttons=self._midimap[u'Main_Button_Matrix'],
                  delete_button=self._midimap[u'Delete_Button'],
                  duplicate_button=self._midimap[u'Duplicate_Button'],
                  double_button=self._midimap[u'Double_Loop_Button'],
                  quantize_button=self._midimap[u'Quantize_Button']))
        action_button_background = BackgroundComponent(name=u'No_Op_Buttons')
        self._action_button_background_layer_mode = LayerMode(
            action_button_background,
            Layer(delete_button=self._midimap[u'Delete_Button'],
                  quantize_button=self._midimap[u'Quantize_Button'],
                  duplicate_button=self._midimap[u'Duplicate_Button'],
                  double_button=self._midimap[u'Double_Loop_Button']))
        self._clip_delete_layer_mode = AddLayerMode(
            self._clip_actions_component,
            layer=Layer(delete_button=self._midimap[u'Delete_Button']))
        self._create_session_zooming_modes()
        self._create_session_mode()
        self._create_note_modes()
        self._create_device_mode()
        self._create_user_mode()
        self._create_record_arm_mode()
        self._create_track_select_mode()
        self._create_mute_mode()
        self._create_solo_mode()
        self._create_volume_mode()
        self._create_pan_mode()
        self._create_sends_mode()
        self._create_stop_clips_mode()
        self._modes.layer = Layer(
            session_mode_button=self._midimap[u'Session_Mode_Button'],
            note_mode_button=self._midimap[u'Note_Mode_Button'],
            device_mode_button=self._midimap[u'Device_Mode_Button'],
            user_mode_button=self._midimap[u'User_Mode_Button'],
            record_arm_mode_button=self._midimap[u'Record_Arm_Mode_Button'],
            track_select_mode_button=self.
            _midimap[u'Track_Select_Mode_Button'],
            mute_mode_button=self._midimap[u'Mute_Mode_Button'],
            solo_mode_button=self._midimap[u'Solo_Mode_Button'],
            volume_mode_button=self._midimap[u'Volume_Mode_Button'],
            pan_mode_button=self._midimap[u'Pan_Mode_Button'],
            sends_mode_button=self._midimap[u'Sends_Mode_Button'],
            stop_clip_mode_button=self._midimap[u'Stop_Clip_Mode_Button'])
        self._modes.selected_mode = u'session_mode'
        self._on_layout_changed.subject = self._modes

    def _create_session_zooming_modes(self):
        session_zoom_layer = Layer(
            button_matrix=self._midimap[u'Main_Button_Matrix'],
            nav_left_button=self._midimap[u'Arrow_Left_Button'],
            nav_right_button=self._midimap[u'Arrow_Right_Button'],
            nav_up_button=self._midimap[u'Arrow_Up_Button'],
            nav_down_button=self._midimap[u'Arrow_Down_Button'])
        session_zooming_layer_mode = LayerMode(self._session_zoom,
                                               session_zoom_layer)
        self._session_zooming_manager = SessionZoomingManagerComponent(
            self._modes, is_enabled=False)
        session_zooming_button_layer_mode = LayerMode(
            self._session_zooming_manager,
            Layer(
                session_zooming_button=self._midimap[u'Session_Mode_Button']))
        self._prioritized_session_zooming_button_layer_mode = LayerMode(
            self._session_zooming_manager,
            Layer(session_zooming_button=self._midimap[u'Session_Mode_Button'],
                  priority=1))
        self._session_zooming_background = BackgroundComponent(
            name=u'Session_Zooming_Background')
        session_zooming_background_layer_mode = LayerMode(
            self._session_zooming_background,
            Layer(scene_launch_buttons=self.
                  _midimap[u'Scene_Launch_Button_Matrix'],
                  delete_button=self._midimap[u'Delete_Button'],
                  quantize_button=self._midimap[u'Quantize_Button'],
                  duplicate_button=self._midimap[u'Duplicate_Button'],
                  double_loop_button=self._midimap[u'Double_Loop_Button']))
        self._modes.add_mode(u'session_zooming_mode', [
            self._session_zooming_manager, session_zooming_button_layer_mode,
            session_zooming_layer_mode, session_zooming_background_layer_mode
        ])
        self._modes.add_mode(u'prioritized_session_zooming_mode', [
            partial(self._layout_switch, consts.SESSION_LAYOUT_SYSEX_BYTE),
            self._session_zooming_manager,
            self._prioritized_session_zooming_button_layer_mode,
            session_zooming_layer_mode, session_zooming_background_layer_mode,
            self.update
        ])

    def _create_session_mode(self):
        self._modes.add_mode(
            u'session_mode', [
                partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
                self._session_layer_mode,
                self._session.update_navigation_buttons
            ],
            behaviour=CancelingReenterBehaviour(u'session_zooming_mode'))

    def _create_note_modes(self):
        note_mode_matrix_translation = self._create_translation(
            u'Note_Mode_Matrix_Translation',
            consts.CHROM_MAP_CHANNEL,
            Layer(button_matrix=self._midimap[u'Main_Button_Matrix'],
                  note_button_matrix=self._midimap[u'Note_Button_Matrix'],
                  drum_matrix=self._midimap[u'Drum_Button_Matrix'],
                  mixer_button_matrix=self._midimap[u'Mixer_Button_Matrix']),
            should_enable=False)
        note_mode_scene_launch_translation = self._create_translation(
            u'Note_Mode_Scene_Launch_Translation', consts.CHROM_MAP_CHANNEL,
            Layer(scene_launch_buttons=self.
                  _midimap[u'Scene_Launch_Button_Matrix']))
        scale_setup_mode_button_lighting = LedLightingComponent(
            name=u'LED_Lighting_Component',
            is_enabled=False,
            layer=Layer(button=self._midimap.with_shift(u'Note_Mode_Button')))
        drum_mode_note_matrix_translation = self._create_translation(
            u'Drum_Mode_Note_Button_Translation',
            0,
            Layer(note_button_matrix=self._midimap[u'Note_Button_Matrix']),
            should_enable=False,
            should_reset=False)
        drum_group_layer_mode = LayerMode(
            self._drum_group,
            layer=Layer(
                scroll_up_button=self._midimap[u'Arrow_Left_Button'],
                scroll_down_button=self._midimap[u'Arrow_Right_Button'],
                scroll_page_up_button=self._midimap[u'Arrow_Up_Button'],
                scroll_page_down_button=self._midimap[u'Arrow_Down_Button'],
                drum_matrix=self._midimap[u'Drum_Button_Matrix'],
                select_button=self._midimap[u'Shift_Button'],
                delete_button=self._midimap[u'Delete_Button']))
        self._note_modes = SpecialModesComponent(name=u'Note_Modes')
        self._note_modes.add_mode(u'chromatic_mode', [
            partial(self._layout_setup, consts.NOTE_LAYOUT_SYSEX_BYTE),
            self._clip_delete_layer_mode, note_mode_matrix_translation,
            scale_setup_mode_button_lighting
        ])
        self._note_modes.add_mode(u'drum_mode', [
            partial(self._layout_setup,
                    consts.DRUM_LAYOUT_SYSEX_BYTE), self._setup_drum_group,
            drum_group_layer_mode, drum_mode_note_matrix_translation
        ])
        self._note_modes.add_mode(u'audio_mode', [
            partial(self._layout_setup, consts.AUDIO_LAYOUT_SYSEX_BYTE),
            self._clip_delete_layer_mode
        ])
        self._note_modes.set_enabled(False)
        self._modes.add_mode(u'note_mode', [
            note_mode_scene_launch_translation, self._note_modes,
            self._select_note_mode, self._select_target_track,
            self._clip_actions_component, self._show_playing_clip,
            self._set_clip_actions_type
        ],
                             behaviour=ReenterBehaviour(
                                 self.toggle_detail_view))
        self._session_record.set_modes_component(self._modes)
        self._session_record.set_note_mode_name(u'note_mode')

    def _create_device_mode(self):
        device_mode_scene_launch_translation = self._create_translation(
            u'Device_Mode_Scene_Launch_Translation', consts.DEVICE_MAP_CHANNEL,
            Layer(scene_launch_buttons=self.
                  _midimap[u'Scene_Launch_Button_Matrix']))
        device_layer_mode = LayerMode(
            self._device,
            layer=Layer(
                parameter_controls=self._midimap[u'Slider_Button_Matrix']))
        device_nav_layer_mode = LayerMode(
            self._device_navigation,
            layer=Layer(
                device_nav_left_button=self._midimap[u'Arrow_Left_Button'],
                device_nav_right_button=self._midimap[u'Arrow_Right_Button']))
        device_background_layer_mode = LayerMode(
            self._device_background,
            layer=Layer(arrow_up_button=self._midimap[u'Arrow_Up_Button'],
                        arrow_down_button=self._midimap[u'Arrow_Down_Button']))
        self._modes.add_mode(u'device_mode', [
            partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
            self._device, device_layer_mode, device_nav_layer_mode,
            device_background_layer_mode, self._clip_actions_component,
            self._clip_delete_layer_mode, device_mode_scene_launch_translation,
            self._show_playing_clip, self._set_clip_actions_type
        ],
                             behaviour=ReenterBehaviour(
                                 self.toggle_detail_view))

    def _create_user_mode(self):
        self._modes.add_mode(
            u'user_mode',
            [partial(self._layout_setup, consts.USER_LAYOUT_SYSEX_BYTE)])

    def _create_record_arm_mode(self):
        arm_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(arm_buttons=self._midimap[u'Mixer_Button_Matrix']))
        self._modes.add_mode(
            u'record_arm_mode', [
                partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
                self._session_layer_mode, arm_layer_mode,
                self._session_zooming_manager,
                self._prioritized_session_zooming_button_layer_mode,
                self._session.update_navigation_buttons
            ],
            behaviour=SpecialReenterBehaviour(u'session_mode'))

    def _create_track_select_mode(self):
        track_select_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(
                track_select_buttons=self._midimap[u'Mixer_Button_Matrix']))
        self._modes.add_mode(
            u'track_select_mode', [
                partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
                self._session_layer_mode, track_select_layer_mode,
                self._session_zooming_manager,
                self._prioritized_session_zooming_button_layer_mode,
                self._session.update_navigation_buttons
            ],
            behaviour=SpecialReenterBehaviour(u'session_mode'))

    def _create_mute_mode(self):
        mute_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(mute_buttons=self._midimap[u'Mixer_Button_Matrix']))
        self._modes.add_mode(
            u'mute_mode', [
                partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
                self._session_layer_mode, mute_layer_mode,
                self._session_zooming_manager,
                self._prioritized_session_zooming_button_layer_mode,
                self._session.update_navigation_buttons
            ],
            behaviour=SpecialReenterBehaviour(u'session_mode'))

    def _create_solo_mode(self):
        solo_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(solo_buttons=self._midimap[u'Mixer_Button_Matrix']))
        self._modes.add_mode(
            u'solo_mode', [
                partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
                self._session_layer_mode, solo_layer_mode,
                self._session_zooming_manager,
                self._prioritized_session_zooming_button_layer_mode,
                self._session.update_navigation_buttons
            ],
            behaviour=SpecialReenterBehaviour(u'session_mode'))

    def _create_volume_mode(self):
        volume_mode_scene_launch_translation = self._create_translation(
            u'Volume_Mode_Scene_Launch_Translation', consts.VOLUME_MAP_CHANNEL,
            Layer(scene_launch_buttons=self.
                  _midimap[u'Scene_Launch_Button_Matrix']))
        volume_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(
                volume_controls=self._midimap[u'Slider_Button_Matrix']))
        self._modes.add_mode(
            u'volume_mode', [
                partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
                volume_layer_mode, self._action_button_background_layer_mode,
                self._session_zooming_manager,
                self._prioritized_session_zooming_button_layer_mode,
                volume_mode_scene_launch_translation,
                self._session.update_navigation_buttons
            ],
            behaviour=SpecialReenterBehaviour(u'session_mode'))

    def _create_pan_mode(self):
        pan_mode_scene_launch_translation = self._create_translation(
            u'Pan_Mode_Scene_Launch_Translation', consts.PAN_MAP_CHANNEL,
            Layer(scene_launch_buttons=self.
                  _midimap[u'Scene_Launch_Button_Matrix']))
        pan_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(pan_controls=self._midimap[u'Slider_Button_Matrix']))
        self._modes.add_mode(
            u'pan_mode', [
                partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
                pan_layer_mode, self._action_button_background_layer_mode,
                self._session_zooming_manager,
                self._prioritized_session_zooming_button_layer_mode,
                pan_mode_scene_launch_translation,
                self._session.update_navigation_buttons
            ],
            behaviour=SpecialReenterBehaviour(u'session_mode'))

    def _create_sends_mode(self):
        send_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(send_controls=self._midimap[u'Slider_Button_Matrix'],
                        send_select_buttons=self.
                        _midimap[u'Scene_Launch_Button_Matrix']))
        self._modes.add_mode(
            u'sends_mode', [
                partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
                send_layer_mode, self._action_button_background_layer_mode,
                self._session_zooming_manager,
                self._prioritized_session_zooming_button_layer_mode,
                self._session.update_navigation_buttons
            ],
            behaviour=SpecialReenterBehaviour(u'session_mode'))

    def _create_stop_clips_mode(self):
        stop_layer_mode = AddLayerMode(
            self._session,
            Layer(
                stop_track_clip_buttons=self._midimap[u'Mixer_Button_Matrix'],
                stop_scene_clip_buttons=self.
                _midimap[u'Scene_Stop_Button_Matrix'],
                stop_all_clips_button=self._midimap[u'Stop_All_Clips_Button']))
        self._modes.add_mode(
            u'stop_clip_mode', [
                partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
                self._session_layer_mode, stop_layer_mode,
                self._session_zooming_manager,
                self._prioritized_session_zooming_button_layer_mode,
                self._session.update_navigation_buttons
            ],
            behaviour=SpecialReenterBehaviour(u'session_mode'))

    def toggle_detail_view(self):
        view = self.application().view
        if view.is_view_visible(u'Detail'):
            if view.is_view_visible(u'Detail/DeviceChain'):
                view.show_view(u'Detail/Clip')
            else:
                view.show_view(u'Detail/DeviceChain')

    def _create_user(self):
        self._user_matrix_component = UserMatrixComponent(
            name=u'User_Matrix_Component',
            is_enabled=False,
            layer=Layer(user_button_matrix_ch_6=self.
                        _midimap[u'User_Button_Matrix_Ch_6'],
                        user_button_matrix_ch_7=self.
                        _midimap[u'User_Button_Matrix_Ch_7'],
                        user_button_matrix_ch_8=self.
                        _midimap[u'User_Button_Matrix_Ch_8'],
                        user_button_matrix_ch_14=self.
                        _midimap[u'User_Button_Matrix_Ch_14'],
                        user_button_matrix_ch_15=self.
                        _midimap[u'User_Button_Matrix_Ch_15'],
                        user_button_matrix_ch_16=self.
                        _midimap[u'User_Button_Matrix_Ch_16'],
                        user_left_side_button_matrix_ch_6=self.
                        _midimap[u'User_Left_Side_Button_Matrix_Ch_6'],
                        user_left_side_button_matrix_ch_7=self.
                        _midimap[u'User_Left_Side_Button_Matrix_Ch_7'],
                        user_left_side_button_matrix_ch_8=self.
                        _midimap[u'User_Left_Side_Button_Matrix_Ch_8'],
                        user_left_side_button_matrix_ch_14=self.
                        _midimap[u'User_Left_Side_Button_Matrix_Ch_14'],
                        user_left_side_button_matrix_ch_15=self.
                        _midimap[u'User_Left_Side_Button_Matrix_Ch_15'],
                        user_left_side_button_matrix_ch_16=self.
                        _midimap[u'User_Left_Side_Button_Matrix_Ch_16'],
                        user_right_side_button_matrix_ch_6=self.
                        _midimap[u'User_Right_Side_Button_Matrix_Ch_6'],
                        user_right_side_button_matrix_ch_7=self.
                        _midimap[u'User_Right_Side_Button_Matrix_Ch_7'],
                        user_right_side_button_matrix_ch_8=self.
                        _midimap[u'User_Right_Side_Button_Matrix_Ch_8'],
                        user_right_side_button_matrix_ch_14=self.
                        _midimap[u'User_Right_Side_Button_Matrix_Ch_14'],
                        user_right_side_button_matrix_ch_15=self.
                        _midimap[u'User_Right_Side_Button_Matrix_Ch_15'],
                        user_right_side_button_matrix_ch_16=self.
                        _midimap[u'User_Right_Side_Button_Matrix_Ch_16'],
                        user_bottom_button_matrix_ch_6=self.
                        _midimap[u'User_Bottom_Button_Matrix_Ch_6'],
                        user_bottom_button_matrix_ch_7=self.
                        _midimap[u'User_Bottom_Button_Matrix_Ch_7'],
                        user_bottom_button_matrix_ch_8=self.
                        _midimap[u'User_Bottom_Button_Matrix_Ch_8'],
                        user_bottom_button_matrix_ch_14=self.
                        _midimap[u'User_Bottom_Button_Matrix_Ch_14'],
                        user_bottom_button_matrix_ch_15=self.
                        _midimap[u'User_Bottom_Button_Matrix_Ch_15'],
                        user_bottom_button_matrix_ch_16=self.
                        _midimap[u'User_Bottom_Button_Matrix_Ch_16'],
                        user_arrow_button_matrix_ch_6=self.
                        _midimap[u'User_Arrow_Button_Matrix_Ch_6'],
                        user_arrow_button_matrix_ch_7=self.
                        _midimap[u'User_Arrow_Button_Matrix_Ch_7'],
                        user_arrow_button_matrix_ch_8=self.
                        _midimap[u'User_Arrow_Button_Matrix_Ch_8'],
                        user_arrow_button_matrix_ch_14=self.
                        _midimap[u'User_Arrow_Button_Matrix_Ch_14'],
                        user_arrow_button_matrix_ch_15=self.
                        _midimap[u'User_Arrow_Button_Matrix_Ch_15'],
                        user_arrow_button_matrix_ch_16=self.
                        _midimap[u'User_Arrow_Button_Matrix_Ch_16']))
        self._user_matrix_component.set_enabled(True)

    @subject_slot(u'drum_group')
    def _on_drum_group_changed(self):
        if self._note_modes.selected_mode == u'drum_mode':
            self._drum_group.set_drum_group_device(
                self._drum_group_finder.drum_group)
        if self._modes.selected_mode == u'note_mode':
            self._select_note_mode()
        else:
            self.release_controlled_track()
        self._update_note_mode_button(
            self._drum_group_finder.drum_group is not None)

    def _select_note_mode(self):
        u"""
        Selects which note mode to use depending on the kind of
        current target track and its device chain.  Will also
        select the target if specified.
        """
        track = self._target_track_component.target_track
        drum_device = self._drum_group_finder.drum_group
        if track is None or track.is_foldable or track in self.song(
        ).return_tracks or track == self.song(
        ).master_track or track.is_frozen or track.has_audio_input:
            self._note_modes.selected_mode = u'audio_mode'
        elif drum_device:
            self._note_modes.selected_mode = u'drum_mode'
        else:
            self._note_modes.selected_mode = u'chromatic_mode'
        self._modes.update()
        if self._note_modes.selected_mode == u'audio_mode':
            self.release_controlled_track()
        else:
            self.set_controlled_track(
                self._target_track_component.target_track)

    def _select_target_track(self):
        track = self._target_track_component.target_track
        if track != self.song().view.selected_track:
            self.song().view.selected_track = track

    def _update_note_mode_button(self, focused_track_is_drum_track):
        button = self._midimap[u'Note_Mode_Button']
        if focused_track_is_drum_track:
            button.default_states = {
                True: u'Mode.Drum.On',
                False: u'Mode.Drum.Off'
            }
        else:
            button.default_states = {
                True: u'Mode.Chromatic.On',
                False: u'Mode.Chromatic.Off'
            }
        button.reset_state()
        self._modes.update()

    def _show_playing_clip(self):
        track = None
        if self._use_sel_track():
            track = self.song().view.selected_track
        else:
            track = self._target_track_component.target_track
        if track in self.song().tracks:
            slot_index = track.fired_slot_index
            if slot_index < 0:
                slot_index = track.playing_slot_index
            if slot_index >= 0:
                clip_slot = track.clip_slots[slot_index]
                self.song().view.highlighted_clip_slot = clip_slot

    def _set_clip_actions_type(self):
        self._clip_actions_component.use_selected_track(self._use_sel_track())
        self._clip_actions_component.update()

    def _use_sel_track(self):
        return self._modes.selected_mode == u'device_mode'

    def _should_arm_track(self):
        return self._modes.selected_mode == u'record_arm_mode'

    @subject_slot(u'selected_mode')
    def _on_layout_changed(self, mode):
        if mode == u'note_mode':
            self.set_controlled_track(
                self._target_track_component.target_track)
        else:
            self.release_controlled_track()
        self._session_record.set_enabled(mode != u'user_mode')

    @subject_slot(u'session_record')
    def _on_session_record_changed(self):
        status = self.song().session_record
        feedback_color = int(self._skin[u'Instrument.FeedbackRecord']
                             if status else self._skin[u'Instrument.Feedback'])
        self._c_instance.set_feedback_velocity(feedback_color)

    def _clear_send_cache(self):
        with self.component_guard():
            for control in self.controls:
                control.clear_send_cache()

    def _update_hardware(self):
        self._clear_send_cache()
        self.update()

    def _update_global_components(self):
        self._actions_component.update()
        self._session_record.update()
        self._modifier_background_component.update()

    def _layout_setup(self, mode):
        self._layout_switch(mode)
        self._clear_send_cache()
        self._update_global_components()

    def _layout_switch(self, mode):
        prefix = consts.SYSEX_STANDARD_PREFIX + consts.SYSEX_PARAM_BYTE_LAYOUT
        suffix = consts.SYSEX_STANDARD_SUFFIX
        self._send_midi(prefix + mode + suffix)
        self._last_sent_mode_byte = mode

    def port_settings_changed(self):
        self.set_highlighting_session_component(None)
        super(Launchpad_Pro, self).port_settings_changed()

    def on_identified(self):
        self._send_challenge()

    def _send_challenge(self):
        challenge_bytes = []
        for index in range(4):
            challenge_bytes.append(self._challenge >> 8 * index & 127)

        challenge = consts.CHALLENGE_PREFIX + tuple(challenge_bytes) + (247, )
        self._send_midi(challenge)

    def _on_handshake_successful(self):
        self._do_send_midi(consts.LIVE_MODE_SWITCH_REQUEST)
        with self.component_guard():
            self._modes.set_enabled(True)
            self._actions_component.set_enabled(True)
            self._session_record.set_enabled(True)
            self._modifier_background_component.set_enabled(True)
            self._shifted_background.set_enabled(True)
            self.release_controlled_track()
            self.set_feedback_channels(consts.FEEDBACK_CHANNELS)
        if self._last_sent_mode_byte is not None:
            self._layout_setup(self._last_sent_mode_byte)
        self.set_highlighting_session_component(self._session)
        self.update()

    def _is_challenge_response(self, midi_bytes):
        return len(
            midi_bytes
        ) == 10 and midi_bytes[:7] == consts.SYSEX_STANDARD_PREFIX + consts.SYSEX_CHALLENGE_RESPONSE_BYTE

    def _is_response_valid(self, midi_bytes):
        response = long(midi_bytes[7])
        response += long(midi_bytes[8] << 8)
        return response == Live.Application.encrypt_challenge2(self._challenge)

    def handle_sysex(self, midi_bytes):
        if len(midi_bytes) < 7:
            pass
        elif self._is_challenge_response(
                midi_bytes) and self._is_response_valid(midi_bytes):
            self._on_handshake_successful()
        elif midi_bytes[6] == consts.SYSEX_STATUS_BYTE_LAYOUT and midi_bytes[
                7] == consts.NOTE_LAYOUT_SYSEX_BYTE[0]:
            self._update_hardware()
        elif midi_bytes[6] in (consts.SYSEX_STATUS_BYTE_MODE,
                               consts.SYSEX_STATUS_BYTE_LAYOUT):
            pass
        else:
            super(Launchpad_Pro, self).handle_sysex(midi_bytes)
Example #8
0
class Crate(ControlSurface):
	__module__ = __name__
	__doc__ = " Monomodular controller script for Crate "


	def __init__(self, *a, **k):
		super(Crate, self).__init__(*a, **k)
		self._host_name = 'Crate'
		self._version_check = '1.0'
		self._rgb = 0
		self._timer = 0
		self._touched = 0
		self.flash_status = 1
		with self.component_guard():
			self._setup_monobridge()
			self._setup_controls()
			self._setup_session()
			self._setup_next_buttons()
			self._setup_tempo()
			self._setup_modes()
			self._create_fallback_control_owner()
		self.schedule_message(1, self._open_log)
		self.schedule_message(3, self._initialize_surface)
	

	def _open_log(self):
		self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) + " " + str(self._version_check) + " log opened =>>>>>>>>>>>>>>>>>>>") 
		self.show_message(str(self._host_name) + ' Control Surface Loaded')
	

	def _initialize_surface(self):
		debug('setting to main mode')
		#self._main_modes.selected_mod = 'Main'
		#self._session.set_enabled(True)
	

	def port_settings_changed(self):
		debug('port settings changed!')
		self._connected = False
		super(Crate, self).port_settings_changed()
	

	def _setup_monobridge(self):
		self._monobridge = MonoBridgeElement(self)
		self._monobridge.name = 'MonoBridge'
	

	def _with_shift(self, button):
		return ComboElement(button, modifiers=[self._shift_button])
	

	def _setup_controls(self):
		self._button = [CrateButtonElement(True, MIDI_NOTE_TYPE, 0, index, name = 'Button_' + str(index), script = self) for index in range(20)]
		self._track_button = [CrateButtonElement(True, MIDI_NOTE_TYPE, 0, index+50, name = 'Button_' + str(index+50), script = self) for index in range(6)]
		self._next_button = [CrateButtonElement(True, MIDI_NOTE_TYPE, 0, index+60, name = 'Button_' + str(index+60), script = self) for index in range(2)]
		self._crate_button = [CrateButtonElement(True, MIDI_NOTE_TYPE, 0, index+70, name = 'Button_' + str(index+70), script = self) for index in range(3)]
		#self._tempo_slider = EncoderElement(MIDI_CC_TYPE, 0, 0, Live.MidiMap.MapMode.absolute, name = 'Slider')

		self._matrix = ButtonMatrixElement(name = 'Matrix', rows = [[self._button[index]] for index in range(20)])

		self._left_matrix = ButtonMatrixElement(name = 'Left_Matrix', rows = [[self._button[index]] for index in range(10)])
		self._right_matrix = ButtonMatrixElement(name = 'Right_Matrix', rows = [[self._button[index+10]] for index in range(10)])

		self._track_select_matrix = ButtonMatrixElement(name = 'Track_Matrix', rows = [self._track_button])

	

	def _setup_session(self):
		self._left_session = CrateSessionComponent(script = self, name = 'Session_Component_A', num_tracks = 1, num_scenes = 20, autonaming = True, is_enabled = False, layer = Layer(priority = 1, clip_launch_buttons = self._matrix, track_nav_buttons = self._track_select_matrix))
		self._left_session.set_group_track('DECK A')
		self._left_session_zooming = SessionZoomingComponent(session = self._left_session)

		self._right_session = CrateSessionComponent(script = self, name = 'Session_Component_B', num_tracks = 1, num_scenes = 20, autonaming = True, is_enabled = False, layer = Layer(priority = 1, clip_launch_buttons = self._matrix, track_nav_buttons = self._track_select_matrix))
		self._right_session.set_group_track('DECK B')
		self._right_session_zooming = SessionZoomingComponent(session = self._right_session)

		self._left_set_session = CrateSetSessionComponent(script = self, name = 'Session_Component_SETA', num_tracks = 1, num_scenes = 10, autonaming = True, is_enabled = False, layer = Layer(priority = 1, clip_launch_buttons = self._left_matrix))
		self._left_set_session.set_group_track('SET A')
		self._left_set_session_zooming = SessionZoomingComponent(session = self._left_set_session)

		self._right_set_session = CrateSetSessionComponent(script = self, name = 'Session_Component_SETB', num_tracks = 1, num_scenes = 10, autonaming = True, is_enabled = False, layer = Layer(priority = 1, clip_launch_buttons = self._right_matrix))
		self._right_set_session.set_group_track('SET B')
		self._right_set_session_zooming = SessionZoomingComponent(session = self._right_set_session)
	

	def _setup_next_buttons(self):
		self._next_a_button = FireNextClipComponent()
		self._next_a_button.set_track('SET A')
		self._next_a_button.layer = Layer(button = self._next_button[0])

		self._next_b_button = FireNextClipComponent()
		self._next_b_button.set_track('SET B')
		self._next_b_button.layer = Layer(button = self._next_button[1])
	

	def _setup_tempo(self):
		self._on_tempo_changed.subject = self.song()
		self._on_tempo_changed()
	

	@subject_slot('value')
	def _on_tempo_slider_value(self, value):
		self.song().tempo = ((value/127.)*979.)+20.
	

	@subject_slot('tempo')
	def _on_tempo_changed(self, *a, **k):
		debug('on tempo changed:', self.song().tempo)
		new_tempo = self.song().tempo
		#self._on_tempo_slider_value.subject and self._on_tempo_slider_value.subject.send_value(((new_tempo-20)/979)*127)
		self.send_tempo('Tempo '+str(new_tempo))
	

	def _setup_modes(self):

		next_buttons = CompoundMode(self._next_a_button, self._next_a_button)
		self._main_modes = ModesComponent(name = 'MainModes')
		self._main_modes.add_mode('disabled', None)
		self._main_modes.add_mode('left_session', [self._left_session, next_buttons])
		self._main_modes.add_mode('right_session', [self._right_session, next_buttons])
		self._main_modes.add_mode('set_session', [self._left_set_session, self._right_set_session, next_buttons])
		self._main_modes.layer = Layer(priority = 6, left_session_button = self._crate_button[0], right_session_button = self._crate_button[1], set_session_button = self._crate_button[2])
		self._main_modes.selected_mode = 'set_session'
		self._main_modes.set_enabled(True)

		#self._next_a_button.set_enabled(True)
		#self._next_b_button.set_enabled(True)
	

	def _create_fallback_control_owner(self):
		self.register_disconnectable(SimpleLayerOwner(layer=Layer(_matrix=self._matrix, priority=0)))
	

	def update_display(self):
		super(Crate, self).update_display()
		self._timer = (self._timer + 1) % 256
		self.flash()
	

	def flash(self):
		if(self.flash_status > 0):
			for control in self.controls:
				if isinstance(control, MonoButtonElement):
					control.flash(self._timer)		
	

	@subject_slot('appointed_device')
	def _on_device_changed(self):
		debug('appointed device changed, script')
	

	def generate_strip_string(self, display_string):
		NUM_CHARS_PER_DISPLAY_STRIP = 12
		if (not display_string):
			return (' ' * NUM_CHARS_PER_DISPLAY_STRIP)
		if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))):
			display_string = display_string[:-2]
		if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)):
			for um in [' ',
			 'i',
			 'o',
			 'u',
			 'e',
			 'a']:
				while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)):
					um_pos = display_string.rfind(um, 1)
					display_string = (display_string[:um_pos] + display_string[(um_pos + 1):])
		else:
			display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1))
		ret = u''
		for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)):
			if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)):
				ret += ' '
			else:
				ret += display_string[i]

		ret += ' '
		ret = ret.replace(' ', '_')
		assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
		return ret
	

	def notification_to_bridge(self, name, value, sender):
		if(isinstance(sender, (MonoEncoderElement, CodecEncoderElement))):
			pn = str(self.generate_strip_string(name))
			pv = str(self.generate_strip_string(value))
			self._monobridge._send(sender.name, 'lcd_name', pn)
			self._monobridge._send(sender.name, 'lcd_value', pv)
	

	def touched(self):
		if self._touched is 0:
			self._monobridge._send('touch', 'on')
			self.schedule_message(2, self.check_touch)
		self._touched +=1
	

	def check_touch(self):
		if self._touched > 5:
			self._touched = 5
		elif self._touched > 0:
			self._touched -= 1
		if self._touched is 0:
			self._monobridge._send('touch', 'off')
		else:
			self.schedule_message(2, self.check_touch)
	

	def handle_sysex(self, midi_bytes):
		pass
	

	def disconnect(self):
		self.log_message("<<<<<<<<<<<<<<<<<<<<<<<<< " + str(self._host_name) + " log closed >>>>>>>>>>>>>>>>>>>>>>>>>")
		super(Crate, self).disconnect()
	

	def handle_sysex(self, midi_bytes):
		#debug('sysex: ', str(midi_bytes))
		pass
	

	def clip_name(self, sender, name):
		offset = self._button.index(sender)
		shortname = encode_name_to_sysex(name)
		display_sysex = (240,
			 0,
			 0,
			 102,
			 1,
			 offset) + tuple(shortname) + (247,)
		self._do_send_midi(display_sysex)
	

	def track_name(self, offset, name):
		shortname = encode_name_to_sysex(name)
		display_sysex = (240,
			 0,
			 0,
			 102,
			 2,
			 offset) + tuple(shortname) + (247,)
		self._do_send_midi(display_sysex)
	

	def send_tempo(self, tempo):
		shortname = encode_name_to_sysex(tempo)
		display_sysex = (240,
			 0,
			 0,
			 102,
			 3,) + tuple(shortname) + (247,)
		self._do_send_midi(display_sysex)
	



#	a
class Roland_A_PRO(ControlSurface):
    def __init__(self, *a, **k):
        super(Roland_A_PRO, self).__init__(*a, **k)
        with self.component_guard():
            self._create_controls()
            self._create_transport()
            self._create_mixer()
            self._create_device()
            self._create_drums()
            self._create_modes()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[
            EncoderElement(MIDI_CC_TYPE,
                           0,
                           identifier,
                           Live.MidiMap.MapMode.absolute,
                           name=b'Encoder_%d' % index)
            for index, identifier in enumerate(ENCODER_IDS)
        ]])
        self._master_encoder = EncoderElement(MIDI_CC_TYPE,
                                              0,
                                              10,
                                              Live.MidiMap.MapMode.absolute,
                                              name=b'Master_Encoder')
        self._sliders = ButtonMatrixElement(rows=[[
            SliderElement(
                MIDI_CC_TYPE, 0, identifier, name=b'Slider_%d' % index)
            for index, identifier in enumerate(SLIDER_IDS)
        ]])
        self._master_slider = SliderElement(MIDI_CC_TYPE,
                                            0,
                                            7,
                                            name=b'Master_Slider')
        self._play_button = ButtonElement(True, MIDI_CC_TYPE, 0, 26)
        self._stop_button = ButtonElement(True, MIDI_CC_TYPE, 0, 25)
        self._record_button = ButtonElement(True, MIDI_CC_TYPE, 0, 28)
        self._forward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 24)
        self._backward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 21)
        self._ff_button = ButtonElement(True, MIDI_CC_TYPE, 0, 23)
        self._rw_button = ButtonElement(True, MIDI_CC_TYPE, 0, 22)
        self._device_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 80)
        self._pan_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 81)
        self._send_a_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 82)
        self._send_b_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 83)
        self._pads = ButtonMatrixElement(rows=[[
            ButtonElement(True, MIDI_NOTE_TYPE, 0, identifier)
            for identifier in row
        ] for row in PAD_ROWS])

    def _create_transport(self):
        self._transport = TransportComponent(
            name=b'Transport',
            is_enabled=False,
            layer=Layer(play_button=self._play_button,
                        stop_button=self._stop_button,
                        record_button=self._record_button))
        self._transport.set_enabled(True)

    def _create_mixer(self):
        mixer_size = self._sliders.width()
        self._mixer = MixerComponent(
            mixer_size,
            name=b'Mixer',
            is_enabled=False,
            layer=Layer(volume_controls=self._sliders,
                        prehear_volume_control=self._master_encoder))
        self._mixer.master_strip().layer = Layer(
            volume_control=self._master_slider)
        self._mixer.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(
            device_selection_follows_track_selection=True)
        self._device_navigation = DeviceNavigationComponent()
        self._device.set_enabled(True)
        self._device_navigation.set_enabled(True)
        self.set_device_component(self._device)

    def _create_drums(self):
        self._drums = DrumRackComponent(name=b'Drum_Rack',
                                        is_enabled=False,
                                        layer=Layer(pads=self._pads))
        self._drums.set_enabled(True)

    def _create_modes(self):
        self._encoder_modes = ModesComponent()
        device_layer_mode = LayerMode(self._device,
                                      Layer(parameter_controls=self._encoders))
        device_navigation_layer_mode = LayerMode(
            self._device_navigation,
            Layer(device_nav_right_button=self._forward_button,
                  device_nav_left_button=self._backward_button))
        self._encoder_modes.add_mode(
            b'device_mode', [device_layer_mode, device_navigation_layer_mode])
        self._encoder_modes.add_mode(
            b'pan_mode',
            AddLayerMode(
                self._mixer,
                Layer(pan_controls=self._encoders,
                      bank_up_button=self._forward_button,
                      bank_down_button=self._backward_button,
                      track_up_button=self._ff_button,
                      track_down_button=self._rw_button)))
        send_layer_mode = AddLayerMode(
            self._mixer,
            Layer(send_controls=self._encoders,
                  bank_up_button=self._forward_button,
                  bank_down_button=self._backward_button,
                  track_up_button=self._ff_button,
                  track_down_button=self._rw_button))
        self._encoder_modes.add_mode(
            b'send_a_mode',
            [send_layer_mode,
             partial(self._set_send_index, 0)])
        self._encoder_modes.add_mode(
            b'send_b_mode',
            [send_layer_mode,
             partial(self._set_send_index, 1)])
        self._encoder_modes.layer = Layer(
            device_mode_button=self._device_mode_button,
            pan_mode_button=self._pan_mode_button,
            send_a_mode_button=self._send_a_mode_button,
            send_b_mode_button=self._send_b_mode_button)
        self._encoder_modes.selected_mode = b'device_mode'
        self._encoder_modes.set_enabled(True)

    def _set_send_index(self, index):
        self._mixer.send_index = index
Example #10
0
class Crate(ControlSurface):
    __module__ = __name__
    __doc__ = " Monomodular controller script for Crate "

    def __init__(self, *a, **k):
        super(Crate, self).__init__(*a, **k)
        self._host_name = 'Crate'
        self._version_check = '1.0'
        self._rgb = 0
        self._timer = 0
        self._touched = 0
        self.flash_status = 1
        with self.component_guard():
            self._setup_monobridge()
            self._setup_controls()
            self._setup_session()
            self._setup_next_buttons()
            self._setup_tempo()
            self._setup_modes()
            self._create_fallback_control_owner()
        self.schedule_message(1, self._open_log)
        self.schedule_message(3, self._initialize_surface)

    def _open_log(self):
        self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) +
                         " " + str(self._version_check) +
                         " log opened =>>>>>>>>>>>>>>>>>>>")
        self.show_message(str(self._host_name) + ' Control Surface Loaded')

    def _initialize_surface(self):
        debug('setting to main mode')
        #self._main_modes.selected_mod = 'Main'
        #self._session.set_enabled(True)

    def port_settings_changed(self):
        debug('port settings changed!')
        self._connected = False
        super(Crate, self).port_settings_changed()

    def _setup_monobridge(self):
        self._monobridge = MonoBridgeElement(self)
        self._monobridge.name = 'MonoBridge'

    def _with_shift(self, button):
        return ComboElement(button, modifiers=[self._shift_button])

    def _setup_controls(self):
        self._button = [
            CrateButtonElement(True,
                               MIDI_NOTE_TYPE,
                               0,
                               index,
                               name='Button_' + str(index),
                               script=self) for index in range(20)
        ]
        self._track_button = [
            CrateButtonElement(True,
                               MIDI_NOTE_TYPE,
                               0,
                               index + 50,
                               name='Button_' + str(index + 50),
                               script=self) for index in range(6)
        ]
        self._next_button = [
            CrateButtonElement(True,
                               MIDI_NOTE_TYPE,
                               0,
                               index + 60,
                               name='Button_' + str(index + 60),
                               script=self) for index in range(2)
        ]
        self._crate_button = [
            CrateButtonElement(True,
                               MIDI_NOTE_TYPE,
                               0,
                               index + 70,
                               name='Button_' + str(index + 70),
                               script=self) for index in range(3)
        ]
        #self._tempo_slider = EncoderElement(MIDI_CC_TYPE, 0, 0, Live.MidiMap.MapMode.absolute, name = 'Slider')

        self._matrix = ButtonMatrixElement(name='Matrix',
                                           rows=[[self._button[index]]
                                                 for index in range(20)])

        self._left_matrix = ButtonMatrixElement(name='Left_Matrix',
                                                rows=[[self._button[index]]
                                                      for index in range(10)])
        self._right_matrix = ButtonMatrixElement(
            name='Right_Matrix',
            rows=[[self._button[index + 10]] for index in range(10)])

        self._track_select_matrix = ButtonMatrixElement(
            name='Track_Matrix', rows=[self._track_button])

    def _setup_session(self):
        self._left_session = CrateSessionComponent(
            script=self,
            name='Session_Component_A',
            num_tracks=1,
            num_scenes=20,
            autonaming=True,
            is_enabled=False,
            layer=Layer(priority=1,
                        clip_launch_buttons=self._matrix,
                        track_nav_buttons=self._track_select_matrix))
        self._left_session.set_group_track('DECK A')
        self._left_session_zooming = SessionZoomingComponent(
            session=self._left_session)

        self._right_session = CrateSessionComponent(
            script=self,
            name='Session_Component_B',
            num_tracks=1,
            num_scenes=20,
            autonaming=True,
            is_enabled=False,
            layer=Layer(priority=1,
                        clip_launch_buttons=self._matrix,
                        track_nav_buttons=self._track_select_matrix))
        self._right_session.set_group_track('DECK B')
        self._right_session_zooming = SessionZoomingComponent(
            session=self._right_session)

        self._left_set_session = CrateSetSessionComponent(
            script=self,
            name='Session_Component_SETA',
            num_tracks=1,
            num_scenes=10,
            autonaming=True,
            is_enabled=False,
            layer=Layer(priority=1, clip_launch_buttons=self._left_matrix))
        self._left_set_session.set_group_track('SET A')
        self._left_set_session_zooming = SessionZoomingComponent(
            session=self._left_set_session)

        self._right_set_session = CrateSetSessionComponent(
            script=self,
            name='Session_Component_SETB',
            num_tracks=1,
            num_scenes=10,
            autonaming=True,
            is_enabled=False,
            layer=Layer(priority=1, clip_launch_buttons=self._right_matrix))
        self._right_set_session.set_group_track('SET B')
        self._right_set_session_zooming = SessionZoomingComponent(
            session=self._right_set_session)

    def _setup_next_buttons(self):
        self._next_a_button = FireNextClipComponent()
        self._next_a_button.set_track('SET A')
        self._next_a_button.layer = Layer(button=self._next_button[0])

        self._next_b_button = FireNextClipComponent()
        self._next_b_button.set_track('SET B')
        self._next_b_button.layer = Layer(button=self._next_button[1])

    def _setup_tempo(self):
        self._on_tempo_changed.subject = self.song()
        self._on_tempo_changed()

    @subject_slot('value')
    def _on_tempo_slider_value(self, value):
        self.song().tempo = ((value / 127.) * 979.) + 20.

    @subject_slot('tempo')
    def _on_tempo_changed(self, *a, **k):
        debug('on tempo changed:', self.song().tempo)
        new_tempo = self.song().tempo
        #self._on_tempo_slider_value.subject and self._on_tempo_slider_value.subject.send_value(((new_tempo-20)/979)*127)
        self.send_tempo('Tempo ' + str(new_tempo))

    def _setup_modes(self):

        next_buttons = CompoundMode(self._next_a_button, self._next_a_button)
        self._main_modes = ModesComponent(name='MainModes')
        self._main_modes.add_mode('disabled', None)
        self._main_modes.add_mode('left_session',
                                  [self._left_session, next_buttons])
        self._main_modes.add_mode('right_session',
                                  [self._right_session, next_buttons])
        self._main_modes.add_mode(
            'set_session',
            [self._left_set_session, self._right_set_session, next_buttons])
        self._main_modes.layer = Layer(
            priority=6,
            left_session_button=self._crate_button[0],
            right_session_button=self._crate_button[1],
            set_session_button=self._crate_button[2])
        self._main_modes.selected_mode = 'set_session'
        self._main_modes.set_enabled(True)

        #self._next_a_button.set_enabled(True)
        #self._next_b_button.set_enabled(True)

    def _create_fallback_control_owner(self):
        self.register_disconnectable(
            SimpleLayerOwner(layer=Layer(_matrix=self._matrix, priority=0)))

    def update_display(self):
        super(Crate, self).update_display()
        self._timer = (self._timer + 1) % 256
        self.flash()

    def flash(self):
        if (self.flash_status > 0):
            for control in self.controls:
                if isinstance(control, MonoButtonElement):
                    control.flash(self._timer)

    @subject_slot('appointed_device')
    def _on_device_changed(self):
        debug('appointed device changed, script')

    def generate_strip_string(self, display_string):
        NUM_CHARS_PER_DISPLAY_STRIP = 12
        if (not display_string):
            return (' ' * NUM_CHARS_PER_DISPLAY_STRIP)
        if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1))
                and (display_string.endswith('dB') and
                     (display_string.find('.') != -1))):
            display_string = display_string[:-2]
        if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)):
            for um in [' ', 'i', 'o', 'u', 'e', 'a']:
                while ((len(display_string) >
                        (NUM_CHARS_PER_DISPLAY_STRIP - 1))
                       and (display_string.rfind(um, 1) != -1)):
                    um_pos = display_string.rfind(um, 1)
                    display_string = (display_string[:um_pos] +
                                      display_string[(um_pos + 1):])
        else:
            display_string = display_string.center(
                (NUM_CHARS_PER_DISPLAY_STRIP - 1))
        ret = u''
        for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)):
            if ((ord(display_string[i]) > 127)
                    or (ord(display_string[i]) < 0)):
                ret += ' '
            else:
                ret += display_string[i]

        ret += ' '
        ret = ret.replace(' ', '_')
        assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
        return ret

    def notification_to_bridge(self, name, value, sender):
        if (isinstance(sender, (MonoEncoderElement, CodecEncoderElement))):
            pn = str(self.generate_strip_string(name))
            pv = str(self.generate_strip_string(value))
            self._monobridge._send(sender.name, 'lcd_name', pn)
            self._monobridge._send(sender.name, 'lcd_value', pv)

    def touched(self):
        if self._touched is 0:
            self._monobridge._send('touch', 'on')
            self.schedule_message(2, self.check_touch)
        self._touched += 1

    def check_touch(self):
        if self._touched > 5:
            self._touched = 5
        elif self._touched > 0:
            self._touched -= 1
        if self._touched is 0:
            self._monobridge._send('touch', 'off')
        else:
            self.schedule_message(2, self.check_touch)

    def handle_sysex(self, midi_bytes):
        pass

    def disconnect(self):
        self.log_message("<<<<<<<<<<<<<<<<<<<<<<<<< " + str(self._host_name) +
                         " log closed >>>>>>>>>>>>>>>>>>>>>>>>>")
        super(Crate, self).disconnect()

    def handle_sysex(self, midi_bytes):
        #debug('sysex: ', str(midi_bytes))
        pass

    def clip_name(self, sender, name):
        offset = self._button.index(sender)
        shortname = encode_name_to_sysex(name)
        display_sysex = (240, 0, 0, 102, 1,
                         offset) + tuple(shortname) + (247, )
        self._do_send_midi(display_sysex)

    def track_name(self, offset, name):
        shortname = encode_name_to_sysex(name)
        display_sysex = (240, 0, 0, 102, 2,
                         offset) + tuple(shortname) + (247, )
        self._do_send_midi(display_sysex)

    def send_tempo(self, tempo):
        shortname = encode_name_to_sysex(tempo)
        display_sysex = (
            240,
            0,
            0,
            102,
            3,
        ) + tuple(shortname) + (247, )
        self._do_send_midi(display_sysex)


#	a
Example #11
0
class Launchkey_MK2(OptimizedControlSurface):
    identity_request_delay = 0.5

    def __init__(self, c_instance, *a, **k):
        super(Launchkey_MK2, self).__init__(c_instance=c_instance, *a, **k)
        self._is_25_key_model = False
        self._is_in_control_on = True
        self._identity_response_pending = False
        with self.component_guard():
            self._skin = make_skin()
            with inject(skin=const(self._skin)).everywhere():
                self._create_controls()
        self._request_task = self._tasks.add(
            Task.sequence(Task.wait(self.identity_request_delay),
                          Task.run(self._send_identity_request)))
        self._request_task.kill()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[
            make_encoder(identifier, name=u'Encoder_%d' % (index, ))
            for index, identifier in enumerate(range(21, 29))
        ]])
        self._top_pad_row = ButtonMatrixElement(rows=[[
            make_button(identifier, name=u'Pad_0_%d' % (index, ))
            for index, identifier in enumerate(range(96, 104))
        ]])
        self._bottom_pad_row_raw = [
            make_button(identifier, name=u'Pad_1_%d' % (index, ))
            for index, identifier in enumerate(range(112, 120))
        ]
        self._bottom_pad_row = ButtonMatrixElement(
            rows=[self._bottom_pad_row_raw])
        self._top_launch_button = make_button(104, name=u'Scene_Launch_Button')
        self._bottom_launch_button = make_button(120,
                                                 name=u'Stop_All_Clips_Button')
        self._scene_up_button = make_button(112,
                                            MIDI_CC_TYPE,
                                            name=u'Scene_Up_Button')
        self._scene_down_button = make_button(113,
                                              MIDI_CC_TYPE,
                                              name=u'Scene_Down_Button')
        self._stop_button = make_button(114, MIDI_CC_TYPE, name=u'Stop_Button')
        self._play_button = make_button(115, MIDI_CC_TYPE, name=u'Play_Button')
        self._loop_button = make_button(116, MIDI_CC_TYPE, name=u'Loop_Button')
        self._record_button = make_button(117,
                                          MIDI_CC_TYPE,
                                          name=u'Record_Button')
        self._sliders = ButtonMatrixElement(rows=[[
            make_slider(identifier, name=u'Slider_%d' % (index, ))
            for index, identifier in enumerate(range(41, 49))
        ]])
        self._master_slider = make_slider(7, name=u'Master_Slider')
        self._25_key_slider = make_slider(7, name=u'Slider', channel=0)
        self._mute_buttons_raw = [
            make_button(identifier,
                        MIDI_CC_TYPE,
                        name=u'Mute_Button_%d' % (index, ))
            for index, identifier in enumerate(range(51, 59))
        ]
        self._mute_buttons = ButtonMatrixElement(rows=[self._mute_buttons_raw])
        self._master_button = make_button(59,
                                          MIDI_CC_TYPE,
                                          name=u'Master_Button')
        self._track_left_button = make_button(102,
                                              MIDI_CC_TYPE,
                                              name=u'Track_Left_Button')
        self._track_right_button = make_button(103,
                                               MIDI_CC_TYPE,
                                               name=u'Track_Right_Button')
        self._device_mode_button = self._bottom_pad_row_raw[0]
        self._pan_mode_button = self._bottom_pad_row_raw[1]
        self._send_mode_buttons = dict()
        for index in range(consts.MAX_SENDS):
            setattr(self, u'_send_%d_button' % (index, ),
                    self._bottom_pad_row_raw[index + 2])
            self._send_mode_buttons[u'send_%d_mode_button' %
                                    (index, )] = getattr(
                                        self, u'_send_%d_button' % (index, ))

        self._extended_mode_button = make_button(
            12, name=u'Dummy_Extended_Mode_Button')
        self._extended_mode_button.add_value_listener(nop)
        self._encoder_incontrol_button = make_button(
            13, is_momentary=False, name=u'Encoder_InControl_Button')
        self._encoder_incontrol_button.add_value_listener(nop)
        self._slider_incontrol_button = make_button(
            14, is_momentary=False, name=u'Fader_InControl_Button')
        self._slider_incontrol_button.add_value_listener(nop)
        self._pad_incontrol_button = make_button(15,
                                                 is_momentary=False,
                                                 name=u'Pad_InControl_Button')
        self._pad_incontrol_button.add_value_listener(self._update_pads)
        self._encoder_incontrol_button2 = make_button(
            16, name=u'Encoder_InControl_Button')
        self._pad_in_control_status_button = make_button(
            11, name=u'Dummy_InControl_Button')

    def _create_session(self):
        self._session = SessionComponent(
            name=u'Session',
            is_enabled=False,
            num_tracks=self._top_pad_row.width(),
            num_scenes=self._top_pad_row.height(),
            enable_skinning=True,
            layer=Layer(clip_launch_buttons=self._top_pad_row,
                        scene_launch_buttons=ButtonMatrixElement(
                            rows=[[self._top_launch_button]]),
                        stop_track_clip_buttons=self._bottom_pad_row,
                        stop_all_clips_button=self._bottom_launch_button))
        self._session.set_rgb_mode(LIVE_COLORS_TO_MIDI_VALUES, RGB_COLOR_TABLE)
        self._session.set_mixer(self._mixer)
        self._session.set_enabled(True)

    def _setup_navigation(self):
        self._session_navigation = SessionNavigationComponent(
            is_enabled=False,
            name=u'Session_Navigation',
            layer=Layer(next_track_button=self._track_right_button,
                        prev_track_button=self._track_left_button,
                        next_scene_button=self._scene_down_button,
                        prev_scene_button=self._scene_up_button))
        self._session_navigation.set_enabled(True)

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

    def _create_mixer(self):
        mixer_volume_layer = None
        if self._is_25_key_model:
            mixer_volume_layer = Layer(volume_control=self._25_key_slider)
        else:
            mixer_volume_layer = Layer(volume_controls=self._sliders)
        self._mixer = MixerComponent(is_enabled=False,
                                     name=u'Mixer',
                                     num_tracks=self._sliders.width(),
                                     layer=mixer_volume_layer)
        if not self._is_25_key_model:
            self._mixer.master_strip().layer = Layer(
                volume_control=self._master_slider)
        self._mixer.set_enabled(True)
        self._mute_button_modes = ModesComponent()
        mute_mode = AddLayerMode(self._mixer,
                                 Layer(mute_buttons=self._mute_buttons))
        solo_mode = AddLayerMode(self._mixer,
                                 Layer(solo_buttons=self._mute_buttons))
        self._mute_button_modes.add_mode(u'mute_mode', mute_mode)
        self._mute_button_modes.add_mode(u'solo_mode',
                                         solo_mode,
                                         behaviour=CancellableBehaviour())
        self._mute_button_modes.layer = Layer(
            solo_mode_button=self._master_button)
        self._mute_button_modes.selected_mode = u'mute_mode'
        self._mute_button_modes.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(
            name=u'Device',
            is_enabled=False,
            device_selection_follows_track_selection=True)
        self.set_device_component(self._device)
        self._device.set_enabled(True)

    def _create_background(self):
        self._background = BackgroundComponent(name=u'BackgroundComponent')

    def _create_encoder_modes(self):
        self._encoder_modes = DisablingModesComponent()
        self._encoder_modes.default_behaviour = mixin(SkinableBehaviourMixin,
                                                      ImmediateBehaviour)()
        device_mode = LayerMode(
            self._device,
            Layer(parameter_controls=self._encoders,
                  bank_buttons=self._top_pad_row))
        pan_mode = AddLayerMode(self._mixer,
                                Layer(pan_controls=self._encoders))
        sends_mode = AddLayerMode(self._mixer,
                                  Layer(send_controls=self._encoders))
        background_mode = LayerMode(self._background,
                                    Layer(bank_buttons=self._top_pad_row))
        self._encoder_modes.add_mode(u'device_mode',
                                     device_mode,
                                     is_enabled=True)
        self._encoder_modes.add_mode(u'pan_mode', [pan_mode, background_mode],
                                     is_enabled=True)
        for index in range(6):
            self._encoder_modes.add_mode(u'send_%d_mode' % (index, ), [
                sends_mode,
                partial(self._set_send_index, index), background_mode
            ],
                                         is_enabled=False)

        self._encoder_modes.selected_mode = u'device_mode'
        self._encoder_modes.set_enabled(True)

    def _create_mode_selector(self):
        self._mode_selector = ModesComponent()
        mode_selection = LayerMode(
            self._encoder_modes,
            Layer(device_mode_button=self._device_mode_button,
                  pan_mode_button=self._pan_mode_button,
                  **self._send_mode_buttons))
        device_navigation = AddLayerMode(
            self._device,
            Layer(device_nav_left_button=self._track_left_button,
                  device_nav_right_button=self._track_right_button))
        self._mode_selector.add_mode(u'mode_selection', [
            partial(self._toggle_in_control, True), mode_selection,
            device_navigation
        ],
                                     behaviour=MomentaryBehaviour())
        session_control = AddLayerMode(
            self._session, Layer(clip_launch_buttons=self._top_pad_row))
        self._mode_selector.add_mode(
            u'session_mode',
            [partial(self._toggle_in_control, False), session_control])
        self._mode_selector.layer = Layer(
            mode_selection_button=self._encoder_incontrol_button2)

    def _create_in_control_status_listener(self):
        self._in_control_status = InControlStatusComponent(
            set_is_in_control_on=self._set_is_in_control_on,
            is_enabled=False,
            layer=Layer(
                in_control_status_button=self._pad_in_control_status_button))
        self._in_control_status.set_enabled(True)

    @subject_slot(u'value')
    def _update_pads(self, value):
        if value:
            self.update()

    @subject_slot(u'return_tracks')
    def _on_return_tracks_changed(self):
        num_sends = self._mixer.num_sends
        for index in range(6):
            self._encoder_modes.set_mode_enabled(
                u'send_%d_mode' % (index, ),
                True if index < num_sends else False)

    def _set_send_index(self, index):
        self._mixer.send_index = index

    def _set_is_in_control_on(self, value):
        self._is_in_control_on = value

    def _toggle_in_control(self, value):
        if not self._is_in_control_on:
            self._send_midi(consts.DRUM_IN_CONTROL_ON_MESSAGE
                            if value else consts.DRUM_IN_CONTROL_OFF_MESSAGE)

    def port_settings_changed(self):
        self._disconnect_and_unregister_all_components()
        self._request_task.restart()

    def handle_sysex(self, midi_bytes):
        if self._is_identity_response(midi_bytes):
            product_id_bytes = self._extract_product_id_bytes(midi_bytes)
            if self._is_identity_response_valid(product_id_bytes):
                self._set_model_type(product_id_bytes)
                self._request_task.kill()
                if self._identity_response_pending:
                    self.on_identified()
                    self._identity_response_pending = False
            else:
                self.log_message(
                    u'MIDI device responded with wrong product id (%s).' %
                    (str(product_id_bytes), ))
        else:
            super(Launchkey_MK2, self).handle_sysex(midi_bytes)

    def _extract_product_id_bytes(self, midi_bytes):
        return midi_bytes[5:]

    def _is_identity_response(self, midi_bytes):
        return midi_bytes[3:5] == (6, 2)

    def _is_identity_response_valid(self, product_id_bytes):
        return product_id_bytes[:
                                3] == consts.PRODUCT_ID_BYTE_PREFIX and product_id_bytes[
                                    3] in consts.PRODUCT_ID_BYTES

    def _set_model_type(self, product_id_bytes):
        self._is_25_key_model = product_id_bytes[
            3] == consts.LAUNCHKEY_25_ID_BYTE

    def _send_identity_request(self):
        self._identity_response_pending = True
        self._send_midi(consts.IDENTITY_REQUEST)

    def on_identified(self):
        self._extended_mode_button.turn_on()
        with self.component_guard():
            self._create_mixer()
            self._create_session()
            self._setup_navigation()
            self._create_transport()
            self._create_device()
            self._create_background()
            self._create_encoder_modes()
            self._create_mode_selector()
            self._create_in_control_status_listener()
            self._on_return_tracks_changed.subject = self.song()
            self._on_return_tracks_changed()
        self._mode_selector.selected_mode = u'session_mode'
        self.update()

    def disconnect(self):
        self._extended_mode_button.turn_off()
        super(Launchkey_MK2, self).disconnect()
Example #12
0
class MonoPedal(ControlSurface):
    def __init__(self, *a, **k):
        super(MonoPedal, self).__init__(*a, **k)
        self._monomod_version = 'b995'
        self._codec_version = 'b996'
        self._cntrlr_version = 'b996'
        self._cntrlr = None
        self._host_name = 'MonoPedal'
        self._color_type = 'OhmRGB'
        self.hosts = []
        self._timer = 0
        self.flash_status = 1
        self._touched = 0
        self._last_main_mode = 'looper'
        with self.component_guard():
            self._setup_monobridge()
            self._setup_controls()
            self._setup_looper()
            self._setup_launcher()
            self._setup_device_control()
            self._setup_modes()
        self.schedule_message(1, self._open_log)
        #self._loop_selector.set_enabled(True)

    """script initialization methods"""

    def _open_log(self):
        self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) +
                         " " + str(self._monomod_version) +
                         " log opened =>>>>>>>>>>>>>>>>>>>")
        self.show_message(str(self._host_name) + ' Control Surface Loaded')

    def _setup_monobridge(self):
        self._monobridge = MonoBridgeElement(self)
        self._monobridge.name = 'MonoBridge'

    def _setup_controls(self):
        self._pedal = [None for index in range(8)]
        for index in range(7):
            self._pedal[index] = DoublePressElement(
                MonoButtonElement(True, MIDI_CC_TYPE, 0, PEDAL_DEFS[index],
                                  'Pedal_' + str(index), self))
            #is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self
            self._pedal[index].name = 'Pedal_' + str(index)
            self._pedal[index]._report = False
        self._pedal[7] = LoopPedalExpressionElement(
            self, MIDI_CC_TYPE, 0, 1, Live.MidiMap.MapMode.absolute)
        self._pedal[7].name = 'Pedal_' + str(7)
        self._pedal[7]._report = False
        self._leds = [None for index in range(4)]
        for index in range(4):
            red_led = ButtonElement(True, MIDI_NOTE_TYPE, 0, LED_DEFS[index])
            green_led = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                      LED_DEFS[index] + 4)
            blue_led = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                     LED_DEFS[index] + 8)
            self._leds[index] = RGB_LED(red_led, green_led, blue_led, True,
                                        MIDI_NOTE_TYPE, 0, index + 13,
                                        'LED_' + str(index), self)
        self._select_buttons = ButtonMatrixElement()
        self._select_buttons.name = 'SelectMatrix'
        self._select_buttons.add_row(
            [self._pedal[6], self._pedal[5], self._pedal[4], self._pedal[3]])
        self._doublepress_select_buttons = ButtonMatrixElement()
        self._doublepress_select_buttons.name = 'DoublepressSelectMatrix'
        self._doublepress_select_buttons.add_row([
            self._pedal[6].double_press, self._pedal[5].double_press,
            self._pedal[4].double_press, self._pedal[3].double_press
        ])

        self._record_button = self._pedal[1]
        self._mute_button = self._pedal[2]
        self._overdub_button = self._pedal[0]

    def _setup_looper(self):
        self._looper = MonolooperComponent(self._leds, self)
        self._looper.layer = Layer(
            select_buttons=self._select_buttons,
            doublepress_select_buttons=self._doublepress_select_buttons,
            overdub_button=self._pedal[2],
            record_button=self._pedal[1],
            mute_button=self._pedal[0],
            expression_pedal=self._pedal[7],
        )

    def _setup_launcher(self):
        self._launcher = LauncherComponent(self._leds, self)
        self._launcher.set_enabled(False)
        self._launcher.layer = Layer(
            select_buttons=self._select_buttons,
            doublepress_select_buttons=self._doublepress_select_buttons,
            fire1_button=self._pedal[2],
            fire2_button=self._pedal[1],
            fire3_button=self._pedal[0],
            expression_pedal=self._pedal[7])

    def _setup_device_control(self):
        self._device_control = DeviceControlComponent(self._leds, self)
        self._device_control.set_enabled(False)
        self._device_control.layer = Layer(
            select_buttons=self._select_buttons,
            doublepress_select_buttons=self._doublepress_select_buttons,
            toggle1_button=self._pedal[2],
            toggle2_button=self._pedal[1],
            toggle3_button=self._pedal[0],
            expression_pedal=self._pedal[7])

    def _setup_modes(self):
        self._button_modes = ModesComponent(name='Button_Modes')
        self._button_modes.add_mode('launcher', self._launcher)
        self._button_modes.add_mode('looper', self._looper)
        self._button_modes.add_mode('device', self._device_control)
        self._button_modes.selected_mode = 'looper'
        self._button_modes.set_enabled(True)

    def receive_led(self, button, value):
        #self.log_message('receive led: ' + str(index) + ' ' + str(value))
        pass

    def toggle_mode(self):
        self._button_modes.selected_mode = 'launcher' if self._button_modes.selected_mode is 'looper' else 'looper'
        self._last_main_mode = self._button_modes.selected_mode
        #self.log_message('toggle mode to: ' + str(self._button_modes.selected_mode))

    def toggle_device_control(self, x):
        self._button_modes.selected_mode = 'device' if not self._button_modes.selected_mode is 'device' else self._last_main_mode
        if self._button_modes.selected_mode is 'device':
            self._device_control.set_bank(x)

    """called on timer"""

    def update_display(self):
        super(MonoPedal, self).update_display()
        self._timer = (self._timer + 1) % 256
        self.flash()

    def flash(self):
        if (self.flash_status > 0):
            for control in self.controls:
                if isinstance(control, MonoButtonElement):
                    control.flash(self._timer)
Example #13
0
class PHAZE(APC40_MkII):
  """ APC40Mk2 script with step sequencer mode """
  def __init__(self, *a, **k):
    self._double_press_context = DoublePressContext()
    APC40_MkII.__init__(self, *a, **k)
    with self.component_guard():
      self._skin = make_default_skin()
  #    self._create_session()
      self._clip_creator = ClipCreator()
      self._init_background()
      self._init_step_sequencer()
      self._init_drum_component()
      self._init_instrument()
      self._init_note_repeat()
      self._init_matrix_modes() 
      self._create_device()
#      self._create_view_control()
      self._on_selected_track_changed()
    
    self.set_pad_translations(PAD_TRANSLATIONS)
    self.set_feedback_channels(FEEDBACK_CHANNELS)

  
  
  def _create_controls(self):
    """ Add some additional stuff baby """
    super(PHAZE, self)._create_controls()
    self._grid_resolution = GridResolution()
    self._velocity_slider = ButtonSliderElement(tuple(self._scene_launch_buttons_raw[::-1])) 
    double_press_rows = recursive_map(DoublePressElement, self._matrix_rows_raw) 
    self._double_press_matrix = ButtonMatrixElement(name='Double_Press_Matrix', rows=double_press_rows)
    self._double_press_event_matrix = ButtonMatrixElement(name='Double_Press_Event_Matrix', rows=recursive_map(lambda x: x.double_press, double_press_rows))
    self._playhead = PlayheadElement(self._c_instance.playhead)

    # Make these prioritized resources, which share between Layers() equally
    # Rather than building a stack
 
    """not sure but we greened out below on 05/11/17.. maybe work on order of definitions so as to tidy up some"""
 
    self._pan_button._resource_type = PrioritizedResource 
    self._user_button._resource_type = PrioritizedResource 
    
#    self._view_control = ViewControlComponent(name='View_Control')
#    self._view_control.set_enabled(False)
 

#  def _create_session(self):
      
#      def when_bank_on(button):
#        return self._bank_toggle.create_toggle_element(on_control=button)
    
#      def when_bank_off(button):
#        return self._bank_toggle.create_toggle_element(off_control=button)      
      
      
      
      
 #     self._session = SessionComponent(NUM_TRACKS, NUM_SCENES, 
 #     auto_name=True, is_enabled=False, enable_skinning=True, 
 #     layer=Layer(track_bank_left_button=when_bank_off(self._left_button), 
 #     track_bank_right_button=when_bank_off(self._right_button), 
 #     scene_bank_up_button=when_bank_off(self._up_button), 
 #     scene_bank_down_button=when_bank_off(self._down_button), 
 #     page_left_button=when_bank_on(self._left_button), 
 #     page_right_button=when_bank_on(self._right_button), 
 #     page_up_button=when_bank_on(self._up_button), 
 #     page_down_button=when_bank_on(self._down_button), 
 #     stop_track_clip_buttons=self._stop_buttons, 
 #     stop_all_clips_button=self._stop_all_button, 
 #     scene_launch_buttons=self._scene_launch_buttons, 
 #     clip_launch_buttons=self._session_matrix))
 #     clip_color_table = colors.CLIP_COLOR_TABLE.copy()
 #     clip_color_table[16777215] = 119
 #     self._session.set_rgb_mode(clip_color_table, colors.RGB_COLOR_TABLE)
 #     self._session_zoom = SessionZoomingComponent(self._session, name=u'Session_Overview', enable_skinning=True, is_enabled=False, layer=Layer(button_matrix=self._shifted_matrix, nav_left_button=self._with_shift(self._left_button), nav_right_button=self._with_shift(self._right_button), nav_up_button=self._with_shift(self._up_button), nav_down_button=self._with_shift(self._down_button), scene_bank_buttons=self._shifted_scene_buttons))
  
  
  
#  def _init_session(self):
#      self._session_mode = LazyEnablingMode(self._create_session)  
  
  
  def _create_device(self):
      self._device = DeviceComponent(name=u'Device', is_enabled=False, layer=Layer(parameter_controls=self._device_controls, bank_buttons=self._device_bank_buttons, bank_prev_button=self._device_prev_bank_button, bank_next_button=self._device_next_bank_button, on_off_button=self._device_on_off_button, lock_button=self._device_lock_button), device_selection_follows_track_selection=True)
  
  
  def _create_view_control(self):
      self._view_control = DetailViewCntrlComponent(name=u'View_Control', is_enabled=False, layer=Layer(device_nav_left_button=self._prev_device_button, device_nav_right_button=self._next_device_button, device_clip_toggle_button=self._clip_device_button, detail_toggle_button=self._detail_view_button))
      self._view_control.device_clip_toggle_button.pressed_color = u'DefaultButton.On'  
  
 
  def _init_background(self):
      self._background = BackgroundComponent(is_root=True)
      self._background.layer = Layer(velocity_slider = self._velocity_slider, stop_buttons = self._stop_buttons)#, display_line2=self._display_line2, display_line3=self._display_line3, display_line4=self._display_line4, top_buttons=self._select_buttons, bottom_buttons=self._track_state_buttons, scales_button=self._scale_presets_button, octave_up=self._octave_up_button, octave_down=self._octave_down_button, side_buttons=self._side_buttons, repeat_button=self._repeat_button, accent_button=self._accent_button, double_button=self._double_button, in_button=self._in_button, out_button=self._out_button, param_controls=self._global_param_controls, param_touch=self._global_param_touch_buttons, tempo_control_tap=self._tempo_control_tap, master_control_tap=self._master_volume_control_tap, touch_strip=self._touch_strip_control, touch_strip_tap=self._touch_strip_tap, nav_up_button=self._nav_up_button, nav_down_button=self._nav_down_button, nav_left_button=self._nav_left_button, nav_right_button=self._nav_right_button, aftertouch=self._aftertouch_control, pad_parameters=self._pad_parameter_control, _notification=self._notification.use_single_line(2), priority=consts.BACKGROUND_PRIORITY)
      self._matrix_background = BackgroundComponent()
      self._matrix_background.set_enabled(False)
      self._matrix_background.layer = Layer(matrix=self._session_matrix)
    #  self._mod_background = ModifierBackgroundComponent(is_root=True)
    #  self._mod_background.layer = Layer(shift_button=self._shift_button, velocity_slider = self._velocity_slider, stop_buttons = self._stop_buttons)
 
 
  def _init_step_sequencer(self):
    self._step_sequencer = StepSeqComponent(grid_resolution = self._grid_resolution)
    self._step_sequencer.layer = self._create_step_sequencer_layer()
  
 
 
  """added sunday PM  05/11/17"""
 
 
  def _init_note_repeat(self):
      self._note_repeat = NoteRepeatComponent(name='Note_Repeat')
      self._note_repeat.set_enabled(False)
      self._note_repeat.set_note_repeat(self._c_instance.note_repeat)
      self._note_repeat.layer = Layer(
     # aftertouch_control=self._aftertouch_control, 
      select_buttons=self._stop_buttons, 
     # pad_parameters=self._pad_parameter_control
      )
      self._note_repeat.layer.priority = consts.DIALOG_PRIORITY
      self._note_repeat_enabler = EnablingModesComponent(name='Note_Repeat_Enabler', component=self._note_repeat, toggle_value='DefaultButton.Alert', disabled_value='DefaultButton.On')
      self._note_repeat_enabler.set_enabled(False)
      self._note_repeat_enabler.layer = Layer(toggle_button=self._bank_button) 
 
 
  """added sunday PM 15:25 22/10/17"""
  
  def _init_drum_component(self):
    self._drum_component = DrumGroupComponent(name='Drum_Group', is_enabled=False)
    self._drum_component.layer = Layer(
    drum_matrix=self._session_matrix, 
#    page_strip=self._touch_strip_control, 
#    scroll_strip=self._with_shift(self._touch_strip_control), 
#    solo_button=self._global_solo_button, 
    select_button=self._metronome_button, 
#    delete_button=self._delete_button, 
    scroll_page_up_button=self._up_button, 
    scroll_page_down_button=self._down_button, 
#    quantize_button=self._quantize_button, 
#    mute_button=self._global_mute_button, 
    scroll_up_button=self._with_shift(self._up_button), 
    scroll_down_button=self._with_shift(self._down_button))
    
#    self._drum_component.select_drum_pad = self._selector.on_select_drum_pad
#    self._drum_component.quantize_pitch = self._quantize.quantize_pitch



  
  """lew sunday"""
  def _init_instrument(self):
    instrument_basic_layer = Layer(
    #octave_strip=self._with_shift(self._touch_strip_control), 
   # scales_toggle_button=self._tap_tempo_button, 
    
 #   capture_button = self._tap_tempo_button,
    octave_up_button=self._up_button, octave_down_button=self._down_button, 
    scale_up_button=self._with_shift(self._up_button), 
    scale_down_button=self._with_shift(self._down_button))
    self._instrument = MelodicComponent(skin=self._skin, is_enabled=False, 
    clip_creator=self._clip_creator, name='Melodic_Component', 
    grid_resolution=self._grid_resolution, 
    #note_editor_settings=self._add_note_editor_setting(), 
    layer=self._create_instrument_layer(), instrument_play_layer=instrument_basic_layer + Layer(matrix=self._session_matrix), 
    #touch_strip=self._touch_strip_control, touch_strip_indication=self._with_firmware_version(1, 16, ComboElement(self._touch_strip_control, modifiers=[self._select_button])), 
    #touch_strip_toggle=self._with_firmware_version(1, 16, ComboElement(self._touch_strip_tap, modifiers=[self._select_button])), 
    #aftertouch_control=self._aftertouch_control, delete_button=self._delete_button), 
    instrument_sequence_layer=instrument_basic_layer)# + Layer(note_strip=self._touch_strip_control))
    self._on_note_editor_layout_changed.subject = self._instrument



  def _init_matrix_modes(self):
    """ Switch between Session and StepSequencer modes """
    
 
 
   
    """here we go trying to switch.... lew  05:53   21/10/17"""
    
    self._auto_arm = AutoArmComponent(name='Auto_Arm')
    
    self._drum_group_finder = DrumGroupFinderComponent()
    self._on_drum_group_changed.subject = self._drum_group_finder
    
    
    self._drum_modes = ModesComponent(name='Drum_Modes', is_enabled=False)
    self._drum_modes.add_mode('sequencer', self._step_sequencer)   
    self._drum_modes.add_mode('64pads', self._drum_component)                                     # added 15:18 subday 22/10/17     can maybe look into this. causes issues when trying to scroll.(drumcomp1)
    
    self._drum_modes.selected_mode = 'sequencer'
   
    self._note_modes = ModesComponent(name='Note_Modes')#, is_enabled=False)
    self._note_modes.add_mode('drums', [self._note_repeat_enabler, self._drum_modes])
    self._drum_modes.selected_mode = 'sequencer'
    self._note_modes.add_mode('looper', self._audio_loop if consts.PROTO_AUDIO_NOTE_MODE else self._matrix_background)
    self._note_modes.add_mode('instrument', [self._note_repeat_enabler, self._instrument])
    self._note_modes.add_mode('disabled', self._matrix_background)
    self._note_modes.selected_mode = 'disabled'    
    self._note_modes.set_enabled(False)
    
    
    
    def switch_note_mode_layout():
      self._matrix_modes.selected_mode = 'note'

      if self._note_modes.selected_mode == 'instrument':
        getattr(self._instrument, 'cycle_mode', nop)()
      elif self._note_modes.selected_mode == 'drums':
        getattr(self._drum_modes, 'cycle_mode', nop)()    
    
    
    self._matrix_modes = ModesComponent(name='Matrix_Modes', is_root=True)
    self._matrix_modes.add_mode('session', self._session_mode_layers())
    self._matrix_modes.add_mode('note', [self._drum_group_finder, self._view_control, self._note_modes],behaviour=self._auto_arm.auto_arm_restore_behaviour(ReenterBehaviour, on_reenter=switch_note_mode_layout))
    
    self._matrix_modes.selected_mode = 'note'
    self._matrix_modes.layer = Layer(session_button=self._pan_button, note_button=self._user_button)
    
    self._on_matrix_mode_changed.subject = self._matrix_modes   
    self._matrix_modes.selected_mode = 'note'


    #added for looping capability
    #self._looper = LooperComponent(self)               
    #self._looper.name = 'looper_Component'    
    
  
  def _session_mode_layers(self):
    return [ self._session, self._session_zoom]

  def _create_step_sequencer_layer(self):
    return Layer(
        velocity_slider = self._velocity_slider,
        drum_matrix = self._session_matrix.submatrix[:4, 1:5],  # [4, 1:5],  mess with this for possible future 32 pad drum rack :
     

        button_matrix = self._double_press_matrix.submatrix[4:8, 1:5],   # [4:8, 1:5],
        
      #  next_page_button = self._bank_button,
        
        select_button = self._user_button,
        delete_button = self._stop_all_button,
        playhead = self._playhead,
        quantization_buttons = self._stop_buttons,
        shift_button = self._shift_button,
        loop_selector_matrix = self._double_press_matrix.submatrix[:4, :1],                # changed from [:8, :1] so as to enable bottem row of rack   . second value clip length rows
        short_loop_selector_matrix = self._double_press_event_matrix.submatrix[:4, :1],     # changed from [:8, :1] no change noticed as of yet   
        drum_bank_up_button = self._up_button,
        drum_bank_down_button = self._down_button)
 #       capture_button = self._tap_tempo_button)
        
  
  """lew sunday"""
  
  def _create_instrument_layer(self):
    return Layer(
      playhead=self._playhead, 
      #mute_button=self._global_mute_button, 
      quantization_buttons=self._stop_buttons, 
      loop_selector_matrix=self._double_press_matrix.submatrix[:8, :1],# [:, 0]
      short_loop_selector_matrix=self._double_press_event_matrix.submatrix[:, 0],# [:, 0]
      note_editor_matrices=ButtonMatrixElement([[ self._session_matrix.submatrix[:, 4 - row] for row in xrange(7) ]]))
      #note_editor_matrices=ButtonMatrixElement([[ self._session_matrix.submatrix[:, 7 - row] for row in xrange(7) ]]))
  
  
  def _session_layer(self):
    def when_bank_on(button):
      return self._bank_toggle.create_toggle_element(on_control=button)
    def when_bank_off(button):
      return self._bank_toggle.create_toggle_element(off_control=button)
    return Layer(
      track_bank_left_button = when_bank_off(self._left_button), 
      track_bank_right_button = when_bank_off(self._right_button), 
      scene_bank_up_button = when_bank_off(self._up_button), 
      scene_bank_down_button = when_bank_off(self._down_button), 
      page_left_button = when_bank_on(self._left_button), 
      page_right_button = when_bank_on(self._right_button), 
      page_up_button = when_bank_on(self._up_button), 
      page_down_button = when_bank_on(self._down_button), 
    #  stop_track_clip_buttons = self._stop_buttons,
      stop_all_clips_button = self._stop_all_button, 
      scene_launch_buttons = self._scene_launch_buttons, 
      clip_launch_buttons = self._session_matrix)

  def _session_zoom_layer(self):
    return Layer(button_matrix=self._shifted_matrix, 
      nav_left_button=self._with_shift(self._left_button), 
      nav_right_button=self._with_shift(self._right_button), 
      nav_up_button=self._with_shift(self._up_button), 
      nav_down_button=self._with_shift(self._down_button), 
      scene_bank_buttons=self._shifted_scene_buttons)

  
  @subject_slot('selected_mode')
  def _on_matrix_mode_changed(self, mode):
      self._update_auto_arm(selected_mode=mode)  
  
  
  def _update_auto_arm(self, selected_mode = None):
      self._auto_arm.set_enabled(selected_mode or self._matrix_modes.selected_mode == 'note')  
  
  
  @subject_slot('drum_group')
  def _on_drum_group_changed(self):
      self._select_note_mode()


  def _select_note_mode(self):
    """
    Selects which note mode to use depending on the kind of
    current selected track and its device chain...
    """
    track = self.song().view.selected_track
    drum_device = self._drum_group_finder.drum_group
    self._step_sequencer.set_drum_group_device(drum_device)
    self._drum_component.set_drum_group_device(drum_device)
    if track == None or track.is_foldable or track in self.song().return_tracks or track == self.song().master_track or track.is_frozen:
      self._note_modes.selected_mode = 'disabled'
    elif track and track.has_audio_input:
      self._note_modes.selected_mode = 'looper'
    elif drum_device:
      self._note_modes.selected_mode = 'drums'
    else:
      self._note_modes.selected_mode = 'instrument'
    self.reset_controlled_track()


  # added so as to have looping with pan_button held
#    self._select_modes = SelectComponent(self, tuple(self._raw_select_buttons), self._metronome_button, self._nudge_down_button, self._nudge_up_button, self._tap_tempo_button, self._transport, self._looper, self._session, self._session_matrix) 
#    self._select_modes.name = 'Select_Modes'
#    self._select_modes.set_mode_toggle(self._pan_button)  
  
  
  
  # commented to test 0:47 
  
  # EVENT HANDLING FUNCTIONS
 # def reset_controlled_track(self):
   # self.set_controlled_track(self.song().view.selected_track)
  
  
  
  """lew sunday"""


  @subject_slot('selected_mode')
  def _on_note_editor_layout_changed(self, mode):
      self.reset_controlled_track(mode)  
  
  
  def reset_controlled_track(self, mode = None):
    if mode == None:
      mode = self._instrument.selected_mode
    if self._instrument.is_enabled() and mode == 'sequence':
      self.release_controlled_track()
    else:
      self.set_controlled_track(self.song().view.selected_track)  
  
  
  
  def update(self):
    self.reset_controlled_track()
    self.set_feedback_channels(FEEDBACK_CHANNELS)  # push added line
    super(PHAZE, self).update()

  
  
  def _on_selected_track_changed(self):
      super(PHAZE, self)._on_selected_track_changed()
      self.reset_controlled_track()
      self._select_note_mode()
  #    self._main_modes.pop_groups(['add_effect'])
      self._note_repeat_enabler.selected_mode = 'disabled'  
  
  
  
  @contextmanager
  def component_guard(self):
    """ Customized to inject additional things """
    with super(PHAZE, self).component_guard():
      with self.make_injector().everywhere():
        yield

  def make_injector(self):
    """ Adds some additional stuff to the injector, used in BaseMessenger """
    return inject(
      double_press_context = const(self._double_press_context),
      control_surface = const(self),
     
      log_message = const(self.log_message))