예제 #1
0
    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)
예제 #2
0
파일: Serato.py 프로젝트: cce/buttons
class Serato(ControlSurface):

    def __init__(self, c_instance):
        publish_in_cs_list = True
        ControlSurface.__init__(self, c_instance, not publish_in_cs_list)
        self._device_selection_follows_track_selection = True
        with self.component_guard():
            self._matrix = None
            self._session = None
            self._mixer = None
            self._device = None
            self._scene_launch_buttons = None
            self._track_arm_buttons = None
            self._track_solo_buttons = None
            self._track_mute_buttons = None
            self._track_stop_buttons = None
            self._track_select_buttons = None
            self._device_on_off_button = None
            self._shift_button = None
            self._serato_interface = PySCAClipControl()
            self._serato_interface.PySCA_InitializeClipControl()
            self._setup_session_control()
            self._setup_mixer_control()
            self._setup_device_control()
            self._session.set_mixer(self._mixer)
            self.set_highlighting_session_component(self._session)
        return

    def disconnect(self):
        ControlSurface.disconnect(self)
        self._serato_interface.PySCA_DeinitializeClipControl()
        self._serato_interface = None
        return

    def connect_script_instances(self, instanciated_scripts):
        """ Called by the Application as soon as all scripts are initialized.
            You can connect yourself to other running scripts here, as we do it
            connect the extension modules (MackieControlXTs).
        """
        for control_surface in self._control_surfaces():
            control_surface_session = control_surface.highlighting_session_component()
            if control_surface_session:
                self._session.sync_to(control_surface_session)
                self._on_track_list_changed()
                break

    def build_midi_map(self, midi_map_handle):
        pass

    def update_display(self):
        ControlSurface.update_display(self)
        while self._serato_interface.PySCA_HasIncomingEvent():
            new_event = self._serato_interface.PySCA_GetIncomingEvent()
            if not self._handle_session_event(new_event):
                if not self._handle_mixer_event(new_event):
                    if not self._handle_device_event(new_event):
                        print 'Unhandled Event: ' + str(new_event)

    def _setup_session_control(self):
        is_momentary = True
        self._session = SpecialSessionComponent(NUM_TRACKS, NUM_SCENES)
        self._session.set_serato_interface(self._serato_interface)
        self._matrix = ButtonMatrixElement()
        self._scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_SCENES) ]
        self._track_stop_buttons = [ ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_TRACKS) ]
        stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
        self._session.set_stop_all_clips_button(stop_all_button)
        self._session.set_stop_track_clip_buttons(tuple(self._track_stop_buttons))
        for scene_index in range(NUM_SCENES):
            scene = self._session.scene(scene_index)
            button_row = []
            scene.set_launch_button(self._scene_launch_buttons[scene_index])
            scene.set_index(scene_index)
            scene.set_serato_interface(self._serato_interface)
            for track_index in range(NUM_TRACKS):
                button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(button)
                clip_slot.set_serato_interface(self._serato_interface)

            self._matrix.add_row(tuple(button_row))

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(NUM_TRACKS)
        self._mixer.set_serato_interface(self._serato_interface)
        self._mixer.master_strip().set_serato_interface(self._serato_interface)
        self._track_arm_buttons = []
        self._track_solo_buttons = []
        self._track_mute_buttons = []
        self._track_select_buttons = []
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
        for track in range(NUM_TRACKS):
            strip = self._mixer.channel_strip(track)
            strip.set_serato_interface(self._serato_interface)
            self._track_arm_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_solo_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_mute_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_select_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            strip.set_arm_button(self._track_arm_buttons[-1])
            strip.set_solo_button(self._track_solo_buttons[-1])
            strip.set_mute_button(self._track_mute_buttons[-1])
            strip.set_select_button(self._track_select_buttons[-1])
            strip.set_shift_button(self._shift_button)

    def _setup_device_control(self):
        is_momentary = True
        self._device_on_off_button = ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)
        self._device = SpecialDeviceComponent()
        self._device.set_serato_interface(self._serato_interface)
        self._device.set_parameter_controls(tuple([ SliderElement(MIDI_CC_TYPE, 0, 0) for index in range(NUM_PARAMS) ]))
        self._device.set_on_off_button(self._device_on_off_button)
        self.set_device_component(self._device)

    def _handle_session_event(self, event):
        result = False
        if event.type in CLIP_EVENTS:
            value = 127 * int(event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventClipPlayedDown)
            track_index = event.key1 - 1
            scene_index = event.key2 - 1
            if track_index in range(NUM_TRACKS) and scene_index in range(NUM_SCENES):
                self._matrix.get_button(track_index, scene_index).receive_value(value)
            result = True
        elif event.type in SCENE_EVENTS:
            value = 127 * int(event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventScenePlayedDown)
            scene_index = event.key1 - 1
            if scene_index in range(NUM_SCENES):
                self._scene_launch_buttons[scene_index].receive_value(value)
            result = True
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixSizeChanged:
            new_width = event.key1
            new_height = event.key2
            self._session.set_size(new_width, new_height)
            result = True
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixOffsetChanged:
            x_increment = event.key1
            y_increment = event.key2
            self._session.move_by(x_increment, y_increment)
            result = True
        return result

    def _handle_mixer_event(self, event):
        result = True
        track_index = event.key1 - 1
        value = event.key2
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackMasterGainChange:
            self._mixer.master_strip().set_track_volume(fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackStopped:
            self.song().stop_all_clips()
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackSelect:
            self.song().view.selected_track = self.song().master_track
        else:
            result = track_index in range(NUM_TRACKS) and self._handle_strip_event(event)
        return result

    def _handle_strip_event(self, event):
        result = True
        track_index = event.key1 - 1
        value = event.key2
        if value == 0:
            self._shift_button.receive_value(127)
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSolo:
            self._track_solo_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackRecord:
            self._track_arm_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackActive:
            self._track_mute_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackStopped:
            self._track_stop_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSelect:
            self._track_select_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackGainChange:
            self._mixer.channel_strip(track_index).set_track_volume(fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendAChange:
            self._mixer.channel_strip(track_index).set_send(0, fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendBChange:
            self._mixer.channel_strip(track_index).set_send(1, fixed_value(value))
        else:
            result = False
        self._shift_button.receive_value(0)
        return result

    def _handle_device_event(self, event):
        result = True
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceValueChanged:
            self._device.set_parameter_value(event.key1 - 1, fixed_value(event.key2))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceActivate:
            self._device_on_off_button.receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceFocusMove:
            self._move_device_focus(event.key1)
        else:
            result = False
        return result

    def _move_device_focus(self, increment):
        if not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain'):
            self.application().view.show_view('Detail')
            self.application().view.show_view('Detail/DeviceChain')
        else:
            modifier_pressed = True
            direction = Live.Application.Application.View.NavDirection.left
            if increment > 0:
                direction = Live.Application.Application.View.NavDirection.right
            self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)
class MatrixModesComponent(ModeSelectorComponent):
    ' SelectorComponent that assigns matrix to different functions '
    __module__ = __name__

    def __init__(self, matrix, session, zooming, stop_buttons, parent):
        assert isinstance(matrix, ButtonMatrixElement)
        ModeSelectorComponent.__init__(self)
        self._controls = None
        self._session = session
        self._session_zoom = zooming
        self._matrix = matrix
        self._track_stop_buttons = stop_buttons
        self._stop_button_matrix = ButtonMatrixElement(
        )  #new dummy matrix for stop buttons, to allow note mode/user mode switching
        button_row = []
        for track_index in range(8):
            button = self._track_stop_buttons[track_index]
            button_row.append(button)
        self._stop_button_matrix.add_row(tuple(button_row))
        self._mode_index = 0
        self._last_mode = 0
        self._parent = parent
        self._parent.set_pad_translations(
            PAD_TRANSLATIONS)  #comment out to remove Drum Rack mapping

    def disconnect(self):
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)
        self._controls = None
        self._session = None
        self._session_zoom = None
        self._matrix = None
        self._track_stop_buttons = None
        self._stop_button_matrix = None
        ModeSelectorComponent.disconnect(self)

    def set_mode(
            self,
            mode):  #override ModeSelectorComponent set_mode, to avoid flickers
        assert isinstance(mode, int)
        assert (mode in range(self.number_of_modes()))
        if (self._mode_index != mode):
            self._last_mode = self._mode_index  # keep track of previous mode, to allow refresh after Note Mode only
            self._mode_index = mode
            self._set_modes()

    def set_mode_buttons(self, buttons):
        assert isinstance(buttons, (tuple, type(None)))
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)

        self._modes_buttons = []
        if (buttons != None):
            for button in buttons:
                assert isinstance(button, ButtonElement)
                identify_sender = True
                button.add_value_listener(self._mode_value, identify_sender)
                self._modes_buttons.append(button)
            for index in range(len(self._modes_buttons)):
                if (index == self._mode_index):
                    self._modes_buttons[index].turn_on()
                else:
                    self._modes_buttons[index].turn_off()

    def number_of_modes(self):
        return 8

    def update(self):
        pass

    def _set_modes(self):
        if self.is_enabled():
            self._session.set_allow_update(False)
            self._session_zoom.set_allow_update(False)
            assert (self._mode_index in range(self.number_of_modes()))
            for index in range(len(self._modes_buttons)):
                if (index == self._mode_index):
                    self._modes_buttons[index].turn_on()
                else:
                    self._modes_buttons[index].turn_off()
            self._session.set_stop_track_clip_buttons(
                tuple(self._track_stop_buttons))
            for track_index in range(8):
                button = self._track_stop_buttons[track_index]
                button.use_default_message()
                button.set_enabled(True)
                button.set_force_next_value()
                button.send_value(0)
            self._session_zoom.set_enabled(True)
            self._session.set_enabled(True)
            self._session.set_show_highlight(True)
            self._session_zoom.set_zoom_button(self._parent._shift_button)
            for scene_index in range(5):
                scene = self._session.scene(scene_index)
                for track_index in range(8):
                    button = self._matrix.get_button(track_index, scene_index)
                    button.use_default_message()
                    clip_slot = scene.clip_slot(track_index)
                    clip_slot.set_launch_button(button)
                    button.set_enabled(True)

            if (self._mode_index == 0):  #Clip Launch
                self._session_zoom._zoom_value(1)  #zoom out
                pass

            elif (self._mode_index == 1):  #Session Overview
                self._session_zoom.set_enabled(True)
                self._session_zoom._is_zoomed_out = True
                self._session_zoom._scene_bank_index = int(
                    ((self._session_zoom._session.scene_offset() /
                      self._session_zoom._session.height()) /
                     self._session_zoom._buttons.height()))
                self._session.set_enabled(False)
                self._session_zoom.update()
                self._session_zoom.set_zoom_button(None)

            elif (self._mode_index == 2):
                self._set_note_mode(PATTERN_1, CHANNEL_1, NOTEMAP_1,
                                    USE_STOP_ROW_1, IS_NOTE_MODE_1)
            elif (self._mode_index == 3):
                self._set_note_mode(PATTERN_2, CHANNEL_2, NOTEMAP_2,
                                    USE_STOP_ROW_2, IS_NOTE_MODE_2)
            elif (self._mode_index == 4):
                self._set_note_mode(PATTERN_3, CHANNEL_3, NOTEMAP_3,
                                    USE_STOP_ROW_3, IS_NOTE_MODE_3)
            elif (self._mode_index == 5):
                self._set_note_mode(PATTERN_4, CHANNEL_4, NOTEMAP_4,
                                    USE_STOP_ROW_4, IS_NOTE_MODE_4)
            elif (self._mode_index == 6):
                self._set_note_mode(PATTERN_5, CHANNEL_5, NOTEMAP_5,
                                    USE_STOP_ROW_5, IS_NOTE_MODE_5)
            elif (self._mode_index == 7):
                self._set_note_mode(PATTERN_6, CHANNEL_6, NOTEMAP_6,
                                    USE_STOP_ROW_6, IS_NOTE_MODE_6)
            else:
                pass  #assert False
            self._session.set_allow_update(True)
            self._session_zoom.set_allow_update(True)
            #self._rebuild_callback()

    def _set_note_mode(self,
                       pattern,
                       channel,
                       notemap,
                       use_stop_row=False,
                       is_note_mode=True):
        self._session_zoom.set_zoom_button(None)
        self._session_zoom.set_enabled(False)
        for scene_index in range(5):
            scene = self._session.scene(scene_index)
            for track_index in range(8):
                clip_slot = scene.clip_slot(track_index)
                button = self._matrix.get_button(track_index, scene_index)
                clip_slot.set_launch_button(None)
                button.set_channel(
                    channel)  #remap all Note Mode notes to new channel
                button.set_identifier(notemap[scene_index][track_index])
                #button.send_value(pattern[scene_index][track_index], True)
                button.set_on_off_values(pattern[scene_index][track_index], 0)
                button.set_force_next_value()
                button.turn_on()
                #button.turn_off()
                if is_note_mode == True:
                    button.set_enabled(False)
        if use_stop_row == True:
            self._session.set_stop_track_clip_buttons(None)
            for track_index in range(8):
                button = self._stop_button_matrix.get_button(track_index, 0)
                button.set_channel(
                    channel)  #remap all Note Mode notes to new channel
                button.set_identifier(notemap[5][track_index])
                button.set_force_next_value()
                button.send_value(pattern[5][track_index])
                #button.receive_value(pattern[5][track_index]) #TODO - feedback?
                if is_note_mode == True:
                    button.set_enabled(False)
        else:
            #self._session.set_enabled(True)
            for track_index in range(8):
                button = self._stop_button_matrix.get_button(track_index, 0)
                button.send_value(0, True)
        self._session.set_enabled(True)
        self._session.set_show_highlight(True)
