def _setup_session_control(self):
     is_momentary = True
     num_tracks = 1  #single column
     num_scenes = 7  #seven rows, which will be mapped to seven "white" notes
     global session  #We want to instantiate the global session as a SessionComponent object (it was a global "None" type up until now...)
     session = SessionComponent(
         num_tracks, num_scenes
     )  #(num_tracks, num_scenes) A session highlight ("red box") will appear with any two non-zero values
     session.set_offsets(
         0, 0
     )  #(track_offset, scene_offset) Sets the initial offset of the "red box" from top left
     """set up the session navigation buttons"""
     session.set_select_buttons(
         ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 25),
         ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 27)
     )  # (next_button, prev_button) Scene select buttons - up & down - we'll also use a second ControlComponent for this (yellow box)
     session.set_scene_bank_buttons(
         ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 51),
         ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 49)
     )  # (up_button, down_button) This is to move the "red box" up or down (increment track up or down, not screen up or down, so they are inversed)
     #session.set_track_bank_buttons(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 56), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 54)) # (right_button, left_button) This moves the "red box" selection set left & right. We'll put our track selection in Part B of the script, rather than here...
     session.set_stop_all_clips_button(
         ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 70))
     session.selected_scene().set_launch_button(
         ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 30))
     """Here we set up the scene launch assignments for the session"""
     launch_notes = [
         60, 62, 64, 65, 67, 69, 71
     ]  #this is our set of seven "white" notes, starting at C4
     for index in range(
             num_scenes
     ):  #launch_button assignment must match number of scenes
         session.scene(index).set_launch_button(
             ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                           launch_notes[index])
         )  #step through the scenes (in the session) and assign corresponding note from the launch_notes array
     """Here we set up the track stop launch assignment(s) for the session"""  #The following code is set up for a longer array (we only have one track, so it's over-complicated, but good for future adaptation)..
     stop_track_buttons = []
     for index in range(num_tracks):
         stop_track_buttons.append(
             ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                           58 + index)
         )  #this would need to be adjusted for a longer array (because we've already used the next note numbers elsewhere)
     session.set_stop_track_clip_buttons(
         tuple(stop_track_buttons))  #array size needs to match num_tracks
     """Here we set up the clip launch assignments for the session"""
     clip_launch_notes = [
         48, 50, 52, 53, 55, 57, 59
     ]  #this is a set of seven "white" notes, starting at C3
     for index in range(num_scenes):
         session.scene(index).clip_slot(0).set_launch_button(
             ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                           clip_launch_notes[index])
         )  #step through scenes and assign a note to first slot of each
     """Here we set up a mixer and channel strip(s) which move with the session"""
     session.set_mixer(
         mixer)  #Bind the mixer to the session so that they move together
Exemple #2
0
    def _create_session_control(self):
        is_momentary = True
        num_tracks = 1
        num_scenes = 7
        global session
        session = SessionComponent(num_tracks, num_scenes)
        session.set_offsets(0, 0)
        """set up the session navigation buttons"""
        session.set_select_buttons(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 25),
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 27))
        session.set_scene_bank_buttons(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 51),
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 49))
        session.set_stop_all_clips_button(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 70))
        session.selected_scene().set_launch_button(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 30))
        """Here we set up the scene launch assignments for the session"""
        launch_notes = [60, 62, 64, 65, 67, 69, 71]
        for index in range(num_scenes):
            session.scene(index).set_launch_button(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                              launch_notes[index]))
        """Here we set up the track stop launch assignment(s) for the session"""
        stop_track_buttons = []
        for index in range(num_tracks):
            stop_track_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                              58 + index))
        session.set_stop_track_clip_buttons(tuple(stop_track_buttons))
        """Here we set up the clip launch assignments for the session"""
        clip_launch_notes = [48, 50, 52, 53, 55, 57, 59]
        for index in range(num_scenes):
            session.scene(index).clip_slot(0).set_launch_button(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                              clip_launch_notes[index]))
        """Here we set up a mixer and channel strip(s) which move with the session"""

        self.log_message("Captain's log stardate 3")
class Launchkey(ControlSurface):
    """ Script for Novation's Launchkey 25/49/61 keyboards """
    def __init__(self,
                 c_instance,
                 control_factory=LaunchkeyControlFactory(),
                 identity_response=SIZE_RESPONSE):
        ControlSurface.__init__(self, c_instance)
        self._control_factory = control_factory
        self._identity_response = identity_response
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._suggested_input_port = 'Launchkey InControl'
            self._suggested_output_port = 'Launchkey InControl'
            self._has_sliders = True
            self._current_midi_map = None
            self._master_slider = make_slider(7, 'Master_Volume_Control')
            self._modes_buttons = []
            for index in range(3):
                button = ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, 0,
                                       13 + index)
                self._modes_buttons.append(button)
                self._modes_buttons[-1].add_value_listener(
                    self._dummy_listener)

            self._setup_mixer()
            self._setup_session()
            self._setup_transport()
            self._setup_device()
            self._setup_navigation()
            for component in self.components:
                component.set_enabled(False)

        return

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self.schedule_message(2, self._send_midi, LIVE_MODE_ON)
        self.schedule_message(3, self._send_midi, SIZE_QUERY)

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:11] == self._identity_response:
            self._has_sliders = midi_bytes[11] != 48
            self._send_midi(LED_FLASHING_ON)
            self._update_mixer_offset()
            for control in self.controls:
                if isinstance(control, InputControlElement):
                    control.clear_send_cache()

            for component in self.components:
                component.set_enabled(True)

            if self._has_sliders:
                self._mixer.master_strip().set_volume_control(
                    self._master_slider)
                self._mixer.update()
            else:
                self._mixer.master_strip().set_volume_control(None)
                for index in range(len(self._sliders)):
                    self._mixer.channel_strip(index).set_volume_control(None)
                    self._mixer.channel_strip(index).set_mute_button(None)
                    slider = self._sliders[index]
                    slider.release_parameter()

                self._mixer.selected_strip().set_volume_control(
                    self._master_slider)
            self.request_rebuild_midi_map()
        return

    def disconnect(self):
        ControlSurface.disconnect(self)
        for button in self._modes_buttons:
            if button.value_has_listener(self._dummy_listener):
                button.remove_value_listener(self._dummy_listener)

        self._modes_buttons = None
        self._encoders = None
        self._sliders = None
        self._strip_buttons = None
        self._master_slider = None
        self._current_midi_map = None
        self._transport_view_modes = None
        self._send_midi(LED_FLASHING_OFF)
        self._send_midi(LIVE_MODE_OFF)
        return

    def build_midi_map(self, midi_map_handle):
        self._current_midi_map = midi_map_handle
        ControlSurface.build_midi_map(self, midi_map_handle)

    def _setup_mixer(self):
        mute_solo_flip_button = make_button(59, 'Master_Button')
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.master_strip().set_volume_control(self._master_slider)
        self._sliders = []
        self._strip_buttons = []
        for index in range(8):
            strip = self._mixer.channel_strip(index)
            strip.name = 'Channel_Strip_' + str(index)
            strip.set_invert_mute_feedback(True)
            self._sliders.append(
                make_slider(41 + index, 'Volume_Control_%d' % index))
            strip.set_volume_control(self._sliders[-1])
            self._strip_buttons.append(
                make_button(51 + index, 'Mute_Button_%d' % index))

        self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons),
                                                mute_solo_flip_button)

    def _setup_session(self):
        scene_launch_button = self._control_factory.create_scene_launch_button(
        )
        scene_stop_button = self._control_factory.create_scene_stop_button()
        self._session = SessionComponent(8, 0)
        self._session.name = 'Session_Control'
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(scene_launch_button)
        self._session.selected_scene().set_triggered_value(GREEN_BLINK)
        self._session.set_stop_all_clips_button(scene_stop_button)
        scene_stop_button.set_on_off_values(AMBER_FULL, LED_OFF)
        self._session.set_mixer(self._mixer)
        self._session.set_stop_clip_value(AMBER_HALF)
        self._session.set_stop_clip_triggered_value(GREEN_BLINK)
        clip_launch_buttons = []
        clip_stop_buttons = []
        for index in range(8):
            clip_launch_buttons.append(
                self._control_factory.create_clip_launch_button(index))
            clip_stop_buttons.append(
                self._control_factory.create_clip_stop_button(index))
            clip_slot = self._session.selected_scene().clip_slot(index)
            clip_slot.set_triggered_to_play_value(GREEN_BLINK)
            clip_slot.set_triggered_to_record_value(RED_BLINK)
            clip_slot.set_stopped_value(AMBER_FULL)
            clip_slot.set_started_value(GREEN_FULL)
            clip_slot.set_recording_value(RED_FULL)
            clip_slot.set_launch_button(clip_launch_buttons[-1])
            clip_slot.name = 'Selected_Clip_Slot_' + str(index)

        self._session.set_stop_track_clip_buttons(tuple(clip_stop_buttons))

    def _setup_transport(self):
        rwd_button = make_button(112, 'Rwd_Button')
        ffwd_button = make_button(113, 'FFwd_Button')
        stop_button = make_button(114, 'Stop_Button')
        play_button = make_button(115, 'Play_Button')
        loop_button = make_button(116, 'Loop_Button')
        rec_button = make_button(117, 'Record_Button')
        transport = TransportComponent()
        transport.name = 'Transport'
        transport.set_stop_button(stop_button)
        transport.set_play_button(play_button)
        transport.set_record_button(rec_button)
        transport.set_loop_button(loop_button)
        self._transport_view_modes = TransportViewModeSelector(
            transport, self._session, ffwd_button, rwd_button)
        self._transport_view_modes.name = 'Transport_View_Modes'

    def _setup_device(self):
        encoders = [
            make_encoder(21 + index, 'Device_Control_%d' % index)
            for index in xrange(8)
        ]
        self._encoders = tuple(encoders)
        device = DeviceComponent(device_selection_follows_track_selection=True)
        device.name = 'Device_Component'
        self.set_device_component(device)
        device.set_parameter_controls(self._encoders)

    def _setup_navigation(self):
        self._next_track_button = self._control_factory.create_next_track_button(
        )
        self._prev_track_button = self._control_factory.create_prev_track_button(
        )
        self._session_navigation = SessionNavigationComponent(
            name='Session_Navigation')
        self._session_navigation.set_next_track_button(self._next_track_button)
        self._session_navigation.set_prev_track_button(self._prev_track_button)

    def _dummy_listener(self, value):
        pass

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._update_mixer_offset()

    def _update_mixer_offset(self):
        all_tracks = self._session.tracks_to_use()
        selected_track = self.song().view.selected_track
        num_strips = self._session.width()
        if selected_track in all_tracks:
            track_index = list(all_tracks).index(selected_track)
            new_offset = track_index - track_index % num_strips
            self._session.set_offsets(new_offset, self._session.scene_offset())