예제 #4
0
class AumPC20(APC):
	__doc__ = " Script for Akai's APC20 Controller "


	def __init__(self, c_instance):
		self._shift_modes = None
		APC.__init__(self, c_instance)
		return None
	

	def disconnect(self):
		self._shift_modes = None
		APC.disconnect(self)
		return None
	

	def _activate_combination_mode(self, track_offset, support_devices):
		APC._activate_combination_mode(self, track_offset, support_devices)
		if support_devices:
			self._shift_modes.invert_assignment()
	

	def _setup_session_control(self):
		is_momentary = True
		self._shift_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81, self)		   
		self._session = APCSessionComponent(8, 5)
		self._session.name = 'Session_Control'
		self._matrix = ButtonMatrixElement()
		self._matrix.name = 'Button_Matrix'
		scene_launch_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82), self) for index in range(5) ]
		self._scene_launch_buttons = scene_launch_buttons
		track_stop_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52, self) for index in range(8) ]
		self._track_stop_buttons = track_stop_buttons
		for index in range(len(scene_launch_buttons)):
			scene_launch_buttons[index].name = 'Scene_'+ str(index) + '_Launch_Button'
		for index in range(len(track_stop_buttons)):
			track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button'
		self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		self._session.set_stop_track_clip_value(2)
		for scene_index in range(5):
			scene = self._session.scene(scene_index)
			scene.name = 'Scene_' + str(scene_index)
			button_row = []
			scene.set_launch_button(scene_launch_buttons[scene_index])
			scene.set_triggered_value(2)
			for track_index in range(8):
				button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53), self)
				button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button'
				button_row.append(button)
				clip_slot = scene.clip_slot(track_index)
				clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index)
				clip_slot.set_triggered_to_play_value(2)
				clip_slot.set_triggered_to_record_value(4)
				clip_slot.set_stopped_value(5)
				clip_slot.set_started_value(1)
				clip_slot.set_recording_value(3)
				clip_slot.set_launch_button(button)

			self._matrix.add_row(tuple(button_row))
		self._session.selected_scene().name = 'Selected_Scene'
		self._session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
		self._session_zoom = ShiftableZoomingComponent(self._session, tuple(track_stop_buttons))
		self._session_zoom.name = 'Session_Overview'
		self._session_zoom.set_button_matrix(self._matrix)
		self._session_zoom.set_zoom_button(self._shift_button)
		self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
		self._session_zoom.set_stopped_value(3)
		self._session_zoom.set_selected_value(5)
	

	def _setup_mixer_control(self):
		is_momentary = True
		self._mixer = SpecialMixerComponent(8)
		self._mixer.name = 'Mixer'
		self._mixer.master_strip().name = 'Master_Channel_Strip'
		self._mixer.selected_strip().name = 'Selected_Channel_Strip'
		self._solo_buttons = []
		for track in range(8):
			strip = self._mixer.channel_strip(track)
			strip.name = 'Channel_Strip_' + str(track)
			solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, self)
			self._solo_buttons.append(solo_button)
			mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)
			solo_button.name = str(track) + '_Solo_Button'
			mute_button.name = str(track) + '_Mute_Button'
			strip.set_solo_button(solo_button)
			strip.set_mute_button(mute_button)
			strip.set_shift_button(self._shift_button)
			strip.set_invert_mute_feedback(True)
		master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
		prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
		master_volume_control.name = 'Master_Volume_Control'
		prehear_control.name = 'Prehear_Volume_Control'
		self._mixer.set_prehear_volume_control(prehear_control)
		self._mixer.master_strip().set_volume_control(master_volume_control)
	

	def _setup_custom_components(self):
		is_momentary = True
		master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80)
		self._master_select_button = master_select_button
		master_select_button.name = 'Master_Select_Button'
		select_buttons = []
		self._select_buttons = []
		arm_buttons = []
		sliders = []
		for track in range(8):
			select_buttons.append(FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51, self))
			self._select_buttons.append(select_buttons[track])
			arm_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48))
			if track is 7:
				self._user3 = arm_buttons[track]
			sliders.append(MonoEncoderElement2(MIDI_CC_TYPE, track, 7, Live.MidiMap.MapMode.absolute, 'Slider_' + str(track), track, self))
			#sliders.append(MonoEncoderElement2(MIDI_CC_TYPE, track, 7))
			select_buttons[-1].name = str(track) + '_Select_Button'
			arm_buttons[-1].name = str(track) + '_Arm_Button'
			#sliders[-1].name = str(track) + '_Volume_Control'
		transport = TransportComponent()
		transport.name = 'Transport'
		slider_modes = SliderModesComponent(self._mixer, tuple(sliders))
		slider_modes.name = 'Slider_Modes'
		self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message, self)
		self._shift_modes.name = 'Shift_Modes'
		self._shift_modes.set_mode_toggle(self._shift_button)
	

	def _product_model_id_byte(self):
		return 123
	

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

	def _setup_monomod(self):
		self._host = MonomodComponent(self)
		self._host.name = 'Monomod_Host'
		self._host._set_nav_buttons = self._mod_set_nav_buttons(self._host)
		self._host._update_nav_buttons = self._mod_update_nav_buttons(self._host)
		self._host._set_nav_buttons = self._mod_set_nav_buttons(self._host)
		self.hosts = [self._host]
		self._monomod = ButtonMatrixElement()
		self._monomod.name = 'Monomod'
		for row in range(5):
			button_row = []
			for column in range(8):
				button_row.append(self._matrix.get_button(column, row))
			self._monomod.add_row(tuple(button_row))
		self._monomod.add_row(tuple(self._track_stop_buttons))
		self._monomod.add_row(tuple(self._select_buttons))
		self._monomod.add_row(tuple(self._solo_buttons))
		self._monomod_mode = MonomodModeComponent(self._monomod_mode_update, self)
		self._monomod_mode.name = "Monomod_Mode_Component"
	

	def _monomod_mode_update(self):
		if(self._monomod_mode._mode_index == 0) or (self._host._active_client == None):
			self.flash_status = 0
			self._host.set_enabled(False)
			self._host._set_button_matrix(None)
			#self._host._set_nav_buttons(None)
			self._host._set_lock_button(None)
			self._host._set_alt_button(None)
			self._host._set_shift_button(None)
			self._host._set_nav_buttons(None)
			self._scene_launch_buttons[2].set_on_off_values(127, 0)	
			self._scene_launch_buttons[3].set_on_off_values(127, 0)	
			self._monomod.reset()
			self._shift_modes.set_enabled(True)
			#self._session.set_track_bank_buttons(self._right_button, self._left_button)
			#self._session.set_scene_bank_buttons(self._down_button, self._up_button)
			for track in range(8):
				self._mixer.channel_strip(track).set_select_button(self._select_buttons[track])
				self._mixer.channel_strip(track).set_solo_button(self._solo_buttons[track])
			#self._transport.set_nudge_buttons(self._nudge_up_button, self._nudge_down_button)
			self._session.set_enabled(True)
			self._session_zoom._is_zoomed_out = False
			self._session_zoom.set_enabled(True)
			self.request_rebuild_midi_map()
			self._master_select_button.turn_off()
			
		elif(self._monomod_mode._mode_index == 1):
			if self._shift_modes._note_mode_active is True:
				self._shift_modes._mode_callback(ABLETON_MODE)
				self._shift_modes._note_mode_active = False
				self._session_zoom.set_ignore_buttons(False)
				self._shift_modes._transport.update()
				self._shift_modes._on_note_mode_changed()
			#self._transport.set_nudge_buttons(None, None)
			self._shift_modes.set_enabled(False)
			for track in range(8):
				self._mixer.channel_strip(track).set_select_button(None)
				self._mixer.channel_strip(track).set_solo_button(None)
			for scene in range(5):
				self._scene_launch_buttons[scene].turn_off()
			self._session.set_enabled(False)
			self._session_zoom.set_enabled(False)
			#self._session.set_track_bank_buttons(None, None)
			#self._session.set_scene_bank_buttons(None, None)
			self.flash_status = 1
			self._monomod.reset()
			self._host._set_button_matrix(self._monomod)
			#self._host._set_nav_buttons([self._up_button, self._down_button, self._left_button, self._right_button])
			self._host._set_shift_button(self._shift_button)
			self._host._set_lock_button(self._scene_launch_buttons[0])
			self._host._set_alt_button(self._scene_launch_buttons[1])
			self._host._set_nav_buttons([self._scene_launch_buttons[2], self._scene_launch_buttons[3]])
			self._host.set_enabled(True)
			self.request_rebuild_midi_map()
			self._master_select_button.turn_on()
	

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

		ret += ' '
		assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
		return ret
	

	def notification_to_bridge(self, name, value, sender):
		if isinstance(sender, MonoEncoderElement2):
			self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name)))
			self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value)))
	

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

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

	def get_clip_names(self):
		clip_names = []
		for scene in self._session._scenes:
			for clip_slot in scene._clip_slots:
				if clip_slot.has_clip() is True:
					clip_names.append(clip_slot._clip_slot)##.clip.name)
					return clip_slot._clip_slot
					##self.log_message(str(clip_slot._clip_slot.clip.name))
		return clip_names
	



	def update_display(self):
		""" Live -> Script
		Aka on_timer. Called every 100 ms and should be used to update display relevant
		parts of the controller
		"""
		for message in self._scheduled_messages:
			message['Delay'] -= 1
			if (message['Delay'] == 0):
				if (message['Parameter'] != None):
					message['Message'](message['Parameter'])
				else:
					message['Message']()
					del self._scheduled_messages[self._scheduled_messages.index(message)]

		for callback in self._timer_callbacks:
			callback()
		self._timer = (self._timer + 1) % 256
		self.flash()
	

	def flash(self):
		if(self.flash_status > 0):
			for row in range(8):
				for column in range(8):
					button = self._monomod.get_button(column, row)
					if(button._flash_state > 0):
						button.flash(self._timer)
	