Exemple #4
0
class LaunchpadSimple(ControlSurface):
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)

        with self.component_guard():
            self._suggested_input_port = 'Launchpad'
            self._suggested_output_port = 'Launchpad'

            # Launchpad configuration
            self._send_midi(LAUNCHPAD_RESET)
            self._send_midi(LAUNCHPAD_ENABLE_BLINKING)

            # make buttons
            top_buttons = [
                make_button(MIDI_CC_TYPE, 104 + i) for i in range(8)
            ]
            side_buttons = [
                make_button(MIDI_NOTE_TYPE, 8 + 16 * i) for i in range(8)
            ]

            matrix = ButtonMatrixElement()
            for row in range(8):
                button_row = [
                    make_button(MIDI_NOTE_TYPE, 16 * row + col)
                    for col in range(8)
                ]
                matrix.add_row(tuple(button_row))

            # mixer and session components
            self._mixer = MixerComponent(8)
            self._session = SessionComponent(8, SCENES_AMOUNT)
            self._session.set_mixer(self._mixer)
            self.set_highlighting_session_component(self._session)

            # navigation
            for button in top_buttons[:4]:
                button.set_on_off_values(GREEN_FULL, GREEN_THIRD)
            self._session.set_scene_bank_buttons(top_buttons[1],
                                                 top_buttons[0])
            self._session.set_track_bank_buttons(top_buttons[3],
                                                 top_buttons[2])

            # clip launch
            for scene_index in range(SCENES_AMOUNT):
                scene = self._session.scene(scene_index)
                scene.set_launch_button(side_buttons[scene_index])
                scene.set_triggered_value(GREEN_BLINK)
                scene.set_scene_value(GREEN_THIRD)
                scene.set_no_scene_value(LED_OFF)

                for track_index in range(8):
                    clip_slot = scene.clip_slot(track_index)
                    clip_slot.set_launch_button(
                        matrix.get_button(track_index, scene_index))
                    clip_slot.set_triggered_to_play_value(GREEN_BLINK)
                    clip_slot.set_triggered_to_record_value(RED_BLINK)
                    clip_slot.set_started_value(GREEN_FULL)
                    clip_slot.set_stopped_value(AMBER_THIRD)
                    clip_slot.set_recording_value(RED_FULL)

            # track stop
            self._session.set_stop_track_clip_buttons(
                [matrix.get_button(i, ROW_STOP) for i in range(8)])
            self._session.set_stop_clip_value(RED_THIRD)
            self._session.set_stop_clip_triggered_value(RED_BLINK)

            button_stop_all = side_buttons[ROW_STOP]
            button_stop_all.set_on_off_values(RED_FULL, RED_THIRD)
            self._session.set_stop_all_clips_button(button_stop_all)

            # track select
            self._mixer.set_track_select_buttons(
                [matrix.get_button(i, ROW_SELECT) for i in range(8)])
            self._mixer.set_track_select_values(AMBER_FULL, AMBER_THIRD,
                                                LED_OFF)

            button_select_master = side_buttons[ROW_SELECT]
            button_select_master.set_on_off_values(AMBER_FULL, AMBER_THIRD)
            self._mixer.set_master_select_button(button_select_master)

            # delete clip button
            self._delete_button = top_buttons[INDEX_DELETE_BUTTON]
            self._delete_button.set_on_off_values(RED_BLINK, RED_THIRD)
            self._delete_button.add_value_listener(self._delete_value_listener)

            self._del_pressed = False
            self._delete_button.turn_off()

            # quantization toggle
            self._quantization_toggle = QuantizationToggle(
                top_buttons[INDEX_QUANTIZATION_BUTTON], self.song(),
                GREEN_THIRD, RED_THIRD)

            # browser view toggle
            self._browser_view_toggle = ViewToggle(
                side_buttons[INDEX_BROWSER_VIEW_BUTTON], ABLETON_VIEW_BROWSER,
                GREEN_THIRD, RED_THIRD)

            # detail view toggle
            self._device_view_toggle = DetailViewToggle(
                side_buttons[INDEX_DETAIL_VIEW_BUTTON], GREEN_THIRD, RED_THIRD,
                LED_OFF)

    def disconnect(self):
        self._send_midi(LAUNCHPAD_RESET)
        ControlSurface.disconnect(self)

        self._delete_button.remove_value_listener(self._delete_value_listener)
        self._delete_button = None
        self._quantization_toggle.disconnect()
        self._quantization_toggle = None
        self._browser_view_toggle.disconnect()
        self._browser_view_toggle = None
        self._device_view_toggle.disconnect()
        self._device_view_toggle = None

        self._session = None
        self._mixer = None

    def receive_midi(self, midi_bytes):
        if self._del_pressed and self._delete_clip(midi_bytes):
            return
        else:
            ControlSurface.receive_midi(self, midi_bytes)

    def _delete_value_listener(self, value):
        self._del_pressed = (value == 127)
        self._delete_button.set_light(self._del_pressed)

    def _delete_clip(self, midi_bytes):
        if midi_bytes[0] == MIDI_NOTE_ON_VALUE:
            row, col = launchpad_button_loc(midi_bytes[1])
            if row < SCENES_AMOUNT and col < 8:
                self._session.scene(row).clip_slot(col)._do_delete_clip()
                return True
        return False
Exemple #5
0
class Launchkey(ControlSurface):
    """ Script for Novation's Launchkey 25/49/61 keyboards """

    def __init__(self, c_instance, control_factory = LaunchkeyControlFactory(), identity_response = SIZE_RESPONSE):
        ControlSurface.__init__(self, c_instance)
        self._control_factory = control_factory
        self._identity_response = identity_response
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = 'Launchkey InControl'
            self._suggested_output_port = 'Launchkey InControl'
            self._has_sliders = True
            self._current_midi_map = None
            self._master_slider = make_slider(7, 'Master_Volume_Control')
            self._modes_buttons = []
            for index in range(3):
                button = ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, 0, 13 + index)
                self._modes_buttons.append(button)
                self._modes_buttons[-1].add_value_listener(self._dummy_listener)

            self._setup_mixer()
            self._setup_session()
            self._setup_transport()
            self._setup_device()
            self._setup_navigation()
            for component in self.components:
                component.set_enabled(False)

        return

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self.schedule_message(2, self._send_midi, LIVE_MODE_ON)
        self.schedule_message(3, self._send_midi, SIZE_QUERY)

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:11] == self._identity_response:
            self._has_sliders = midi_bytes[11] != 48
            self._send_midi(LED_FLASHING_ON)
            self._update_mixer_offset()
            for control in self.controls:
                if isinstance(control, InputControlElement):
                    control.clear_send_cache()

            for component in self.components:
                component.set_enabled(True)

            if self._has_sliders:
                self._mixer.master_strip().set_volume_control(self._master_slider)
                self._mixer.update()
            else:
                self._mixer.master_strip().set_volume_control(None)
                for index in range(len(self._sliders)):
                    self._mixer.channel_strip(index).set_volume_control(None)
                    self._mixer.channel_strip(index).set_mute_button(None)
                    slider = self._sliders[index]
                    slider.release_parameter()

                self._mixer.selected_strip().set_volume_control(self._master_slider)
            self.request_rebuild_midi_map()
        return

    def disconnect(self):
        ControlSurface.disconnect(self)
        for button in self._modes_buttons:
            if button.value_has_listener(self._dummy_listener):
                button.remove_value_listener(self._dummy_listener)

        self._modes_buttons = None
        self._encoders = None
        self._sliders = None
        self._strip_buttons = None
        self._master_slider = None
        self._current_midi_map = None
        self._transport_view_modes = None
        self._send_midi(LED_FLASHING_OFF)
        self._send_midi(LIVE_MODE_OFF)
        return

    def build_midi_map(self, midi_map_handle):
        self._current_midi_map = midi_map_handle
        ControlSurface.build_midi_map(self, midi_map_handle)

    def _setup_mixer(self):
        mute_solo_flip_button = make_button(59, 'Master_Button')
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.master_strip().set_volume_control(self._master_slider)
        self._sliders = []
        self._strip_buttons = []
        for index in range(8):
            strip = self._mixer.channel_strip(index)
            strip.name = 'Channel_Strip_' + str(index)
            strip.set_invert_mute_feedback(True)
            self._sliders.append(make_slider(41 + index, 'Volume_Control_%d' % index))
            strip.set_volume_control(self._sliders[-1])
            self._strip_buttons.append(make_button(51 + index, 'Mute_Button_%d' % index))

        self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)

    def _setup_session(self):
        scene_launch_button = self._control_factory.create_scene_launch_button()
        scene_stop_button = self._control_factory.create_scene_stop_button()
        self._session = SessionComponent(8, 0)
        self._session.name = 'Session_Control'
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(scene_launch_button)
        self._session.selected_scene().set_triggered_value(GREEN_BLINK)
        self._session.set_stop_all_clips_button(scene_stop_button)
        scene_stop_button.set_on_off_values(AMBER_FULL, LED_OFF)
        self._session.set_mixer(self._mixer)
        self._session.set_stop_clip_value(AMBER_HALF)
        self._session.set_stop_clip_triggered_value(GREEN_BLINK)
        clip_launch_buttons = []
        clip_stop_buttons = []
        for index in range(8):
            clip_launch_buttons.append(self._control_factory.create_clip_launch_button(index))
            clip_stop_buttons.append(self._control_factory.create_clip_stop_button(index))
            clip_slot = self._session.selected_scene().clip_slot(index)
            clip_slot.set_triggered_to_play_value(GREEN_BLINK)
            clip_slot.set_triggered_to_record_value(RED_BLINK)
            clip_slot.set_stopped_value(AMBER_FULL)
            clip_slot.set_started_value(GREEN_FULL)
            clip_slot.set_recording_value(RED_FULL)
            clip_slot.set_launch_button(clip_launch_buttons[-1])
            clip_slot.name = 'Selected_Clip_Slot_' + str(index)

        self._session.set_stop_track_clip_buttons(tuple(clip_stop_buttons))

    def _setup_transport(self):
        rwd_button = make_button(112, 'Rwd_Button')
        ffwd_button = make_button(113, 'FFwd_Button')
        stop_button = make_button(114, 'Stop_Button')
        play_button = make_button(115, 'Play_Button')
        loop_button = make_button(116, 'Loop_Button')
        rec_button = make_button(117, 'Record_Button')
        transport = TransportComponent()
        transport.name = 'Transport'
        transport.set_stop_button(stop_button)
        transport.set_play_button(play_button)
        transport.set_record_button(rec_button)
        transport.set_loop_button(loop_button)
        self._transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button)
        self._transport_view_modes.name = 'Transport_View_Modes'

    def _setup_device(self):
        encoders = [ make_encoder(21 + index, 'Device_Control_%d' % index) for index in xrange(8) ]
        self._encoders = tuple(encoders)
        device = DeviceComponent()
        device.name = 'Device_Component'
        self.set_device_component(device)
        device.set_parameter_controls(self._encoders)

    def _setup_navigation(self):
        self._next_track_button = self._control_factory.create_next_track_button()
        self._prev_track_button = self._control_factory.create_prev_track_button()
        self._session_navigation = SessionNavigationComponent(name='Session_Navigation')
        self._session_navigation.set_next_track_button(self._next_track_button)
        self._session_navigation.set_prev_track_button(self._prev_track_button)

    def _dummy_listener(self, value):
        pass

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._update_mixer_offset()

    def _update_mixer_offset(self):
        all_tracks = self._session.tracks_to_use()
        selected_track = self.song().view.selected_track
        num_strips = self._session.width()
        if selected_track in all_tracks:
            track_index = list(all_tracks).index(selected_track)
            new_offset = track_index - track_index % num_strips
            self._session.set_offsets(new_offset, self._session.scene_offset())
Exemple #6
0
class MPK_mini_hero(ControlSurface):
    """ Script for Novation's Launchkey 25/49/61 keyboards """

    def __init__(self, c_instance, identity_response = SIZE_RESPONSE):
        ControlSurface.__init__(self, c_instance)
        self._identity_response = identity_response
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = 'MPK mini'
            self._suggested_output_port = 'MPK mini'

            self._setup_buttons()
            self._setup_components()

            for component in self.components:
                component.set_enabled(True) # Puvodne False

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        
        # for val in range(127):
        #     self.schedule_message(2, self._send_midi, (144, val, 0))
            
        # self.schedule_message(3, self._send_midi, (144, 9, 127))

    def handle_sysex(self, midi_bytes):
        self._send_midi(LED_FLASHING_ON)
        self._update_mixer_offset()
        for control in self.controls:
            if isinstance(control, InputControlElement):
                control.clear_send_cache()

        for component in self.components:
            component.set_enabled(True)

        self.request_rebuild_midi_map()

    def disconnect(self):
        ControlSurface.disconnect(self)

        self._encoders = None
        self._transport_view_modes = None
        self._send_midi(LED_FLASHING_OFF)
        self._send_midi(LIVE_MODE_OFF)

    def _setup_buttons(self):
        # Pads CC Mode
        self._scene_launch_button = make_pad_button(PAD_MODE_CC, 1, 'Scene_Launch_Button')
        self._overdub_button = make_pad_button(PAD_MODE_CC, 2, 'Session_Overdub_Button')
        self._ffwd_button = make_pad_button(PAD_MODE_CC, 3, 'FFwd_Button')
        self._clip_undo_button = make_pad_button(PAD_MODE_CC, 4, 'Clip_Undo_Button')
        self._prev_track_button = make_pad_button(PAD_MODE_CC, 5, 'Prev_Track_Button')
        self._next_track_button = make_pad_button(PAD_MODE_CC, 6, 'Next_Track_Button')
        self._rwd_button = make_pad_button(PAD_MODE_CC, 7, 'Rwd_Button')
        self._scene_stop_button = make_pad_button(PAD_MODE_CC, 9, 'Scene_Stop_Button')
        self._stop_button = make_pad_button(PAD_MODE_CC, 10, 'Stop_Button')
        self._play_button = make_pad_button(PAD_MODE_CC, 11, 'Play_Button')
        self._loop_button = make_pad_button(PAD_MODE_CC, 12, 'Loop_Button')
        self._rec_button = make_pad_button(PAD_MODE_CC, 13, 'Record_Button')

        # Pads Notes Mode
        self._clip_launch_buttons = [ make_pad_button(PAD_MODE_NOTES, index, 'Clip_Launch_%d' % index) for index in xrange(8) ]
        self._clip_stop_buttons = [ make_pad_button(PAD_MODE_NOTES, 8 + index, 'Clip_Stop_%d' % index) for index in xrange(8) ]

        # Encoders

        self._encoders = tuple([ make_encoder(21 + index, 'Device_Control_%d' % index) for index in xrange(8) ])

        # Scenes

        self._scene_launch_buttons = []
        for key_no in [0,2,4,5,7,9,11,  12,14,16,17,19,21,23,  24]:
            self._scene_launch_buttons.append(make_scene_button(key_no, 'Scene_Launch_%d' % key_no))

    def _setup_components(self):
        
        # Session

        self._session = SessionComponent(8, len(self._scene_launch_buttons))
        self._session.name = 'Session_Control'
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(self._scene_launch_button)
        self._session.set_stop_all_clips_button(self._scene_stop_button)

        for index in range(8):
            clip_slot = self._session.selected_scene().clip_slot(index)
            clip_slot.set_launch_button(self._clip_launch_buttons[index])
            clip_slot.name = 'Selected_Clip_Slot_' + str(index)

        self._session.set_stop_track_clip_buttons(tuple(self._clip_stop_buttons))

        # Undo

        self._do_undo.subject = self._clip_undo_button;

        # Transport

        transport = TransportComponent()
        transport.name = 'Transport'
        transport.set_stop_button(self._stop_button)
        transport.set_play_button(self._play_button)
        transport.set_record_button(self._rec_button)
        transport.set_loop_button(self._loop_button)

        self._transport_view_modes = TransportViewModeSelector(transport, self._session, self._ffwd_button, self._rwd_button)
        self._transport_view_modes.name = 'Transport_View_Modes'

        session_recording = SessionRecordingComponent(ClipCreator(), ViewControlComponent(), name='Session_Recording', is_enabled=False, layer=Layer(record_button=self._overdub_button))

        # Device

        # device = DeviceComponent()
        # device.name = 'Device_Component'
        # self.set_device_component(device)
        # device.set_parameter_controls(self._encoders)

        # Navigation

        self._session_navigation = SessionNavigationComponent(name='Session_Navigation')
        self._session_navigation.set_next_track_button(self._next_track_button)
        self._session_navigation.set_prev_track_button(self._prev_track_button)

        # Playing
        # self._session.set_scene_launch_buttons(tuple(self._scene_launch_buttons))
        for index in range(len(self._scene_launch_buttons)):
            scene = self._session.scene(index)
            scene.set_launch_button(self._scene_launch_buttons[index])

    @subject_slot('value')
    def _do_undo(self, value):
        if value:
            if self.song().can_undo == 1:
                self.song().undo()
                self.show_message(str('UNDO'))

    def _dummy_listener(self, value):
        pass

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._update_mixer_offset()

    def _update_mixer_offset(self):
        all_tracks = self._session.tracks_to_use()
        selected_track = self.song().view.selected_track
        num_strips = self._session.width()
        if selected_track in all_tracks:
            track_index = list(all_tracks).index(selected_track)
            new_offset = track_index - track_index % num_strips
            self._session.set_offsets(new_offset, self._session.scene_offset())
class LaunchpadSimple(ControlSurface):
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)

        with self.component_guard():
            self._suggested_input_port = "Launchpad"
            self._suggested_output_port = "Launchpad"

            # Launchpad configuration
            self._send_midi(LAUNCHPAD_RESET)
            self._send_midi(LAUNCHPAD_ENABLE_BLINKING)

            # make buttons
            top_buttons = [make_button(MIDI_CC_TYPE, 104 + i) for i in range(8)]
            side_buttons = [make_button(MIDI_NOTE_TYPE, 8 + 16 * i) for i in range(8)]

            matrix = ButtonMatrixElement()
            for row in range(8):
                button_row = [make_button(MIDI_NOTE_TYPE, 16 * row + col) for col in range(8)]
                matrix.add_row(tuple(button_row))

            # mixer and session components
            self._mixer = MixerComponent(8)
            self._session = SessionComponent(8, SCENES_AMOUNT)
            self._session.set_mixer(self._mixer)
            self.set_highlighting_session_component(self._session)

            # navigation
            for button in top_buttons[:4]:
                button.set_on_off_values(GREEN_FULL, GREEN_THIRD)
            self._session.set_scene_bank_buttons(top_buttons[1], top_buttons[0])
            self._session.set_track_bank_buttons(top_buttons[3], top_buttons[2])

            # clip launch
            for scene_index in range(SCENES_AMOUNT):
                scene = self._session.scene(scene_index)
                scene.set_launch_button(side_buttons[scene_index])
                scene.set_triggered_value(GREEN_BLINK)
                scene.set_scene_value(GREEN_THIRD)
                scene.set_no_scene_value(LED_OFF)

                for track_index in range(8):
                    clip_slot = scene.clip_slot(track_index)
                    clip_slot.set_launch_button(matrix.get_button(track_index, scene_index))
                    clip_slot.set_triggered_to_play_value(GREEN_BLINK)
                    clip_slot.set_triggered_to_record_value(RED_BLINK)
                    clip_slot.set_started_value(GREEN_FULL)
                    clip_slot.set_stopped_value(AMBER_THIRD)
                    clip_slot.set_recording_value(RED_FULL)

            # track stop
            self._session.set_stop_track_clip_buttons([matrix.get_button(i, ROW_STOP) for i in range(8)])
            self._session.set_stop_clip_value(RED_THIRD)
            self._session.set_stop_clip_triggered_value(RED_BLINK)

            button_stop_all = side_buttons[ROW_STOP]
            button_stop_all.set_on_off_values(RED_FULL, RED_THIRD)
            self._session.set_stop_all_clips_button(button_stop_all)

            # track select
            self._mixer.set_track_select_buttons([matrix.get_button(i, ROW_SELECT) for i in range(8)])
            self._mixer.set_track_select_values(AMBER_FULL, AMBER_THIRD, LED_OFF)

            button_select_master = side_buttons[ROW_SELECT]
            button_select_master.set_on_off_values(AMBER_FULL, AMBER_THIRD)
            self._mixer.set_master_select_button(button_select_master)

            # delete clip button
            self._delete_button = top_buttons[INDEX_DELETE_BUTTON]
            self._delete_button.set_on_off_values(RED_BLINK, RED_THIRD)
            self._delete_button.add_value_listener(self._delete_value_listener)

            self._del_pressed = False
            self._delete_button.turn_off()

            # quantization toggle
            self._quantization_toggle = QuantizationToggle(
                top_buttons[INDEX_QUANTIZATION_BUTTON], self.song(), GREEN_THIRD, RED_THIRD
            )

            # browser view toggle
            self._browser_view_toggle = ViewToggle(
                side_buttons[INDEX_BROWSER_VIEW_BUTTON], ABLETON_VIEW_BROWSER, GREEN_THIRD, RED_THIRD
            )

            # detail view toggle
            self._device_view_toggle = DetailViewToggle(
                side_buttons[INDEX_DETAIL_VIEW_BUTTON], GREEN_THIRD, RED_THIRD, LED_OFF
            )

    def disconnect(self):
        self._send_midi(LAUNCHPAD_RESET)
        ControlSurface.disconnect(self)

        self._delete_button.remove_value_listener(self._delete_value_listener)
        self._delete_button = None
        self._quantization_toggle.disconnect()
        self._quantization_toggle = None
        self._browser_view_toggle.disconnect()
        self._browser_view_toggle = None
        self._device_view_toggle.disconnect()
        self._device_view_toggle = None

        self._session = None
        self._mixer = None

    def receive_midi(self, midi_bytes):
        if self._del_pressed and self._delete_clip(midi_bytes):
            return
        else:
            ControlSurface.receive_midi(self, midi_bytes)

    def _delete_value_listener(self, value):
        self._del_pressed = value == 127
        self._delete_button.set_light(self._del_pressed)

    def _delete_clip(self, midi_bytes):
        if midi_bytes[0] == MIDI_NOTE_ON_VALUE:
            row, col = launchpad_button_loc(midi_bytes[1])
            if row < SCENES_AMOUNT and col < 8:
                self._session.scene(row).clip_slot(col)._do_delete_clip()
                return True
        return False