### Mod Overrides ####

	def _mod_set_nav_buttons(self, mod):	
		def _set_nav_buttons(buttons):
			if mod._nav_buttons != None:
				mod._nav_buttons[0].remove_value_listener(mod._nav_up_value)
				mod._nav_buttons[1].remove_value_listener(mod._nav_down_value)
			mod._nav_buttons = buttons
			if buttons != None:
				assert len(buttons) == 2
				for button in buttons:
					assert isinstance(button, FlashingButtonElement)
				mod._nav_buttons[0].set_on_off_values(8, 2)	
				mod._nav_buttons[0].add_value_listener(mod._nav_up_value)
				mod._nav_buttons[1].set_on_off_values(8, 2)	
				mod._nav_buttons[1].add_value_listener(mod._nav_down_value)
		return _set_nav_buttons
	

	def _mod_update_nav_buttons(self, mod):
		def _update_nav_buttons():
			if mod._nav_buttons != None:
				if(mod._y > 0):
					mod._nav_buttons[0].turn_on()
				else:
					mod._nav_buttons[0].turn_off()
				if(mod._y < 8):
					mod._nav_buttons[1].turn_on()
				else:
					mod._nav_buttons[1].turn_off() 
		return _update_nav_buttons
class Serato(ControlSurface):

    def __init__(self, c_instance):
        publish_in_cs_list = True
        ControlSurface.__init__(self, c_instance, not publish_in_cs_list)
        self._device_selection_follows_track_selection = True
        with self.component_guard():
            self._matrix = None
            self._session = None
            self._mixer = None
            self._device = None
            self._scene_launch_buttons = None
            self._track_arm_buttons = None
            self._track_solo_buttons = None
            self._track_mute_buttons = None
            self._track_stop_buttons = None
            self._track_select_buttons = None
            self._device_on_off_button = None
            self._shift_button = None
            self._serato_interface = PySCAClipControl()
            self._serato_interface.PySCA_InitializeClipControl()
            self._setup_session_control()
            self._setup_mixer_control()
            self._setup_device_control()
            self._session.set_mixer(self._mixer)
            self.set_highlighting_session_component(self._session)

    def disconnect(self):
        ControlSurface.disconnect(self)
        self._serato_interface.PySCA_DeinitializeClipControl()
        self._serato_interface = None

    def connect_script_instances(self, instanciated_scripts):
        """ Called by the Application as soon as all scripts are initialized.
            You can connect yourself to other running scripts here, as we do it
            connect the extension modules (MackieControlXTs).
        """
        for control_surface in self._control_surfaces():
            control_surface_session = control_surface.highlighting_session_component()
            if control_surface_session:
                self._session.sync_to(control_surface_session)
                self._on_track_list_changed()
                break

    def build_midi_map(self, midi_map_handle):
        pass

    def update_display(self):
        ControlSurface.update_display(self)
        while self._serato_interface.PySCA_HasIncomingEvent():
            new_event = self._serato_interface.PySCA_GetIncomingEvent()
            if not self._handle_session_event(new_event):
                if not self._handle_mixer_event(new_event):
                    if not self._handle_device_event(new_event):
                        print 'Unhandled Event: ' + str(new_event)

    def _setup_session_control(self):
        is_momentary = True
        self._session = SpecialSessionComponent(NUM_TRACKS, NUM_SCENES)
        self._session.set_serato_interface(self._serato_interface)
        self._matrix = ButtonMatrixElement()
        self._scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_SCENES) ]
        self._track_stop_buttons = [ ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_TRACKS) ]
        stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
        self._session.set_stop_all_clips_button(stop_all_button)
        self._session.set_stop_track_clip_buttons(tuple(self._track_stop_buttons))
        for scene_index in range(NUM_SCENES):
            scene = self._session.scene(scene_index)
            button_row = []
            scene.set_launch_button(self._scene_launch_buttons[scene_index])
            scene.set_index(scene_index)
            scene.set_serato_interface(self._serato_interface)
            for track_index in range(NUM_TRACKS):
                button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(button)
                clip_slot.set_serato_interface(self._serato_interface)

            self._matrix.add_row(tuple(button_row))

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(NUM_TRACKS)
        self._mixer.set_serato_interface(self._serato_interface)
        self._mixer.master_strip().set_serato_interface(self._serato_interface)
        self._track_arm_buttons = []
        self._track_solo_buttons = []
        self._track_mute_buttons = []
        self._track_select_buttons = []
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
        for track in range(NUM_TRACKS):
            strip = self._mixer.channel_strip(track)
            strip.set_serato_interface(self._serato_interface)
            self._track_arm_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_solo_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_mute_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_select_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            strip.set_arm_button(self._track_arm_buttons[-1])
            strip.set_solo_button(self._track_solo_buttons[-1])
            strip.set_mute_button(self._track_mute_buttons[-1])
            strip.set_select_button(self._track_select_buttons[-1])
            strip.set_shift_button(self._shift_button)

    def _setup_device_control(self):
        is_momentary = True
        self._device_on_off_button = ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)
        self._device = SpecialDeviceComponent()
        self._device.set_serato_interface(self._serato_interface)
        self._device.set_parameter_controls(tuple([ SliderElement(MIDI_CC_TYPE, 0, 0) for index in range(NUM_PARAMS) ]))
        self._device.set_on_off_button(self._device_on_off_button)
        self.set_device_component(self._device)

    def _handle_session_event(self, event):
        result = False
        if event.type in CLIP_EVENTS:
            value = 127 * int(event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventClipPlayedDown)
            track_index = event.key1 - 1
            scene_index = event.key2 - 1
            if track_index in range(NUM_TRACKS) and scene_index in range(NUM_SCENES):
                self._matrix.get_button(track_index, scene_index).receive_value(value)
            result = True
        elif event.type in SCENE_EVENTS:
            value = 127 * int(event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventScenePlayedDown)
            scene_index = event.key1 - 1
            if scene_index in range(NUM_SCENES):
                self._scene_launch_buttons[scene_index].receive_value(value)
            result = True
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixSizeChanged:
            new_width = event.key1
            new_height = event.key2
            self._session.set_size(new_width, new_height)
            result = True
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixOffsetChanged:
            x_increment = event.key1
            y_increment = event.key2
            self._session.move_by(x_increment, y_increment)
            result = True
        return result

    def _handle_mixer_event(self, event):
        result = True
        track_index = event.key1 - 1
        value = event.key2
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackMasterGainChange:
            self._mixer.master_strip().set_track_volume(fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackStopped:
            self.song().stop_all_clips()
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackSelect:
            self.song().view.selected_track = self.song().master_track
        else:
            result = track_index in range(NUM_TRACKS) and self._handle_strip_event(event)
        return result

    def _handle_strip_event(self, event):
        result = True
        track_index = event.key1 - 1
        value = event.key2
        if value == 0:
            self._shift_button.receive_value(127)
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSolo:
            self._track_solo_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackRecord:
            self._track_arm_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackActive:
            self._track_mute_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackStopped:
            self._track_stop_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSelect:
            self._track_select_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackGainChange:
            self._mixer.channel_strip(track_index).set_track_volume(fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendAChange:
            self._mixer.channel_strip(track_index).set_send(0, fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendBChange:
            self._mixer.channel_strip(track_index).set_send(1, fixed_value(value))
        else:
            result = False
        self._shift_button.receive_value(0)
        return result

    def _handle_device_event(self, event):
        result = True
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceValueChanged:
            self._device.set_parameter_value(event.key1 - 1, fixed_value(event.key2))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceActivate:
            self._device_on_off_button.receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceFocusMove:
            self._move_device_focus(event.key1)
        else:
            result = False
        return result

    def _move_device_focus(self, increment):
        if not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain'):
            self.application().view.show_view('Detail')
            self.application().view.show_view('Detail/DeviceChain')
        else:
            modifier_pressed = True
            direction = Live.Application.Application.View.NavDirection.left
            if increment > 0:
                direction = Live.Application.Application.View.NavDirection.right
            self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)
예제 #6
0
    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
            )
class TwisterControlSurface(ControlSurface):
    """
    Custom control for the DJ Tech Tools Midi Fighter Twister controller
    """
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)

        with self.component_guard():
            self._skin = make_default_skin()
            self._setup_controls()
            self._setup_background()
            self._setup_modes()

    def _setup_background(self):
        background = BackgroundComponent()
        background.layer = Layer(priority=-100,
                                 knobs=self._knobs,
                                 lights=self._buttons)

    def _setup_controls(self):
        knobs = [[self._make_knob(row, col) for col in range(4)]
                 for row in range(4)]
        buttons = [[self._make_button(row, col) for col in range(4)]
                   for row in range(4)]
        self._knobs = ButtonMatrixElement(knobs)
        self._buttons = ButtonMatrixElement(buttons)

    def _make_knob(self, row, col):
        return SliderElementEx(msg_type=MIDI_CC_TYPE,
                               channel=KNOB_CHANNEL,
                               identifier=row * 4 + col)

    def _make_button(self, row, col):
        return ButtonElementEx(msg_type=MIDI_CC_TYPE,
                               channel=BUTTON_CHANNEL,
                               identifier=row * 4 + col,
                               is_momentary=True,
                               skin=self._skin)

    def _setup_modes(self):
        self._modes = ModesComponentEx()
        mappings = dict()
        for n in range(4):
            self._create_page(n)
            mappings["page{}_mode_button".format(
                n + 1)] = self._buttons.get_button(n, 0)
        self._modes.layer = Layer(priority=10, **mappings)
        self._modes.selected_mode = 'page1_mode'

    def _create_page(self, index):
        page_num = index + 1
        mode_name = "page{}_mode".format(page_num)
        msg = lambda: self.show_message("Switched to page {}".format(page_num))

        devices = [
            DeviceComponentEx(schedule_message=self.schedule_message,
                              top_buttons=self._buttons.submatrix[:, 0],
                              log=self.log_message) for n in range(3)
        ]

        layers = [
            Layer(knobs=self._knobs.submatrix[:, n + 1],
                  buttons=self._buttons.submatrix[:, n + 1]) for n in range(3)
        ]

        modes = [LayerMode(devices[n], layers[n]) for n in range(3)]

        self._modes.add_mode(mode_name, modes + [msg])