Exemple #8
0
class MPK_mini_hero(ControlSurface):
    """ Script for Novation's Launchkey 25/49/61 keyboards """
    def __init__(self, c_instance, identity_response=SIZE_RESPONSE):
        ControlSurface.__init__(self, c_instance)
        self._identity_response = identity_response
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = 'MPK mini'
            self._suggested_output_port = 'MPK mini'

            self._setup_buttons()
            self._setup_components()

            for component in self.components:
                component.set_enabled(True)  # Puvodne False

    def refresh_state(self):
        ControlSurface.refresh_state(self)

        # for val in range(127):
        #     self.schedule_message(2, self._send_midi, (144, val, 0))

        # self.schedule_message(3, self._send_midi, (144, 9, 127))

    def handle_sysex(self, midi_bytes):
        self._send_midi(LED_FLASHING_ON)
        self._update_mixer_offset()
        for control in self.controls:
            if isinstance(control, InputControlElement):
                control.clear_send_cache()

        for component in self.components:
            component.set_enabled(True)

        self.request_rebuild_midi_map()

    def disconnect(self):
        ControlSurface.disconnect(self)

        self._encoders = None
        self._transport_view_modes = None
        self._send_midi(LED_FLASHING_OFF)
        self._send_midi(LIVE_MODE_OFF)

    def _setup_buttons(self):
        # Pads CC Mode
        self._scene_launch_button = make_pad_button(PAD_MODE_CC, 1,
                                                    'Scene_Launch_Button')
        self._overdub_button = make_pad_button(PAD_MODE_CC, 2,
                                               'Session_Overdub_Button')
        self._ffwd_button = make_pad_button(PAD_MODE_CC, 3, 'FFwd_Button')
        self._clip_undo_button = make_pad_button(PAD_MODE_CC, 4,
                                                 'Clip_Undo_Button')
        self._prev_track_button = make_pad_button(PAD_MODE_CC, 5,
                                                  'Prev_Track_Button')
        self._next_track_button = make_pad_button(PAD_MODE_CC, 6,
                                                  'Next_Track_Button')
        self._rwd_button = make_pad_button(PAD_MODE_CC, 7, 'Rwd_Button')
        self._scene_stop_button = make_pad_button(PAD_MODE_CC, 9,
                                                  'Scene_Stop_Button')
        self._stop_button = make_pad_button(PAD_MODE_CC, 10, 'Stop_Button')
        self._play_button = make_pad_button(PAD_MODE_CC, 11, 'Play_Button')
        self._loop_button = make_pad_button(PAD_MODE_CC, 12, 'Loop_Button')
        self._rec_button = make_pad_button(PAD_MODE_CC, 13, 'Record_Button')

        # Pads Notes Mode
        self._clip_launch_buttons = [
            make_pad_button(PAD_MODE_NOTES, index, 'Clip_Launch_%d' % index)
            for index in xrange(8)
        ]
        self._clip_stop_buttons = [
            make_pad_button(PAD_MODE_NOTES, 8 + index, 'Clip_Stop_%d' % index)
            for index in xrange(8)
        ]

        # Encoders

        self._encoders = tuple([
            make_encoder(21 + index, 'Device_Control_%d' % index)
            for index in xrange(8)
        ])

        # Scenes

        self._scene_launch_buttons = []
        for key_no in [0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19, 21, 23, 24]:
            self._scene_launch_buttons.append(
                make_scene_button(key_no, 'Scene_Launch_%d' % key_no))

    def _setup_components(self):

        # Session

        self._session = SessionComponent(8, len(self._scene_launch_buttons))
        self._session.name = 'Session_Control'
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(
            self._scene_launch_button)
        self._session.set_stop_all_clips_button(self._scene_stop_button)

        for index in range(8):
            clip_slot = self._session.selected_scene().clip_slot(index)
            clip_slot.set_launch_button(self._clip_launch_buttons[index])
            clip_slot.name = 'Selected_Clip_Slot_' + str(index)

        self._session.set_stop_track_clip_buttons(
            tuple(self._clip_stop_buttons))

        # Undo

        self._do_undo.subject = self._clip_undo_button

        # Transport

        transport = TransportComponent()
        transport.name = 'Transport'
        transport.set_stop_button(self._stop_button)
        transport.set_play_button(self._play_button)
        transport.set_record_button(self._rec_button)
        transport.set_loop_button(self._loop_button)

        self._transport_view_modes = TransportViewModeSelector(
            transport, self._session, self._ffwd_button, self._rwd_button)
        self._transport_view_modes.name = 'Transport_View_Modes'

        session_recording = SessionRecordingComponent(
            ClipCreator(),
            ViewControlComponent(),
            name='Session_Recording',
            is_enabled=False,
            layer=Layer(record_button=self._overdub_button))

        # Device

        # device = DeviceComponent()
        # device.name = 'Device_Component'
        # self.set_device_component(device)
        # device.set_parameter_controls(self._encoders)

        # Navigation

        self._session_navigation = SessionNavigationComponent(
            name='Session_Navigation')
        self._session_navigation.set_next_track_button(self._next_track_button)
        self._session_navigation.set_prev_track_button(self._prev_track_button)

        # Playing
        # self._session.set_scene_launch_buttons(tuple(self._scene_launch_buttons))
        for index in range(len(self._scene_launch_buttons)):
            scene = self._session.scene(index)
            scene.set_launch_button(self._scene_launch_buttons[index])

    @subject_slot('value')
    def _do_undo(self, value):
        if value:
            if self.song().can_undo == 1:
                self.song().undo()
                self.show_message(str('UNDO'))

    def _dummy_listener(self, value):
        pass

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._update_mixer_offset()

    def _update_mixer_offset(self):
        all_tracks = self._session.tracks_to_use()
        selected_track = self.song().view.selected_track
        num_strips = self._session.width()
        if selected_track in all_tracks:
            track_index = list(all_tracks).index(selected_track)
            new_offset = track_index - track_index % num_strips
            self._session.set_offsets(new_offset, self._session.scene_offset())
Exemple #9
0
class midi_twister_110(ControlSurface):
    def __init__(self, c_instance):
        super(midi_twister_110, self).__init__(c_instance)
        with self.component_guard():
            global active_mode
            active_mode = "_mode1"
            self._set_active_mode()
            self.show_message("Modified by XXPW")

    def _mode1(self):
        self.show_message("_mode1 is active")
        # mixer
        global mixer
        num_tracks = 32
        num_returns = 7
        self.mixer = MixerComponent(num_tracks, num_returns)
        self.mixer.set_track_offset(0)
        self.song().view.selected_track = self.mixer.channel_strip(0)._track
        # sends
        send0_controls = (
            SliderElement(MIDI_CC_TYPE, 0, 32),
            SliderElement(MIDI_CC_TYPE, 0, 36),
            SliderElement(MIDI_CC_TYPE, 0, 40),
            None,
            None,
            None,
            None,
            None,
        )
        self.mixer.channel_strip(0).set_send_controls(tuple(send0_controls))
        self.mixer.channel_strip(0).set_volume_control(
            SliderElement(MIDI_CC_TYPE, 0, 44))
        send1_controls = (
            SliderElement(MIDI_CC_TYPE, 0, 33),
            SliderElement(MIDI_CC_TYPE, 0, 37),
            SliderElement(MIDI_CC_TYPE, 0, 41),
            None,
            None,
            None,
            None,
            None,
        )
        self.mixer.channel_strip(1).set_send_controls(tuple(send1_controls))
        self.mixer.channel_strip(1).set_volume_control(
            SliderElement(MIDI_CC_TYPE, 0, 45))

        send2_controls = (
            SliderElement(MIDI_CC_TYPE, 0, 34),
            SliderElement(MIDI_CC_TYPE, 0, 38),
            SliderElement(MIDI_CC_TYPE, 0, 42),
            None,
            None,
            None,
            None,
            None,
        )
        self.mixer.channel_strip(2).set_send_controls(tuple(send2_controls))
        self.mixer.channel_strip(2).set_volume_control(
            SliderElement(MIDI_CC_TYPE, 0, 46))
        send3_controls = (
            SliderElement(MIDI_CC_TYPE, 0, 35),
            SliderElement(MIDI_CC_TYPE, 0, 39),
            SliderElement(MIDI_CC_TYPE, 0, 43),
            None,
            None,
            None,
            None,
            None,
        )
        self.mixer.channel_strip(3).set_send_controls(tuple(send3_controls))
        self.mixer.channel_strip(3).set_volume_control(
            SliderElement(MIDI_CC_TYPE, 0, 47))
        # session
        global _session
        num_tracks = 4
        num_scenes = 3
        session_buttons = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
        self._pads = [
            ButtonElement(1, MIDI_CC_TYPE, 1, session_buttons[index])
            for index in range(num_tracks * num_scenes)
        ]
        self._grid = ButtonMatrixElement(rows=[
            self._pads[(index * num_tracks):(index * num_tracks) + num_tracks]
            for index in range(num_scenes)
        ])
        self._session = SessionComponent(num_tracks, num_scenes)
        self._session.set_clip_launch_buttons(self._grid)
        self.set_highlighting_session_component(self._session)
        # session track stop
        stop_track_buttons = [12, 13, 14, 15]
        self._track_stop_buttons = [
            ButtonElement(1, MIDI_CC_TYPE, 1, stop_track_buttons[index])
            for index in range(num_tracks)
        ]
        self._session.set_stop_track_clip_buttons(
            tuple(self._track_stop_buttons))
        # session navigation
        self.session_left = ButtonElement(1, MIDI_CC_TYPE, 3, 8)
        self._session.set_page_left_button(self.session_left)
        self.session_left.add_value_listener(self._reload_active_devices,
                                             identify_sender=False)
        self.session_right = ButtonElement(1, MIDI_CC_TYPE, 3, 11)
        self._session.set_page_right_button(self.session_right)
        self.session_right.add_value_listener(self._reload_active_devices,
                                              identify_sender=False)
        self.session_up = ButtonElement(1, MIDI_CC_TYPE, 3, 10)
        self._session.set_page_up_button(self.session_up)
        self.session_up.add_value_listener(self._reload_active_devices,
                                           identify_sender=False)
        self.session_down = ButtonElement(1, MIDI_CC_TYPE, 3, 13)
        self._session.set_page_down_button(self.session_down)
        self.session_down.add_value_listener(self._reload_active_devices,
                                             identify_sender=False)
        self._session._link()
        self._session.set_mixer(self.mixer)
        #self._session.set_mixer(self.mixer)
        self._mode1_devices()
        self.add_device_listeners()
        # button: next device
        self.next_device = ButtonElement(0, MIDI_CC_TYPE, 1, 25)
        self.next_device.add_value_listener(self._next_device_value,
                                            identify_sender=False)
        # button: prev device
        self.previous_device = ButtonElement(1, MIDI_CC_TYPE, 1, 24)
        self.previous_device.add_value_listener(self._prev_device_value,
                                                identify_sender=False)
        # transport
        global transport
        self.transport = TransportComponent()
        self.transport.name = 'Transport'
        loop_button = ButtonElement(1, MIDI_CC_TYPE, 1, 50)
        loop_button.name = 'loop_button'
        self.transport.set_loop_button(loop_button)
        stop_button = ButtonElement(1, MIDI_CC_TYPE, 1, 49)
        stop_button.name = 'stop_button'
        self.transport.set_stop_button(stop_button)
        play_button = ButtonElement(1, MIDI_CC_TYPE, 1, 48)
        play_button.name = 'play_button'
        self.transport.set_play_button(play_button)
        # button: track navigation right
        self.track_navigation_right = ButtonElement(1, MIDI_CC_TYPE, 3, 17)
        self.track_navigation_right.add_value_listener(
            self._track_navigation_right_track_nav, identify_sender=False)
        # button: track navigation left
        self.track_navigation_left = ButtonElement(1, MIDI_CC_TYPE, 3, 14)
        self.track_navigation_left.add_value_listener(
            self._track_navigation_left_track_nav, identify_sender=False)

    def _remove_mode1(self):
        # mixer
        global mixer
        self._remove_mode1_devices()
        self.remove_device_listeners()
        send0_controls = (
            None,
            None,
            None,
            None,
            None,
            None,
            None,
            None,
        )
        self.mixer.channel_strip(0).set_send_controls(tuple(send0_controls))
        send1_controls = (
            None,
            None,
            None,
            None,
            None,
            None,
            None,
            None,
        )
        self.mixer.channel_strip(1).set_send_controls(tuple(send1_controls))
        send2_controls = (
            None,
            None,
            None,
            None,
            None,
            None,
            None,
            None,
        )
        self.mixer.channel_strip(2).set_send_controls(tuple(send2_controls))
        send3_controls = (
            None,
            None,
            None,
            None,
            None,
            None,
            None,
            None,
        )
        self.mixer.channel_strip(3).set_send_controls(tuple(send3_controls))
        # session
        global _session
        self._session.set_clip_launch_buttons(None)
        self.set_highlighting_session_component(None)
        self._session.set_mixer(None)
        self._session.set_stop_all_clips_button(None)
        # session track stop
        self._track_stop_buttons = None
        self._session.set_stop_track_clip_buttons(None)
        # session scene launch
        self._scene_launch_buttons = None
        self._session.set_scene_launch_buttons(None)
        # session navigation
        self.session_left.remove_value_listener(self._reload_active_devices)
        self._session.set_page_left_button(None)
        self.session_right.remove_value_listener(self._reload_active_devices)
        self._session.set_page_right_button(None)
        self.session_up.remove_value_listener(self._reload_active_devices)
        self._session.set_page_up_button(None)
        self.session_down.remove_value_listener(self._reload_active_devices)
        self._session.set_page_down_button(None)
        self._session = None
        self.next_device.remove_value_listener(self._next_device_value)
        self.next_device = None
        self.previous_device.remove_value_listener(self._prev_device_value)
        self.previous_device = None
        # transport
        global transport
        self.transport.set_loop_button(None)
        self.transport.set_stop_button(None)
        self.transport.set_play_button(None)
        self.transport = None
        self.track_navigation_right.remove_value_listener(
            self._track_navigation_right_track_nav)
        self.track_navigation_right = None
        self.track_navigation_left.remove_value_listener(
            self._track_navigation_left_track_nav)
        self.track_navigation_left = None

    def _mode1_devices(self):
        global mixer
        global _session
        # device
        self.mixer.selected_strip().set_volume_control(
            SliderElement(MIDI_CC_TYPE, 0, 28))
        self.mixer.selected_strip().set_pan_control(
            SliderElement(MIDI_CC_TYPE, 0, 29))
        self.mixer.selected_strip().set_mute_button(
            ButtonElement(1, MIDI_CC_TYPE, 1, 28))
        self.mixer.selected_strip().set_solo_button(
            ButtonElement(1, MIDI_CC_TYPE, 1, 29))

        if (len(self.mixer.selected_strip()._track.devices) > 0):
            global device_tracktype_selected__chain_number_selected
            self.device_tracktype_selected__chain_number_selected = DeviceComponent(
            )
            device_controls = (
                SliderElement(MIDI_CC_TYPE, 0, 16),
                SliderElement(MIDI_CC_TYPE, 0, 17),
                SliderElement(MIDI_CC_TYPE, 0, 18),
                SliderElement(MIDI_CC_TYPE, 0, 19),
                SliderElement(MIDI_CC_TYPE, 0, 20),
                SliderElement(MIDI_CC_TYPE, 0, 21),
                SliderElement(MIDI_CC_TYPE, 0, 22),
                SliderElement(MIDI_CC_TYPE, 0, 23),
            )
            self.device_tracktype_selected__chain_number_selected.set_parameter_controls(
                tuple(device_controls))
            self.set_device_component(
                self.device_tracktype_selected__chain_number_selected)
            self.device_tracktype_selected__chain_number_selected.set_on_off_button(
                ButtonElement(1, MIDI_CC_TYPE, 1, 26))
            self.device_tracktype_selected__chain_number_selected.set_bank_nav_buttons(
                ButtonElement(0, MIDI_CC_TYPE, 1, 31),
                ButtonElement(1, MIDI_CC_TYPE, 1, 33))

    def _remove_mode1_devices(self):
        global mixer
        global _session
        # device
        if (hasattr(self, 'device_tracktype_selected__chain_number_selected')):
            global device_tracktype_selected__chain_number_selected
            device_controls = (
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
            )
            self.device_tracktype_selected__chain_number_selected.set_parameter_controls(
                tuple(device_controls))
            self.device_tracktype_selected__chain_number_selected.set_on_off_button(
                None)
            self.device_tracktype_selected__chain_number_selected.set_bank_nav_buttons(
                None, None)
            self.set_device_component(
                self.device_tracktype_selected__chain_number_selected)

    def add_device_listeners(self):
        global mixer
        num_of_tracks = len(self.song().tracks)
        value = "add device listener"
        for index in range(num_of_tracks):
            self.song().tracks[index].add_devices_listener(
                self._reload_active_devices)

    def remove_device_listeners(self):
        global mixer
        num_of_tracks = len(self.song().tracks)
        value = "remove device listener"
        for index in range(num_of_tracks):
            self.song().tracks[index].remove_devices_listener(
                self._reload_active_devices)

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._display_reset_delay = 0
        value = "selected track changed"
        self._reload_active_devices(value)

    def _reload_active_devices(self, value=None):
        self._remove_active_devices()
        self._set_active_devices()

    def _set_active_devices(self):
        global active_mode
        # activate mode
        if (active_mode == "_mode1") and (hasattr(self, '_mode1_devices')):
            self._mode1_devices()

    def _remove_active_devices(self):
        global active_mode
        # remove activate mode
        if (active_mode == "_mode1") and (hasattr(self, '_mode1_devices')):
            self._remove_mode1_devices()

    def _next_device_value(self, value):
        if value > 0:
            self._device = self.song().view.selected_track.view.selected_device
            if self._device is not None:
                self.song().view.select_device(
                    self.song().view.selected_track.devices[
                        self.selected_device_idx() + 1])

    def _prev_device_value(self, value):
        if value > 0:
            self._device = self.song().view.selected_track.view.selected_device
            if self._device is not None:
                self.song().view.select_device(
                    self.song().view.selected_track.devices[
                        self.selected_device_idx() - 1])

    def selected_device_idx(self):
        self._device = self.song().view.selected_track.view.selected_device
        return self.tuple_index(self.song().view.selected_track.devices,
                                self._device)

    def _track_navigation_right_track_nav(self, value):
        if value > 0:
            self.song().view.selected_track = self.song().tracks[
                self.selected_track_idx() + 1]

    def _track_navigation_left_track_nav(self, value):
        if value > 0:
            self.song().view.selected_track = self.song().tracks[
                self.selected_track_idx() - 1]

    def selected_track_idx(self):
        return self.tuple_index(self.song().tracks,
                                self.song().view.selected_track)

    def _set_active_mode(self):
        global active_mode
        # activate mode
        if active_mode == "_mode1":
            self._mode1()

    def _remove_active_mode(self):
        global active_mode
        # remove activate mode
        if active_mode == "_mode1":
            self._remove_mode1()

    def _activate_mode1(self, value):
        global active_mode
        if value > 0:
            self._remove_active_mode()
            active_mode = "_mode1"
            self._set_active_mode()

    def _activate_shift_mode1(self, value):
        global active_mode
        if value > 0:
            self._remove_active_mode()
            self._mode1()
        else:
            self._remove_mode1()
            self._set_active_mode()

    def tuple_index(self, tuple, obj):
        for i in xrange(0, len(tuple)):
            if (tuple[i] == obj):
                return i
        return (False)

    def disconnect(self):
        super(midi_twister_110, self).disconnect()
Exemple #10
0
class joyMIDI(ControlSurface):
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            self.setup_transport()
            self.setup_mixer()
            self.setup_session()

    def setup_transport(self):
        # elements
        self.play_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 93)
        self.stop_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 94)
        self.record_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 95)
        # transport
        self.transport = TransportComponent()
        self.transport.set_play_button(self.play_button)
        self.transport.set_stop_button(self.stop_button)
        self.transport.set_record_button(self.record_button)

    def setup_mixer(self):
        # elements
        self.mute_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                         92)  # tracks, return_tracks
        self.solo_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                         84)  # tracks, return_tracks
        self.arm_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 85)  # tracks
        self.senda_up_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                             96)  # tracks, return_tracks
        self.senda_down_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                               88)  # tracks, return_tracks
        self.sendb_up_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                             97)  # tracks, return_tracks
        self.sendb_down_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                               89)  # tracks, return_tracks
        self.pan_up_button = ButtonElement(
            True, MIDI_NOTE_TYPE, 0, 98)  # tracks, return_tracks, master_track
        self.pan_down_button = ButtonElement(
            True, MIDI_NOTE_TYPE, 0, 90)  # tracks, return_tracks, master_track
        self.volume_up_button = ButtonElement(
            True, MIDI_NOTE_TYPE, 0, 99)  # tracks, return_tracks, master_track
        self.volume_down_button = ButtonElement(
            True, MIDI_NOTE_TYPE, 0, 91)  # tracks, return_tracks, master_track
        self.track_nav_encoder = EncoderElement(
            MIDI_CC_TYPE, 0, 14, Live.MidiMap.MapMode.relative_binary_offset)
        # mixer
        self.mixer = MixerComponent(7, 2)
        self.mixer.selected_strip().set_mute_button(self.mute_button)
        self.mixer.selected_strip().set_solo_button(self.solo_button)
        self.mixer.selected_strip().set_arm_button(self.arm_button)
        # send A/B, pan, volume
        self.senda_up_button.add_value_listener(self.on_senda_up_changed)
        self.senda_down_button.add_value_listener(self.on_senda_down_changed)
        self.sendb_up_button.add_value_listener(self.on_sendb_up_changed)
        self.sendb_down_button.add_value_listener(self.on_sendb_down_changed)
        self.pan_up_button.add_value_listener(self.on_pan_up_changed)
        self.pan_down_button.add_value_listener(self.on_pan_down_changed)
        self.volume_up_button.add_value_listener(self.on_volume_up_changed)
        self.volume_down_button.add_value_listener(self.on_volume_down_changed)
        # nav
        self.track_nav_encoder.add_value_listener(self.on_mixer_track_nav)

    def on_senda_up_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.sends[0]
            param.value = max(
                param.min,
                min(param.max,
                    param.value + ((param.max - param.min) / SEND_STEPS)))

    def on_senda_down_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.sends[0]
            param.value = max(
                param.min,
                min(param.max,
                    param.value - ((param.max - param.min) / SEND_STEPS)))

    def on_sendb_up_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.sends[1]
            param.value = max(
                param.min,
                min(param.max,
                    param.value + ((param.max - param.min) / SEND_STEPS)))

    def on_sendb_down_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.sends[1]
            param.value = max(
                param.min,
                min(param.max,
                    param.value - ((param.max - param.min) / SEND_STEPS)))

    def on_pan_up_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.panning
            param.value = max(
                param.min,
                min(param.max,
                    param.value + ((param.max - param.min) / PAN_STEPS)))

    def on_pan_down_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.panning
            param.value = max(
                param.min,
                min(param.max,
                    param.value - ((param.max - param.min) / PAN_STEPS)))

    def on_volume_up_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.volume
            param.value = max(
                param.min,
                min(param.max,
                    param.value + ((param.max - param.min) / VOLUME_STEPS)))

    def on_volume_down_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.volume
            param.value = max(
                param.min,
                min(param.max,
                    param.value - ((param.max - param.min) / VOLUME_STEPS)))

    def on_mixer_track_nav(self, value):
        move = -1 if value > 64 else +1
        # get tracks-info
        tracks = self.song().tracks
        return_tracks = self.song().return_tracks
        master_track = self.song().master_track
        all_tracks = list(chain(tracks, return_tracks))
        all_tracks.append(master_track)
        num_tracks = len(tracks)
        num_return_tracks = len(return_tracks)
        num_master_track = 1
        num_all_tracks = num_tracks + num_return_tracks + num_master_track
        # update selected-track
        index = index_if(lambda t: t == self.song().view.selected_track,
                         all_tracks)
        index += move
        index = min(max(index, 0), num_all_tracks - 1)
        self.song().view.selected_track = all_tracks[index]

    def setup_session(self):
        num_tracks = 7
        num_scenes = 1
        track_offset = 0
        scene_offset = 0
        # elements
        self.clip_launch_buttons = ButtonMatrixElement(rows=[[
            ButtonElement(True, MIDI_NOTE_TYPE, 0, 76 + i)
            for i in range(num_tracks)
        ]])
        self.clip_stop_buttons = [
            ButtonElement(True, MIDI_NOTE_TYPE, 0, 68 + i)
            for i in range(num_tracks)
        ]
        self.scene_launch_buttons = ButtonMatrixElement(rows=[[
            ButtonElement(True, MIDI_NOTE_TYPE, 0, 83 + i)
            for i in range(num_scenes)
        ]])
        self.scene_stop_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 75)
        self.session_scene_nav_encoder = EncoderElement(
            MIDI_CC_TYPE, 0, 15, Live.MidiMap.MapMode.relative_binary_offset)
        # session
        self.session = SessionComponent(num_tracks, num_scenes)
        self.session.set_offsets(track_offset, scene_offset)
        self.session.add_offset_listener(self.on_session_offset_changed)
        self.set_highlighting_session_component(self.session)
        # clips
        self.session.set_clip_launch_buttons(self.clip_launch_buttons)
        self.session.set_stop_track_clip_buttons(self.clip_stop_buttons)
        self.session.set_scene_launch_buttons(self.scene_launch_buttons)
        self.session.set_stop_all_clips_button(self.scene_stop_button)
        # nav
        self.session_scene_nav_encoder.add_value_listener(
            self.on_session_scene_nav)

    def on_session_offset_changed(self):
        pass

    def on_session_scene_nav(self, value):
        value -= 64
        value = -value
        track_offset = self.session.track_offset()
        scene_offset = max(0, self.session.scene_offset() + value)
        self.session.set_offsets(track_offset, scene_offset)

    def disconnect(self):
        u"""Live -> Script
        Called right before we get disconnected from Live.
        """
        self.log_message('disconnect')
        self.show_message('disconnect')