예제 #8
0
class AumPC40(APC):
    __doc__ = " Script for Akai's APC40 Controller "

    def __init__(self, c_instance):
        APC.__init__(self, c_instance)
        self._device_selection_follows_track_selection = True

    def _setup_session_control(self):
        is_momentary = True
        self._shift_button = FlashingButtonElement(is_momentary,
                                                   MIDI_NOTE_TYPE, 0, 98, self)
        right_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                             96, self)
        self._right_button = right_button
        left_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                            97, self)
        self._left_button = left_button
        up_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94,
                                          self)
        self._up_button = up_button
        down_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                            95, self)
        self._down_button = down_button
        right_button.name = 'Bank_Select_Right_Button'
        left_button.name = 'Bank_Select_Left_Button'
        up_button.name = 'Bank_Select_Up_Button'
        down_button.name = 'Bank_Select_Down_Button'
        self._session = PedaledSessionComponent(8, 5)
        self._session.name = 'Session_Control'
        self._session.set_track_bank_buttons(right_button, left_button)
        self._session.set_scene_bank_buttons(down_button, up_button)
        matrix = ButtonMatrixElement()
        self._matrix = matrix  # added a
        matrix.name = 'Button_Matrix'
        scene_launch_buttons = [
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82))
            for index in range(5)
        ]
        track_stop_buttons = [
            FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52,
                                  self) for index in range(8)
        ]
        self._track_stop_buttons = track_stop_buttons  # added a
        for index in range(len(scene_launch_buttons)):
            scene_launch_buttons[index].name = 'Scene_' + str(
                index) + '_Launch_Button'
        for index in range(len(track_stop_buttons)):
            track_stop_buttons[index].name = 'Track_' + str(
                index) + '_Stop_Button'
        stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81)
        stop_all_button.name = 'Stop_All_Clips_Button'
        self._session.set_stop_all_clips_button(stop_all_button)
        self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
        self._session.set_stop_track_clip_value(2)
        for scene_index in range(5):
            scene = self._session.scene(scene_index)
            scene.name = 'Scene_' + str(scene_index)
            button_row = []
            scene.set_launch_button(scene_launch_buttons[scene_index])
            scene.set_triggered_value(2)
            for track_index in range(8):
                button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                               track_index, (scene_index + 53),
                                               self)
                button.name = str(track_index) + '_Clip_' + str(
                    scene_index) + '_Button'
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                    scene_index)
                clip_slot.set_triggered_to_play_value(2)
                clip_slot.set_triggered_to_record_value(4)
                clip_slot.set_stopped_value(5)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(3)
                clip_slot.set_launch_button(button)
            matrix.add_row(tuple(button_row))
        self._session.set_slot_launch_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67))
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
        self._session_zoom = SessionZoomingComponent(self._session)
        self._session_zoom.name = 'Session_Overview'
        self._session_zoom.set_button_matrix(matrix)
        self._session_zoom.set_zoom_button(self._shift_button)
        self._session_zoom.set_nav_buttons(up_button, down_button, left_button,
                                           right_button)
        self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
        self._session_zoom.set_stopped_value(3)
        self._session_zoom.set_selected_value(5)
        return None

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._solo_buttons = []  # added a
        self._select_buttons = []  # added a
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            volume_control = MonoEncoderElement2(MIDI_CC_TYPE, track, 7,
                                                 Live.MidiMap.MapMode.absolute,
                                                 'Slider_' + str(track), track,
                                                 self)
            arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)
            solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                                track, 50, self)
            self._solo_buttons.append(solo_button)  # added a
            mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        49)
            select_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                                  track, 51, self)
            self._select_buttons.append(select_button)  # added a
            #volume_control.name = str(track) + '_Volume_Control'
            arm_button.name = str(track) + '_Arm_Button'
            solo_button.name = str(track) + '_Solo_Button'
            mute_button.name = str(track) + '_Mute_Button'
            select_button.name = str(track) + '_Select_Button'
            strip.set_volume_control(volume_control)
            strip.set_arm_button(arm_button)
            strip.set_solo_button(solo_button)
            strip.set_mute_button(mute_button)
            strip.set_select_button(select_button)
            strip.set_shift_button(self._shift_button)
            strip.set_invert_mute_feedback(True)
        crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                             80)
        self._master_select_button = master_select_button
        prehear_control = EncoderElement(
            MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
        crossfader.name = 'Crossfader'
        master_volume_control.name = 'Master_Volume_Control'
        master_select_button.name = 'Master_Select_Button'
        prehear_control.name = 'Prehear_Volume_Control'
        self._mixer.set_crossfader_control(crossfader)
        self._mixer.set_prehear_volume_control(prehear_control)
        self._mixer.master_strip().set_volume_control(master_volume_control)
        self._mixer.master_strip().set_select_button(master_select_button)

    def _setup_custom_components(self):
        self._setup_device_and_transport_control()
        self._setup_global_control()

    def _setup_device_and_transport_control(self):
        is_momentary = True
        device_bank_buttons = []
        device_param_controls = []
        bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button',
                              'Previous_Device_Button', 'Next_Device_Button',
                              'Detail_View_Button', 'Rec_Quantization_Button',
                              'Midi_Overdub_Button', 'Metronome_Button')
        for index in range(8):
            device_bank_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 58 + index))
            device_bank_buttons[-1].name = bank_button_labels[index]
            ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0,
                                             24 + index)
            ringed_encoder = MonoRingedEncoderElement(
                MIDI_CC_TYPE, 0, 16 + index, Live.MidiMap.MapMode.absolute,
                index, self)
            ringed_encoder.set_ring_mode_button(ring_mode_button)
            ringed_encoder.name = 'Device_Control_' + str(index)
            ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button'
            device_param_controls.append(ringed_encoder)
        device = ShiftableDeviceComponent(self)
        device.name = 'Device_Component'
        device.set_bank_buttons(tuple(device_bank_buttons))
        device.set_shift_button(self._shift_button)
        device.set_parameter_controls(tuple(device_param_controls))
        device.set_on_off_button(device_bank_buttons[1])
        self.set_device_component(device)
        detail_view_toggler = DetailViewCntrlComponent()
        detail_view_toggler.name = 'Detail_View_Control'
        detail_view_toggler.set_shift_button(self._shift_button)
        detail_view_toggler.set_device_clip_toggle_button(
            device_bank_buttons[0])
        detail_view_toggler.set_detail_toggle_button(device_bank_buttons[4])
        detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2],
                                                   device_bank_buttons[3])
        transport = ShiftableTransportComponent()
        transport.name = 'Transport'
        self._transport = transport
        play_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 91)
        stop_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 92)
        record_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 93)
        nudge_up_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                                0, 100, self)
        self._nudge_up_button = nudge_up_button
        nudge_down_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                                  0, 101, self)
        self._nudge_down_button = nudge_down_button
        tap_tempo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99)
        play_button.name = 'Play_Button'
        stop_button.name = 'Stop_Button'
        record_button.name = 'Record_Button'
        nudge_up_button.name = 'Nudge_Up_Button'
        nudge_down_button.name = 'Nudge_Down_Button'
        tap_tempo_button.name = 'Tap_Tempo_Button'
        transport.set_shift_button(self._shift_button)
        transport.set_play_button(play_button)
        transport.set_stop_button(stop_button)
        transport.set_record_button(record_button)
        transport.set_nudge_buttons(nudge_up_button, nudge_down_button)
        transport.set_tap_tempo_button(tap_tempo_button)
        transport.set_quant_toggle_button(device_bank_buttons[5])
        transport.set_overdub_button(device_bank_buttons[6])
        transport.set_metronome_button(device_bank_buttons[7])
        bank_button_translator = ShiftTranslatorComponent()
        bank_button_translator.set_controls_to_translate(
            tuple(device_bank_buttons))
        bank_button_translator.set_shift_button(self._shift_button)

    def _setup_global_control(self):
        is_momentary = True
        global_bank_buttons = []
        global_param_controls = []
        for index in range(8):
            ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0,
                                        56 + index)
            ringed_encoder = MonoRingedEncoderElement(
                MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute,
                index + 8, self)
            ringed_encoder.name = 'Track_Control_' + str(index)
            ring_button.name = ringed_encoder.name + '_Ring_Mode_Button'
            ringed_encoder.set_ring_mode_button(ring_button)
            global_param_controls.append(ringed_encoder)
        global_bank_buttons = []
        global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button',
                              'Send_C_Button')
        for index in range(4):
            global_bank_buttons.append(
                ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 87 + index))
            global_bank_buttons[-1].name = global_bank_labels[index]
        encoder_modes = EncModeSelectorComponent(self._mixer)
        encoder_modes.name = 'Track_Control_Modes'
        encoder_modes.set_modes_buttons(global_bank_buttons)
        encoder_modes.set_controls(tuple(global_param_controls))
        global_translation_selector = ChannelTranslationSelector()
        global_translation_selector.name = 'Global_Translations'
        global_translation_selector.set_controls_to_translate(
            tuple(global_param_controls))
        global_translation_selector.set_mode_buttons(
            tuple(global_bank_buttons))

    def _product_model_id_byte(self):
        return 115

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

    def _setup_monomod(self):
        self._host = MonomodComponent(self)
        self._host.name = 'Monomod_Host'
        self.hosts = [self._host]
        self._monomod = ButtonMatrixElement()
        self._monomod.name = 'Monomod'
        for row in range(5):
            button_row = []
            for column in range(8):
                button_row.append(self._matrix.get_button(column, row))
            self._monomod.add_row(tuple(button_row))
        self._monomod.add_row(tuple(self._track_stop_buttons))
        self._monomod.add_row(tuple(self._select_buttons))
        self._monomod.add_row(tuple(self._solo_buttons))
        self._monomod_mode = MonomodModeComponent(self._monomod_mode_update,
                                                  self)
        self._monomod_mode.name = "Monomod_Mode_Component"

    def _monomod_mode_update(self):
        if (self._monomod_mode._mode_index == 0) or (self._host._active_client
                                                     == None):
            self.flash_status = 0
            self._host.set_enabled(False)
            self._host._set_button_matrix(None)
            self._host._set_nav_buttons(None)
            self._host._set_lock_button(None)
            self._host._set_alt_button(None)
            self._host._set_shift_button(None)
            self._monomod.reset()
            self._session.set_track_bank_buttons(self._right_button,
                                                 self._left_button)
            self._session.set_scene_bank_buttons(self._down_button,
                                                 self._up_button)
            for track in range(8):
                self._mixer.channel_strip(track).set_select_button(
                    self._select_buttons[track])
                self._mixer.channel_strip(track).set_solo_button(
                    self._solo_buttons[track])
            self._transport.set_nudge_buttons(self._nudge_up_button,
                                              self._nudge_down_button)
            self._session.set_enabled(True)
            self._session_zoom._is_zoomed_out = False
            self._session_zoom.set_enabled(True)
            self.request_rebuild_midi_map()
            self._master_select_button.turn_off()

        elif (self._monomod_mode._mode_index == 1):
            self._transport.set_nudge_buttons(None, None)
            for track in range(8):
                self._mixer.channel_strip(track).set_select_button(None)
                self._mixer.channel_strip(track).set_solo_button(None)
            self._session.set_enabled(False)
            self._session_zoom.set_enabled(False)
            self._session.set_track_bank_buttons(None, None)
            self._session.set_scene_bank_buttons(None, None)
            self.flash_status = 1
            self._monomod.reset()
            self._host._set_button_matrix(self._monomod)
            self._host._set_nav_buttons([
                self._up_button, self._down_button, self._left_button,
                self._right_button
            ])
            self._host._set_shift_button(self._shift_button)
            self._host._set_lock_button(self._nudge_up_button)
            self._host._set_alt_button(self._nudge_down_button)
            self._host.set_enabled(True)
            self.request_rebuild_midi_map()
            self._master_select_button.turn_on()

    """m4l bridge"""

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

        ret += ' '
        assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
        return ret

    def notification_to_bridge(self, name, value, sender):
        if isinstance(sender, (MonoRingedEncoderElement, MonoEncoderElement2)):
            self._monobridge._send(sender.name, 'lcd_name',
                                   str(self.generate_strip_string(name)))
            self._monobridge._send(sender.name, 'lcd_value',
                                   str(self.generate_strip_string(value)))

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

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

    def get_clip_names(self):
        clip_names = []
        for scene in self._session._scenes:
            for clip_slot in scene._clip_slots:
                if clip_slot.has_clip() is True:
                    clip_names.append(clip_slot._clip_slot)  ##.clip.name)
                    return clip_slot._clip_slot
                    ##self.log_message(str(clip_slot._clip_slot.clip.name))
        return clip_names

    def update_display(self):
        """ Live -> Script
		Aka on_timer. Called every 100 ms and should be used to update display relevant
		parts of the controller
		"""
        for message in self._scheduled_messages:
            message['Delay'] -= 1
            if (message['Delay'] == 0):
                if (message['Parameter'] != None):
                    message['Message'](message['Parameter'])
                else:
                    message['Message']()
                    del self._scheduled_messages[
                        self._scheduled_messages.index(message)]

        for callback in self._timer_callbacks:
            callback()
        self._timer = (self._timer + 1) % 256
        self.flash()

    def flash(self):
        if (self.flash_status > 0):
            for row in range(8):
                for column in range(8):
                    button = self._monomod.get_button(column, row)
                    if (button._flash_state > 0):
                        button.flash(self._timer)