class NanoKontrolShift(ControlSurface):
    __module__ = __name__
    __doc__ = " NanoKontrolShift controller script "

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self._suppress_session_highlight = True
        self._suppress_send_midi = True  # Turn off rebuild MIDI map until after we're done setting up
        self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= NanoKontrolShift log opened =--------------") # Writes message into Live's main log file. This is a ControlSurface method.
        with self.component_guard():
            # OBJECTS
            self.session = None #session object
            self.mixer = None #mixer object
            self.view = None #clip/device view object
            self.device = None #device object
            self.transport = None #transport object
            # MODES
            self._shift_button = None
            self._shift_button_pressed = False
            self._alt_button = None
            self._alt_button_pressed = False
            self._ctrl_button = None
            self._ctrl_button_pressed = False
            # INITIALIZE MIXER, SESSIONS
            self._setup_session_control()  # Setup the session object
            self._setup_mixer_control() # Setup the mixer object
            self._setup_view_control() # Setup the clip/view toggler
            self.session.set_mixer(self.mixer) # Bind mixer to session
            self._setup_device_control() # Setup the device object
            self._setup_transport_control() # Setup transport object
            self.set_device_component(self.device) # Bind device to control surface
            # SET INITIAL SESSION/MIXER AND MODIFIERS BUTTONS
            self._set_modifiers_buttons()
            self.__update_matrix()
            # self.set_highlighting_session_component(self.session)

            for component in self.components:
                component.set_enabled(True)

        # self._suppress_session_highlight = True
        self._suppress_send_midi = True # Turn rebuild back on, once we're done setting up

    def _setup_session_control(self):
        self.show_message("#################### SESSION: ON ##############################")
        is_momentary = True
        # CREATE SESSION, SET OFFSETS, BUTTONS NAVIGATION AND BUTTON MATRIX
        self.session = SessionComponent(num_tracks, num_scenes) #(num_tracks, num_scenes)
        self.session.set_offsets(0, 0)
        # self.session.set_scene_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_down), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_up))
        # self.session.set_track_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_right), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_left)) # (right_button, left_button) This moves the "red box" selection set left & right. We'll use the mixer track selection instead...

    def _setup_mixer_control(self):
        is_momentary = True
        #CREATE MIXER, SET OFFSET (SPECIALMIXERCOMPONENT USES SPECIALCHANNELSTRIP THAT ALLOWS US TO UNFOLD TRACKS WITH TRACK SELECT BUTTON)
        self.mixer = SpecialMixerComponent(num_tracks, 0, False, False) # 4 tracks, 2 returns, no EQ, no filters
        self.mixer.name = 'Mixer'
        self.mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)

    def _setup_view_control(self):
        # CREATES OBJECT SO WE CAN TOGGLE DEVICE/CLIP, LOCK DEVICE
        self.view = ViewTogglerComponent(num_tracks, self)

    def _setup_device_control(self):
        # CREATE DEVICE TO ASSIGN PARAMETERS BANK
        self.device = DeviceComponent()
        self.device.name = 'Device_Component'

    def _setup_transport_control(self):
        # CREATE TRANSPORT DEVICE
        self.transport = SpecialTransportComponent(self)


    def _on_selected_scene_changed(self):
        # ALLOWS TO GRAB THE FIRST DEVICE OF A SELECTED TRACK IF THERE'S ANY
        ControlSurface._on_selected_track_changed(self)
        track = self.song().view.selected_track
        if (track.devices is not None):
            self._ignore_track_selection = True
            device_to_select = track.devices[0]
            self.song().view.select_device(device_to_select)
            self._device_component.set_device(device_to_select)
        self._ignore_track_selection = False

    """                                 LED ON, OFF, FLASH WITH SESSION CLIPS                                             """

    # UPDATING BUTTONS FROM CLIP MATRIX IN NK AS SESSION MOVES
    def __update_matrix(self):
        for scene_index in range(num_scenes):
            scene = self.session.scene(scene_index)
            for track_index in range(num_tracks):
                clip_slot = scene.clip_slot(track_index)
                button = clip_slot._launch_button_value.subject
                value_to_send = -1
                if clip_slot._clip_slot != None:
                    if clip_slot.has_clip():
                        value_to_send = 127
                        if clip_slot._clip_slot.clip.is_triggered:
                            if clip_slot._clip_slot.clip.will_record_on_start:
                                value_to_send = clip_slot._triggered_to_record_value
                            else:
                                value_to_send = clip_slot._triggered_to_play_value
                        '''
                        elif clip_slot._clip_slot.clip.is_playing:
                            if clip_slot._clip_slot.clip.is_recording:
                                value_to_send = 127
                                #########      CLIPS PLAYING WILL FLASH
                                for i in range(2000):
                                    if i % 50 == 0:
                                        button.send_value(127)
                                    else:
                                        button.send_value(0)
                            else:
                                for i in range(2000):
                                    if i % 50 == 0:
                                        button.send_value(127)
                                    else:
                                        button.send_value(0)
                        '''
                    elif clip_slot._clip_slot.is_triggered:
                        if clip_slot._clip_slot.will_record_on_start:
                            value_to_send = clip_slot._triggered_to_record_value
                        else:
                            value_to_send = clip_slot._triggered_to_play_value
                    elif clip_slot._clip_slot.is_playing:
                        if clip_slot._clip_slot.is_recording:
                            value_to_send = clip_slot._recording_value
                        else:
                            value_to_send = clip_slot._started_value
                    elif clip_slot._clip_slot.controls_other_clips:
                        value_to_send = 0
                '''
                if value_to_send in range(128):
                    button.send_value(value_to_send)
                else:
                    button.turn_off()
                '''

    """                                 MODIFIERS, MODES, KEYS CONFIG                                             """

    #MODES ARE HERE: INITIALIZATIONS, DISCONNECTS BUTTONS, SLIDERS, ENCODERS
    def _clear_controls(self):
        # TURNING OFF ALL LEDS IN MATRIX
        self._turn_off_matrix()
        # SESSION
        resetsend_controls = []
        self.mixer.send_controls = []
        for scene_index in range(num_scenes):
            scene = self.session.scene(scene_index)
            scene.set_launch_button(None)
            for track_index in range(num_tracks):
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(None)
        self.session.set_stop_track_clip_buttons(None)
        self.session.set_stop_all_clips_button(None)
            # REMOVE LISTENER TO SESSION MOVES
        if self.session.offset_has_listener(self.__update_matrix):
            self.session.remove_offset_listener(self.__update_matrix)
        self.session.set_stop_all_clips_button(None)
        # MIXER
        self.mixer._set_send_nav(None, None)
        for track_index in range(num_tracks):
            strip = self.mixer.channel_strip(track_index)
            strip.set_solo_button(None)
            strip.set_mute_button(None)
            strip.set_arm_button(None)
            resetsend_controls.append(None)
            strip.set_select_button(None)
            for i in range(12):
                self.mixer.send_controls.append(None)
            strip.set_send_controls(tuple(self.mixer.send_controls))
        self.mixer.set_resetsend_buttons(tuple(resetsend_controls))
        # VIEW
        self.view.set_device_nav_buttons(None, None)
        detailclip_view_controls = []
        for track_index in range(num_tracks):
            detailclip_view_controls.append(None)
        self.view.set_buttons(tuple(detailclip_view_controls))
        # DEVICE PARAMETERS
        device_param_controls = []
        self.device.set_parameter_controls(tuple(device_param_controls))
        self.device.set_on_off_button(None)
        self.device.set_lock_button(None)
        # TRANSPORT
        self.transport.set_stop_button(None)
        self.transport.set_play_button(None)
        self.transport.set_record_button(None)
        self.transport._set_quant_toggle_button(None)
        self.transport.set_metronome_button(None)
        self.transport._set_tempo_buttons(None, None)

        self.log_message("Controls Cleared")

    def _set_normal_mode(self):
        is_momentary = True
        self.mixer._set_send_nav(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_up), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_down))
        for index in range(num_tracks):
            strip = self.mixer.channel_strip(index)
            strip.name = 'Mixer_ChannelStrip_' + str(index)
            self.mixer._update_send_index(self.mixer.sends_index)
            strip.set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL, mixer_volumefader_cc[index]))
            self.mixer.send_controls[self.mixer.sends_index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, mixer_sendknob_cc[index], Live.MidiMap.MapMode.absolute)
            strip.set_send_controls(tuple(self.mixer.send_controls))
            strip._invert_mute_feedback = True
        ### SET ARM, SOLO, MUTE
        for index in range(num_tracks):
            strip = self.mixer.channel_strip(index)
            strip.set_send_controls(tuple(self.mixer.send_controls))
            strip.set_solo_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_solo_cc[index]))
            strip.set_mute_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_mute_cc[index]))
            strip.set_arm_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_arm_cc[index]))
            # self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_stop_cc))
            for i in range(12):
                self.mixer.send_controls.append(None)
            self.mixer.send_controls[self.mixer.sends_index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, mixer_sendknob_cc[index], Live.MidiMap.MapMode.absolute)
            strip.set_send_controls(tuple(self.mixer.send_controls))
            strip._invert_mute_feedback = True
        self.mixer._update_send_index(self.mixer.sends_index)


    def _set_alt_mode(self):
        is_momentary = True
        self.mixer._set_send_nav(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_up), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_down))
        stop_track_controls = []
        resetsend_controls = []
        button = None
        buttons = None
        # SET SESSION TRACKSTOP, TRACK SELECT, RESET SEND KNOB
        for index in range(num_tracks):
            strip = self.mixer.channel_strip(index)
            strip.set_select_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_select_cc[index]))
            button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, stop_track_cc[index])
            stop_track_controls.append(button)
            buttons = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_resetsend_cc[index])
            resetsend_controls.append(buttons)
        self.session.set_stop_track_clip_buttons(tuple(stop_track_controls))
        self.mixer.set_resetsend_buttons(tuple(resetsend_controls))
        self.mixer._update_send_index(self.mixer.sends_index)


    def _set_ctrl_mode(self):
        # CLIP/DEVICE VIEW TOGGLE
        is_momentary = True
        self.view.set_device_nav_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, device_left_cc), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, device_right_cc))
        button = None
        detailclip_view_controls = []
        for index in range(num_tracks):
            button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, detailclip_view_cc[index])
            detailclip_view_controls.append(button)
        self.view.set_buttons(tuple(detailclip_view_controls))
        # DEVICE ON/OFF, LOCK AND PARAMETERS
        device_param_controls = []
        onoff_control = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, onoff_device_cc)
        setlock_control = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, lock_device_cc)
        for index in range(num_tracks):
            knob = None
            knob = EncoderElement(MIDI_CC_TYPE, CHANNEL, device_param_cc[index], Live.MidiMap.MapMode.absolute)
            device_param_controls.append(knob)
        if None not in device_param_controls:
            self.device.set_parameter_controls(tuple(device_param_controls))
        self.device.set_on_off_button(onoff_control)
        self.device.set_lock_button(setlock_control)
        # TRANSPORT
        # self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_stop_cc))
        # self.transport.set_play_button(ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, transport_play_cc))
        # self.transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_record_cc))
        self.transport._set_quant_toggle_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_quantization_cc))
        self.transport.set_metronome_button(ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, transport_metronome_cc))
        self.transport._set_tempo_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_tempodown_cc), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_tempoup_cc))
        # SESSION STOP ALL CLIPS AND SCENE LAUNCH
        self.session.set_stop_all_clips_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_stopall_cc))
        for index in range(num_scenes):
            self.session.scene(index).set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_scenelaunch_cc[index]))

    def _set_modifiers_buttons(self):
        is_momentary = True
        self._shift_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, shift_mod)
        self._alt_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, alt_mod)
        self._ctrl_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, ctrl_mod)

        if (self._shift_button != None):
            self._shift_button.add_value_listener(self._shift_value)

        if (self._alt_button != None):
            self._alt_button.add_value_listener(self._alt_value)

        if (self._ctrl_button != None):
            self._ctrl_button.add_value_listener(self._ctrl_value)
        #INIT NORMAL MODE
        self._manage_modes(0)

    # MODIFIERS LISTENERS FUNCS ARE HERE
    def _shift_value(self, value):
        assert isinstance(value, int)
        assert isinstance(self._shift_button, ButtonElement)
        if value == 127:
            if self._shift_button_pressed is False:
                self._unpress_modes()
                self._shift_button_pressed = True
                self._manage_modes(0)

    def _alt_value(self, value):
        assert isinstance(value, int)
        assert isinstance(self._alt_button, ButtonElement)
        if value == 127:
            if self._alt_button_pressed is False:
                self._unpress_modes()
                self._alt_button_pressed = True
                self._manage_modes(2)

    def _ctrl_value(self, value):
        assert isinstance(value, int)
        assert isinstance(self._ctrl_button, ButtonElement)
        if value == 127:
            if self._ctrl_button_pressed is False:
                self._unpress_modes()
                self._ctrl_button_pressed = True
                self._manage_modes(3)

    def _manage_modes(self, mode_index):
        if mode_index == 0:
            self._clear_controls()
            self._set_normal_mode()
            # self._shift_button.turn_on()
            self._alt_button.turn_on()
            self._ctrl_button.turn_on()
            self.log_message("NORMAL ON")
        elif mode_index == 2:
            self._clear_controls()
            self._set_alt_mode()
            self._alt_button.turn_on()
            self._shift_button.turn_off()
            self._ctrl_button.turn_off()
            self.log_message("ALT ON")
        elif mode_index == 3:
            self._clear_controls()
            self._set_ctrl_mode()
            self._ctrl_button.turn_on()
            self._shift_button.turn_off()
            self._alt_button.turn_off()
            self.log_message("CTRL ON")

    def _unpress_modes(self):
        self._shift_button_pressed = False
        self._alt_button_pressed = False
        self._ctrl_button_pressed = False

    def _turn_off_matrix(self):
        for index in range(24):
            self._send_midi(tuple([176,index+16,0]))

    def disconnect(self):
        """clean things up on disconnect"""
        self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= NanoKontrolShift log closed =--------------") #Create entry in log file
        self._clear_controls()
        self.session = None
        self.mixer = None
        self.view = None
        self.device = None
        self.transport = None
        # MODES
        self._shift_button = None
        self._alt_button = None
        self._ctrl_button = None
        # SENDS
        self.send_button_up = None
        self.send_button_down = None
        self.send_controls = []
        self.send_reset = []

        self.set_device_component(None)
        ControlSurface.disconnect(self)
        return None