예제 #9
0
class KontrolF1(ControlSurface):
    __module__ = __name__
    __doc__ = " Script for Native Instruments Traktor Kontrol F1 Controller "

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self.set_suppress_rebuild_requests(True)
        self._suppress_send_midi = True
        self._suppress_session_highlight = True

        self._suggested_input_port = 'Traktor Kontrol F1'
        self._suggested_output_port = 'Traktor Kontrol F1'

        self._blink_state = False

        self._matrix = ButtonMatrixElement()
        for row in range(HEIGHT):
            button_row = [ ConfigurableButtonElement(c_instance, True, MIDI_CC_TYPE, 2, ((row * HEIGHT) + column)) for column in range(WIDTH) ]
            self._matrix.add_row(tuple(button_row))

        self._nav_buttons  = [ ConfigurableButtonElement(c_instance, True, MIDI_CC_TYPE, 0, NAV_ENCODER),
                               ConfigurableButtonElement(c_instance, True, MIDI_CC_TYPE, 0, TOGGLE_LEFT_DOWN) ]
        self._scene_buttons = [ ConfigurableButtonElement(c_instance, True, MIDI_CC_TYPE, 0, SCENE_LAUNCH[index]) for index in range(HEIGHT) ]
        
        self._stop_buttons = []
        for index in range(WIDTH):
            self._stop_buttons.append(ConfigurableButtonElement(c_instance, True, MIDI_CC_TYPE, 0, STOP_LAUNCH[index]))
        
        self._session = SpecialSessionComponent(self._matrix.width(), self._matrix.height())

        self._all_buttons = []
        for button in (self._scene_buttons + self._nav_buttons + self._stop_buttons):
            self._all_buttons.append(button)

        for scene_index in range(self._matrix.height()):
            for track_index in range(self._matrix.width()):
                self._all_buttons.append(self._matrix.get_button(track_index, scene_index))
        self._all_buttons = tuple(self._all_buttons)



        self._suppress_session_highlight = False
        self.set_suppress_rebuild_requests(False)
        self._suppress_send_midi = False
        self.set_enabled(True)
        self.update()
        self._set_session_highlight(0,0,WIDTH,HEIGHT,True)

    def disconnect(self):
        self._suppress_send_midi = True

        self._session = None
        for button in self._all_buttons:
            button.set_on_off_values(127, 0)

        self._matrix = None
        self._stop_buttons = None
        self._scene_buttons = None
        self._nav_buttons = None

        ControlSurface.disconnect(self)
        self._suppress_send_midi = False

    def update_display(self):
        tracks = self.song().visible_tracks
        number_tracks = len(tracks)

        if self._blink_state:
            self._blink_state = False
        else:
            self._blink_state = True

        for track in range(WIDTH):
            to = track + self._session._track_offset
            if (to < number_tracks):
                for y in range(HEIGHT):
                    ys = self._session._scene_offset+y
                    yx = (y*4)+track
                    slot = tracks[to].clip_slots[ys]
                    if (slot.controls_other_clips) or (slot.has_clip):
                        if slot.is_triggered:
                            if self._blink_state:
                                self._send_midi(tuple([178,yx,40]))
                            else:
                                self._send_midi(tuple([178,yx,127]))
               


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

    def _send_midi(self, midi_bytes):
        if (not self._suppress_send_midi):
            ControlSurface._send_midi(self, midi_bytes)

    def _update_hardware(self):
        pass

    def _send_challenge(self):
        pass

    def _config_value(self, value):
        assert (value in range(128))

    def _set_session_highlight(self, track_offset, scene_offset, width, height, include_return_tracks):
        ControlSurface._set_session_highlight(self, track_offset, scene_offset, width, height, include_return_tracks)

    def _install_forwarding(self, control):
        result = ControlSurface._install_forwarding(self, control)
        return result

    def _translate_message(self, type, from_identifier, from_channel, to_identifier, to_channel):
        ControlSurface._translate_message(self, type, from_identifier, from_channel, to_identifier, to_channel)


    def on_enabled_changed(self):
        self.update()

    def update(self):
        for scene_index in range(HEIGHT):
            self._scene_buttons[scene_index].set_enabled(True)
            self._stop_buttons[scene_index].set_enabled(True)
            for track_index in range(WIDTH):
                self._matrix.get_button(track_index, scene_index).set_enabled(True)


        for button in self._nav_buttons:
            button.set_enabled(True)

        self._session.set_allow_update(False)


        for scene_index in range(HEIGHT):
            scene = self._session.scene(scene_index)
            scene.set_launch_button(self._scene_buttons[scene_index])
            for track_index in range(WIDTH):
                scene.clip_slot(track_index).set_launch_button(self._matrix.get_button(track_index, scene_index))

        #self.log_message(str(tuple(self._stop_buttons)))
        self._session.set_stop_track_clip_buttons(tuple(self._stop_buttons))
        self._session.set_track_bank_buttons(self._nav_buttons[1], self._nav_buttons[1])
        self._session.set_scene_bank_buttons(self._nav_buttons[0], self._nav_buttons[0])
        self._session.set_allow_update(True)