Exemple #12
0
class MPK_SessionControl(ControlSurface):
    __module__ = __name__
    __doc__ = "MPK Session Control Script"

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            self._setup_mixer_control()
            self._setup_transport_control()
            self._setup_session_control()
            self._setup_channel_strip_control()
            self.set_highlighting_session_component(self.session)

    # Sets up the control surface ('colored box')
    def _setup_session_control(self):
        num_tracks = 3  # 3 columns (tracks)
        num_scenes = 1  # 1 row (scenes)

        # a session highlight ("red box") will appear with any two non-zero values
        self.session = SessionComponent(num_tracks, num_scenes)
        # (track_offset, scene_offset) Sets the initial offset of the "red box" from top left
        self.session.set_offsets(0, 0)

        self.session.set_select_buttons(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                          KEYBOARD_HIGH_C - 7),
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                          KEYBOARD_HIGH_C - 6))

        # These calls control the actual movement of the box; however, we're just
        # using scene and track select to move around
        # self.session.set_scene_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 86), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 85))
        # self.session.set_track_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 15), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 14))

        # Launch current scene with top right pad
        self.session.selected_scene().set_launch_button(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, BANK_B[3]))
        # Stop all clips with bottom right pad
        self.session.set_stop_all_clips_button(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, BANK_B[7]))

        # First three pads launch clips in box
        clip_launch_notes = [BANK_B[0], BANK_B[1], BANK_B[2]]
        clip_select_notes = [
            KEYBOARD_MID_C - 6, KEYBOARD_MID_C - 4, KEYBOARD_MID_C - 2
        ]

        for tracks in range(num_tracks):
            self.session.scene(0).clip_slot(tracks).set_launch_button(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                              clip_launch_notes[tracks]))
            self.session.scene(0).clip_slot(tracks).set_select_button(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                              clip_select_notes[tracks]))
            self.session.scene(0).clip_slot(tracks).set_started_value(1)
            self.session.scene(0).clip_slot(tracks).set_stopped_value(0)

        # Bottom three pads stop current tracks in box
        track_stop_notes = [BANK_B[4], BANK_B[5], BANK_B[6]]
        # This looks unnecessary but I don't know the actual API call to to set the stop track button for the selected track
        stop_track_buttons = []
        for tracks in range(num_tracks):
            stop_track_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                              track_stop_notes[tracks]))

        self.session.set_stop_track_clip_buttons(tuple(stop_track_buttons))

        #here we set up a mixer and channel strip(s) which move with the session
        self.session.set_mixer(
            self.mixer
        )  #bind the mixer to the session so that they move together
        selected_scene = self.song(
        ).view.selected_scene  #this is from the Live API
        all_scenes = self.song().scenes
        index = list(all_scenes).index(selected_scene)
        self.session.set_offsets(0, index)  #(track_offset, scene_offset)

    def _setup_transport_control(self):
        self.transport = TransportComponent()
        self.transport.set_stop_button(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                          KEYBOARD_LOW_C))
        self.transport.set_play_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 113))
        self.transport.set_metronome_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 114))
        self.transport.set_tap_tempo_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 81))

    def _setup_mixer_control(self):
        #set up the mixer
        self.mixer = MixerComponent(
            NUM_TRACKS, 2)  #(num_tracks, num_returns, with_eqs, with_filters)
        self.mixer.set_track_offset(
            0)  #sets start point for mixer strip (offset from left)
        self.mixer.selected_strip().set_arm_button(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                          KEYBOARD_HIGH_C))
        self.mixer.set_select_buttons(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                          KEYBOARD_HIGH_C - 2),
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                          KEYBOARD_HIGH_C - 4))
        self.mixer.master_strip().set_volume_control(
            SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[3]))
        #self.mixer.master_strip().set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[7]))
        #set the selected strip to the first track, so that we don't assign a button to arm the master track, which would cause an assertion error
        self.song().view.selected_track = self.mixer.channel_strip(0)._track
        self.mixer.selected_strip().set_volume_control(
            SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[0]))
        #self.mixer.selected_strip().set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[4]))

        selected_track = self.song().view.selected_track
        all_tracks = ((self.song().tracks + self.song().return_tracks) +
                      (self.song().master_track, ))
        currentTrackIndex = list(all_tracks).index(selected_track)
        if currentTrackIndex < len(all_tracks) - 1:
            self.mixer.channel_strip(currentTrackIndex + 1).set_volume_control(
                SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[1]))
            #self.mixer.channel_strip(currentTrackIndex + 1).set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[5]))
        if currentTrackIndex < len(all_tracks) - 2:
            self.mixer.channel_strip(currentTrackIndex + 2).set_volume_control(
                SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[2]))
            #self.mixer.channel_strip(currentTrackIndex + 2).set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[6]))

    def _setup_channel_strip_control(self):
        self.channelstrip = ChannelStripComponent()
        self.channelstrip.set_track(self.mixer.channel_strip(0)._track)

    def _on_selected_track_changed(self):
        """This is an override, to add special functionality (we want to move the session to the selected track, when it changes)
    Note that it is sometimes necessary to reload Live (not just the script) when making changes to this function"""
        ControlSurface._on_selected_track_changed(
            self
        )  # This will run component.on_selected_track_changed() for all components
        """here we set the mixer and session to the selected track, when the selected track changes"""
        selected_track = self.song(
        ).view.selected_track  #this is how to get the currently selected track, using the Live API
        self.mixer.channel_strip(0).set_track(selected_track)
        all_tracks = (
            (self.song().tracks + self.song().return_tracks) +
            (self.song().master_track, )
        )  #this is from the MixerComponent's _next_track_value method
        index = list(all_tracks).index(selected_track)  #and so is this

        self.session.set_offsets(
            index, self.session._scene_offset
        )  #(track_offset, scene_offset); we leave scene_offset unchanged, but set track_offset to the selected track. This allows us to jump the red box to the selected track.

    def _on_selected_scene_changed(self):
        """This is an override, to add special functionality (we want to move the session to the selected scene, when it changes)"""
        """When making changes to this function on the fly, it is sometimes necessary to reload Live (not just the script)..."""
        ControlSurface._on_selected_scene_changed(
            self
        )  # This will run component.on_selected_scene_changed() for all components
        """Here we set the mixer and session to the selected track, when the selected track changes"""
        selected_scene = self.song(
        ).view.selected_scene  #this is how we get the currently selected scene, using the Live API
        all_scenes = self.song().scenes  #then get all of the scenes
        index = list(all_scenes).index(
            selected_scene
        )  #then identify where the selected scene sits in relation to the full list
        self.session.set_offsets(
            self.session._track_offset, index
        )  #(track_offset, scene_offset) Set the session's scene offset to match the selected track (but make no change to the track offset)

    def disconnect(self):
        #clean things up on disconnect

        #create entry in log file
        self.log_message(
            time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) +
            "----------MPK SessionControl log closed----------")

        ControlSurface.disconnect(self)
        return None
class NanoKontrolShift(ControlSurface):
    __module__ = __name__
    __doc__ = " NanoKontrolShift controller script "

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self._suppress_session_highlight = True
        self._suppress_send_midi = True  # Turn off rebuild MIDI map until after we're done setting up
        self.log_message(
            time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) +
            "--------------= NanoKontrolShift log opened =--------------"
        )  # Writes message into Live's main log file. This is a ControlSurface method.
        with self.component_guard():
            # OBJECTS
            self.session = None  # session object
            self.mixer = None  # mixer object
            self.view = None  # clip/device view object
            self.device = None  # device object
            self.transport = None  # transport object
            # MODES
            self._shift_button = None
            self._shift_button_pressed = False
            self._alt_button = None
            self._alt_button_pressed = False
            self._ctrl_button = None
            self._ctrl_button_pressed = False
            # INITIALIZE MIXER, SESSIONS
            self._setup_session_control()  # Setup the session object
            self._setup_mixer_control()  # Setup the mixer object
            self._setup_view_control()  # Setup the clip/view toggler
            self.session.set_mixer(self.mixer)  # Bind mixer to session
            self._setup_device_control()  # Setup the device object
            self._setup_transport_control()  # Setup transport object
            self.set_device_component(
                self.device)  # Bind device to control surface
            # SET INITIAL SESSION/MIXER AND MODIFIERS BUTTONS
            self._set_modifiers_buttons()
            self.__update_matrix()
            self.set_highlighting_session_component(self.session)

            for component in self.components:
                component.set_enabled(True)

        # self._suppress_session_highlight = True
        self._suppress_send_midi = True  # Turn rebuild back on, once we're done setting up

    def _setup_session_control(self):
        self.show_message(
            "#################### SESSION: ON ##############################")
        is_momentary = True
        # CREATE SESSION, SET OFFSETS, BUTTONS NAVIGATION AND BUTTON MATRIX
        self.session = SessionComponent(num_tracks,
                                        num_scenes)  # (num_tracks, num_scenes)
        self.session.set_offsets(0, 0)
        # self.session.set_scene_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_down), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_up))
        self.session.set_track_bank_buttons(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_right),
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_left)
        )  # (right_button, left_button) This moves the "red box" selection set left & right. We'll use the mixer track selection instead...

    def _setup_mixer_control(self):
        is_momentary = True
        # CREATE MIXER, SET OFFSET (SPECIALMIXERCOMPONENT USES SPECIALCHANNELSTRIP THAT ALLOWS US TO UNFOLD TRACKS WITH TRACK SELECT BUTTON)
        self.mixer = SpecialMixerComponent(
            num_tracks, 0, False,
            False)  # 4 tracks, 2 returns, no EQ, no filters
        self.mixer.name = 'Mixer'
        self.mixer.set_track_offset(
            0)  # Sets start point for mixer strip (offset from left)

    def _setup_view_control(self):
        # CREATES OBJECT SO WE CAN TOGGLE DEVICE/CLIP, LOCK DEVICE
        self.view = ViewTogglerComponent(num_tracks, self)

    def _setup_device_control(self):
        # CREATE DEVICE TO ASSIGN PARAMETERS BANK
        self.device = DeviceComponent()
        self.device.name = 'Device_Component'

    def _setup_transport_control(self):
        # CREATE TRANSPORT DEVICE
        self.transport = SpecialTransportComponent(self)

    def _on_selected_scene_changed(self):
        # ALLOWS TO GRAB THE FIRST DEVICE OF A SELECTED TRACK IF THERE'S ANY
        ControlSurface._on_selected_track_changed(self)
        track = self.song().view.selected_track
        if (track.devices is not None):
            self._ignore_track_selection = True
            device_to_select = track.devices[0]
            self.song().view.select_device(device_to_select)
            self._device_component.set_device(device_to_select)
        self._ignore_track_selection = False

    """                                 LED ON, OFF, FLASH WITH SESSION CLIPS                                             """

    # UPDATING BUTTONS FROM CLIP MATRIX IN NK AS SESSION MOVES
    def __update_matrix(self):
        for scene_index in range(num_scenes):
            scene = self.session.scene(scene_index)
            for track_index in range(num_tracks):
                clip_slot = scene.clip_slot(track_index)
                button = clip_slot._launch_button_value.subject
                value_to_send = -1
                if clip_slot._clip_slot != None:
                    if clip_slot.has_clip():
                        value_to_send = 127
                        if clip_slot._clip_slot.clip.is_triggered:
                            if clip_slot._clip_slot.clip.will_record_on_start:
                                value_to_send = clip_slot._triggered_to_record_value
                            else:
                                value_to_send = clip_slot._triggered_to_play_value
                        '''
                        elif clip_slot._clip_slot.clip.is_playing:
                            if clip_slot._clip_slot.clip.is_recording:
                                value_to_send = 127
                                #########      CLIPS PLAYING WILL FLASH
                                for i in range(2000):
                                    if i % 50 == 0:
                                        button.send_value(127)
                                    else:
                                        button.send_value(0)
                            else:
                                for i in range(2000):
                                    if i % 50 == 0:
                                        button.send_value(127)
                                    else:
                                        button.send_value(0)
                        '''
                    elif clip_slot._clip_slot.is_triggered:
                        if clip_slot._clip_slot.will_record_on_start:
                            value_to_send = clip_slot._triggered_to_record_value
                        else:
                            value_to_send = clip_slot._triggered_to_play_value
                    elif clip_slot._clip_slot.is_playing:
                        if clip_slot._clip_slot.is_recording:
                            value_to_send = clip_slot._recording_value
                        else:
                            value_to_send = clip_slot._started_value
                    elif clip_slot._clip_slot.controls_other_clips:
                        value_to_send = 0
                '''
                if value_to_send in range(128):
                    button.send_value(value_to_send)
                else:
                    button.turn_off()
                '''

    """                                 MODIFIERS, MODES, KEYS CONFIG                                             """

    # MODES ARE HERE: INITIALIZATIONS, DISCONNECTS BUTTONS, SLIDERS, ENCODERS
    def _clear_controls(self):
        # TURNING OFF ALL LEDS IN MATRIX
        self._turn_off_matrix()
        # SESSION
        resetsend_controls = []
        self.mixer.send_controls = []
        for scene_index in range(num_scenes):
            scene = self.session.scene(scene_index)
            scene.set_launch_button(None)
            for track_index in range(num_tracks):
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(None)
        self.session.set_stop_track_clip_buttons(None)
        self.session.set_stop_all_clips_button(None)
        # REMOVE LISTENER TO SESSION MOVES
        if self.session.offset_has_listener(self.__update_matrix):
            self.session.remove_offset_listener(self.__update_matrix)
        self.session.set_stop_all_clips_button(None)
        # MIXER
        self.mixer._set_send_nav(None, None)
        for track_index in range(num_tracks):
            strip = self.mixer.channel_strip(track_index)
            strip.set_solo_button(None)
            strip.set_mute_button(None)
            strip.set_arm_button(None)
            resetsend_controls.append(None)
            strip.set_select_button(None)
            for i in range(12):
                self.mixer.send_controls.append(None)
            strip.set_send_controls(tuple(self.mixer.send_controls))
        self.mixer.set_resetsend_buttons(tuple(resetsend_controls))
        # VIEW
        self.view.set_device_nav_buttons(None, None)
        detailclip_view_controls = []
        for track_index in range(num_tracks):
            detailclip_view_controls.append(None)
        self.view.set_buttons(tuple(detailclip_view_controls))
        # DEVICE PARAMETERS
        device_param_controls = []
        self.device.set_parameter_controls(tuple(device_param_controls))
        self.device.set_on_off_button(None)
        self.device.set_lock_button(None)
        # TRANSPORT
        self.transport.set_stop_button(None)
        self.transport.set_play_button(None)
        self.transport.set_record_button(None)
        self.transport._set_quant_toggle_button(None)
        self.transport.set_metronome_button(None)
        self.transport._set_tempo_buttons(None, None)

        self.log_message("Controls Cleared")

    def _set_normal_mode(self):
        is_momentary = True
        self.mixer._set_send_nav(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_up),
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_down))
        for index in range(num_tracks):
            strip = self.mixer.channel_strip(index)
            strip.name = 'Mixer_ChannelStrip_' + str(index)
            self.mixer._update_send_index(self.mixer.sends_index)
            strip.set_volume_control(
                SliderElement(MIDI_CC_TYPE, CHANNEL,
                              mixer_volumefader_cc[index]))
            self.mixer.send_controls[self.mixer.sends_index] = EncoderElement(
                MIDI_CC_TYPE, CHANNEL, mixer_sendknob_cc[index],
                Live.MidiMap.MapMode.absolute)
            strip.set_send_controls(tuple(self.mixer.send_controls))
            strip._invert_mute_feedback = True
        ### SET ARM, SOLO, MUTE
        for index in range(num_tracks):
            strip = self.mixer.channel_strip(index)
            strip.set_send_controls(tuple(self.mixer.send_controls))
            strip.set_solo_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                              track_solo_cc[index]))
            strip.set_mute_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                              track_mute_cc[index]))
            strip.set_arm_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                              track_arm_cc[index]))
            # self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_stop_cc))
            for i in range(12):
                self.mixer.send_controls.append(None)
            self.mixer.send_controls[self.mixer.sends_index] = EncoderElement(
                MIDI_CC_TYPE, CHANNEL, mixer_sendknob_cc[index],
                Live.MidiMap.MapMode.absolute)
            strip.set_send_controls(tuple(self.mixer.send_controls))
            strip._invert_mute_feedback = True
        self.mixer._update_send_index(self.mixer.sends_index)

    def _set_alt_mode(self):
        is_momentary = True
        self.mixer._set_send_nav(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_up),
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_down))
        stop_track_controls = []
        resetsend_controls = []
        button = None
        buttons = None
        # SET SESSION TRACKSTOP, TRACK SELECT, RESET SEND KNOB
        for index in range(num_tracks):
            strip = self.mixer.channel_strip(index)
            strip.set_select_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                              track_select_cc[index]))
            button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                   stop_track_cc[index])
            stop_track_controls.append(button)
            buttons = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                    track_resetsend_cc[index])
            resetsend_controls.append(buttons)
        self.session.set_stop_track_clip_buttons(tuple(stop_track_controls))
        self.mixer.set_resetsend_buttons(tuple(resetsend_controls))
        self.mixer._update_send_index(self.mixer.sends_index)

    def _set_ctrl_mode(self):
        # CLIP/DEVICE VIEW TOGGLE
        is_momentary = True
        self.view.set_device_nav_buttons(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, device_left_cc),
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                          device_right_cc))
        button = None
        detailclip_view_controls = []
        for index in range(num_tracks):
            button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL,
                                   detailclip_view_cc[index])
            detailclip_view_controls.append(button)
        self.view.set_buttons(tuple(detailclip_view_controls))
        # DEVICE ON/OFF, LOCK AND PARAMETERS
        device_param_controls = []
        onoff_control = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                      onoff_device_cc)
        setlock_control = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                        lock_device_cc)
        for index in range(num_tracks):
            knob = None
            knob = EncoderElement(MIDI_CC_TYPE, CHANNEL,
                                  device_param_cc[index],
                                  Live.MidiMap.MapMode.absolute)
            device_param_controls.append(knob)
        if None not in device_param_controls:
            self.device.set_parameter_controls(tuple(device_param_controls))
        self.device.set_on_off_button(onoff_control)
        self.device.set_lock_button(setlock_control)
        # TRANSPORT
        # self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_stop_cc))
        # self.transport.set_play_button(ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, transport_play_cc))
        # self.transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_record_cc))
        self.transport._set_quant_toggle_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                          transport_quantization_cc))
        self.transport.set_metronome_button(
            ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL,
                          transport_metronome_cc))
        self.transport._set_tempo_buttons(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                          transport_tempodown_cc),
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                          transport_tempoup_cc))
        # SESSION STOP ALL CLIPS AND SCENE LAUNCH
        self.session.set_stop_all_clips_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                          session_stopall_cc))
        for index in range(num_scenes):
            self.session.scene(index).set_launch_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                              session_scenelaunch_cc[index]))

    def _set_modifiers_buttons(self):
        is_momentary = True
        self._shift_button = ButtonElement(not is_momentary, MIDI_CC_TYPE,
                                           CHANNEL, shift_mod)
        self._alt_button = ButtonElement(not is_momentary, MIDI_CC_TYPE,
                                         CHANNEL, alt_mod)
        self._ctrl_button = ButtonElement(not is_momentary, MIDI_CC_TYPE,
                                          CHANNEL, ctrl_mod)

        if (self._shift_button != None):
            self._shift_button.add_value_listener(self._shift_value)

        if (self._alt_button != None):
            self._alt_button.add_value_listener(self._alt_value)

        if (self._ctrl_button != None):
            self._ctrl_button.add_value_listener(self._ctrl_value)
        # INIT NORMAL MODE
        self._manage_modes(0)

    # MODIFIERS LISTENERS FUNCS ARE HERE
    def _shift_value(self, value):
        assert isinstance(value, int)
        assert isinstance(self._shift_button, ButtonElement)
        if value == 127:
            if self._shift_button_pressed is False:
                self._unpress_modes()
                self._shift_button_pressed = True
                self._manage_modes(0)

    def _alt_value(self, value):
        assert isinstance(value, int)
        assert isinstance(self._alt_button, ButtonElement)
        if value == 127:
            if self._alt_button_pressed is False:
                self._unpress_modes()
                self._alt_button_pressed = True
                self._manage_modes(2)

    def _ctrl_value(self, value):
        assert isinstance(value, int)
        assert isinstance(self._ctrl_button, ButtonElement)
        if value == 127:
            if self._ctrl_button_pressed is False:
                self._unpress_modes()
                self._ctrl_button_pressed = True
                self._manage_modes(3)

    def _manage_modes(self, mode_index):
        if mode_index == 0:
            self._clear_controls()
            self._set_normal_mode()
            # self._shift_button.turn_on()
            self._alt_button.turn_on()
            self._ctrl_button.turn_on()
            self.log_message("NORMAL ON")
        elif mode_index == 2:
            self._clear_controls()
            self._set_alt_mode()
            self._alt_button.turn_on()
            self._shift_button.turn_off()
            self._ctrl_button.turn_off()
            self.log_message("ALT ON")
        elif mode_index == 3:
            self._clear_controls()
            self._set_ctrl_mode()
            self._ctrl_button.turn_on()
            self._shift_button.turn_off()
            self._alt_button.turn_off()
            self.log_message("CTRL ON")

    def _unpress_modes(self):
        self._shift_button_pressed = False
        self._alt_button_pressed = False
        self._ctrl_button_pressed = False

    def _turn_off_matrix(self):
        for index in range(24):
            self._send_midi(tuple([176, index + 16, 0]))

    def disconnect(self):
        """clean things up on disconnect"""
        self.log_message(
            time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) +
            "--------------= NanoKontrolShift log closed =--------------"
        )  # Create entry in log file
        self._clear_controls()
        self.session = None
        self.mixer = None
        self.view = None
        self.device = None
        self.transport = None
        # MODES
        self._shift_button = None
        self._alt_button = None
        self._ctrl_button = None
        # SENDS
        self.send_button_up = None
        self.send_button_down = None
        self.send_controls = []
        self.send_reset = []

        self.set_device_component(None)
        ControlSurface.disconnect(self)
        return None