예제 #10
0
class AumPC40(APC):
	__doc__ = " Script for Akai's APC40 Controller "
	
	def __init__(self, c_instance):
		APC.__init__(self, c_instance)
		self._device_selection_follows_track_selection = True


	def _setup_session_control(self):
		is_momentary = True
		self._shift_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98, self)		   
		right_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96, self)
		self._right_button = right_button
		left_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97, self)
		self._left_button = left_button
		up_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94, self)
		self._up_button = up_button
		down_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95, self)
		self._down_button = down_button
		right_button.name = 'Bank_Select_Right_Button'
		left_button.name = 'Bank_Select_Left_Button'
		up_button.name = 'Bank_Select_Up_Button'
		down_button.name = 'Bank_Select_Down_Button'
		self._session = PedaledSessionComponent(8, 5)
		self._session.name = 'Session_Control'
		self._session.set_track_bank_buttons(right_button, left_button)
		self._session.set_scene_bank_buttons(down_button, up_button)
		matrix = ButtonMatrixElement()
		self._matrix = matrix  # added a
		matrix.name = 'Button_Matrix'
		scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82)) for index in range(5) ]
		track_stop_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52, self) for index in range(8) ]
		self._track_stop_buttons = track_stop_buttons  # added a
		for index in range(len(scene_launch_buttons)):
			scene_launch_buttons[index].name = 'Scene_'+ str(index) + '_Launch_Button'
		for index in range(len(track_stop_buttons)):
			track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button'
		stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81)
		stop_all_button.name = 'Stop_All_Clips_Button'
		self._session.set_stop_all_clips_button(stop_all_button)
		self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		self._session.set_stop_track_clip_value(2)
		for scene_index in range(5):
			scene = self._session.scene(scene_index)
			scene.name = 'Scene_' + str(scene_index)
			button_row = []
			scene.set_launch_button(scene_launch_buttons[scene_index])
			scene.set_triggered_value(2)
			for track_index in range(8):
				button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53), self)
				button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button'
				button_row.append(button)
				clip_slot = scene.clip_slot(track_index)
				clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index)
				clip_slot.set_triggered_to_play_value(2)
				clip_slot.set_triggered_to_record_value(4)
				clip_slot.set_stopped_value(5)
				clip_slot.set_started_value(1)
				clip_slot.set_recording_value(3)
				clip_slot.set_launch_button(button)
			matrix.add_row(tuple(button_row))
		self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67))
		self._session.selected_scene().name = 'Selected_Scene'
		self._session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
		self._session_zoom = SessionZoomingComponent(self._session)
		self._session_zoom.name = 'Session_Overview'
		self._session_zoom.set_button_matrix(matrix)
		self._session_zoom.set_zoom_button(self._shift_button)
		self._session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button)
		self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
		self._session_zoom.set_stopped_value(3)
		self._session_zoom.set_selected_value(5)
		return None	  
	

	def _setup_mixer_control(self):
		is_momentary = True
		self._mixer = SpecialMixerComponent(8)
		self._mixer.name = 'Mixer'
		self._mixer.master_strip().name = 'Master_Channel_Strip'
		self._mixer.selected_strip().name = 'Selected_Channel_Strip'
		self._solo_buttons = []	# added a
		self._select_buttons = []	# added a
		for track in range(8):
			strip = self._mixer.channel_strip(track)
			strip.name = 'Channel_Strip_' + str(track)
			volume_control = MonoEncoderElement2(MIDI_CC_TYPE, track, 7, Live.MidiMap.MapMode.absolute, 'Slider_' + str(track), track, self)
			arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)
			solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, self)
			self._solo_buttons.append(solo_button)	# added a
			mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)
			select_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51, self)
			self._select_buttons.append(select_button)	# added a
			#volume_control.name = str(track) + '_Volume_Control'
			arm_button.name = str(track) + '_Arm_Button'
			solo_button.name = str(track) + '_Solo_Button'
			mute_button.name = str(track) + '_Mute_Button'
			select_button.name = str(track) + '_Select_Button'
			strip.set_volume_control(volume_control)
			strip.set_arm_button(arm_button)
			strip.set_solo_button(solo_button)
			strip.set_mute_button(mute_button)
			strip.set_select_button(select_button)
			strip.set_shift_button(self._shift_button)
			strip.set_invert_mute_feedback(True)
		crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
		master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
		master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80)
		self._master_select_button = master_select_button
		prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
		crossfader.name = 'Crossfader'
		master_volume_control.name = 'Master_Volume_Control'
		master_select_button.name = 'Master_Select_Button'
		prehear_control.name = 'Prehear_Volume_Control'
		self._mixer.set_crossfader_control(crossfader)
		self._mixer.set_prehear_volume_control(prehear_control)
		self._mixer.master_strip().set_volume_control(master_volume_control)
		self._mixer.master_strip().set_select_button(master_select_button)
	

	def _setup_custom_components(self):
		self._setup_device_and_transport_control()
		self._setup_global_control()
	

	def _setup_device_and_transport_control(self):
		is_momentary = True
		device_bank_buttons = []
		device_param_controls = []
		bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Metronome_Button')
		for index in range(8):
			device_bank_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 58 + index))
			device_bank_buttons[-1].name = bank_button_labels[index]
			ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 24 + index)
			ringed_encoder = MonoRingedEncoderElement(MIDI_CC_TYPE, 0, 16 + index, Live.MidiMap.MapMode.absolute, index, self)
			ringed_encoder.set_ring_mode_button(ring_mode_button)
			ringed_encoder.name = 'Device_Control_' + str(index)
			ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button'
			device_param_controls.append(ringed_encoder)
		device = ShiftableDeviceComponent(self)
		device.name = 'Device_Component'
		device.set_bank_buttons(tuple(device_bank_buttons))
		device.set_shift_button(self._shift_button)
		device.set_parameter_controls(tuple(device_param_controls))
		device.set_on_off_button(device_bank_buttons[1])
		self.set_device_component(device)
		detail_view_toggler = DetailViewCntrlComponent()
		detail_view_toggler.name = 'Detail_View_Control'
		detail_view_toggler.set_shift_button(self._shift_button)
		detail_view_toggler.set_device_clip_toggle_button(device_bank_buttons[0])
		detail_view_toggler.set_detail_toggle_button(device_bank_buttons[4])
		detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3])
		transport = ShiftableTransportComponent()
		transport.name = 'Transport'
		self._transport = transport
		play_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 91)
		stop_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 92)
		record_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 93)
		nudge_up_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 100, self)
		self._nudge_up_button = nudge_up_button
		nudge_down_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 101, self)
		self._nudge_down_button = nudge_down_button
		tap_tempo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99)
		play_button.name = 'Play_Button'
		stop_button.name = 'Stop_Button'
		record_button.name = 'Record_Button'
		nudge_up_button.name = 'Nudge_Up_Button'
		nudge_down_button.name = 'Nudge_Down_Button'
		tap_tempo_button.name = 'Tap_Tempo_Button'
		transport.set_shift_button(self._shift_button)
		transport.set_play_button(play_button)
		transport.set_stop_button(stop_button)
		transport.set_record_button(record_button)
		transport.set_nudge_buttons(nudge_up_button, nudge_down_button)
		transport.set_tap_tempo_button(tap_tempo_button)
		transport.set_quant_toggle_button(device_bank_buttons[5])
		transport.set_overdub_button(device_bank_buttons[6])
		transport.set_metronome_button(device_bank_buttons[7])
		bank_button_translator = ShiftTranslatorComponent()
		bank_button_translator.set_controls_to_translate(tuple(device_bank_buttons))
		bank_button_translator.set_shift_button(self._shift_button)
	

	def _setup_global_control(self):
		is_momentary = True
		global_bank_buttons = []
		global_param_controls = []
		for index in range(8):
			ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 56 + index)
			ringed_encoder = MonoRingedEncoderElement(MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute, index + 8, self)
			ringed_encoder.name = 'Track_Control_' + str(index)
			ring_button.name = ringed_encoder.name + '_Ring_Mode_Button'
			ringed_encoder.set_ring_mode_button(ring_button)
			global_param_controls.append(ringed_encoder)
		global_bank_buttons = []
		global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button')
		for index in range(4):
			global_bank_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 87 + index))
			global_bank_buttons[-1].name = global_bank_labels[index]
		encoder_modes = EncModeSelectorComponent(self._mixer)
		encoder_modes.name = 'Track_Control_Modes'
		encoder_modes.set_modes_buttons(global_bank_buttons)
		encoder_modes.set_controls(tuple(global_param_controls))
		global_translation_selector = ChannelTranslationSelector()
		global_translation_selector.name = 'Global_Translations'
		global_translation_selector.set_controls_to_translate(tuple(global_param_controls))
		global_translation_selector.set_mode_buttons(tuple(global_bank_buttons))
	

	def _product_model_id_byte(self):
		return 115
	

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

	def _setup_monomod(self):
		self._host = MonomodComponent(self)
		self._host.name = 'Monomod_Host'
		self.hosts = [self._host]
		self._monomod = ButtonMatrixElement()
		self._monomod.name = 'Monomod'
		for row in range(5):
			button_row = []
			for column in range(8):
				button_row.append(self._matrix.get_button(column, row))
			self._monomod.add_row(tuple(button_row))
		self._monomod.add_row(tuple(self._track_stop_buttons))
		self._monomod.add_row(tuple(self._select_buttons))
		self._monomod.add_row(tuple(self._solo_buttons))
		self._monomod_mode = MonomodModeComponent(self._monomod_mode_update, self)
		self._monomod_mode.name = "Monomod_Mode_Component"
	

	def _monomod_mode_update(self):
		if(self._monomod_mode._mode_index == 0) or (self._host._active_client == None):
			self.flash_status = 0
			self._host.set_enabled(False)
			self._host._set_button_matrix(None)
			self._host._set_nav_buttons(None)
			self._host._set_lock_button(None)
			self._host._set_alt_button(None)
			self._host._set_shift_button(None)
			self._monomod.reset()
			self._session.set_track_bank_buttons(self._right_button, self._left_button)
			self._session.set_scene_bank_buttons(self._down_button, self._up_button)
			for track in range(8):
				self._mixer.channel_strip(track).set_select_button(self._select_buttons[track])
				self._mixer.channel_strip(track).set_solo_button(self._solo_buttons[track])
			self._transport.set_nudge_buttons(self._nudge_up_button, self._nudge_down_button)
			self._session.set_enabled(True)
			self._session_zoom._is_zoomed_out = False
			self._session_zoom.set_enabled(True)
			self.request_rebuild_midi_map()
			self._master_select_button.turn_off()
			
		elif(self._monomod_mode._mode_index == 1):
			self._transport.set_nudge_buttons(None, None)
			for track in range(8):
				self._mixer.channel_strip(track).set_select_button(None)
				self._mixer.channel_strip(track).set_solo_button(None)
			self._session.set_enabled(False)
			self._session_zoom.set_enabled(False)
			self._session.set_track_bank_buttons(None, None)
			self._session.set_scene_bank_buttons(None, None)
			self.flash_status = 1
			self._monomod.reset()
			self._host._set_button_matrix(self._monomod)
			self._host._set_nav_buttons([self._up_button, self._down_button, self._left_button, self._right_button])
			self._host._set_shift_button(self._shift_button)
			self._host._set_lock_button(self._nudge_up_button)
			self._host._set_alt_button(self._nudge_down_button)
			self._host.set_enabled(True)
			self.request_rebuild_midi_map()
			self._master_select_button.turn_on()
	

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

		ret += ' '
		assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
		return ret
	

	def notification_to_bridge(self, name, value, sender):
		if isinstance(sender, (MonoRingedEncoderElement, MonoEncoderElement2)):
			self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name)))
			self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value)))
	

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

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

	def get_clip_names(self):
		clip_names = []
		for scene in self._session._scenes:
			for clip_slot in scene._clip_slots:
				if clip_slot.has_clip() is True:
					clip_names.append(clip_slot._clip_slot)##.clip.name)
					return clip_slot._clip_slot
					##self.log_message(str(clip_slot._clip_slot.clip.name))
		return clip_names
	



	def update_display(self):
		""" Live -> Script
		Aka on_timer. Called every 100 ms and should be used to update display relevant
		parts of the controller
		"""
		for message in self._scheduled_messages:
			message['Delay'] -= 1
			if (message['Delay'] == 0):
				if (message['Parameter'] != None):
					message['Message'](message['Parameter'])
				else:
					message['Message']()
					del self._scheduled_messages[self._scheduled_messages.index(message)]

		for callback in self._timer_callbacks:
			callback()
		self._timer = (self._timer + 1) % 256
		self.flash()
	

	def flash(self):
		if(self.flash_status > 0):
			for row in range(8):
				for column in range(8):
					button = self._monomod.get_button(column, row)
					if(button._flash_state > 0):
						button.flash(self._timer)
class TwisterControlSurface(ControlSurface):

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)

        self._handle_track_change.subject = self.song().view

        with self.component_guard():
            self._skin = make_default_skin()
            self._setup_controls()
            self._setup_background()
            self._setup_device()
            self._setup_mixer()
            self._setup_metronome()
            self._setup_modes()
            self._handle_track_change()

    @subject_slot('selected_track')
    def _handle_track_change(self):
        track = self.song().view.selected_track
        self._select_device_on_track(track)

        # only change sends if the device isnt locked -- keeps strip in sync
        # with the locked device
        if not self._device._locked_to_device:
            self._strip.set_track(track)

    def _select_device_on_track(self, track):
        if not track or not len(track.devices):
            return
        device = track.devices[0]
        self._device.set_device(device)

    def _setup_background(self):
        background = BackgroundComponent()
        background.layer = Layer(priority = -100, knobs = self._knobs, lights = self._buttons)

    def _setup_device(self):
        self._device = DeviceComponentEx()
        self.set_device_component(self._device)
        self._adhoc_devices = [ DeviceComponentEx() for n in range(4) ]
        for device in self._adhoc_devices:
            device.set_lock_callback(lambda device = device: self._lock_device(device))

    def _lock_device(self, device):
        focused = self.song().appointed_device
        current = device._device
        locked = device._locked_to_device

        if not locked:
            device.set_lock_to_device(True, focused)
            self.show_message('Locked ' + focused.name + ' to adhoc device')
        else:
            device.set_lock_to_device(False, None)
            device.set_device(focused)
            self.show_message('Adhoc device unlocked')

    def _setup_metronome(self):
        self._metronome = MetronomeComponent()

    def _setup_mixer(self):
        self._strip = ChannelStripComponentEx()
        self._mixer = MixerComponentEx(num_returns = 8)

    def _setup_controls(self):
        knobs = [ [ self._make_knob(row, col) for col in range(4) ] for row in range(4) ]
        buttons = [ [ self._make_button(row, col) for col in range(4) ] for row in range(4) ]
        self._knobs = ButtonMatrixElement(knobs)
        self._buttons = ButtonMatrixElement(buttons)

    def _make_knob(self, row, col):
        return SliderElementEx(
            msg_type = MIDI_CC_TYPE,
            channel = KNOB_CHANNEL,
            identifier = row * 4 + col)

    def _make_button(self, row, col):
        return ButtonElementEx(
            msg_type = MIDI_CC_TYPE,
            channel = BUTTON_CHANNEL,
            identifier = row * 4 + col,
            is_momentary = True,
            skin = self._skin)

    def _setup_modes(self):
        self._modes = ModesComponentEx()
        self._setup_main_mode()
        self._setup_adhoc_mode()
        self._modes.layer = Layer(priority = 10,
            adhoc_mode_button = self._buttons.get_button(0, 0),
            main_mode_button = self._buttons.get_button(1, 0))
        self._modes.selected_mode = 'adhoc_mode'

    def _setup_adhoc_mode(self):
        device_layers = [ Layer(
            lock_button = self._buttons.get_button(n, 3),
            on_off_button = self._buttons.get_button(n, 2),
            param_offset_button = self._buttons.get_button(n, 1),
            parameter_controls = self._knobs.submatrix[n, 3::-1]) for n in range(4) ]

        self._modes.add_mode('adhoc_mode', [
            lambda: self.show_message('Switched to ad-hoc device mode') ] + [
            LayerMode(self._adhoc_devices[n], device_layers[n]) for n in range(4) ])

    def _setup_main_mode(self):
        strip_layer = Layer(
            volume_control = self._knobs.get_button(3, 0),
            arm_button = self._buttons.get_button(3, 0),
            send_controls = self._knobs.submatrix[:, 1])
        mixer_layer = Layer(
            prehear_volume_control = self._knobs.get_button(0, 0),
            return_track_select_buttons = self._buttons.submatrix[:, 1])
        device_layer = Layer(
            on_off_button = self._buttons.get_button(3, 3),
            parameter_controls = self._knobs.submatrix[:, 2:],
            lock_button = self._buttons.get_button(2, 3))
        metronome_layer = Layer(
            lights = self._buttons.submatrix[:, 2])

        device_bg = BackgroundComponent(color = 'Device.Background')
        device_bg_layer = Layer(priority = -10,
            lights = self._buttons.submatrix[:, 2:])

        self._modes.add_mode('main_mode', [
            lambda: self.show_message('Switched to main mode'),
            LayerMode(self._strip, strip_layer),
            LayerMode(self._mixer, mixer_layer),
            LayerMode(self._metronome, metronome_layer),
            LayerMode(device_bg, device_bg_layer),
            LayerMode(self._device, device_layer) ])
class MatrixModesComponent(ModeSelectorComponent):
    ' SelectorComponent that assigns matrix to different functions '
    __module__ = __name__

    def __init__(self, matrix, session, zooming, stop_buttons, parent):
        assert isinstance(matrix, ButtonMatrixElement)
        ModeSelectorComponent.__init__(self)
        self._controls = None
        self._session = session
        self._session_zoom = zooming
        self._matrix = matrix
        self._track_stop_buttons = stop_buttons
        self._stop_button_matrix = ButtonMatrixElement() #new dummy matrix for stop buttons, to allow note mode/user mode switching
        button_row = []
        for track_index in range(8):
            button = self._track_stop_buttons[track_index]
            button_row.append(button)
        self._stop_button_matrix.add_row(tuple(button_row))
        self._nav_left_button = None
        self._nav_right_button = None
        self._mode_index = 0
        self._last_mode = 0
        self._parent = parent
        self._parent.set_pad_translations(PAD_TRANSLATIONS) #comment out to remove Drum Rack mapping
        self._vu = None
        self._shift_button = self._parent._shift_button
        self._shift_button.add_value_listener(self._shift_value)

        
    def disconnect(self):
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)
        self._controls = None
        self._session = None
        self._session_zoom = None
        self._matrix = None
        self._track_stop_buttons = None
        self._stop_button_matrix = None
        self._shift_button.remove_value_listener(self._shift_value)
        ModeSelectorComponent.disconnect(self)

        
    def set_mode(self, mode): #override ModeSelectorComponent set_mode, to avoid flickers
        assert isinstance(mode, int)
        assert (mode in range(self.number_of_modes()))
        if (self._mode_index != mode):
            self._last_mode = 0 # self._mode_index # keep track of previous mode, to allow refresh after Note Mode only
            self._mode_index = mode
            self._set_modes()
            
            
    def set_mode_buttons(self, buttons):
        assert isinstance(buttons, (tuple,
                                    type(None)))
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)

        self._modes_buttons = []
        if (buttons != None):
            for button in buttons:
                assert isinstance(button, ButtonElement)
                identify_sender = True
                button.add_value_listener(self._mode_value, identify_sender)
                self._modes_buttons.append(button)
            for index in range(len(self._modes_buttons)):
                if (index == self._mode_index):
                    self._modes_buttons[index].turn_on()
                else:
                    self._modes_buttons[index].turn_off()


    def _mode_value(self, value, sender):
        assert (len(self._modes_buttons) > 0)
        assert isinstance(value, int)
        assert isinstance(sender, ButtonElement)
        assert (self._modes_buttons.count(sender) == 1)
        if self.is_enabled():
            if ((value is not 0) or (not sender.is_momentary())):
                self.set_mode(self._modes_buttons.index(sender))                    

    def number_of_modes(self):
        return 8
    
    def update(self):
        pass

    def get_mode_index_value(self):
        return self._mode_index
    
    def _set_modes(self):
        if self.is_enabled():
            if self._vu != None:
                self._vu.disconnect()
            
            self._session.set_allow_update(False)
            self._session_zoom.set_allow_update(False)
            assert (self._mode_index in range(self.number_of_modes()))
            for index in range(len(self._modes_buttons)):
                if (index == self._mode_index):
                    self._modes_buttons[index].turn_on()
                else:
                    self._modes_buttons[index].turn_off()
            self._session.set_stop_track_clip_buttons(tuple(self._track_stop_buttons))            
            for track_index in range(8):
                button = self._track_stop_buttons[track_index]
                button.use_default_message()
                button.set_enabled(True)
                button.set_force_next_value()
                button.send_value(0)
            self._session_zoom.set_enabled(True)
            self._session.set_enabled(True)
            self._session.set_show_highlight(True)
            self._session_zoom.set_zoom_button(self._parent._shift_button)
            for scene_index in range(5):
                scene = self._session.scene(scene_index) 
                for track_index in range(8):                
                    button = self._matrix.get_button(track_index, scene_index)
                    button.use_default_message()
                    clip_slot = scene.clip_slot(track_index)
                    clip_slot.set_launch_button(button)
                    button.set_enabled(True)
                
            if (self._mode_index == 0): #Clip Launch
                self._session_zoom._on_zoom_value(1) #zoom out

                        
            elif (self._mode_index == 1): #Session Overview
                self._session_zoom.set_zoom_button(None)
                self._session_zoom.set_enabled(True)
                self._session_zoom._is_zoomed_out = True
                self._session_zoom._scene_bank_index = int(((self._session_zoom._session.scene_offset() / self._session_zoom._session.height()) / self._session_zoom._buttons.height()))               
                self._session.set_enabled(False)
                self._session_zoom.update()

    
            elif (self._mode_index == 2):
                self._set_note_mode(PATTERN_1, CHANNEL_1, NOTEMAP_1, USE_STOP_ROW_1, IS_NOTE_MODE_1)
            elif (self._mode_index == 3):
                self._set_note_mode(PATTERN_2, CHANNEL_2, NOTEMAP_2, USE_STOP_ROW_2, IS_NOTE_MODE_2)
            elif (self._mode_index == 4):
                self._set_note_mode(PATTERN_3, CHANNEL_3, NOTEMAP_3, USE_STOP_ROW_3, IS_NOTE_MODE_3)
            elif (self._mode_index == 5):
                self._set_note_mode(PATTERN_4, CHANNEL_4, NOTEMAP_4, USE_STOP_ROW_4, IS_NOTE_MODE_4)
            elif (self._mode_index == 6):
                self._set_note_mode(PATTERN_5, CHANNEL_5, NOTEMAP_5, USE_STOP_ROW_5, IS_NOTE_MODE_5)
            elif (self._mode_index == 7):
                self._set_note_mode(PATTERN_6, CHANNEL_6, NOTEMAP_6, True, False)
                # VU Meters
                self._session.set_enabled(False)
                self._session_zoom._on_zoom_value(1) #zoom out
                self._session_zoom.set_enabled(True)
                self._session_zoom._is_zoomed_out = False
                self._session_zoom.set_zoom_button(self._parent._shift_button)
                self._session_zoom.update()
                self._update_vu_meters()

            else:
                pass
            self._session.set_allow_update(True)
            self._session_zoom.set_allow_update(True)
            #self._rebuild_callback()


    def _set_note_mode(self, pattern, channel, notemap, use_stop_row = False, is_note_mode = True):
        self._session_zoom.set_zoom_button(None)
        self._session_zoom.set_enabled(False)
        for scene_index in range(5):
            scene = self._session.scene(scene_index) 
            for track_index in range(8):
                clip_slot = scene.clip_slot(track_index)
                button = self._matrix.get_button(track_index, scene_index)
                clip_slot.set_launch_button(None)
                button.set_channel(channel) #remap all Note Mode notes to new channel
                button.set_identifier(notemap[scene_index][track_index])
                button.set_on_off_values(pattern[scene_index][track_index], 0)
                button.set_force_next_value()
                button.turn_on()
                if is_note_mode == True:
                    button.set_enabled(False)
        if use_stop_row == True:
            self._session.set_stop_track_clip_buttons(None)
            for track_index in range(8):
                button = self._stop_button_matrix.get_button(track_index, 0)
                button.set_channel(channel) #remap all Note Mode notes to new channel
                button.set_identifier(notemap[5][track_index])
                button.set_force_next_value()
                button.send_value(pattern[5][track_index])
                if is_note_mode == True:
                    button.set_enabled(False)
        else:
            for track_index in range(8):
                button = self._stop_button_matrix.get_button(track_index, 0)
                button.send_value(0, True)
        self._session.set_enabled(True)
        self._session.set_show_highlight(True)


    def _on_track_offset_changed(self):
        if (self.is_enabled() and self._mode_index == 7):
            self._update_vu_meters()

    def _shift_value(self, value):
        if (self.is_enabled() and self._mode_index == 7 and self._vu != None):
            if value != 0:
                self._vu.disconnect()
                self._vu.disable()
            else:
                self._update_vu_meters()
                self._vu.enable()

    
    def _update_vu_meters(self):
        if self._vu == None:
            self._vu = VUMeters(self._parent)
        else:
            self._vu.disconnect()
        self._vu.observe( int(self._session_zoom._session.track_offset()) )