def _setup_session_control(self):
        is_momentary = True

        # Size of session box
        num_tracks = 8 # column
        num_scenes = 1 # row


        """ Buttons declaration """
        # Navigation
        button_navig_up = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_session_up)
        button_navig_down = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_session_down)


        """ Declare our session box """
        global session #We want to instantiate the global session as a SessionComponent object (it was a global "None" type up until now...)
        session = SessionComponent(num_tracks, num_scenes) #(num_tracks, num_scenes) A session highlight ("red box") will appear with any two non-zero values
        session.set_offsets(0, 0) #(track_offset, scene_offset) Sets the initial offset of the "red box" from top left
        session._do_show_highlight()   #to ensure that this session will be highlighted


        """ Buttons association """
        # Navigation up, down, left, right
        session.set_scene_bank_buttons(button_navig_down, button_navig_up)
        # Launch selected clip
        for index in range(num_tracks):
            session.scene(0).clip_slot(index).set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_session_launch_clip[index]))
        # Stop selected track
        stop_track_buttons = []
        for index in range(num_tracks):
            stop_track_buttons.append(ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_session_stop_track[index]))
        session.set_stop_track_clip_buttons(tuple(stop_track_buttons)) #array size needs to match num_tracks
Example #2
0
class AAB(ControlSurface):
	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		with self.component_guard():
			self.session = SessionComponent(4, 4)
			self.session.set_offsets(0, 0)
			self.session.scene(0).clip_slot(0).set_launch_button(ButtonElement(False, 
																1, 6, 2))
			self.session.scene(0).clip_slot(1).set_launch_button(ButtonElement(False, 
																0, 6, 0))

			self.set_highlighting_session_component(self.session)
Example #3
0
	def _setup_session_control(self):
		is_momentary = True
		num_tracks = COLS
		num_scenes = ROWS
		global session
		session = SessionComponent(num_tracks, num_scenes)
		session.name = "Session"
		session.set_offsets(0, 0)
		self._session = session
		self._session.set_stop_track_clip_value(0)
		self._scene = [None for index in range(ROWS)]
		for row in range(num_scenes):
			self._scene[row] = session.scene(row)
			self._scene[row].name = 'Scene_' + str(row)
			for column in range(num_tracks):
				clip_slot = self._scene[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_' + str(row)
				clip_slot.set_triggered_to_play_value(64)
				clip_slot.set_triggered_to_record_value(64)
				clip_slot.set_stopped_value(0)
				clip_slot.set_started_value(64)
				clip_slot.set_recording_value(64)
				#clip_slot.set_launch_button(self._grid[column][row]) #comment out if you don't want clip launch
		session.set_mixer(mixer)
		self._session_zoom = SessionZoomingComponent(session)
		self._session_zoom.name = 'Session_Overview'
		self._session_zoom.set_stopped_value(0)
		self._session_zoom.set_playing_value(64)
		self._session_zoom.set_selected_value(64)
		if STANDALONE is True:
			self.set_highlighting_session_component(self._session)
			self._session.set_track_bank_buttons(self._grid[5][3], self._grid[4][3])   #comment out when using with Griid
			self._session.set_scene_bank_buttons(self._grid[7][3], self._grid[6][3])	# comment out when using with Griid
    def _create_session(self):
        session = SessionComponent(self.SESSION_WIDTH, self.SESSION_HEIGHT, auto_name=True, enable_skinning=True, is_enabled=False, layer=Layer(scene_launch_buttons=self.wrap_matrix(self._scene_launch_buttons), clip_launch_buttons=self._session_matrix, stop_all_clips_button=self._stop_all_button, track_bank_left_button=self._left_button, track_bank_right_button=self._right_button, scene_bank_up_button=self._up_button, scene_bank_down_button=self._down_button))
        for scene_index in xrange(self.SESSION_HEIGHT):
            for track_index in xrange(self.SESSION_WIDTH):
                slot = session.scene(scene_index).clip_slot(track_index)
                slot.layer = Layer(select_button=self._shift_button)

        return session
Example #5
0
class MaschinAble(ControlSurface):
	__module__ = __name__
	__doc__ = '''Midi Remote Script for Clip launch control on the\n
Native Instruments Maschine Controller'''

	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		self.log_message("====================== MaschineAble Log opened ======================")
		self.set_suppress_rebuild_requests(True)
		self._suggested_input_port = 'Maschine Controller In'
		self._suggested_output_port = 'Maschine Controller Out'
		self.session = None
		self._setup_session_control()
		self.set_suppress_rebuild_requests(False)
		
	def _setup_session_control(self):
		is_momentary = True
		num_tracks = 4
		num_scenes = 4
		
		self.session = SessionComponent(num_tracks, num_scenes)
		self.session.name = 'MaschinAble_session_control'
		matrix = ButtonMatrixElement()
		
		self.session.set_offsets(0, 0)
		
		up_button = ButtonElement(is_momentary, 1, 1, 108)
		down_button = ButtonElement(is_momentary, 1, 1, 109)
		left_button = ButtonElement(is_momentary, 1, 1, 110)
		right_button = ButtonElement(is_momentary, 1, 1, 111)
		
		self.session.set_track_bank_buttons(right_button, left_button)
		self.session.set_scene_bank_buttons(down_button, up_button)
		
		launch_notes_start_from = 112
		launch_notes = range(launch_notes_start_from, launch_notes_start_from + 16)
		current_scene = list(
			self.song().scenes).index(self.song().view.selected_scene)
		current_track = list(
			self.song().tracks).index(self.song().view.selected_track)
		for scene_index in range(num_scenes):
			button_row = []
			for track_index in range(num_tracks):
				clip_slot = self.session.scene(num_scenes - 1 - scene_index + current_scene).clip_slot(track_index + current_track)
				button = ButtonElement(is_momentary, 0, 1, launch_notes[track_index+(4*scene_index)])
				button_row.append(button)
				if clip_slot.has_clip:
					clip_slot.set_stopped_value(1)
				else:
					clip_slot.set_stopped_value(0)
				clip_slot.set_triggered_to_play_value(2)
				clip_slot.set_triggered_to_record_value(2)
				clip_slot.set_launch_button(button)
			matrix.add_row(tuple(button_row))
			
	def disconnect(self):
		ControlSurface.disconnect(self)
		self.log_message("====================== MaschineAble Log closed ======================")
    def _setup_selection_box_control(self, indexDicer):
        is_momentary = True


        # Size of session box
        num_tracks = 1 #1 column
        num_scenes = 1 #1 row


        """ Buttons declaration """
        # Navigation
        button_navig_up = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[0])
        button_navig_down = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[1])
        button_navig_left = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[3])
        button_navig_right = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[4])
        # Launch clip
        button_launch_clip = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[2])
        # Stop track
        button_stop_track = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_shifted[2])
        # Stop all tracks
        #button_stop_track_all


        """ Declare our session box """
        global session #We want to instantiate the global session as a SessionComponent object (it was a global "None" type up until now...)
        session = SessionComponent(num_tracks, num_scenes) #(num_tracks, num_scenes) A session highlight ("red box") will appear with any two non-zero values
        session.set_offsets(indexDicer * 4, 0) #(track_offset, scene_offset) Sets the initial offset of the "red box" from top left
        session._do_show_highlight()   #to ensure that this session will be highlighted


        """ Buttons association """
        # Navigation up, down, left, right
        session.set_scene_bank_buttons(button_navig_down, button_navig_up)
        session.set_track_bank_buttons(button_navig_right, button_navig_left)
        # Launch selected clip
        session.scene(0).clip_slot(0).set_launch_button(button_launch_clip)
        # Stop selected track
        stop_track_buttons = []
        stop_track_buttons.append(button_stop_track)
        session.set_stop_track_clip_buttons(tuple(stop_track_buttons)) #array size needs to match num_tracks
	def _setup_session_control(self):
		is_momentary = True
		num_tracks = 7
		num_scenes = 5 
		global session
		session = SessionComponent(num_tracks, num_scenes)
		session.name = "Session"
		self._session = session	
		session.set_offsets(0, 0)	 
		self._scene = [None for index in range(6)]
		for row in range(num_scenes):
			self._scene[row] = session.scene(row)
			self._scene[row].name = 'Scene_' + str(row)
			for column in range(num_tracks):
				clip_slot = self._scene[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_' + str(row)		
		session.set_mixer(self._mixer)
		self._session_zoom = SessionZoomingComponent(session)	 
		self._session_zoom.name = 'Session_Overview'
Example #8
0
class midilooper(ControlSurface):

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            self._instance = c_instance
            self._has_slider_section = True
            self.log_message("Midilooper initializing...")
            # register_sender(self)
            self._session = SessionComponent(NUM_TRACKS, NUM_ROWS)
            self._session.name = 'Session_Control'
            self._mixer = MixerComponent(NUM_TRACKS, NUM_RETURNS)
            for track in range(NUM_TRACKS):
                strip = self._mixer.channel_strip(track)
                strip.name = 'Channel_Strip_' + str(track)
                # encoder = EncoderElement(MIDI_CC_TYPE, 0, 20 + track, Live.MidiMap.MapMode.absolute)
                control = SliderElement(MIDI_CC_TYPE, 0, 20+track)
                control.name = str(track) + '_Volume_Control'
                strip.set_volume_control(control)
            for track in range(NUM_RETURNS):
                strip = self._mixer.return_strip(track)
                control = SliderElement(MIDI_CC_TYPE, 0, 40+track)
                control.name = str(track) + '_Return_Control'
                strip.set_volume_control(control)
            strip = self._mixer.master_strip()
            strip.name = 'Master_Channel_Strip'
            control = SliderElement(MIDI_CC_TYPE, 0, 50)
            control.name = 'Master_Volume_Control'
            strip.set_volume_control(control)
            self._session.set_offsets(0, 0);
            self._session.set_mixer(self._mixer)
            for row in range(NUM_ROWS):
                scene = self._session.scene(row)
                for track in range(NUM_TRACKS):
                    slot = scene.clip_slot(track)
                    button = ButtonElement(True, MIDI_NOTE_TYPE, track, 36+row)
                    slot.set_launch_button(button)
            self.set_highlighting_session_component(self._session)
            self.request_rebuild_midi_map()
            self.log_message("Midilooper initialized.")

    def disconnect(self):
        ControlSurface.disconnect(self)
    def _create_session(self):
        session = SessionComponent(
            self.SESSION_WIDTH,
            self.SESSION_HEIGHT,
            auto_name=True,
            enable_skinning=True,
            is_enabled=False,
            layer=Layer(scene_launch_buttons=self.wrap_matrix(
                self._scene_launch_buttons),
                        clip_launch_buttons=self._session_matrix,
                        stop_all_clips_button=self._stop_all_button,
                        track_bank_left_button=self._left_button,
                        track_bank_right_button=self._right_button,
                        scene_bank_up_button=self._up_button,
                        scene_bank_down_button=self._down_button))
        for scene_index in xrange(self.SESSION_HEIGHT):
            for track_index in xrange(self.SESSION_WIDTH):
                slot = session.scene(scene_index).clip_slot(track_index)
                slot.layer = Layer(select_button=self._shift_button)

        return session
Example #10
0
 def _setup_session_control(self):
     is_momentary = True
     num_tracks = 7
     num_scenes = 7  ###changed from 5 for HH
     global session
     session = SessionComponent(num_tracks, num_scenes)
     session.name = "Session"
     session.set_offsets(0, 0)
     self._session = session
     self._scene = [None for index in range(num_scenes)]
     for row in range(num_scenes):
         self._scene[row] = session.scene(row)
         self._scene[row].name = 'Scene_' + str(row)
         for column in range(num_tracks):
             clip_slot = self._scene[row].clip_slot(column)
             clip_slot.name = str(column) + '_Clip_Slot_' + str(row)
     session.set_mixer(mixer)
     self._session_zoom = SessionZoomingComponent(session)
     self._session_zoom.name = 'Session_Overview'
     #self._session_zoom.set_enabled(False)
     self.set_highlighting_session_component(self._session)
Example #11
0
	def _setup_session_control(self):
		global session
		is_momentary = True
		num_tracks = 7
		num_scenes = 5
		session = SessionComponent(num_tracks, num_scenes)
		session.name = 'Session'
		self._session = session
		session.set_offsets(0, 0)
		self._scene = [ None for index in range(6) ]
		for row in range(num_scenes):
			self._scene[row] = session.scene(row)
			self._scene[row].name = 'Scene_' + str(row)
			for column in range(num_tracks):
				clip_slot = self._scene[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_' + str(row)

		session.set_mixer(self._mixer)
		session.set_show_highlight(True)
		self._session_zoom = SessionZoomingComponent(session)
		self._session_zoom.name = 'Session_Overview'
		self.set_highlighting_session_component(self._session)
Example #12
0
 def _setup_session_control(self):
     is_momentary = True
     num_tracks = COLS
     num_scenes = ROWS
     global session
     session = SessionComponent(num_tracks, num_scenes)
     session.name = "Session"
     session.set_offsets(0, 0)
     self._session = session
     self._session.set_stop_track_clip_value(0)
     self._scene = [None for index in range(ROWS)]
     for row in range(num_scenes):
         self._scene[row] = session.scene(row)
         self._scene[row].name = 'Scene_' + str(row)
         for column in range(num_tracks):
             clip_slot = self._scene[row].clip_slot(column)
             clip_slot.name = str(column) + '_Clip_Slot_' + str(row)
             clip_slot.set_triggered_to_play_value(64)
             clip_slot.set_triggered_to_record_value(64)
             clip_slot.set_stopped_value(0)
             clip_slot.set_started_value(64)
             clip_slot.set_recording_value(64)
             #clip_slot.set_launch_button(self._grid[column][row]) #comment out if you don't want clip launch
     session.set_mixer(mixer)
     self._session_zoom = SessionZoomingComponent(session)
     self._session_zoom.name = 'Session_Overview'
     self._session_zoom.set_stopped_value(0)
     self._session_zoom.set_playing_value(64)
     self._session_zoom.set_selected_value(64)
     if STANDALONE is True:
         self.set_highlighting_session_component(self._session)
         self._session.set_track_bank_buttons(
             self._grid[5][3],
             self._grid[4][3])  #comment out when using with Griid
         self._session.set_scene_bank_buttons(
             self._grid[7][3],
             self._grid[6][3])  # comment out when using with Griid
Example #13
0
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self._device_selection_follows_track_selection = True
        with self.component_guard():
            self._suppress_send_midi = True
            self._suppress_session_highlight = True
            self._control_is_with_automap = False
            is_momentary = True
            self._suggested_input_port = 'Akai MPD26'
            self._suggested_output_port = 'Akai MPD26'
            self.log("BEFORE mixer")
            self._setup_mixer_control()
            self._setup_device_control()

            # self.clipcontrol(8)

            self.log("AFTER MIXER")
            """SESSION ViEW"""
            global session
            session = SessionComponent(GRIDSIZE[0], GRIDSIZE[1])
            session.name = 'Session_Control'
            matrix = ButtonMatrixElement()
            matrix.name = 'Button_Matrix'
            up_button = ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, UP_BUTTON)
            down_button = ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL,
                                        DOWN_BUTTON)
            left_button = ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL,
                                        LEFT_BUTTON)
            right_button = ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL,
                                         RIGHT_BUTTON)

            # session.set_scene_bank_buttons(down_button, up_button) #enabling these and disabling the below zoom buttons will move one scene/track per button press
            # session.set_track_bank_buttons(right_button, left_button) #

            session_zoom = SessionZoomingComponent(session)
            session_zoom.set_nav_buttons(
                up_button, down_button, left_button, right_button
            )  #these make it so you move the maximum number of scenes/tracks per button press. much more useful than moving by single scenes/tracks

            session_stop_buttons = []
            for row in range(GRIDSIZE[0]):
                button_row = []
                scene = session.scene(row)
                scene.name = 'Scene_' + str(row)
                scene.set_launch_button(
                    ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL,
                                  SCENE_BUTTONS[row]))
                scene.set_triggered_value(2)
                session_stop_buttons.append(
                    (ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL,
                                   TRACK_STOPS[row])))

                for column in range(GRIDSIZE[1]):
                    button = ConfigurableButtonElement(
                        True, MIDI_NOTE_TYPE, CHANNEL,
                        LAUNCH_BUTTONS[row][column])
                    button.name = str(column) + '_Clip_' + str(row) + '_Button'
                    button_row.append(button)
                    clip_slot = scene.clip_slot(column)
                    clip_slot.name = str(column) + '_Clip_Slot_' + str(row)
                    clip_slot.set_launch_button(button)

                matrix.add_row(tuple(button_row))

            self._suppress_session_highlight = False
            self._suppress_send_midi = False
            self.set_highlighting_session_component(session)
            session.set_mixer(mixer)
            session.set_stop_track_clip_buttons(tuple(session_stop_buttons))
Example #14
0
	def _setup_session_control(self):
		is_momentary = True
		self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87)		   
		right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 67)
		left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 66)
		up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 71)
		down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 68)
		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'
		global session
		session = SessionComponent(7, 8)
		session.name = 'Session_Control'
		session.set_track_bank_buttons(right_button, left_button)
		session.set_scene_bank_buttons(down_button, up_button)
		matrix = ButtonMatrixElement()
		matrix.name = 'Button_Matrix'
		scene_launch_notes = [56,57,58,59,60,61,62,63]
		scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, scene_launch_notes[index]) for index in range(8) ]
		#track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ]
		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)
		#button_notes = [0,8,16,24,32,40,48,56,1,9,17,25,33,41,49,57,2,10,18,26,34,42,50,58,3,11,19,27,35,43,51,59,4,12,20,28,36,44,52,60,5,13,21,29,37,45,53,61,6,14,22,30,38,46,54,62]
		for scene_index in range(8):
			scene = 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(7):
				button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, (track_index * 8) + scene_index)
				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(0)
				clip_slot.set_started_value(64)
				#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))
		session.selected_scene().name = 'Selected_Scene'
		#session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
		#session_zoom = SessionZoomingComponent(session)
		#session_zoom.name = 'Session_Overview'
		#session_zoom.set_button_matrix(matrix)
		#session_zoom.set_zoom_button(self._shift_button)
		#session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button)
		#session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
		#session_zoom.set_stopped_value(0)
		#session_zoom.set_selected_value(127)
		session.set_mixer(mixer)
		self.set_highlighting_session_component(session)
		return None #return session
Example #15
0
class MPK_mini_hero(ControlSurface):
    """ Script for Novation's Launchkey 25/49/61 keyboards """
    def __init__(self, c_instance, identity_response=SIZE_RESPONSE):
        ControlSurface.__init__(self, c_instance)
        self._identity_response = identity_response
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = 'MPK mini'
            self._suggested_output_port = 'MPK mini'

            self._setup_buttons()
            self._setup_components()

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

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

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

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

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

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

        self.request_rebuild_midi_map()

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

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

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

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

        # Encoders

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

        # Scenes

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

    def _setup_components(self):

        # Session

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

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

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

        # Undo

        self._do_undo.subject = self._clip_undo_button

        # Transport

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

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

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

        # Device

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

        # Navigation

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

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

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

    def _dummy_listener(self, value):
        pass

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

    def _update_mixer_offset(self):
        all_tracks = self._session.tracks_to_use()
        selected_track = self.song().view.selected_track
        num_strips = self._session.width()
        if selected_track in all_tracks:
            track_index = list(all_tracks).index(selected_track)
            new_offset = track_index - track_index % num_strips
            self._session.set_offsets(new_offset, self._session.scene_offset())
class DC1(ControlSurface):
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        is_momentary = True
        self._timer = 0                             #used for flashing states, and is incremented by each call from self._update_display()
        self._touched = 0    
        self.flash_status = 1 # Used in FlashingButtonElement (kludge for our purposes)       
        self._device_selection_follows_track_selection = True
        
        with self.component_guard():
            self._setup_transport_control()

            if USE_MIXER_CONTROLS == True:
                self.mixer_control()
            if USE_SESSION_VIEW == True:
                self.session_control()        
            self.setup_device_control()
    
    
    def _setup_transport_control(self):
        is_momentary = True # We'll only be using momentary buttons here
        self.transport = TransportComponent() #Instantiate a Transport Component
        """set up the buttons"""
        self.transport.set_play_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 60)) #ButtonElement(is_momentary, msg_type, channel, identifier) Note that the MIDI_NOTE_TYPE constant is defined in the InputControlElement module
        self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 61))
        self.transport.set_record_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 62))


    def mixer_control(self):
        is_momentary = True
        self.num_tracks = N_TRACKS
        if(USE_SENDS == True):
            self.mixer = MixerComponent(N_TRACKS, N_SENDS_PER_TRACK, USE_MIXER_EQ, USE_MIXER_FILTERS)
        else:
            self.mixer = MixerComponent(N_TRACKS,0, USE_MIXER_EQ, USE_MIXER_FILTERS)
        self.mixer.name = 'Mixer'
        self.mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
        for index in range(N_TRACKS):
            self.mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index)
            self.mixer.channel_strip(index)._invert_mute_feedback = True             


        if(USE_SELECT_BUTTONS == True):
            self.selectbuttons = [None for index in range(N_TRACKS)]
            for index in range(len(SELECT_BUTTONS)):
                self.selectbuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,SELECT_BUTTONS[index], 'Select_Button', self)
                self.mixer.channel_strip(index).set_select_button(self.selectbuttons[index])
                self.selectbuttons[index].set_on_value(SELECT_BUTTON_ON_COLOR)
                self.selectbuttons[index].set_off_value(SELECT_BUTTON_OFF_COLOR)

        if(USE_SOLO_BUTTONS == True):
            self.solobuttons = [None for index in range(N_TRACKS)]
            for index in range(len(SOLO_BUTTONS)):
                self.solobuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,SOLO_BUTTONS[index], 'Solo_Button', self)
                self.mixer.channel_strip(index).set_solo_button(self.solobuttons[index])
                self.solobuttons[index].set_on_value(SOLO_BUTTON_ON_COLOR)
                self.solobuttons[index].set_off_value(SOLO_BUTTON_OFF_COLOR)



        if(USE_ARM_BUTTONS == True):
            self.armbuttons = [None for index in range(N_TRACKS)]
            for index in range(len(ARM_BUTTONS)):
                self.armbuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,ARM_BUTTONS[index], 'Arm_Button', self)
                self.mixer.channel_strip(index).set_arm_button(self.armbuttons[index])
                self.armbuttons[index].set_on_value(ARM_BUTTON_ON_COLOR)
                self.armbuttons[index].set_off_value(ARM_BUTTON_OFF_COLOR)
		
        if(USE_MUTE_BUTTONS == True):
            self.mutebuttons = [None for index in range(N_TRACKS)]
            for index in range(len(MUTE_BUTTONS)):
                self.mutebuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,MUTE_BUTTONS[index], 'Mute_Button', self)
                self.mixer.channel_strip(index).set_mute_button(self.mutebuttons[index])
                self.mutebuttons[index].set_on_value(MUTE_BUTTON_ON_COLOR)
                self.mutebuttons[index].set_off_value(MUTE_BUTTON_OFF_COLOR)
                
        if(USE_SENDS == True):
            self.sendencoders = [None for index in range(len(SEND_ENCODERS))]
            for index in range(len(SEND_ENCODERS)):
                self.sendencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, SEND_ENCODERS[index], Live.MidiMap.MapMode.absolute)
            for index in range(len(SEND_ENCODERS)/N_SENDS_PER_TRACK):
                self.mixer.channel_strip(index).set_send_controls(tuple(self.sendencoders[(index*N_SENDS_PER_TRACK):((index*N_SENDS_PER_TRACK)+N_SENDS_PER_TRACK-1)]))

                
        if(USE_VOLUME_CONTROLS == True):
            self.volencoders = [None for index in range(len(VOLUME_ENCODERS))]
            for index in range (len(VOLUME_ENCODERS)):
                self.volencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, VOLUME_ENCODERS[index], Live.MidiMap.MapMode.absolute)
                self.mixer.channel_strip(index).set_volume_control(self.volencoders[index])
      
    def session_control(self):
        is_momentary = True
        self._timer = 0
        self.flash_status = 1
        self.grid = [None for index in range(N_TRACKS*N_SCENES)]
        for index in range(N_TRACKS*N_SCENES):
            self.grid[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,TRACK_CLIP_BUTTONS[index], 'Grid' + str(index), self)
            self.grid[index].set_off_value(0)
            self.grid[index].turn_off()
            
        self.matrix = ButtonMatrixElement()
        for row in range(N_SCENES):
            button_row = []
            for column in range(N_TRACKS):
                button_row.append(self.grid[row+(column*N_SCENES)])
            self.matrix.add_row(tuple(button_row))
        self.session = SessionComponent(N_TRACKS,N_SCENES)
        self.session.name = "Session"
        self.session.set_offsets(0,0)

        self.scene = [None for index in range(N_SCENES)]
        for row in range(N_SCENES):
            self.scene[row] = self.session.scene(row)
            self.scene[row].name = 'Scene_'+str(row)
            for column in range(N_TRACKS):
                clip_slot = self.scene[row].clip_slot(column)
                clip_slot.name = str(column)+'_Clip_Slot'+str(row)
                self.scene[row].clip_slot(column).set_triggered_to_play_value(CLIP_TRG_PLAY_COLOR)
                self.scene[row].clip_slot(column).set_stopped_value(CLIP_STOP_COLOR)
                self.scene[row].clip_slot(column).set_started_value(CLIP_STARTED_COLOR)
        self.set_highlighting_session_component(self.session)        
        self.session_zoom = DeprecatedSessionZoomingComponent(self.session)                 #this creates the ZoomingComponent that allows navigation when the shift button is pressed
        self.session_zoom.name = 'Session_Overview'                            #name it so we can access it in m4l
        self.session_zoom.set_stopped_value(ZOOM_STOPPED)            #set the zooms stopped color
        self.session_zoom.set_playing_value(ZOOM_PLAYING)            #set the zooms playing color
        self.session_zoom.set_selected_value(ZOOM_SELECTED)            #set the zooms selected color
        self.session_zoom.set_button_matrix(self.matrix)                        #assign the ButtonMatrixElement that we created in _setup_controls() to the zooming component so that we can control it
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 63)
        self.session_zoom.set_zoom_button(self._shift_button)                   #assign a shift button so that we can switch states between the SessionComponent and the SessionZoomingComponent

        self.looper = LooperComponent(self)
        self.log_message(str(len(STOP_BUTTONS)))
        if(USE_STOP_BUTTONS == True):
            self.stopbuttons = [None for index in range(N_TRACKS)]
            for index in range(len(STOP_BUTTONS)):
                self.stopbuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,STOP_BUTTONS[index], 'Stop_Button', self)
                self.session.set_stop_track_clip_buttons(self.stopbuttons)
                self.stopbuttons[index].set_on_value(STOP_BUTTON_ON_COLOR)
                self.stopbuttons[index].set_off_value(STOP_BUTTON_OFF_COLOR)
        self.scrollencoder = ScrollEncoderElement(MIDI_CC_TYPE, CHANNEL, 32, Live.MidiMap.MapMode.absolute, self.session, self.transport, self.mixer, self.looper)
        self.scrollencoder.set_nav_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 0))
        self.scrollencoder.set_transport_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 7))
        self.scrollencoder.set_scene_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 3))
        self.scrollencoder.set_library_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 4))
        self.scrollencoder.set_button1(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 1))
        self.scrollencoder.set_button2(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 2))
        self.scrollencoder.set_button3(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 5))
        self.scrollencoder.set_button4(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 6))
        self.scrollencoder.set_encoder_button(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 32))
		

        for column in range(N_TRACKS):
            for row in range(N_SCENES):
                self.scene[row].clip_slot(column).set_launch_button(self.grid[row+(column*N_SCENES)])    
    
        for index in range(N_TRACKS*N_SCENES):
            self.grid[index].clear_send_cache()      
                
        
        if USE_MIXER_CONTROLS == True:
            self.session.set_mixer(self.mixer)    

        self.refresh_state()
        self.session.set_enabled(True)
        self.session.update()  
              
    def setup_device_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')
        for index in range(4):
            device_bank_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 16 + index))
            device_bank_buttons[-1].name = bank_button_labels[index]
        for index in range(8):
            #ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, 21 + index)
            ringed_encoder = CMDEncoderElement(MIDI_CC_TYPE, CHANNEL, 16 + index, Live.MidiMap.MapMode.relative_binary_offset, 20)
            #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()
        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 = DetailViewControllerComponent(self)
        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_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3])
        
    def update_display(self):
        ControlSurface.update_display(self)
        self._timer = (self._timer + 1) % 256
  
    def disconnect(self):
        self._hosts = []
        ControlSurface.disconnect(self)
        return None        
Example #17
0
class AumTroll_G(AumTroll):


	def __init__(self, *a, **k):
		super(AumTroll_G, self).__init__(*a, **k)
		with self.component_guard():
			self._setup_session_recording_component()
			self._setup_APC_detail_component()
		self.log_message('Aumtroll G 4')
	


	def _setup_session_recording_component(self):
		self._recorder = SessionRecordingComponent(ClipCreator(), ViewControlComponent())
	

	def _setup_APC_detail_component(self):
		self._alt_device_navigator = DetailViewCntrlComponent()
	
	"""the mixer component corresponds and moves with our selection in Live, and allows us to assign physical controls"""
	"""to Live's mixer functions without having to make all the links ourselves"""
	def _setup_mixer_control(self):
		is_momentary = True
		self._num_tracks = (8) 								#A mixer is one-dimensional; 
		self._mixer = MixerComponent(8, 2, True, False)		#These values represent the (Number_of_tracks, Number_of_returns, EQ_component, Filter_component)
		self._mixer.name = 'Mixer'							#We name everything that we might want to access in m4l
		self._mixer.set_track_offset(0) 					#Sets start point for mixer strip (offset from left)
		for index in range(8):								
			#self._mixer.channel_strip(index).set_volume_control(self._fader[index])		#Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it						
			self._mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index)	#We also name the individual channel_strip so we can access it
			self._mixer.track_eq(index).name = 'Mixer_EQ_' + str(index)					#We also name the individual EQ_component so we can access it
			self._mixer.channel_strip(index)._invert_mute_feedback = True				#This makes it so that when a track is muted, the corresponding button is turned off
		self.song().view.selected_track = self._mixer.channel_strip(0)._track 			#set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error
		self._send_reset = ResetSendsComponent(self)		#This creates a custom MonoComponent that allows us to reset all the sends on a track to zero with a single button
		self._send_reset.name = 'Sends_Reset'				#We name it so that we can access it from m4l
	

	"""the session component represents a grid of buttons that can be used to fire, stop, and navigate clips in the session view"""
	def _setup_session_control(self):
		is_momentary = True
		num_tracks = 8															#we are working with a 4x4 grid,	
		num_scenes = 4 															#so the height and width are both set to 4
		self._session = SessionComponent(num_tracks, num_scenes)				#we create our SessionComponent with the variables we set above it
		self._session.name = "Session"											#we name it so we can access it in m4l
		self._session.set_offsets(0, 0)											#we set the initial offset to the far left, top of the session grid
		self._session._track_banking_increment = 4
		self._session.set_stop_clip_value(STOP_CLIP[self._rgb])			#we assign the colors that will be displayed when the stop_clip button is pressed. This value comes from CNTRLR_Map.py, which is imported in the header of our script
		self._scene = [None for index in range(4)]								#we create an array to hold the Scene subcomponents so that we can get to them if we need them.
		for row in range(num_scenes):											#now we'll fill the array with different objects that were created when we called the SessionComponent() module
			self._scene[row] = self._session.scene(row)							#each session row is a SceneComponent
			self._scene[row].name = 'Scene_' + str(row)							#name it so we can access it in m4l
			for column in range(num_tracks):									#now we'll create holders and names for the contents of each scene
				clip_slot = self._scene[row].clip_slot(column)					#we use our assignment of the scene above to gain access to the individual clipslots.  Here, we are just assigning 'clip_slot' each time as a local variable so we can manipulated it's properties
				clip_slot.name = str(column) + '_Clip_Slot' + str(row)			#name it so that we can acces it in m4l
				clip_slot.set_triggered_to_play_value(CLIP_TRG_PLAY[self._rgb])	#set its triggered to play color
				clip_slot.set_triggered_to_record_value(CLIP_TRG_REC[self._rgb])#set its triggered to record color
				clip_slot.set_stopped_value(CLIP_STOP[self._rgb])				#set its stop color
				clip_slot.set_started_value(CLIP_STARTED[self._rgb])			#set its started color
				clip_slot.set_recording_value(CLIP_RECORDING[self._rgb])		#set its recording value
		self._session.set_mixer(self._mixer)									#now we link the MixerComponent we created in _setup_mixer_control() to our session component so that they will follow each other when either is navigated
		self.set_highlighting_session_component(self._session)
		self._session_zoom = SessionZoomingComponent(self._session)	 			#this creates the ZoomingComponent that allows navigation when the shift button is pressed
		self._session_zoom.name = 'Session_Overview'							#name it so we can access it in m4l
		self._session_zoom.set_stopped_value(ZOOM_STOPPED[self._rgb])			#set the zooms stopped color
		self._session_zoom.set_playing_value(ZOOM_PLAYING[self._rgb])			#set the zooms playing color
		self._session_zoom.set_selected_value(ZOOM_SELECTED[self._rgb])			#set the zooms selected color
		self._session_zoom.set_button_matrix(self._matrix)						#assign the ButtonMatrixElement that we created in _setup_controls() to the zooming component so that we can control it
		self._session_zoom.set_zoom_button(self._button[31])					#assign a shift button so that we can switch states between the SessionComponent and the SessionZoomingComponent
	

	"""this section is used so that we can reassign the color properties of each state.  Legacy, from the OhmModes script, to support either RGB or Monochrome"""
	def _assign_session_colors(self):
		num_tracks = 8
		num_scenes = 4 
		self._session.set_stop_clip_value(STOP_ALL[self._rgb])
		for row in range(num_scenes): 
			for column in range(num_tracks):
				self._scene[row].clip_slot(column).set_triggered_to_play_value(CLIP_TRG_PLAY[self._rgb])
				self._scene[row].clip_slot(column).set_triggered_to_record_value(CLIP_TRG_REC[self._rgb])
				self._scene[row].clip_slot(column).set_stopped_value(CLIP_STOP[self._rgb])
				self._scene[row].clip_slot(column).set_started_value(CLIP_STARTED[self._rgb])
				self._scene[row].clip_slot(column).set_recording_value(CLIP_RECORDING[self._rgb])		
		self._session_zoom.set_stopped_value(ZOOM_STOPPED[self._rgb])
		self._session_zoom.set_playing_value(ZOOM_PLAYING[self._rgb])
		self._session_zoom.set_selected_value(ZOOM_SELECTED[self._rgb])
		self.refresh_state()
	

	def deassign_live_controls(self, *a, **k):
		for index in range(4):
			self._encoder[index].send_value(0, True)
			self._encoder[index].clear_send_cache()							
			self._mixer.channel_strip(index+4).set_volume_control(None)		#Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it																#for the left side of the mixer
			self._mixer.channel_strip(index+4).set_solo_button(None)		#remove the solo button assignments
			self._mixer.channel_strip(index+4).set_arm_button(None)		#remove the arm button assignments
			self._mixer.channel_strip(index+4).set_mute_button(None)		#remove the mute button assignments
			self._mixer.channel_strip(index+4).set_select_button(None)	#remove the select button assignments
		#self._alt_device_navigator.set_arrange_session_toggle_button(None)
		self._alt_device_navigator.set_device_clip_toggle_button(None)
		self._alt_device_navigator.set_detail_toggle_button(None)
		self._alt_device_navigator.set_enabled(False)
		#self._alt_device_navigator.set_shift_button(None)
		self._transport.set_nudge_buttons(None, None)
		self._recorder.set_record_button(None)
		self._recorder.set_re_enable_automation_button(None)
		
		super(AumTroll_G, self).deassign_live_controls(*a, **k)
	


	def assign_live_controls(self):
		"""the following lines update all of the controls' last_sent properties, so that they forward the next value they receive regardless of whether or not it is the same as the last it recieved"""
		"""we also reset the encoder rings and buttons, since the device component will not update them if it is not locked to a device in Live"""
		for index in range(16):
			self._grid[index].force_next_send()
		for index in range(32):
			#self._button[index].set_on_off_values(0, 127)
			self._button[index].send_value(0, True)
			self._button[index].force_next_send()
		for index in range(8):
			self._encoder_button[index+4].send_value(0, True)
			self._encoder_button[index+4].force_next_send()
		for index in range(12):
			self._encoder[index].send_value(0, True)
			self._encoder[index].force_next_send()

		"""here we assign the left side of our mixer's buttons on the lower 32 keys"""
		if self._monohm is None:
			with self.component_guard():
				for index in range(4):															#we set up a recursive loop to assign all four of our track channel strips' controls
					self._button[index+16].set_on_value(MUTE[self._rgb])						#set the mute color from the Map.py
					self._mixer.channel_strip(index).set_mute_button(self._button[index+16])	#assign the mute buttons to our mixer channel strips
					self._button[index+28].set_on_value(MUTE[self._rgb])						#set the mute color from the Map.py
					self._mixer.channel_strip(index+4).set_mute_button(self._button[index+28])	#assign the mute buttons to our mixer channel strips

					self._button[index].set_on_off_values(SELECT[self._rgb], SELECT_OFF[self._rgb])
					self._mixer.channel_strip(index).set_select_button(self._button[index])	#assign the select buttons to our mixer channel strips
					self._button[index+12].set_on_off_values(SELECT[self._rgb], SELECT_OFF[self._rgb])	#set the select color from the Map.py
					self._mixer.channel_strip(index+4).set_select_button(self._button[index+12])	#assign the select buttons to our mixer channel strips

				#self._session.set_stop_track_clip_buttons(tuple(self._button[index+4] for index in range(8)))	#these last two lines assign the send_reset buttons and the stop_clip buttons for each track
				for index in range(8):
					#self._button[index + 4].set_on_off_values(SOLO[self._rgb], SOLO[self._rgb])	#this assigns the custom colors defined in the Map.py file to the stop_clip buttons.  They have seperate on/off values, but we assign them both the same value so we can always identify them
					self._mixer.channel_strip(index).set_solo_button(self._button[index+4])
					#self._button[index + 4].send_value(STOP_CLIP[self._rgb], True)				#finally, we send the on/off colors out to turn the LEDs on for the stop clip buttons
				for index in range(4):															#set up a for loop to generate an index for assigning the session nav buttons' colors
					self._button[index + 20].set_on_off_values(SESSION_NAV[self._rgb], SESSION_NAV_OFF[self._rgb])	#assign the colors from Map.py to the session nav buttons
				self._session.set_track_bank_buttons(self._button[21], self._button[20])		#set the track bank buttons for the Session navigation controls
				self._session.set_scene_bank_buttons(self._button[23], self._button[22])		#set the scnee bank buttons for the Session navigation controls

				"""this section assigns the grid to the clip launch functionality of the SessionComponent"""
				for column in range(4):															#we need to set up a double recursion so that we can generate the indexes needed to assign the grid buttons
					for row in range(4):														#the first recursion passes the column index, the second the row index
						self._scene[row].clip_slot(column).set_launch_button(self._grid[(row*4)+column])	#we use the indexes to grab the first the scene and then the clip we assigned above, and then we use them again to define the button held in the grid array that we want to assign to the clip slot from the session component

				for index in range(4):															#set up a for loop to generate an index for assigning the session nav buttons' colors
					self._button[index + 24].set_on_off_values(SHIFTS[self._rgb], SHIFTS_OFF[self._rgb])	#assign the colors from Map.py to the session nav buttons

				self._session.update()															#tell the Session component to update so that the grid will display the currently selected session region
				self._session.set_enabled(True)													#enable the Session Component
				self._session_zoom.set_enabled(True)											#enable the Session Zoom
				
				#self._alt_device_navigator.set_arrange_session_toggle_button(self._encoder_button[4])
				self._alt_device_navigator.set_device_clip_toggle_button(self._encoder_button[5])
				self._alt_device_navigator.set_detail_toggle_button(self._encoder_button[6])
				#self._device_navigator.set_shift_button(self._encoder_button[7])
				self._session_zoom.set_zoom_button(self._encoder_button[7])							#assign the lower right key button to the shift function of the Zoom component

				self._session.set_scene_bank_buttons(self._button[25], self._button[24])
				self._recorder.set_record_button(self._button[27])
				self._recorder.set_re_enable_automation_button(self._button[26])
		else:
			for index in range(8):
				self._mixer2.channel_strip(index).set_volume_control(self._fader[index])
			self._mixer2.set_track_offset(TROLL_OFFSET)
			self._device_selector.set_mode_buttons(self._grid)
			if not self._shifted:
				self._assign_monomodular_controls()
			else:
				self._assign_shifted_controls()
			self._device1.set_parameter_controls(tuple([self._knobs[index] for index in range(8)]))
			self._device2.set_parameter_controls(tuple([self._knobs[index+12] for index in range(8)]))
			self._device1.set_enabled(True)
			self._device2.set_enabled(True)
			self._find_devices()
			self._device1.update()
			self._device2.update()

		"""this section assigns the encoders and encoder buttons"""
		self._device.set_parameter_controls(tuple([self._encoder[index+4] for index in range(8)]))			#assign the encoders from the device component controls - we are doing this here b
		#self._encoder_button[7].set_on_value(DEVICE_LOCK[self._rgb])					#set the on color for the Device lock encoder button
		#self._device.set_lock_button(self._encoder_button[7])							#assign encoder button 7 to the device lock control
		#self._encoder_button[4].set_on_value(DEVICE_ON[self._rgb])						#set the on color for the Device on/off encoder button 
		#self._device.set_on_off_button(self._encoder_button[4])							#assing encoder button 4 to the device on/off control
		for index in range(2):															#setup a recursion to generate indexes so that we can reference the correct controls to assing to the device_navigator functions
			self._encoder_button[index + 8].set_on_value(DEVICE_NAV[self._rgb])			#assign the on color for the device navigator
			self._encoder_button[index + 10].set_on_value(DEVICE_BANK[self._rgb])		#assign the on color for the device bank controls
		self._device_navigator.set_nav_buttons(self._encoder_button[10], self._encoder_button[11]) 	#set the device navigators controls to encoder buttons 10 and 11
		self._device.set_bank_nav_buttons(self._encoder_button[8], self._encoder_button[9]) 	#set the device components bank nav controls to encoder buttons 8 and 9

		"""now we turn on and update some of the components we've just made assignments to"""
		self._device.set_enabled(True)													#enable the Device Component
		self._device_navigator.set_enabled(True)										#enable the Device Navigator
		self._alt_device_navigator.set_enabled(True)
		self._device.update()															#tell the Device component to update its assingments so that it will detect the currently selected device parameters and display them on the encoder rings
Example #18
0
class Midi_Fighter_64(ControlSurface):
    def __init__(self, c_instance):
        super(Midi_Fighter_64, self).__init__(c_instance)
        self._color_skin = make_rgb_skin()
        self._default_skin = make_default_skin()
        with self.component_guard():
            global _map_modes
            _map_modes = Live.MidiMap.MapMode
            self.current_track_offset = 0
            self.current_scene_offset = 0
            # mixer
            global mixer
            num_tracks = 128
            num_returns = 24
            self.mixer = MixerComponent(num_tracks, num_returns)
            global active_mode
            #self._mode0()
            active_mode = "_mode1"
            self._set_active_mode()
            self._set_track_select_led()
            self.show_message("Powered by DJ TechTools")

    '''
    def _mode4(self):
        self.show_message("_mode4 is active")
        # mixer
        global mixer
        # session
        global _session
        num_tracks = 8
        num_scenes = 7
        self._session = SessionComponent(num_tracks, num_scenes)
        clip_color_table = colors.LIVE_COLORS_TO_MIDI_VALUES.copy()
        clip_color_table[16777215] = 119
        self._session.set_rgb_mode(colors.LIVE_COLORS_TO_MIDI_VALUES, colors.RGB_COLOR_TABLE)
        track_offset = self.current_track_offset
        scene_offset = self.current_scene_offset
        self._session.set_offsets(track_offset, scene_offset)
        self._session._reassign_scenes()
        self.set_highlighting_session_component(self._session)
        # clip launch buttons
        session_buttons = [60, 61, 62, 63, 92, 93, 94, 95, 56, 57, 58, 59, 88, 89, 90, 91, 52, 53, 54, 55, 84, 85, 86, 87, 48, 49, 50, 51, 80, 81, 82, 83, 44, 45, 46, 47, 76, 77, 78, 79, 40, 41, 42, 43, 72, 73, 74, 75, 36, 37, 38, 39, 68, 69, 70, 71]
        session_channels = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        session_types = [MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE]
        session_is_momentary = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        self._pads = [ButtonElement(session_is_momentary[index], session_types[index], session_channels[index], session_buttons[index]) for index in range(num_tracks*num_scenes)]
        self._grid = ButtonMatrixElement(rows=[self._pads[(index*num_tracks):(index*num_tracks)+num_tracks] for index in range(num_scenes)])
        self._session.set_clip_launch_buttons(self._grid)
        # LED feedback
        self._session._enable_skinning()
        for scene_index in range(num_scenes):
            scene = self._session.scene(scene_index)
            for track_index in range(num_tracks):
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_triggered_to_play_value(61)
                clip_slot.set_triggered_to_record_value(13)
                clip_slot.set_record_button_value(19)
                #clip_slot.set_stopped_value(49)
                #clip_slot.set_started_value(127)
                clip_slot.set_recording_value(13)
        self.delete_button = ConfigurableButtonElement(0, MIDI_NOTE_TYPE, 1, 67)
        self.delete_button.set_on_off_values(49, 55)
        self._session._link()
        self.refresh_state()
        self.clip_xtra_back = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 96)
        self.clip_xtra_back.add_value_listener(self._activate_mode1,identify_sender= False)
        self.clip_xtra_back.send_value(85)
        # transport
        global transport
        self.transport = TransportComponent()
        self.transport.name = 'Transport'
        overdub_button = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 64)
        overdub_button.set_on_off_values(13, 19)
        overdub_button.name = 'overdub_button'
        self.transport.set_overdub_button(overdub_button)
        if((hasattr(self, 'clip_xtra')) and (self.clip_xtra is not None)):
            self.clip_xtra.send_value(85)

    def _remove_mode4(self):
        # mixer
        global mixer
        # session
        global _session
        # clip launch buttons
        self._session.set_clip_launch_buttons(None)
        self.set_highlighting_session_component(None)
        self.current_track_offset = self._session._track_offset
        self.current_scene_offset = self._session._scene_offset
        self._session._unlink()
        self._session = None
        self.clip_xtra_back.send_value(0)
        self.clip_xtra_back.remove_value_listener(self._activate_mode1)
        self.clip_xtra_back = None
        # transport
        global transport
        self.transport.set_overdub_button(None)
        self.transport = None
        if((hasattr(self, 'clip_xtra')) and (self.clip_xtra is not None)):
            self.clip_xtra.send_value(91)
    '''

    def _mode1(self):
        self.show_message("Script Loaded")
        # mixer
        global mixer
        # session
        global _session
        num_tracks = 8
        num_scenes = 8
        # 		self._session = SessionComponent(auto_name=True, is_enabled=False, enable_skinning=True)
        self._session = SessionComponent(num_tracks, num_scenes)
        clip_color_table = colors.LIVE_COLORS_TO_MIDI_VALUES.copy()
        clip_color_table[16777215] = 119
        self._session.set_rgb_mode(colors.LIVE_COLORS_TO_MIDI_VALUES,
                                   colors.RGB_COLOR_TABLE)
        track_offset = self.current_track_offset
        scene_offset = self.current_scene_offset
        self._session.set_offsets(track_offset, scene_offset)
        self._session._reassign_scenes()
        self.set_highlighting_session_component(self._session)
        # clip launch buttons
        session_buttons = [
            64, 65, 66, 67, 96, 97, 98, 99, 60, 61, 62, 63, 92, 93, 94, 95, 56,
            57, 58, 59, 88, 89, 90, 91, 52, 53, 54, 55, 84, 85, 86, 87, 48, 49,
            50, 51, 80, 81, 82, 83, 44, 45, 46, 47, 76, 77, 78, 79, 40, 41, 42,
            43, 72, 73, 74, 75, 36, 37, 38, 39, 68, 69, 70, 71
        ]
        session_channels = [
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
        ]
        #change all the session channels to 2 in order to use the first bank. This will potentially allow for blinking/flashing animations in the future.
        session_types = [
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE,
            MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE
        ]
        session_is_momentary = [
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
        ]
        self._pads = [
            ButtonElement(session_is_momentary[index], session_types[index],
                          session_channels[index], session_buttons[index])
            for index in range(num_tracks * num_scenes)
        ]
        self._grid = ButtonMatrixElement(rows=[
            self._pads[(index * num_tracks):(index * num_tracks) + num_tracks]
            for index in range(num_scenes)
        ])
        self._session.set_clip_launch_buttons(self._grid)
        # LED feedback
        self._session._enable_skinning()
        for scene_index in range(num_scenes):
            scene = self._session.scene(scene_index)
            for track_index in range(num_tracks):
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_triggered_to_play_value(61)  #orange-red
                clip_slot.set_triggered_to_record_value(13)  #yellow
                clip_slot.set_record_button_value(5)  #bright red
                #clip_slot.set_stopped_value(49) #blue
                #clip_slot.set_started_value(127) #dark red
                clip_slot.set_recording_value(13)  #yellow
        # these are written in decimal format, correspond to the RGB_COLOR_TABLE in pushbase/colors.py
        """
        # session navigation
        self.session_up = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 64)
        self.session_up.set_on_off_values(25, 31)
        self._session.set_page_up_button(self.session_up)
        self.session_down = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 65)
        self.session_down.set_on_off_values(25, 31)
        self._session.set_page_down_button(self.session_down)
        self.session_left = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 66)
        self.session_left.set_on_off_values(25, 31)
        self._session.set_page_left_button(self.session_left)
        self.session_right = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 67)
        # "ConfigurableButtonElement(1," was originally set to 0, fixed by Jademalo
        self.session_right.set_on_off_values(25, 31)
        self._session.set_page_right_button(self.session_right)
        self._session._link()
        self.refresh_state()
        self.clip_xtra = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 96)
        self.clip_xtra.add_value_listener(self._activate_mode4,identify_sender= False)
        self.clip_xtra.send_value(91)
        if((hasattr(self, 'clip_xtra_back')) and (self.clip_xtra_back is not None)):
            self.clip_xtra_back.send_value(91)
        """

    def _remove_mode1(self):
        # mixer
        global mixer
        # session
        global _session
        # clip launch buttons
        self._session.set_clip_launch_buttons(None)
        self.set_highlighting_session_component(None)
        """
        # session navigation
        self._session.set_page_up_button(None)
        self._session.set_page_down_button(None)
        self._session.set_page_left_button(None)
        self._session.set_page_right_button(None)
        self.current_track_offset = self._session._track_offset
        self.current_scene_offset = self._session._scene_offset
        self._session._unlink()
        self._session = None
        self.clip_xtra.send_value(0)
        self.clip_xtra.remove_value_listener(self._activate_mode4)
        self.clip_xtra = None
        if((hasattr(self, 'clip_xtra_back')) and (self.clip_xtra_back is not None)):
            self.clip_xtra_back.send_value(85)
        """

    """
    def _mode2(self):
        self.show_message("_mode2 is active")
        # mixer
        global mixer
        # session
        global _session
        num_tracks = 8
        num_scenes = 7
        self._session = SessionComponent(num_tracks, num_scenes)
        clip_color_table = colors.LIVE_COLORS_TO_MIDI_VALUES.copy()
        clip_color_table[16777215] = 119
        self._session.set_rgb_mode(colors.LIVE_COLORS_TO_MIDI_VALUES, colors.RGB_COLOR_TABLE)
        track_offset = self.current_track_offset
        scene_offset = self.current_scene_offset
        self._session.set_offsets(track_offset, scene_offset)
        self._session._reassign_scenes()
        self.set_highlighting_session_component(self._session)
    # clip launch buttons
        session_buttons = [60, 61, 62, 63, 92, 93, 94, 121, 56, 57, 58, 59, 88, 89, 90, 122, 52, 53, 54, 55, 84, 85, 86, 123, 48, 49, 50, 51, 80, 81, 82, 124, 44, 45, 46, 47, 76, 77, 78, 125, 40, 41, 42, 43, 72, 73, 74, 126, 36, 37, 38, 39, 68, 69, 70, 127]
        # in mode 2, the last buttons in rows aren't used for launching clips and instead are used for launching scenes
        # because of this, the last clip-launching button in every row is moved out of range (121,122,123,124,125,126,127) so it doesn't interfere. clever!
        # 121-127 seems arbitrary, 100-107 probably would have worked just as well since the last midi fighter button is 99 anyways
        session_channels = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        session_types = [MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE]
        session_is_momentary = [1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0]
        self._pads = [ButtonElement(session_is_momentary[index], session_types[index], session_channels[index], session_buttons[index]) for index in range(num_tracks*num_scenes)]
        self._grid = ButtonMatrixElement(rows=[self._pads[(index*num_tracks):(index*num_tracks)+num_tracks] for index in range(num_scenes)])
        self._session.set_clip_launch_buttons(self._grid)
    # session scene launch
        scene_buttons = [95, 91, 87, 83, 79, 75, 71]
        #the last buttons in every row, mentioned earlier
        scene_channels = [1, 1, 1, 1, 1, 1, 1]
        scene_types = [MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE]
        scene_momentarys = [1, 1, 1, 1, 1, 1, 1]
        self._scene_launch_buttons = [ButtonElement(scene_momentarys[index], scene_types[index], scene_channels[index], scene_buttons[index]) for index in range(num_scenes)]
        self._scene_launch_buttons = ButtonMatrixElement(rows=[self._scene_launch_buttons])
        self._session.set_scene_launch_buttons(self._scene_launch_buttons)
    # LED feedback
        self._session._enable_skinning()
        for scene_index in range(num_scenes):
            scene = self._session.scene(scene_index)
            scene.set_scene_value(127)
            scene.set_no_scene_value(0)
            scene.set_triggered_value(61)
            for track_index in range(num_tracks):
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_triggered_to_play_value(61)
                clip_slot.set_triggered_to_record_value(13)
                clip_slot.set_record_button_value(19)
                #clip_slot.set_stopped_value(49)
                #clip_slot.set_started_value(127)
                clip_slot.set_recording_value(13)
        self._session._link()
        self.refresh_state()
        if((hasattr(self, 'scene_shift')) and (self.scene_shift is not None)):
            self.scene_shift.send_value(127)

    def _remove_mode2(self):
    # mixer
        global mixer
    # session
        global _session
    # clip launch buttons
        self._session.set_clip_launch_buttons(None)
        self.set_highlighting_session_component(None)
    # session scene launch
        self._scene_launch_buttons = None
        self._session.set_scene_launch_buttons(None)
        self.current_track_offset = self._session._track_offset
        self.current_scene_offset = self._session._scene_offset
        self._session._unlink()
        self._session = None
        if((hasattr(self, 'scene_shift')) and (self.scene_shift is not None)):
            self.scene_shift.send_value(66)
    """
    """
    def _mode0(self):
        self.show_message("_mode0 is active")
        # mixer
        global mixer
        self.scene_shift = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 99)
        self.scene_shift.add_value_listener(self._activate_shift_mode2,identify_sender= False)
        self.scene_shift.send_value(66)
        self.shift_mixer = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 98)
        self.shift_mixer.add_value_listener(self._activate_shift_mode3,identify_sender= False)
        self.shift_mixer.send_value(37)

    def _remove_mode0(self):
        # mixer
        global mixer
        self.scene_shift.send_value(0)
        self.scene_shift.remove_value_listener(self._activate_shift_mode2)
        self.scene_shift = None
        self.shift_mixer.send_value(0)
        self.shift_mixer.remove_value_listener(self._activate_shift_mode3)
        self.shift_mixer = None
    """
    """
    def _mode3(self):
        self.show_message("_mode3 is active")
        # mixer
        # the set_on_off_values were originally completely different, fixed by Jademalo
        global mixer
        arm_specific_0 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 40)
        arm_specific_0.set_on_off_values(5, 7)
        self.mixer.channel_strip(0).set_arm_button(arm_specific_0)
        arm_specific_1 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 41)
        arm_specific_1.set_on_off_values(5, 7)
        self.mixer.channel_strip(1).set_arm_button(arm_specific_1)
        arm_specific_2 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 42)
        arm_specific_2.set_on_off_values(5, 7)
        self.mixer.channel_strip(2).set_arm_button(arm_specific_2)
        arm_specific_3 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 43)
        arm_specific_3.set_on_off_values(5, 7)
        self.mixer.channel_strip(3).set_arm_button(arm_specific_3)
        arm_specific_4 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 72)
        arm_specific_4.set_on_off_values(5, 7)
        self.mixer.channel_strip(4).set_arm_button(arm_specific_4)
        arm_specific_5 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 73)
        arm_specific_5.set_on_off_values(5, 7)
        self.mixer.channel_strip(5).set_arm_button(arm_specific_5)
        arm_specific_6 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 74)
        arm_specific_6.set_on_off_values(5, 7)
        self.mixer.channel_strip(6).set_arm_button(arm_specific_6)
        arm_specific_7 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 75)
        arm_specific_7.set_on_off_values(5, 7)
        self.mixer.channel_strip(7).set_arm_button(arm_specific_7)
        solo_specific_0 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 44)
        solo_specific_0.set_on_off_values(37, 47)
        self.mixer.channel_strip(0).set_solo_button(solo_specific_0)
        solo_specific_1 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 45)
        solo_specific_1.set_on_off_values(37, 47)
        self.mixer.channel_strip(1).set_solo_button(solo_specific_1)
        solo_specific_2 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 46)
        solo_specific_2.set_on_off_values(37, 47)
        self.mixer.channel_strip(2).set_solo_button(solo_specific_2)
        solo_specific_3 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 47)
        solo_specific_3.set_on_off_values(37, 47)
        self.mixer.channel_strip(3).set_solo_button(solo_specific_3)
        solo_specific_4 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 76)
        solo_specific_4.set_on_off_values(37, 47)
        self.mixer.channel_strip(4).set_solo_button(solo_specific_4)
        solo_specific_5 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 77)
        solo_specific_5.set_on_off_values(37, 47)
        self.mixer.channel_strip(5).set_solo_button(solo_specific_5)
        solo_specific_6 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 78)
        solo_specific_6.set_on_off_values(37, 47)
        self.mixer.channel_strip(6).set_solo_button(solo_specific_6)
        solo_specific_7 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 79)
        solo_specific_7.set_on_off_values(37, 47)
        self.mixer.channel_strip(7).set_solo_button(solo_specific_7)
        mute_specific_0 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 48)
        mute_specific_0.set_on_off_values(13, 15)
        self.mixer.channel_strip(0).set_mute_button(mute_specific_0)
        self.mixer.channel_strip(0).set_invert_mute_feedback(True)
        mute_specific_1 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 49)
        mute_specific_1.set_on_off_values(13, 15)
        self.mixer.channel_strip(1).set_mute_button(mute_specific_1)
        self.mixer.channel_strip(1).set_invert_mute_feedback(True)
        mute_specific_2 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 50)
        mute_specific_2.set_on_off_values(13, 15)
        self.mixer.channel_strip(2).set_mute_button(mute_specific_2)
        self.mixer.channel_strip(2).set_invert_mute_feedback(True)
        mute_specific_3 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 51)
        mute_specific_3.set_on_off_values(13, 15)
        self.mixer.channel_strip(3).set_mute_button(mute_specific_3)
        self.mixer.channel_strip(3).set_invert_mute_feedback(True)
        mute_specific_4 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 80)
        mute_specific_4.set_on_off_values(13, 15)
        self.mixer.channel_strip(4).set_mute_button(mute_specific_4)
        self.mixer.channel_strip(4).set_invert_mute_feedback(True)
        mute_specific_5 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 81)
        mute_specific_5.set_on_off_values(13, 15)
        self.mixer.channel_strip(5).set_mute_button(mute_specific_5)
        self.mixer.channel_strip(5).set_invert_mute_feedback(True)
        mute_specific_6 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 82)
        mute_specific_6.set_on_off_values(13, 15)
        self.mixer.channel_strip(6).set_mute_button(mute_specific_6)
        self.mixer.channel_strip(6).set_invert_mute_feedback(True)
        mute_specific_7 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 83)
        mute_specific_7.set_on_off_values(13, 15)
        self.mixer.channel_strip(7).set_mute_button(mute_specific_7)
        self.mixer.channel_strip(7).set_invert_mute_feedback(True)
    # session
        global _session
        num_tracks = 8
        num_scenes = 7
        self._session = SessionComponent(num_tracks, num_scenes)
        clip_color_table = colors.LIVE_COLORS_TO_MIDI_VALUES.copy()
        clip_color_table[16777215] = 119
        self._session.set_rgb_mode(colors.LIVE_COLORS_TO_MIDI_VALUES, colors.RGB_COLOR_TABLE)
        track_offset = self.current_track_offset
        scene_offset = self.current_scene_offset
        self._session.set_offsets(track_offset, scene_offset)
        self._session._reassign_scenes()
        self.set_highlighting_session_component(self._session)
    # session track stop
        stop_track_buttons = [36, 37, 38, 39, 68, 69, 70, 71]
        stop_track_channels = [1, 1, 1, 1, 1, 1, 1, 1]
        stop_track_types = [MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE, MIDI_NOTE_TYPE]
        stop_track_is_momentary = [0, 0, 0, 0, 0, 0, 0, 0]
        self._track_stop_buttons = [ConfigurableButtonElement(stop_track_is_momentary[index], stop_track_types[index], stop_track_channels[index], stop_track_buttons[index]) for index in range(num_tracks)]
        self._session.set_stop_track_clip_buttons(tuple(self._track_stop_buttons))
    # LED feedback
        self._session._enable_skinning()
        self._session.set_stop_clip_triggered_value(61)
        self._session.set_stop_clip_value(127)
        for scene_index in range(num_scenes):
            scene = self._session.scene(scene_index)
            for track_index in range(num_tracks):
                clip_slot = scene.clip_slot(track_index)
    # session navigation
    # several lines originally missing, added by Jademalo
        self.session_up = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 64)
        self.session_up.set_on_off_values(25, 31)
        self._session.set_page_up_button(self.session_up)
        self.session_down = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 65)
        self.session_down.set_on_off_values(25, 31)
        self._session.set_page_down_button(self.session_down)
        self.session_left = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 66)
        self.session_left.set_on_off_values(25, 31)
        self._session.set_page_left_button(self.session_left)
        self.session_right = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 67)
        self.session_right.set_on_off_values(25, 31)
        self._session.set_page_right_button(self.session_right)
        self._session._link()
        self._session.set_mixer(self.mixer)
        self.refresh_state()
    # select track 1 button
        self.select_1 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 52)
        self.select_1.set_on_off_values(73, 79)
        self.select_1.add_value_listener(self.track_select_1, identify_sender=False)
    # select track 2 button
        self.select_2 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 53)
        self.select_2.set_on_off_values(73, 79)
        self.select_2.add_value_listener(self.track_select_2, identify_sender=False)
    # select track 3 button
        self.select_3 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 54)
        self.select_3.set_on_off_values(73, 79)
        self.select_3.add_value_listener(self.track_select_3, identify_sender=False)
    # select track 4 button
        self.select_4 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 55)
        self.select_4.set_on_off_values(73, 79)
        self.select_4.add_value_listener(self.track_select_4, identify_sender=False)
    # select track 5 button
        self.select_5 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 84)
        self.select_5.set_on_off_values(73, 79)
        self.select_5.add_value_listener(self.track_select_5, identify_sender=False)
    # select track 6 button
        self.select_6 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 85)
        self.select_6.set_on_off_values(73, 79)
        self.select_6.add_value_listener(self.track_select_6, identify_sender=False)
    # select track 7 button
        self.select_7 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 86)
        self.select_7.set_on_off_values(73, 79)
        self.select_7.add_value_listener(self.track_select_7, identify_sender=False)
    # select track 8 button
        self.select_8 = ConfigurableButtonElement(1, MIDI_NOTE_TYPE, 1, 87)
        self.select_8.set_on_off_values(73, 79)
        self.select_8.add_value_listener(self.track_select_8, identify_sender=False)
        if((hasattr(self, 'shift_mixer')) and (self.shift_mixer is not None)):
            self.shift_mixer.send_value(127)

    def _remove_mode3(self):
    # mixer
        global mixer
        self.mixer.channel_strip(0).set_arm_button(None)
        self.mixer.channel_strip(1).set_arm_button(None)
        self.mixer.channel_strip(2).set_arm_button(None)
        self.mixer.channel_strip(3).set_arm_button(None)
        self.mixer.channel_strip(4).set_arm_button(None)
        self.mixer.channel_strip(5).set_arm_button(None)
        self.mixer.channel_strip(6).set_arm_button(None)
        self.mixer.channel_strip(7).set_arm_button(None)
        self.mixer.channel_strip(0).set_solo_button(None)
        self.mixer.channel_strip(1).set_solo_button(None)
        self.mixer.channel_strip(2).set_solo_button(None)
        self.mixer.channel_strip(3).set_solo_button(None)
        self.mixer.channel_strip(4).set_solo_button(None)
        self.mixer.channel_strip(5).set_solo_button(None)
        self.mixer.channel_strip(6).set_solo_button(None)
        self.mixer.channel_strip(7).set_solo_button(None)
        self.mixer.channel_strip(0).set_mute_button(None)
        self.mixer.channel_strip(1).set_mute_button(None)
        self.mixer.channel_strip(2).set_mute_button(None)
        self.mixer.channel_strip(3).set_mute_button(None)
        self.mixer.channel_strip(4).set_mute_button(None)
        self.mixer.channel_strip(5).set_mute_button(None)
        self.mixer.channel_strip(6).set_mute_button(None)
        self.mixer.channel_strip(7).set_mute_button(None)
    # session
        global _session
        self.set_highlighting_session_component(None)
        self._session.set_mixer(None)
    # session track stop
        self._track_stop_buttons = None
        self._session.set_stop_track_clip_buttons(None)
    # session navigation
        self._session.set_page_left_button(None)
        self._session.set_page_right_button(None)
        self.current_track_offset = self._session._track_offset
        self.current_scene_offset = self._session._scene_offset
        self._session._unlink()
        self._session = None
        self.select_1.send_value(0)
        self.select_1.remove_value_listener(self.track_select_1)
        self.select_1 = None
        self.select_2.send_value(0)
        self.select_2.remove_value_listener(self.track_select_2)
        self.select_2 = None
        self.select_3.send_value(0)
        self.select_3.remove_value_listener(self.track_select_3)
        self.select_3 = None
        self.select_4.send_value(0)
        self.select_4.remove_value_listener(self.track_select_4)
        self.select_4 = None
        self.select_5.send_value(0)
        self.select_5.remove_value_listener(self.track_select_5)
        self.select_5 = None
        self.select_6.send_value(0)
        self.select_6.remove_value_listener(self.track_select_6)
        self.select_6 = None
        self.select_7.send_value(0)
        self.select_7.remove_value_listener(self.track_select_7)
        self.select_7 = None
        self.select_8.send_value(0)
        self.select_8.remove_value_listener(self.track_select_8)
        self.select_8 = None
        if((hasattr(self, 'shift_mixer')) and (self.shift_mixer is not None)):
            self.shift_mixer.send_value(37)
    """

    def _set_track_select_led(self):
        self._turn_off_track_select_leds()
        # take sessionbox into account if its present
        offset = 0
        if (hasattr(self, '_session')):
            offset = self._session._track_offset
        num_of_tracks = len(self.song().tracks)
        # next is each track select item
        # select_1
        pos = offset + 0
        pos2 = pos + 1
        if num_of_tracks >= pos2:
            if (self.song().view.selected_track == self.song().tracks[pos]):
                if ((hasattr(self, 'select_1'))
                        and (self.select_1 is not None)):
                    self.select_1.send_value(73)
        # select_2
        pos = offset + 1
        pos2 = pos + 1
        if num_of_tracks >= pos2:
            if (self.song().view.selected_track == self.song().tracks[pos]):
                if ((hasattr(self, 'select_2'))
                        and (self.select_2 is not None)):
                    self.select_2.send_value(73)
        # select_3
        pos = offset + 2
        pos2 = pos + 1
        if num_of_tracks >= pos2:
            if (self.song().view.selected_track == self.song().tracks[pos]):
                if ((hasattr(self, 'select_3'))
                        and (self.select_3 is not None)):
                    self.select_3.send_value(73)
        # select_4
        pos = offset + 3
        pos2 = pos + 1
        if num_of_tracks >= pos2:
            if (self.song().view.selected_track == self.song().tracks[pos]):
                if ((hasattr(self, 'select_4'))
                        and (self.select_4 is not None)):
                    self.select_4.send_value(73)
        # select_5
        pos = offset + 4
        pos2 = pos + 1
        if num_of_tracks >= pos2:
            if (self.song().view.selected_track == self.song().tracks[pos]):
                if ((hasattr(self, 'select_5'))
                        and (self.select_5 is not None)):
                    self.select_5.send_value(73)
        # select_6
        pos = offset + 5
        pos2 = pos + 1
        if num_of_tracks >= pos2:
            if (self.song().view.selected_track == self.song().tracks[pos]):
                if ((hasattr(self, 'select_6'))
                        and (self.select_6 is not None)):
                    self.select_6.send_value(73)
        # select_7
        pos = offset + 6
        pos2 = pos + 1
        if num_of_tracks >= pos2:
            if (self.song().view.selected_track == self.song().tracks[pos]):
                if ((hasattr(self, 'select_7'))
                        and (self.select_7 is not None)):
                    self.select_7.send_value(73)
        # select_8
        pos = offset + 7
        pos2 = pos + 1
        if num_of_tracks >= pos2:
            if (self.song().view.selected_track == self.song().tracks[pos]):
                if ((hasattr(self, 'select_8'))
                        and (self.select_8 is not None)):
                    self.select_8.send_value(73)

    def _turn_off_track_select_leds(self):
        num_of_tracks = len(self.song().tracks)
        # take sessionbox into account if its present
        offset = 0
        if (hasattr(self, '_session')):
            offset = self._session._track_offset
        # select_1
        pos = offset + 0
        pos2 = pos + 1
        if ((num_of_tracks >= pos2) and (hasattr(self, 'select_1'))
                and (self.select_1 is not None)):
            self.select_1.send_value(79)
        elif ((num_of_tracks < pos2) and (hasattr(self, 'select_1'))
              and (self.select_1 is not None)):
            self.select_1.send_value(0)
        # select_2
        pos = offset + 1
        pos2 = pos + 1
        if ((num_of_tracks >= pos2) and (hasattr(self, 'select_2'))
                and (self.select_2 is not None)):
            self.select_2.send_value(79)
        elif ((num_of_tracks < pos2) and (hasattr(self, 'select_2'))
              and (self.select_2 is not None)):
            self.select_2.send_value(0)
        # select_3
        pos = offset + 2
        pos2 = pos + 1
        if ((num_of_tracks >= pos2) and (hasattr(self, 'select_3'))
                and (self.select_3 is not None)):
            self.select_3.send_value(79)
        elif ((num_of_tracks < pos2) and (hasattr(self, 'select_3'))
              and (self.select_3 is not None)):
            self.select_3.send_value(0)
        # select_4
        pos = offset + 3
        pos2 = pos + 1
        if ((num_of_tracks >= pos2) and (hasattr(self, 'select_4'))
                and (self.select_4 is not None)):
            self.select_4.send_value(79)
        elif ((num_of_tracks < pos2) and (hasattr(self, 'select_4'))
              and (self.select_4 is not None)):
            self.select_4.send_value(0)
        # select_5
        pos = offset + 4
        pos2 = pos + 1
        if ((num_of_tracks >= pos2) and (hasattr(self, 'select_5'))
                and (self.select_5 is not None)):
            self.select_5.send_value(79)
        elif ((num_of_tracks < pos2) and (hasattr(self, 'select_5'))
              and (self.select_5 is not None)):
            self.select_5.send_value(0)
        # select_6
        pos = offset + 5
        pos2 = pos + 1
        if ((num_of_tracks >= pos2) and (hasattr(self, 'select_6'))
                and (self.select_6 is not None)):
            self.select_6.send_value(79)
        elif ((num_of_tracks < pos2) and (hasattr(self, 'select_6'))
              and (self.select_6 is not None)):
            self.select_6.send_value(0)
        # select_7
        pos = offset + 6
        pos2 = pos + 1
        if ((num_of_tracks >= pos2) and (hasattr(self, 'select_7'))
                and (self.select_7 is not None)):
            self.select_7.send_value(79)
        elif ((num_of_tracks < pos2) and (hasattr(self, 'select_7'))
              and (self.select_7 is not None)):
            self.select_7.send_value(0)
        # select_8
        pos = offset + 7
        pos2 = pos + 1
        if ((num_of_tracks >= pos2) and (hasattr(self, 'select_8'))
                and (self.select_8 is not None)):
            self.select_8.send_value(79)
        elif ((num_of_tracks < pos2) and (hasattr(self, 'select_8'))
              and (self.select_8 is not None)):
            self.select_8.send_value(0)

    def track_select_1(self, value):
        if value > 0:
            if (hasattr(self, '_session')):
                move = self._session._track_offset + 1
            else:
                move = 1
            num_of_tracks = len(self.song().tracks)
            if num_of_tracks >= move:
                move = move - 1
                self.song().view.selected_track = self.song().tracks[move]

    def track_select_2(self, value):
        if value > 0:
            if (hasattr(self, '_session')):
                move = self._session._track_offset + 2
            else:
                move = 2
            num_of_tracks = len(self.song().tracks)
            if num_of_tracks >= move:
                move = move - 1
                self.song().view.selected_track = self.song().tracks[move]

    def track_select_3(self, value):
        if value > 0:
            if (hasattr(self, '_session')):
                move = self._session._track_offset + 3
            else:
                move = 3
            num_of_tracks = len(self.song().tracks)
            if num_of_tracks >= move:
                move = move - 1
                self.song().view.selected_track = self.song().tracks[move]

    def track_select_4(self, value):
        if value > 0:
            if (hasattr(self, '_session')):
                move = self._session._track_offset + 4
            else:
                move = 4
            num_of_tracks = len(self.song().tracks)
            if num_of_tracks >= move:
                move = move - 1
                self.song().view.selected_track = self.song().tracks[move]

    def track_select_5(self, value):
        if value > 0:
            if (hasattr(self, '_session')):
                move = self._session._track_offset + 5
            else:
                move = 5
            num_of_tracks = len(self.song().tracks)
            if num_of_tracks >= move:
                move = move - 1
                self.song().view.selected_track = self.song().tracks[move]

    def track_select_6(self, value):
        if value > 0:
            if (hasattr(self, '_session')):
                move = self._session._track_offset + 6
            else:
                move = 6
            num_of_tracks = len(self.song().tracks)
            if num_of_tracks >= move:
                move = move - 1
                self.song().view.selected_track = self.song().tracks[move]

    def track_select_7(self, value):
        if value > 0:
            if (hasattr(self, '_session')):
                move = self._session._track_offset + 7
            else:
                move = 7
            num_of_tracks = len(self.song().tracks)
            if num_of_tracks >= move:
                move = move - 1
                self.song().view.selected_track = self.song().tracks[move]

    def track_select_8(self, value):
        if value > 0:
            if (hasattr(self, '_session')):
                move = self._session._track_offset + 8
            else:
                move = 8
            num_of_tracks = len(self.song().tracks)
            if num_of_tracks >= move:
                move = move - 1
                self.song().view.selected_track = self.song().tracks[move]

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._display_reset_delay = 0
        value = "selected track changed"
        if (hasattr(self, '_set_track_select_led')):
            self._set_track_select_led()
        if (hasattr(self, '_reload_active_devices')):
            self._reload_active_devices(value)
        if (hasattr(self, 'update_all_ab_select_LEDs')):
            self.update_all_ab_select_LEDs(1)

    def _is_prev_device_on_or_off(self):
        self._device = self.song().view.selected_track.view.selected_device
        self._device_position = self.selected_device_idx()
        if (self._device is None) or (self._device_position == 0):
            on_off = "off"
        else:
            on_off = "on"
        return on_off

    def _is_nxt_device_on_or_off(self):
        self._selected_device = self.selected_device_idx(
        ) + 1  # add one as this starts from zero
        if (self._device is None) or (self._selected_device == len(
                self.song().view.selected_track.devices)):
            on_off = "off"
        else:
            on_off = "on"
        return on_off

    def _set_active_mode(self):
        global active_mode
        # activate mode
        if active_mode == "_mode4":
            self._mode4()
        elif active_mode == "_mode1":
            self._mode1()
        elif active_mode == "_mode2":
            self._mode2()
        elif active_mode == "_mode0":
            self._mode0()
        elif active_mode == "_mode3":
            self._mode3()

        if hasattr(self, '_set_track_select_led'):
            self._set_track_select_led()
        if hasattr(self, '_turn_on_device_select_leds'):
            self._turn_off_device_select_leds()
            self._turn_on_device_select_leds()
        if hasattr(self, '_all_prev_device_leds'):
            self._all_prev_device_leds()
        if hasattr(self, '_all_nxt_device_leds'):
            self._all_nxt_device_leds()
        if hasattr(self, 'update_all_ab_select_LEDs'):
            self.update_all_ab_select_LEDs(1)

    def _remove_active_mode(self):
        global active_mode
        # remove activate mode
        if active_mode == "_mode4":
            self._remove_mode4()
        elif active_mode == "_mode1":
            self._remove_mode1()
        elif active_mode == "_mode2":
            self._remove_mode2()
        elif active_mode == "_mode0":
            self._remove_mode0()
        elif active_mode == "_mode3":
            self._remove_mode3()

    """
    def _activate_mode4(self,value):
        global active_mode
        global shift_previous_is_active
        if value > 0:
            shift_previous_is_active = "off"
            self._remove_active_mode()
            active_mode = "_mode4"
            self._set_active_mode()
    """

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

    """
    def _activate_mode2(self,value):
        global active_mode
        global shift_previous_is_active
        if value > 0:
            shift_previous_is_active = "off"
            self._remove_active_mode()
            active_mode = "_mode2"
            self._set_active_mode()



    def _activate_mode0(self,value):
        global active_mode
        global shift_previous_is_active
        if value > 0:
            shift_previous_is_active = "off"
            self._remove_active_mode()
            active_mode = "_mode0"
            self._set_active_mode()



    def _activate_mode3(self,value):
        global active_mode
        global shift_previous_is_active
        if value > 0:
            shift_previous_is_active = "off"
            self._remove_active_mode()
            active_mode = "_mode3"
            self._set_active_mode()

    def _activate_shift_mode4(self,value):
        global active_mode
        global previous_shift_mode4
        global shift_previous_is_active
        if value > 0:
            shift_previous_is_active = "on"
            previous_shift_mode4 = active_mode
            self._remove_active_mode()
            active_mode = "_mode4"
            self._set_active_mode()
        elif shift_previous_is_active == "on":
            try:
                previous_shift_mode4
            except NameError:
                self.log_message("previous shift mode not defined yet")
            else:
                self._remove_active_mode()
                active_mode = previous_shift_mode4
                self._set_active_mode()

    def _activate_shift_mode1(self,value):
        global active_mode
        global previous_shift_mode1
        global shift_previous_is_active
        if value > 0:
            shift_previous_is_active = "on"
            previous_shift_mode1 = active_mode
            self._remove_active_mode()
            active_mode = "_mode1"
            self._set_active_mode()
        elif shift_previous_is_active == "on":
            try:
                previous_shift_mode1
            except NameError:
                self.log_message("previous shift mode not defined yet")
            else:
                self._remove_active_mode()
                active_mode = previous_shift_mode1
                self._set_active_mode()



    def _activate_shift_mode2(self,value):
        global active_mode
        global previous_shift_mode2
        global shift_previous_is_active
        if value > 0:
            shift_previous_is_active = "on"
            previous_shift_mode2 = active_mode
            self._remove_active_mode()
            active_mode = "_mode2"
            self._set_active_mode()
        elif shift_previous_is_active == "on":
            try:
                previous_shift_mode2
            except NameError:
                self.log_message("previous shift mode not defined yet")
            else:
                self._remove_active_mode()
                active_mode = previous_shift_mode2
                self._set_active_mode()

    def _activate_shift_mode0(self,value):
        global active_mode
        global previous_shift_mode0
        global shift_previous_is_active
        if value > 0:
            shift_previous_is_active = "on"
            previous_shift_mode0 = active_mode
            self._remove_active_mode()
            active_mode = "_mode0"
            self._set_active_mode()
        elif shift_previous_is_active == "on":
            try:
                previous_shift_mode0
            except NameError:
                self.log_message("previous shift mode not defined yet")
            else:
                self._remove_active_mode()
                active_mode = previous_shift_mode0
                self._set_active_mode()

    def _activate_shift_mode3(self,value):
        global active_mode
        global previous_shift_mode3
        global shift_previous_is_active
        if value > 0:
            shift_previous_is_active = "on"
            previous_shift_mode3 = active_mode
            self._remove_active_mode()
            active_mode = "_mode3"
            self._set_active_mode()
        elif shift_previous_is_active == "on":
            try:
                previous_shift_mode3
            except NameError:
                self.log_message("previous shift mode not defined yet")
            else:
                self._remove_active_mode()
                active_mode = previous_shift_mode3
                self._set_active_mode()
    """

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

    def selected_track_idx(self):
        self._track = self.song().view.selected_track
        self._track_num = self.tuple_index(self.song().tracks, self._track)
        self._track_num = self._track_num + 1
        return self._track_num

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

    def disconnect(self):
        super(Midi_Fighter_64, self).disconnect()
Example #19
0
class MPK_mini_hero(ControlSurface):
    """ Script for Novation's Launchkey 25/49/61 keyboards """

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

            self._setup_buttons()
            self._setup_components()

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

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

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

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

        self.request_rebuild_midi_map()

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

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

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

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

        # Encoders

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

        # Scenes

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

    def _setup_components(self):
        
        # Session

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

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

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

        # Undo

        self._do_undo.subject = self._clip_undo_button;

        # Transport

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

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

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

        # Device

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

        # Navigation

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

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

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

    def _dummy_listener(self, value):
        pass

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self._session = None
        self._mixer = None

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

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

    def _delete_clip(self, midi_bytes):
        if midi_bytes[0] == MIDI_NOTE_ON_VALUE:
            row, col = launchpad_button_loc(midi_bytes[1])
            if row < SCENES_AMOUNT and col < 8:
                self._session.scene(row).clip_slot(col)._do_delete_clip()
                return True
        return False
Example #21
0
class DV1(ControlSurface):
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        is_momentary = True
        self._timer = 0  #used for flashing states, and is incremented by each call from self._update_display()
        self._touched = 0
        self.flash_status = 1  # Used in FlashingButtonElement (kludge for our purposes)
        self._device_selection_follows_track_selection = True

        with self.component_guard():
            self._setup_transport_control()

            if USE_MIXER_CONTROLS == True:
                self.mixer_control()
            if USE_SESSION_VIEW == True:
                self.session_control()
            # self.setup_device_control()

    def _setup_transport_control(self):
        is_momentary = True  # We'll only be using momentary buttons here
        self.transport = TransportComponent(
        )  #Instantiate a Transport Component
        """set up the buttons"""
        self.transport.set_play_button(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 60)
        )  #ButtonElement(is_momentary, msg_type, channel, identifier) Note that the MIDI_NOTE_TYPE constant is defined in the InputControlElement module
        self.transport.set_stop_button(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 61))
        self.transport.set_record_button(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 62))

    def mixer_control(self):
        is_momentary = True
        self.num_tracks = N_TRACKS
        if (USE_SENDS == True):
            self.mixer = MixerComponent(N_TRACKS, N_SENDS_PER_TRACK,
                                        USE_MIXER_EQ, USE_MIXER_FILTERS)
        else:
            self.mixer = MixerComponent(N_TRACKS, 0, USE_MIXER_EQ,
                                        USE_MIXER_FILTERS)
        self.mixer.name = 'Mixer'
        self.mixer.set_track_offset(
            0)  #Sets start point for mixer strip (offset from left)
        for index in range(N_TRACKS):
            self.mixer.channel_strip(
                index).name = 'Mixer_ChannelStrip_' + str(index)
            self.mixer.channel_strip(index)._invert_mute_feedback = True

        if (USE_SELECT_BUTTONS == True):
            self.selectbuttons = [None for index in range(N_TRACKS)]
            for index in range(len(SELECT_BUTTONS)):
                self.selectbuttons[index] = FlashingButtonElement(
                    is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                    SELECT_BUTTONS[index], 'Select_Button', self)
                self.mixer.channel_strip(index).set_select_button(
                    self.selectbuttons[index])
                self.selectbuttons[index].set_on_value(SELECT_BUTTON_ON_COLOR)
                self.selectbuttons[index].set_off_value(
                    SELECT_BUTTON_OFF_COLOR)

        if (USE_SOLO_BUTTONS == True):
            self.solobuttons = [None for index in range(N_TRACKS)]
            for index in range(len(SOLO_BUTTONS)):
                self.solobuttons[index] = FlashingButtonElement(
                    is_momentary, MIDI_NOTE_TYPE, CHANNEL, SOLO_BUTTONS[index],
                    'Solo_Button', self)
                self.mixer.channel_strip(index).set_solo_button(
                    self.solobuttons[index])
                self.solobuttons[index].set_on_value(SOLO_BUTTON_ON_COLOR)
                self.solobuttons[index].set_off_value(SOLO_BUTTON_OFF_COLOR)

        if (USE_ARM_BUTTONS == True):
            self.armbuttons = [None for index in range(N_TRACKS)]
            for index in range(len(ARM_BUTTONS)):
                self.armbuttons[index] = FlashingButtonElement(
                    is_momentary, MIDI_NOTE_TYPE, CHANNEL, ARM_BUTTONS[index],
                    'Arm_Button', self)
                self.mixer.channel_strip(index).set_arm_button(
                    self.armbuttons[index])
                self.armbuttons[index].set_on_value(ARM_BUTTON_ON_COLOR)
                self.armbuttons[index].set_off_value(ARM_BUTTON_OFF_COLOR)

        if (USE_MUTE_BUTTONS == True):
            self.mutebuttons = [None for index in range(N_TRACKS)]
            for index in range(len(MUTE_BUTTONS)):
                self.mutebuttons[index] = FlashingButtonElement(
                    is_momentary, MIDI_NOTE_TYPE, CHANNEL, MUTE_BUTTONS[index],
                    'Mute_Button', self)
                self.mixer.channel_strip(index).set_mute_button(
                    self.mutebuttons[index])
                self.mutebuttons[index].set_on_value(MUTE_BUTTON_ON_COLOR)
                self.mutebuttons[index].set_off_value(MUTE_BUTTON_OFF_COLOR)

        if (USE_SENDS == True):
            self.sendencoders = [None for index in range(len(SEND_ENCODERS))]
            for index in range(len(SEND_ENCODERS)):
                # self.sendencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, SEND_ENCODERS[index], Live.MidiMap.MapMode.absolute)
                self.sendencoders[index] = CMDEncoderElement(
                    MIDI_CC_TYPE, CHANNEL, SEND_ENCODERS[index],
                    Live.MidiMap.MapMode.relative_smooth_binary_offset, 20)
            for index in range(len(SEND_ENCODERS) / N_SENDS_PER_TRACK):
                self.mixer.channel_strip(index).set_send_controls(
                    tuple(self.sendencoders[(index * N_SENDS_PER_TRACK):(
                        (index * N_SENDS_PER_TRACK) + N_SENDS_PER_TRACK)])
                )  # Pas -1, car tuple() fonctionne etrangement en Python ;)

        if (USE_VOLUME_CONTROLS == True):
            self.volencoders = [None for index in range(len(VOLUME_ENCODERS))]
            for index in range(len(VOLUME_ENCODERS)):
                #self.volencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, VOLUME_ENCODERS[index], Live.MidiMap.MapMode.absolute)
                self.volencoders[index] = CMDEncoderElement(
                    MIDI_CC_TYPE, CHANNEL, VOLUME_ENCODERS[index],
                    Live.MidiMap.MapMode.relative_smooth_binary_offset, 20)
                self.mixer.channel_strip(index).set_volume_control(
                    self.volencoders[index])

    def session_control(self):
        is_momentary = True
        self._timer = 0
        self.flash_status = 1
        self.grid = [None for index in range(N_TRACKS * N_SCENES)]
        for index in range(N_TRACKS * N_SCENES):
            self.grid[index] = FlashingButtonElement(is_momentary,
                                                     MIDI_NOTE_TYPE, CHANNEL,
                                                     TRACK_CLIP_BUTTONS[index],
                                                     'Grid' + str(index), self)
            self.grid[index].set_off_value(0)
            self.grid[index].turn_off()

        self.matrix = ButtonMatrixElement()
        for row in range(N_SCENES):
            button_row = []
            for column in range(N_TRACKS):
                button_row.append(self.grid[row + (column * N_SCENES)])
            self.matrix.add_row(tuple(button_row))
        self.session = SessionComponent(N_TRACKS, N_SCENES)
        self.session.name = "Session"
        self.session.set_offsets(0, 0)

        self.scene = [None for index in range(N_SCENES)]
        for row in range(N_SCENES):
            self.scene[row] = self.session.scene(row)
            self.scene[row].name = 'Scene_' + str(row)
            for column in range(N_TRACKS):
                clip_slot = self.scene[row].clip_slot(column)
                clip_slot.name = str(column) + '_Clip_Slot' + str(row)
                self.scene[row].clip_slot(column).set_triggered_to_play_value(
                    CLIP_TRG_PLAY_COLOR)
                self.scene[row].clip_slot(column).set_stopped_value(
                    CLIP_STOP_COLOR)
                self.scene[row].clip_slot(column).set_started_value(
                    CLIP_STARTED_COLOR)
        self.set_highlighting_session_component(self.session)
        #self.session_zoom = DeprecatedSessionZoomingComponent(self.session)                 #this creates the ZoomingComponent that allows navigation when the shift button is pressed
        #self.session_zoom.name = 'Session_Overview'                            #name it so we can access it in m4l
        #self.session_zoom.set_stopped_value(ZOOM_STOPPED)            #set the zooms stopped color
        #self.session_zoom.set_playing_value(ZOOM_PLAYING)            #set the zooms playing color
        #self.session_zoom.set_selected_value(ZOOM_SELECTED)            #set the zooms selected color
        #self.session_zoom.set_button_matrix(self.matrix)                        #assign the ButtonMatrixElement that we created in _setup_controls() to the zooming component so that we can control it
        #self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 84)
        #self.session_zoom.set_zoom_button(self._shift_button)                   #assign a shift button so that we can switch states between the SessionComponent and the SessionZoomingComponent

        #self.looper = LooperComponent(self)
        #self.log_message(str(len(STOP_BUTTONS)))
        #if(USE_STOP_BUTTONS == True):
        #self.stopbuttons = [None for index in range(N_TRACKS)]
        #for index in range(len(STOP_BUTTONS)):
        #self.stopbuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,STOP_BUTTONS[index], 'Stop_Button', self)
        #self.session.set_stop_track_clip_buttons(self.stopbuttons)
        #self.stopbuttons[index].set_on_value(STOP_BUTTON_ON_COLOR)
        #self.stopbuttons[index].set_off_value(STOP_BUTTON_OFF_COLOR)
        #self.scrollencoder = ScrollEncoderElement(MIDI_CC_TYPE, CHANNEL, 32, Live.MidiMap.MapMode.absolute, self.session, self.transport, self.mixer, self.looper)
        #self.scrollencoder.set_nav_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 80))
        #self.scrollencoder.set_transport_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 81))
        #self.scrollencoder.set_scene_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 82))
        #self.scrollencoder.set_library_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 83))
        #self.scrollencoder.set_button1(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 66))
        #self.scrollencoder.set_button2(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 67))
        #self.scrollencoder.set_button3(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 64))
        #self.scrollencoder.set_button4(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 65))
        #self.scrollencoder.set_encoder_button(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 32))

        self.button_left = SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                               CHANNEL, NAVBOX_LEFT_BUTTON)
        self.button_right = SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                                CHANNEL, NAVBOX_RIGHT_BUTTON)
        self.button_up = SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                             CHANNEL, NAVBOX_UP_BUTTON)
        self.button_down = SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                               CHANNEL, NAVBOX_DOWN_BUTTON)

        self.session.set_track_bank_buttons(self.button_right,
                                            self.button_left)
        self.session.set_scene_bank_buttons(self.button_down, self.button_up)

        for column in range(N_TRACKS):
            for row in range(N_SCENES):
                self.scene[row].clip_slot(column).set_launch_button(
                    self.grid[row + (column * N_SCENES)])

        for index in range(N_TRACKS * N_SCENES):
            self.grid[index].clear_send_cache()

        if USE_MIXER_CONTROLS == True:
            self.session.set_mixer(self.mixer)

        self.refresh_state()
        self.session.set_enabled(True)
        self.session.update()

    #def setup_device_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')
    #for index in range(4):
    #device_bank_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 16 + index))
    #device_bank_buttons[-1].name = bank_button_labels[index]
    #for index in range(8):
    ##ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, 21 + index)
    #ringed_encoder = CMDEncoderElement(MIDI_CC_TYPE, CHANNEL, 16 + index, Live.MidiMap.MapMode.relative_binary_offset, 20)
    ##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()
    #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 = DetailViewControllerComponent(self)
    #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_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3])

    def update_display(self):
        ControlSurface.update_display(self)
        self._timer = (self._timer + 1) % 256

    def disconnect(self):
        self._hosts = []
        ControlSurface.disconnect(self)
        return None
Example #22
0
class XoneK2(ControlSurface):
    def __init__(self, instance):
        global g_logger
        g_logger = self.log_message
        super(XoneK2, self).__init__(instance, False)
        with self.component_guard():
            self._set_suppress_rebuild_requests(True)
            self.init_session()
            self.init_mixer()
            self.init_matrix()
            self.init_tempo()

            # connect mixer to session
            self.session.set_mixer(self.mixer)
            self.session.update()
            self.set_highlighting_session_component(self.session)
            self._set_suppress_rebuild_requests(False)

    def init_session(self):
        self.session = SessionComponent(NUM_TRACKS, NUM_SCENES)
        self.session.name = 'Session'
        self.session.set_scene_bank_buttons(button(BUTTON_LL), button(BUTTON_LR))
        self.session.update()

    def init_mixer(self):
        self.mixer = MixerWithDevices(
            num_tracks=NUM_TRACKS,
            device_select=[button(PUSH_ENCODERS[i]) for i in range(NUM_TRACKS)],
            device_encoders=ENCODERS
        )
        self.mixer.id = 'Mixer'

        self.song().view.selected_track = self.mixer.channel_strip(0)._track

        for i in range(NUM_TRACKS):
            self.mixer.channel_strip(i).set_volume_control(fader(FADERS[i]))
            self.mixer.channel_strip(i).set_solo_button(button(BUTTONS3[i]))
            self.mixer.set_eq_controls(i, (
                knob(KNOBS3[i]),
                knob(KNOBS2[i]),
                knob(KNOBS1[i])))
            self.mixer.set_device_controls(i, button(BUTTONS1[i]))

        self.master_encoder = DynamicEncoder(
            ENCODER_LR, self.song().master_track.mixer_device.volume)
        self.cue_encoder = DynamicEncoder(
            ENCODER_LL, self.song().master_track.mixer_device.cue_volume)
        self.mixer.update()

    def init_matrix(self):
        self.matrix = ButtonMatrixElement()

        for scene_index in range(NUM_SCENES):
            scene = self.session.scene(scene_index)
            scene.name = 'Scene ' + str(scene_index)
            button_row = []
            for track_index in range(NUM_TRACKS):
                note_nr = GRID[scene_index][track_index]
                b = button(note_nr, name='Clip %d, %d button' % (scene_index, track_index))
                button_row.append(b)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = 'Clip slot %d, %d' % (scene_index, track_index)
                clip_slot.set_stopped_value(0)
                clip_slot.set_started_value(64)
                clip_slot.set_launch_button(b)
            self.matrix.add_row(tuple(button_row))
        stop_buttons = [button(note_nr) for note_nr in BUTTONS2]
        self.session.set_stop_track_clip_buttons(stop_buttons)

    def init_tempo(self):
        self.transport = CustomTransportComponent()
        self.transport.set_tempo_bumpers(button(PUSH_ENCODER_LR), button(PUSH_ENCODER_LL))
Example #23
0
class AumTroll_G(AumTroll):
    def __init__(self, *a, **k):
        super(AumTroll_G, self).__init__(*a, **k)
        with self.component_guard():
            self._setup_session_recording_component()
            self._setup_APC_detail_component()
        self.log_message('Aumtroll G 4')

    def _setup_session_recording_component(self):
        self._recorder = SessionRecordingComponent(ClipCreator(),
                                                   ViewControlComponent())

    def _setup_APC_detail_component(self):
        self._alt_device_navigator = DetailViewCntrlComponent()

    """the mixer component corresponds and moves with our selection in Live, and allows us to assign physical controls"""
    """to Live's mixer functions without having to make all the links ourselves"""

    def _setup_mixer_control(self):
        is_momentary = True
        self._num_tracks = (8)  #A mixer is one-dimensional;
        self._mixer = MixerComponent(
            8, 2, True, False
        )  #These values represent the (Number_of_tracks, Number_of_returns, EQ_component, Filter_component)
        self._mixer.name = 'Mixer'  #We name everything that we might want to access in m4l
        self._mixer.set_track_offset(
            0)  #Sets start point for mixer strip (offset from left)
        for index in range(8):
            #self._mixer.channel_strip(index).set_volume_control(self._fader[index])		#Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it
            self._mixer.channel_strip(
                index
            ).name = 'Mixer_ChannelStrip_' + str(
                index
            )  #We also name the individual channel_strip so we can access it
            self._mixer.track_eq(index).name = 'Mixer_EQ_' + str(
                index
            )  #We also name the individual EQ_component so we can access it
            self._mixer.channel_strip(
                index
            )._invert_mute_feedback = True  #This makes it so that when a track is muted, the corresponding button is turned off
        self.song().view.selected_track = self._mixer.channel_strip(
            0
        )._track  #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error
        self._send_reset = ResetSendsComponent(
            self
        )  #This creates a custom MonoComponent that allows us to reset all the sends on a track to zero with a single button
        self._send_reset.name = 'Sends_Reset'  #We name it so that we can access it from m4l

    """the session component represents a grid of buttons that can be used to fire, stop, and navigate clips in the session view"""

    def _setup_session_control(self):
        is_momentary = True
        num_tracks = 8  #we are working with a 4x4 grid,
        num_scenes = 4  #so the height and width are both set to 4
        self._session = SessionComponent(
            num_tracks, num_scenes
        )  #we create our SessionComponent with the variables we set above it
        self._session.name = "Session"  #we name it so we can access it in m4l
        self._session.set_offsets(
            0, 0
        )  #we set the initial offset to the far left, top of the session grid
        self._session._track_banking_increment = 4
        self._session.set_stop_clip_value(
            STOP_CLIP[self._rgb]
        )  #we assign the colors that will be displayed when the stop_clip button is pressed. This value comes from CNTRLR_Map.py, which is imported in the header of our script
        self._scene = [
            None for index in range(4)
        ]  #we create an array to hold the Scene subcomponents so that we can get to them if we need them.
        for row in range(
                num_scenes
        ):  #now we'll fill the array with different objects that were created when we called the SessionComponent() module
            self._scene[row] = self._session.scene(
                row)  #each session row is a SceneComponent
            self._scene[row].name = 'Scene_' + str(
                row)  #name it so we can access it in m4l
            for column in range(
                    num_tracks
            ):  #now we'll create holders and names for the contents of each scene
                clip_slot = self._scene[row].clip_slot(
                    column
                )  #we use our assignment of the scene above to gain access to the individual clipslots.  Here, we are just assigning 'clip_slot' each time as a local variable so we can manipulated it's properties
                clip_slot.name = str(column) + '_Clip_Slot' + str(
                    row)  #name it so that we can acces it in m4l
                clip_slot.set_triggered_to_play_value(
                    CLIP_TRG_PLAY[self._rgb])  #set its triggered to play color
                clip_slot.set_triggered_to_record_value(
                    CLIP_TRG_REC[
                        self._rgb])  #set its triggered to record color
                clip_slot.set_stopped_value(
                    CLIP_STOP[self._rgb])  #set its stop color
                clip_slot.set_started_value(
                    CLIP_STARTED[self._rgb])  #set its started color
                clip_slot.set_recording_value(
                    CLIP_RECORDING[self._rgb])  #set its recording value
        self._session.set_mixer(
            self._mixer
        )  #now we link the MixerComponent we created in _setup_mixer_control() to our session component so that they will follow each other when either is navigated
        self.set_highlighting_session_component(self._session)
        self._session_zoom = SessionZoomingComponent(
            self._session
        )  #this creates the ZoomingComponent that allows navigation when the shift button is pressed
        self._session_zoom.name = 'Session_Overview'  #name it so we can access it in m4l
        self._session_zoom.set_stopped_value(
            ZOOM_STOPPED[self._rgb])  #set the zooms stopped color
        self._session_zoom.set_playing_value(
            ZOOM_PLAYING[self._rgb])  #set the zooms playing color
        self._session_zoom.set_selected_value(
            ZOOM_SELECTED[self._rgb])  #set the zooms selected color
        self._session_zoom.set_button_matrix(
            self._matrix
        )  #assign the ButtonMatrixElement that we created in _setup_controls() to the zooming component so that we can control it
        self._session_zoom.set_zoom_button(
            self._button[31]
        )  #assign a shift button so that we can switch states between the SessionComponent and the SessionZoomingComponent

    """this section is used so that we can reassign the color properties of each state.  Legacy, from the OhmModes script, to support either RGB or Monochrome"""

    def _assign_session_colors(self):
        num_tracks = 8
        num_scenes = 4
        self._session.set_stop_clip_value(STOP_ALL[self._rgb])
        for row in range(num_scenes):
            for column in range(num_tracks):
                self._scene[row].clip_slot(column).set_triggered_to_play_value(
                    CLIP_TRG_PLAY[self._rgb])
                self._scene[row].clip_slot(
                    column).set_triggered_to_record_value(
                        CLIP_TRG_REC[self._rgb])
                self._scene[row].clip_slot(column).set_stopped_value(
                    CLIP_STOP[self._rgb])
                self._scene[row].clip_slot(column).set_started_value(
                    CLIP_STARTED[self._rgb])
                self._scene[row].clip_slot(column).set_recording_value(
                    CLIP_RECORDING[self._rgb])
        self._session_zoom.set_stopped_value(ZOOM_STOPPED[self._rgb])
        self._session_zoom.set_playing_value(ZOOM_PLAYING[self._rgb])
        self._session_zoom.set_selected_value(ZOOM_SELECTED[self._rgb])
        self.refresh_state()

    def deassign_live_controls(self, *a, **k):
        for index in range(4):
            self._encoder[index].send_value(0, True)
            self._encoder[index].clear_send_cache()
            self._mixer.channel_strip(index + 4).set_volume_control(
                None
            )  #Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it																#for the left side of the mixer
            self._mixer.channel_strip(index + 4).set_solo_button(
                None)  #remove the solo button assignments
            self._mixer.channel_strip(index + 4).set_arm_button(
                None)  #remove the arm button assignments
            self._mixer.channel_strip(index + 4).set_mute_button(
                None)  #remove the mute button assignments
            self._mixer.channel_strip(index + 4).set_select_button(
                None)  #remove the select button assignments
        #self._alt_device_navigator.set_arrange_session_toggle_button(None)
        self._alt_device_navigator.set_device_clip_toggle_button(None)
        self._alt_device_navigator.set_detail_toggle_button(None)
        self._alt_device_navigator.set_enabled(False)
        #self._alt_device_navigator.set_shift_button(None)
        self._transport.set_nudge_buttons(None, None)
        self._recorder.set_record_button(None)
        self._recorder.set_re_enable_automation_button(None)

        super(AumTroll_G, self).deassign_live_controls(*a, **k)

    def assign_live_controls(self):
        """the following lines update all of the controls' last_sent properties, so that they forward the next value they receive regardless of whether or not it is the same as the last it recieved"""
        """we also reset the encoder rings and buttons, since the device component will not update them if it is not locked to a device in Live"""
        for index in range(16):
            self._grid[index].force_next_send()
        for index in range(32):
            #self._button[index].set_on_off_values(0, 127)
            self._button[index].send_value(0, True)
            self._button[index].force_next_send()
        for index in range(8):
            self._encoder_button[index + 4].send_value(0, True)
            self._encoder_button[index + 4].force_next_send()
        for index in range(12):
            self._encoder[index].send_value(0, True)
            self._encoder[index].force_next_send()
        """here we assign the left side of our mixer's buttons on the lower 32 keys"""
        if self._monohm is None:
            with self.component_guard():
                for index in range(
                        4
                ):  #we set up a recursive loop to assign all four of our track channel strips' controls
                    self._button[index + 16].set_on_value(
                        MUTE[self._rgb])  #set the mute color from the Map.py
                    self._mixer.channel_strip(index).set_mute_button(
                        self._button[index + 16]
                    )  #assign the mute buttons to our mixer channel strips
                    self._button[index + 28].set_on_value(
                        MUTE[self._rgb])  #set the mute color from the Map.py
                    self._mixer.channel_strip(index + 4).set_mute_button(
                        self._button[index + 28]
                    )  #assign the mute buttons to our mixer channel strips

                    self._button[index].set_on_off_values(
                        SELECT[self._rgb], SELECT_OFF[self._rgb])
                    self._mixer.channel_strip(index).set_select_button(
                        self._button[index]
                    )  #assign the select buttons to our mixer channel strips
                    self._button[index + 12].set_on_off_values(
                        SELECT[self._rgb], SELECT_OFF[
                            self._rgb])  #set the select color from the Map.py
                    self._mixer.channel_strip(index + 4).set_select_button(
                        self._button[index + 12]
                    )  #assign the select buttons to our mixer channel strips

                #self._session.set_stop_track_clip_buttons(tuple(self._button[index+4] for index in range(8)))	#these last two lines assign the send_reset buttons and the stop_clip buttons for each track
                for index in range(8):
                    #self._button[index + 4].set_on_off_values(SOLO[self._rgb], SOLO[self._rgb])	#this assigns the custom colors defined in the Map.py file to the stop_clip buttons.  They have seperate on/off values, but we assign them both the same value so we can always identify them
                    self._mixer.channel_strip(index).set_solo_button(
                        self._button[index + 4])
                    #self._button[index + 4].send_value(STOP_CLIP[self._rgb], True)				#finally, we send the on/off colors out to turn the LEDs on for the stop clip buttons
                for index in range(
                        4
                ):  #set up a for loop to generate an index for assigning the session nav buttons' colors
                    self._button[index + 20].set_on_off_values(
                        SESSION_NAV[self._rgb], SESSION_NAV_OFF[self._rgb]
                    )  #assign the colors from Map.py to the session nav buttons
                self._session.set_track_bank_buttons(
                    self._button[21], self._button[20]
                )  #set the track bank buttons for the Session navigation controls
                self._session.set_scene_bank_buttons(
                    self._button[23], self._button[22]
                )  #set the scnee bank buttons for the Session navigation controls
                """this section assigns the grid to the clip launch functionality of the SessionComponent"""
                for column in range(
                        4
                ):  #we need to set up a double recursion so that we can generate the indexes needed to assign the grid buttons
                    for row in range(
                            4
                    ):  #the first recursion passes the column index, the second the row index
                        self._scene[row].clip_slot(column).set_launch_button(
                            self._grid[(row * 4) + column]
                        )  #we use the indexes to grab the first the scene and then the clip we assigned above, and then we use them again to define the button held in the grid array that we want to assign to the clip slot from the session component

                for index in range(
                        4
                ):  #set up a for loop to generate an index for assigning the session nav buttons' colors
                    self._button[index + 24].set_on_off_values(
                        SHIFTS[self._rgb], SHIFTS_OFF[self._rgb]
                    )  #assign the colors from Map.py to the session nav buttons

                self._session.update(
                )  #tell the Session component to update so that the grid will display the currently selected session region
                self._session.set_enabled(True)  #enable the Session Component
                self._session_zoom.set_enabled(True)  #enable the Session Zoom

                #self._alt_device_navigator.set_arrange_session_toggle_button(self._encoder_button[4])
                self._alt_device_navigator.set_device_clip_toggle_button(
                    self._encoder_button[5])
                self._alt_device_navigator.set_detail_toggle_button(
                    self._encoder_button[6])
                #self._device_navigator.set_shift_button(self._encoder_button[7])
                self._session_zoom.set_zoom_button(
                    self._encoder_button[7]
                )  #assign the lower right key button to the shift function of the Zoom component

                self._session.set_scene_bank_buttons(self._button[25],
                                                     self._button[24])
                self._recorder.set_record_button(self._button[27])
                self._recorder.set_re_enable_automation_button(
                    self._button[26])
        else:
            for index in range(8):
                self._mixer2.channel_strip(index).set_volume_control(
                    self._fader[index])
            self._mixer2.set_track_offset(TROLL_OFFSET)
            self._device_selector.set_mode_buttons(self._grid)
            if not self._shifted:
                self._assign_monomodular_controls()
            else:
                self._assign_shifted_controls()
            self._device1.set_parameter_controls(
                tuple([self._knobs[index] for index in range(8)]))
            self._device2.set_parameter_controls(
                tuple([self._knobs[index + 12] for index in range(8)]))
            self._device1.set_enabled(True)
            self._device2.set_enabled(True)
            self._find_devices()
            self._device1.update()
            self._device2.update()
        """this section assigns the encoders and encoder buttons"""
        self._device.set_parameter_controls(
            tuple([self._encoder[index + 4] for index in range(8)])
        )  #assign the encoders from the device component controls - we are doing this here b
        #self._encoder_button[7].set_on_value(DEVICE_LOCK[self._rgb])					#set the on color for the Device lock encoder button
        #self._device.set_lock_button(self._encoder_button[7])							#assign encoder button 7 to the device lock control
        #self._encoder_button[4].set_on_value(DEVICE_ON[self._rgb])						#set the on color for the Device on/off encoder button
        #self._device.set_on_off_button(self._encoder_button[4])							#assing encoder button 4 to the device on/off control
        for index in range(
                2
        ):  #setup a recursion to generate indexes so that we can reference the correct controls to assing to the device_navigator functions
            self._encoder_button[index + 8].set_on_value(
                DEVICE_NAV[
                    self._rgb])  #assign the on color for the device navigator
            self._encoder_button[index + 10].set_on_value(
                DEVICE_BANK[self._rgb]
            )  #assign the on color for the device bank controls
        self._device_navigator.set_nav_buttons(
            self._encoder_button[10], self._encoder_button[11]
        )  #set the device navigators controls to encoder buttons 10 and 11
        self._device.set_bank_nav_buttons(
            self._encoder_button[8], self._encoder_button[9]
        )  #set the device components bank nav controls to encoder buttons 8 and 9
        """now we turn on and update some of the components we've just made assignments to"""
        self._device.set_enabled(True)  #enable the Device Component
        self._device_navigator.set_enabled(True)  #enable the Device Navigator
        self._alt_device_navigator.set_enabled(True)
        self._device.update(
        )  #tell the Device component to update its assingments so that it will detect the currently selected device parameters and display them on the encoder rings
Example #24
0
class OP1(ControlSurface):
	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		self.c_instance = c_instance

		self.retries_count = 0
		self.device_connected = False

		self.clip_color_callbacks = {}
		self.slot_callbacks = {}

		self.text_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x03)
		self.text_end_sequence = (0xf7,)
		self.enable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x02, 0xf7)
		self.disable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x00, 0xf7)

		self.id_sequence = (0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7)

		self.text_color_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x04)

		self.log('INITIALIZING')

		self.app = Live.Application.get_application()

		#maj = self.app.get_major_version()
		#min = self.app.get_minor_version()
		#bug = self.app.get_bugfix_version()
		#self.show_message(str(1) + "." + str(0) + "." + str(9))

		self.show_message("Version " + VERSION)

		# reseting text
		self.write_text(' ')

		# reset display clips
		self.reset_display_clips()

		# getting browser visible state
		self.session_browser_visible = self.app.view.is_view_visible("Browser")
		
		# getting browser visible state
		self.arrange_browser_visible = self.app.view.is_view_visible("Browser")

		# getting session view visible state
		self.session_visible = self.app.view.is_view_visible("Session")

		# getting arrange view visible state
		self.arrange_visible = self.app.view.is_view_visible("Arranger")

		# getting detail view visible state
		self.detail_visible = self.app.view.is_view_visible("Detail")

		# getting back to arranger state
		self.back_to_arranger_state = self.song().back_to_arranger

		# initializing channel strip to null
		self._channel_strip = None

		# initializing transport component
		self._transport = TransportComponent()

		# initializing mixer component
		self._mixer = MixerComponent(NUM_TRACKS,2)

		# initializing session component
		self._session = SessionComponent(NUM_TRACKS,NUM_ROWS)
		self._session.add_offset_listener(self.session_offset_changed)

		# configuring operation mode selector buttons
		self._operation_mode_buttons = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_1_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_2_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_3_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_4_BUTTON), 
		
		# initializing operation mode selector
		self._operation_mode_selector = OP1ModeSelectorComponent(self, self._transport, self._mixer, self._session)
		
		# setting operation mode selector buttons
		self._operation_mode_selector.set_mode_buttons(self._operation_mode_buttons)

		# adding value listener for operation mode index
		self._operation_mode_selector.add_mode_index_listener(self.mode_index_changed)

		# setting global transport assignments
		self._transport.set_record_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_REC_BUTTON))
		self._transport.set_play_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_PLAY_BUTTON))
		self._transport.set_stop_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_STOP_BUTTON))  
		self._transport.set_metronome_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_METRONOME_BUTTON))  
		self._transport.set_tap_tempo_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_HELP_BUTTON))
		self._transport.set_punch_buttons(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS1_BUTTON), ButtonElement(True,MIDI_CC_TYPE, CHANNEL, OP1_SS2_BUTTON))
		self._transport.set_loop_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS3_BUTTON))
		self._transport.set_overdub_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS4_BUTTON))

		# setting global session assignments
		self._session.set_scene_bank_buttons(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_COM),ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MICRO))

		# setting misc listeners
		self.browser_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 15)
		self.browser_toggle_button.add_value_listener(self.browser_toggle_button_callback)

		self.mainview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 16)
		self.mainview_toggle_button.add_value_listener(self.mainview_toggle_button_callback)

		self.detailview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 17)
		self.detailview_toggle_button.add_value_listener(self.detailview_toggle_button_callback)

		self.clear_track_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 25)
		self.clear_track_button.add_value_listener(self.clear_track_button_callback)

		self.back_to_arranger_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 26)
		self.back_to_arranger_button.add_value_listener(self.back_to_arranger_button_callback)

		# adding value listener for selected track change
		self.song().view.add_selected_track_listener(self.selected_track_changed)

		# adding value listener for selected scene change
		self.song().view.add_selected_scene_listener(self.selected_scene_changed)

		# setting assignments for currently selected track
		self.selected_track_changed()

		# setting assignments for currently selected scene
		self.selected_scene_changed()

	def handle_sysex(self, midi_bytes):
		if ((midi_bytes[6]==32) and (midi_bytes[7]==118)):
			self.device_connected = True
			self.log("OP-1 CONNECTED. SENDING ABLETON LIVE MODE INIT SEQUENCE")
			self._send_midi(self.enable_sequence)

	def add_clip_slot_listeners(self):
		#self.log('ADDING CLIP SLOT LISTENERS')
		
		# creating an empty list for all clip slots
		clip_slots = []

		# getting a reference to all tracks
		tracks = self.song().tracks
		
		# appending all tracks clip slots to clip_slots
		for track in tracks:
			clip_slots.append(track.clip_slots)

		# iterating over all clip slots
		for t in range(len(clip_slots)):
			for c in range(len(clip_slots[t])):
				clip_slot = clip_slots[t][c]

				# adding has clip listener to clip slot
				self.add_slot_listener(clip_slot)

				# if clip slot has clip
				if clip_slot.has_clip:
					# adding clip listeners
					self.add_clip_listener(clip_slot.clip)

	def rem_clip_slot_listeners(self):
		#self.log('REMOVING CLIP SLOT LISTENERS')

		# iterate over all clip color change callbacks
		for c in self.clip_color_callbacks:
			# if clip still exists
			if c != None:
				# and it has a has clip listener
				if c.color_has_listener(self.clip_color_callbacks[c]) == 1:
					# remove it
					c.remove_color_listener(self.clip_color_callbacks[c])

		# iterate over all clip slot callbacks
		for cs in self.slot_callbacks:
			# if clip slot still exists
			if cs != None:
				# and it has a has clip listener
				if cs.has_clip_has_listener(self.slot_callbacks[cs]) == 1:
					# remove it
					cs.remove_has_clip_listener(self.slot_callbacks[cs])

	def add_slot_listener(self, cs):
		# setting has clip listener
		callback = lambda :self.has_clip_listener(cs)

		# if we don't have a clip slot has clip listener for this clip slot yet
		if not(self.slot_callbacks.has_key(cs)):
			# adding has clip callback to clip slot
			cs.add_has_clip_listener(callback)

			# saving callback for future release
			self.slot_callbacks[cs] = callback

	def add_clip_listener(self, clip):
		# setting callback for clip color change
		color_callback = lambda :self.update_display_clips()

		# if we don't have a clip color change callback for this clip yet
		if not(self.clip_color_callbacks.has_key(clip)):
			# adding clip color change callback
			clip.add_color_listener(color_callback)

			# saving callback for future release
			self.clip_color_callbacks[clip] = color_callback

	def has_clip_listener(self, cs):
		# clip slot has clip listener callback
		if cs.has_clip:
			# add clip listener
			self.add_clip_listener(cs.clip)
		else:
			# update display if clip slot was removed
			self.update_display_clips()

	def session_offset_changed(self):
		# if session component offset changes, update display
		self.update_display_clips()

	def selected_scene_changed(self):
		# if on clip mode update display
		if (self._operation_mode_selector.mode_index==OP1_MODE_CLIP):
			self.update_display_clip_mode()

	def mode_index_changed(self):
		# update display to current mode info
		if (self._operation_mode_selector.mode_index==OP1_MODE_PERFORM):
			self.update_display_perform_mode()
		elif (self._operation_mode_selector.mode_index==OP1_MODE_CLIP):
			self.update_display_clip_mode()
		elif (self._operation_mode_selector.mode_index==OP1_MODE_TRANSPORT):
			self.update_display_transport_mode()
		elif (self._operation_mode_selector.mode_index==OP1_MODE_MIXER):
			self.update_display_mixer_mode()

	def	clear_track_button_callback(self, value):
		# if clear track button was called, reset track
		if (value==127):
			for i in range(len(self.song().tracks)):
				self.song().tracks[i].arm = 0
				self.song().tracks[i].solo = 0
				self.song().tracks[i].mute = 0

			for i in range(len(self.song().return_tracks)):
				self.song().tracks[i].solo = 0
				self.song().tracks[i].mute = 0

	def clear_return_track_assignment(self, strip):
		# clear return track assingments
		strip.set_volume_control(None)
		strip.set_pan_control(None)
		strip.set_mute_button(None)
		strip.set_solo_button(None)
	
	def clear_track_assignment(self, strip):
		# clear track assignments
		strip.set_volume_control(None)
		strip.set_pan_control(None)
		strip.set_mute_button(None)
		strip.set_solo_button(None)
		strip.set_arm_button(None)

	def clear_tracks_assigments(self):
		# for all normal tracks, clear assignments
		for i in range(NUM_TRACKS):
			strip = self._mixer.channel_strip(i)
			if (strip!=None):
				self.clear_track_assignment(strip)

		# for all return tracks, clear assignments
		for i in range(2):
			return_strip = self._mixer.return_strip(i)
			if (return_strip!=None):
				self.clear_return_track_assignment(return_strip)

	def selected_track_changed(self):
		# if on mixer mode update display
		if (self._operation_mode_selector.mode_index==OP1_MODE_MIXER):
			self.update_display_mixer_mode()

		# clear track assignments
		self.clear_tracks_assigments()

		# getting selected strip
		self._channel_strip = self._mixer.selected_strip()

		# perform track assignments 
		self._channel_strip.set_volume_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_1, Live.MidiMap.MapMode.relative_two_compliment))
		self._channel_strip.set_pan_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_2, Live.MidiMap.MapMode.relative_two_compliment))

		# setting a tuple of encoders to control sends
		send_controls = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_3, Live.MidiMap.MapMode.relative_two_compliment), EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_4, Live.MidiMap.MapMode.relative_two_compliment),

		# setting send encoders
		self._channel_strip.set_send_controls(tuple(send_controls))

		# setting solo button
		self._channel_strip.set_solo_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS6_BUTTON))

		# if track can be armed, set arm button
		if (self._channel_strip._track.can_be_armed):
			self._channel_strip.set_arm_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS7_BUTTON))

		# if track is no master, set mute button
		if (self._channel_strip._track!=self.song().master_track):
			self._channel_strip.set_mute_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS5_BUTTON))


	def browser_toggle_button_callback(self, value):
		if (value==127):
			if (self.session_visible):
				if (self.session_browser_visible==True):
					self.session_browser_visible=False
					self.app.view.hide_view("Browser")
				else:
					self.session_browser_visible=True
					self.app.view.show_view("Browser")

			if (self.arrange_visible):
				if (self.arrange_browser_visible==True):
					self.arrange_browser_visible=False
					self.app.view.hide_view("Browser")
				else:
					self.arrange_browser_visible=True
					self.app.view.show_view("Browser")

	def back_to_arranger_button_callback(self, value):
		if (value==127):
			self.song().back_to_arranger = False

	def mainview_toggle_button_callback(self, value):
		if (value==127):
			if (self.session_visible==True):
				self.session_visible=False
				self.arrange_visible=True
				self.app.view.show_view("Arranger")
				self.arrange_browser_visible = self.app.view.is_view_visible("Browser");
			else:
				self.session_visible=True
				self.arrange_visible=False
				self.app.view.show_view("Session")
				self.session_browser_visible = self.app.view.is_view_visible("Browser");

	def detailview_toggle_button_callback(self, value):
		if (value==127):
			if (self.detail_visible==True):
				self.detail_visible=False
				self.app.view.hide_view("Detail")
			else:
				self.detail_visible=True
				self.app.view.show_view("Detail")

	def write_text(self, msg):
		text_list = []
		sequence = ()
		
		text_list.append(len(msg.strip()))
		
		for i in msg.strip():
   			text_list.append(ord(i))
   		
   		sequence = self.text_start_sequence + tuple(text_list) + self.text_end_sequence
		
		self._send_midi(sequence)

	def suggest_input_port(self):
		return "OP-1 Midi Device"

	def suggest_output_port(self):
		return "OP-1 Midi Device"

	def update_display_perform_mode(self):
		self.write_text("perform\rmode")

	def reset_display_clips(self):
		count = 0
		colors = []
		length = []
		sequence = ()
		
		for i in range (NUM_TRACKS):
			count+=1

			colors.append(0x00)
			colors.append(0x00)
			colors.append(0x00)

		length.append(count)
		sequence = self.text_color_start_sequence + tuple(length) + tuple(colors) + self.text_end_sequence
		self._send_midi(sequence)

	def update_display_clips(self):
		#self.log("UPDATING DISPLAY CLIPS")
		count = 0
		colors = []
		length = []
		sequence = ()
		
		tracks_len = len(self.song().tracks)-self._session._track_offset

		if (tracks_len>NUM_TRACKS):
			tracks_len = NUM_TRACKS

		for i in range (tracks_len):
			count+=1

			clip_slot = self._session.scene(0).clip_slot(i)
			
			if (clip_slot!=None):
				if (clip_slot.has_clip()!=False):
					clip_color = clip_slot._clip_slot.clip.color
					colors.append(((clip_color>>16)&0x000000ff)>>1)
					colors.append(((clip_color>>8)&0x000000ff)>>1)
					colors.append((clip_color&0x000000ff)>>1)
				else:
					colors.append(0x00)
					colors.append(0x00)
					colors.append(0x00)
			else:
				colors.append(0x00)
				colors.append(0x00)
				colors.append(0x00)

		length.append(count)
		sequence = self.text_color_start_sequence + tuple(length) + tuple(colors) + self.text_end_sequence
		self._send_midi(sequence)

	def update_display_clip_mode(self):
		self.write_text("sel. scene\r" + str(self.song().view.selected_scene.name.lower().strip()))

	def update_display_transport_mode(self):
		song_time = str(self.song().get_current_beats_song_time())
		self.write_text("song pos.\r" + song_time[:len(song_time)-4])

	def update_display_mixer_mode(self):
		self.write_text("sel. track\r" + str(self.song().view.selected_track.name.lower()))

	def update_display(self):
		if not(self.device_connected):
			if (self.retries_count<5):
				self.log("TRYING OP-1 CONNECTION")
				self.retries_count+=1
				self._send_midi(self.id_sequence)
				time.sleep(1)

		# if in transport mode, update display with song position
		if (self._operation_mode_selector.mode_index==OP1_MODE_TRANSPORT):
			self.update_display_transport_mode()

		# checking if app current view is session
		if (self.app.view.is_view_visible("Session")):
			# checking if session browser state is diferent from the internal
			if (self.session_browser_visible != self.app.view.is_view_visible("Browser")):
				self.session_browser_visible = self.app.view.is_view_visible("Browser")

		# checking if app current view is arrange
		if (self.app.view.is_view_visible("Arranger")):
			# checking if arrange browser state is diferent from the internal
			if (self.arrange_browser_visible != self.app.view.is_view_visible("Browser")):
				self.arrange_browser_visible = self.app.view.is_view_visible("Browser")

		# checking if app current view is detail
		if (self.app.view.is_view_visible("Detail")):
			# checking if detail state is diferent from the internal
			if (self.detail_visible != self.app.view.is_view_visible("Detail")):
				self.detail_visible = self.app.view.is_view_visible("Detail")

	def refresh_state(self):
		self.log("REFRESH STATE")
		self.retries_count = 0
		self.device_connected = False

	def build_midi_map(self, midi_map_handle):
		#self.log("BUILD MIDI MAP")

		assert (self._suppress_requests_counter == 0)
		self._in_build_midi_map = True
		self._midi_map_handle = midi_map_handle
		self._forwarding_registry = {}
		for control in self.controls:
			if isinstance(control, InputControlElement):
				control.install_connections()
		self._midi_map_handle = None
		self._in_build_midi_map = False
		if (self._pad_translations != None):
			self._c_instance.set_pad_translation(self._pad_translations)

		# remove clip listeners
		self.rem_clip_slot_listeners()
		
		# add clip listeners
		self.add_clip_slot_listeners()
		
		# update display
		self.update_display_clips()
		
	def log(self, msg):
		self.c_instance.log_message("[TE OP-1] " + msg)

	def disconnect(self):
		# removing clip slots listeners
		self.rem_clip_slot_listeners()

		# removing value listener for track changed
		self.song().view.remove_selected_track_listener(self.selected_track_changed)

		# removing value listener for scene changed
		self.song().view.remove_selected_scene_listener(self.selected_scene_changed)

		# removing value listener for operation mode index
		self._operation_mode_selector.remove_mode_index_listener(self.mode_index_changed)

		# removing global transport assignments
		self._transport.set_punch_buttons(None, None)
		self._transport.set_loop_button(None)
		self._transport.set_overdub_button(None)
		self._transport.set_record_button(None)
		self._transport.set_play_button(None)
		self._transport.set_stop_button(None)  
		self._transport.set_metronome_button(None)  
		self._transport.set_tap_tempo_button(None)

		# removing global session assignments
		self._session.set_scene_bank_buttons(None, None)
		
		# removing misc listeners
		self.browser_toggle_button.remove_value_listener(self.browser_toggle_button_callback)
		self.mainview_toggle_button.remove_value_listener(self.mainview_toggle_button_callback)
		self.detailview_toggle_button.remove_value_listener(self.detailview_toggle_button_callback)
		self.clear_track_button.remove_value_listener(self.clear_track_button_callback)
		self.back_to_arranger_button.remove_value_listener(self.back_to_arranger_button_callback)
		
		# sending special ableton mode disable sequence
		self._send_midi(self.disable_sequence)
		
		# disconnecting control surface
		ControlSurface.disconnect(self)
		
		self.log("DISCONNECTED")
Example #25
0
class CNTRL_R_LITE(ControlSurface):
	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		is_momentary = True
		self._timer = 0 # Used in FlashingButtonElement (kludge for our purposes)
		self.flash_status = 1 # Used in FlashingButtonElement (kludge for our purposes)		
		
		if USE_MIXER_CONTROLS == True:
			self.mixer_control()
		
		if USE_SESSION_VIEW == True:
			self.session_control()		
  
	def mixer_control(self):
		is_momentary = True
		self.num_tracks = N_TRACKS
		if(USE_SENDS == True):
			self.mixer = MixerComponent(N_TRACKS, N_SENDS_PER_TRACK, USE_MIXER_EQ, USE_MIXER_FILTERS)
		else:
			self.mixer = MixerComponent(N_TRACKS,0, USE_MIXER_EQ, USE_MIXER_FILTERS)
		self.mixer.name = 'Mixer'
		self.mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
		for index in range(N_TRACKS):
			self.mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index)
			self.mixer.channel_strip(index)._invert_mute_feedback = True 
		self.song().view.selected_track = self.mixer.channel_strip(0)._track
	
		self.log_message(str(len(SOLO_BUTTONS)))
		self.log_message(str(len(MUTE_BUTTONS)))
	
		if(USE_SOLO_BUTTONS == True):
			self.solobuttons = [None for index in range(N_TRACKS)]
			for index in range(len(SOLO_BUTTONS)):
				self.solobuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,SOLO_BUTTONS[index], 'Solo_Button', self)
				self.mixer.channel_strip(index).set_solo_button(self.solobuttons[index])
				self.solobuttons[index].set_on_value(SOLO_BUTTON_ON_COLOR)
				self.solobuttons[index].set_off_value(SOLO_BUTTON_OFF_COLOR)

		if(USE_MUTE_BUTTONS == True):
			self.mutebuttons = [None for index in range(N_TRACKS)]
			for index in range(len(MUTE_BUTTONS)):
				self.mutebuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,MUTE_BUTTONS[index], 'Mute_Button', self)
				self.mixer.channel_strip(index).set_mute_button(self.mutebuttons[index])
				self.mutebuttons[index].set_on_value(MUTE_BUTTON_ON_COLOR)
				self.mutebuttons[index].set_off_value(MUTE_BUTTON_OFF_COLOR)
				
		if(USE_SENDS == True):
			self.sendencoders = [None for index in range(len(SEND_ENCODERS))]
			for index in range(len(SEND_ENCODERS)):
				self.sendencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, SEND_ENCODERS[index], Live.MidiMap.MapMode.absolute)
			for index in range(len(SEND_ENCODERS)/N_SENDS_PER_TRACK):
				self.mixer.channel_strip(index).set_send_controls(tuple(self.sendencoders[(index*N_SENDS_PER_TRACK):((index*N_SENDS_PER_TRACK)+N_SENDS_PER_TRACK-1)]))
				
		if(USE_VOLUME_CONTROLS == True):
			self.volencoders = [None for index in range(len(VOLUME_ENCODERS))]
			for index in range (len(VOLUME_ENCODERS)):
				self.volencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, VOLUME_ENCODERS[index], Live.MidiMap.MapMode.absolute)
				self.mixer.channel_strip(index).set_volume_control(self.volencoders[index])
	  
	def session_control(self):
		is_momentary = True
		self._timer = 0
		self.flash_status = 1
		self.grid = [None for index in range(N_TRACKS*N_SCENES)]
		for index in range(N_TRACKS*N_SCENES):
			self.grid[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,TRACK_CLIP_BUTTONS[index], 'Grid' + str(index), self)
		self.matrix = ButtonMatrixElement()
		for row in range(N_SCENES):
			button_row = []
			for column in range(N_TRACKS):
				button_row.append(self.grid[row+(column*4)])
			self.matrix.add_row(tuple(button_row))
		self.session = SessionComponent(N_TRACKS,N_SCENES)
		self.session.name = "Session"
		self.session.set_offsets(0,0)
		self.scene = [None for index in range(N_SCENES)]
		for row in range(N_SCENES):
			self.scene[row] = self.session.scene(row)
			self.scene[row].name = 'Scene_'+str(row)
			for column in range(N_TRACKS):
				clip_slot = self.scene[row].clip_slot(column)
				clip_slot.name = str(column)+'_Clip_Slot'+str(row)
				self.scene[row].clip_slot(column).set_triggered_to_play_value(CLIP_TRG_PLAY_COLOR)
				self.scene[row].clip_slot(column).set_stopped_value(CLIP_STOP_COLOR)
				self.scene[row].clip_slot(column).set_started_value(CLIP_STARTED_COLOR)
	
    # Clip trigger on grid assignments
		for column in range(N_TRACKS):
			for row in range(N_SCENES):
				self.scene[row].clip_slot(column).set_launch_button(self.grid[row+(column*4)])	
	
		for index in range(N_TRACKS*N_SCENES):
			self.grid[index].clear_send_cache()	  
				
		if USE_SESSION_NAV == True:
			self.navleft = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,NAVBOX_LEFT_BUTTON, 'Nav_Left_Button', self)
			self.navleft.clear_send_cache()
			self.navleft.set_on_off_values(NAVBOX_LEFT_BUTTON_C, NAVBOX_LEFT_BUTTON_C)
			
			self.navright = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,NAVBOX_RIGHT_BUTTON, 'Nav_Right_Button', self)
			self.navright.clear_send_cache()
			self.navright.set_on_off_values(NAVBOX_RIGHT_BUTTON_C, NAVBOX_RIGHT_BUTTON_C)
			
			self.navup = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,NAVBOX_UP_BUTTON, 'Nav_Up_Button', self)
			self.navup.clear_send_cache()
			self.navup.set_on_off_values(NAVBOX_UP_BUTTON_C, NAVBOX_UP_BUTTON_C)
				 
			self.navdown = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,NAVBOX_DOWN_BUTTON, 'Nav_Down_Button', self)
			self.navdown.clear_send_cache()
			self.navdown.set_on_off_values(NAVBOX_DOWN_BUTTON_C, NAVBOX_DOWN_BUTTON_C) 
			
			self.session.set_track_bank_buttons(self.navright, self.navleft)
			self.session.set_scene_bank_buttons(self.navdown, self.navup)
		
		if USE_MIXER_CONTROLS == True:
			self.session.set_mixer(self.mixer)	

		self.refresh_state()
		self.session.set_enabled(True)
		self.session.update()		
			
	def update_display(self):
		ControlSurface.update_display(self)
		self._timer = (self._timer + 1) % 256
		self.flash()
		
	def flash(self):
		if(USE_SESSION_VIEW == True):
			for index in range(N_TRACKS*N_SCENES):
				if(self.grid[index]._flash_state > 0):
					self.grid[index].flash(self._timer)	
		if(USE_SESSION_NAV == True):
			if(self.navleft._flash_state>0):
					self.navleft.flash(self._timer)
			if(self.navright._flash_state>0):
					self.navright.flash(self._timer)
			if(self.navup._flash_state>0):
					self.navup.flash(self._timer)
			if(self.navdown._flash_state>0):
					self.navdown.flash(self._timer)	
		if(USE_MIXER_CONTROLS == True):
			for index in range(N_TRACKS):
				if(USE_SOLO_BUTTONS == True):
					if(self.solobuttons[index]._flash_state > 0):
						self.solobuttons[index].flash(self._timer)				
				if(USE_MUTE_BUTTONS == True):
					if(self.mutebuttons[index]._flash_state > 0):
						self.mutebuttons[index].flash(self._timer)
				

	def disconnect(self):
		self._hosts = []
		self.log_message("--------------= CNTRLR log closed =--------------")
		ControlSurface.disconnect(self)
		return None		
Example #26
0
class Tweaker(ControlSurface):
	__module__ = __name__
	__doc__ = " Tweaker control surface script "


	def __init__(self, c_instance, *a, **k):
		super(Tweaker, self).__init__(c_instance, *a, **k)
		with self.component_guard():
			self._update_linked_device_selection = None
			self._tweaker_version_check = '0.3'
			self.log_message("--------------= Tweaker Session " + str(self._tweaker_version_check) + " log opened =--------------") 
			self._timer = 0
			self.flash_status = 1
			self._last_selected_strip_number = 0
			self._device_selection_follows_track_selection = False
			#self._pad_translations = PAD_TRANSLATION
			self._linked_session = None
			self._mixer_offset = 0
			self._nav_lock = True
			self._setup_controls()
			self._setup_transport_control() 
			self._setup_device_control()
			self._setup_mixer_control()
			self._setup_session_control()
			self._setup_crossfader()
			self._setup_modes() 
			self._setup_pads()
			self._setup_navigation_lock()
			self._setup_arrange_session_toggle()
			#self.assign_main_configuration()
			#self.request_rebuild_midi_map()
			#self._mixer._reassign_tracks()	#this is to update rebuild the cf_assign closure, otherwise the colors aren't correct
			#self.schedule_message(30, self._detect_devices)

			self.show_message('Tweaker Control Surface Loaded')
		self.show_message('Tweaker Control Surface Loaded')
		#self._shift_value(0)  #this updates the pads so that they transmit to Live on the assigned PAD_CHANNEL...also, lights shift button
		self.assign_main_configuration()
		#self.schedule_message(2, self._shift_value, 0)
		self.schedule_message(3, self._mixer._reassign_tracks)
	

	"""script initialization methods"""
	def _setup_controls(self):
		is_momentary = True
		self._grid = [None for index in range(8)]
		for column in range(8):
			self._grid[column] = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, column + (row * 8) + 1, 'Grid_' + str(column) + '_' + str(row), self) for row in range(4)]
		self._button = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_BUTTONS[index], 'Button_' + str(index), self) for index in range(len(TWEAKER_BUTTONS))]
		self._nav = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_NAVS[index], 'Nav_' + str(index), self) for index in range(len(TWEAKER_NAVS))]
		self._encoder_button = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_ENCODER_BUTTONS[index], 'Encoder_Button_' + str(index), self) for index in range(len(TWEAKER_ENCODER_BUTTONS))]
		self._dial = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_DIALS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_DIALS))]
		self._fader = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_FADERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_FADERS))]
		self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute)
		self._encoder = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_ENCODERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_ENCODERS))]
		self._pad = [TweakerMonoButtonElement(False, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_PADS[index], 'Pad_' + str(index), self) for index in range(len(TWEAKER_PADS))]
		for index in range(4):
			self._pad[index].set_enabled(False)
			self._pad[index].set_channel(PAD_CHANNEL)
			self._pad[index].set_identifier(index + 4)
			self._pad[index+4].set_enabled(False)
			self._pad[index+4].set_channel(PAD_CHANNEL)
			self._pad[index+4].set_identifier(index)
		self._pad_pressure = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_PAD_PRESSURES[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_PADS))]
		for index in range(8):
			self._pad_pressure[index]._last_sent = 0
		self._matrix = ButtonMatrixElement()
		self._matrix.name = 'Matrix'
		for row in range(4):
			button_row = []
			for column in range(7):
				button_row.append(self._grid[column][row])
			self._matrix.add_row(tuple(button_row)) 	
		self._send_midi(tuple([240,0,1,106,01,07,21,21,247])) #set all pots to walk mode
		self._send_midi(tuple([240, 0, 1, 106, 1, 6, 127 , 127, 25, 0, 15, 0, 9, PAD_SENSITIVITY, 247]))	#set pads to sensitivity set in Map file
	

	def _setup_transport_control(self):
		self._transport = TransportComponent() 
		self._transport.name = 'Transport'
	

	def _setup_mixer_control(self):
		is_momentary = True
		self._num_tracks = (2) #A mixer is one-dimensional; 
		self._mixer = MixerComponent(2, 0, False, False)
		self._mixer.name = 'Mixer'
		self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer)
		self._device_navigator = [None for index in range(2)]
		self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
		for index in range(2):
			self._mixer.channel_strip(index).set_volume_control(self._fader[index])
			self._mixer.channel_strip(index)._on_cf_assign_changed = self._channelstrip_on_cf_assign_changed(self._mixer.channel_strip(index))
			self._mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index)
			#mixer.track_filter(index).name = 'Mixer_TrackFilter_' + str(index)
			self._mixer.channel_strip(index)._invert_mute_feedback = True
			self._mixer.channel_strip(index)._device_component = self._device[index]
			self._mixer.channel_strip(index).update = self._channelstrip_update(self._mixer.channel_strip(index))
			self._mixer.channel_strip(index)._select_value = self._channelstrip_select_value(self._mixer.channel_strip(index), index)
			self._device_navigator[index] = DetailViewControllerComponent(self, self._mixer.channel_strip(index))
			self._device_navigator[index].name = 'Device_Navigator_'+str(index)
		self._mixer.channel_strip(0).set_track = self._channelstrip_set_track(self._mixer.channel_strip(0), self._channelstrip1_cb)
		self._mixer.channel_strip(1).set_track = self._channelstrip_set_track(self._mixer.channel_strip(1), self._channelstrip2_cb)
		self.song().view.selected_track = self._mixer.channel_strip(0)._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error
		#self._mixer._reassign_tracks()
	

	def _setup_session_control(self):
		is_momentary = True
		num_tracks = NUM_TRACKS
		num_scenes = NUM_SCENES
		self._session = SessionComponent(num_tracks, num_scenes)
		self._session.name = "Session"
		self._session.set_offsets(0, 0)	 
		self._session.set_stop_track_clip_value(STOP_CLIP)
		self._scene = [None for index in range(3)]
		for row in range(num_scenes):
			self._scene[row] = self._session.scene(row)
			self._scene[row].name = 'Scene_' + str(row)
			for column in range(num_tracks):
				clip_slot = self._scene[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_' + str(row)
				clip_slot.set_triggered_to_play_value(CLIP_TRG_PLAY)
				clip_slot.set_triggered_to_record_value(CLIP_TRG_REC)
				clip_slot.set_stopped_value(CLIP_STOP)
				clip_slot.set_started_value(CLIP_STARTED)
				clip_slot.set_recording_value(CLIP_RECORDING)
		self._session._stop_track_value = self._session_stop_track_value(self._session)
		self._session._on_fired_slot_index_changed = self._session_on_fired_slot_index_changed(self._session)
		self._session._change_offsets = self._session_change_offsets(self._session)
		self._session.update = self._session_update(self._session)
		#self._session.add_offset_listener(self._update_navigation_view)
		self._session.set_mixer(self._mixer)
		self.set_highlighting_session_component(self._session)
		self._session_zoom = SessionZoomingComponent(self._session)	 
		self._session_zoom.name = 'Session_Overview'
		self._session_zoom.set_stopped_value(ZOOM_STOPPED)
		self._session_zoom.set_playing_value(ZOOM_PLAYING)
		self._session_zoom.set_selected_value(ZOOM_SELECTED)
		#self._session_zoom.set_enabled(True)
	

	def _setup_device_control(self):
		self._device = [None for index in range(2)]
		for index in range(2):
			self._device[index] = DeviceComponent()
			self._device[index].name = 'Device_Component_'+str(index)
			self._device[index].set_enabled(True)
			self._device[index]._number_of_parameter_banks = self._device_number_of_parameter_banks(self._device[index])
			self._device[index]._assign_parameters = self._device_assign_parameters(self._device[index])
			self._device[index]._device_banks = DEVICE_DICT
			self._device[index]._device_best_banks = DEVICE_BOB_DICT
			self._device[index]._device_bank_names = BANK_NAME_DICT
	

	def _setup_crossfader(self):
		self._mixer.set_crossfader_control(self._crossfader)
	

	def _setup_modes(self):
		self._pad_offset = PadOffsetComponent(self)
		self._pad_offset._set_protected_mode_index(0)
		self._pad_offset.set_enabled(False)
	

	def _setup_pads(self):
		for pad in self._pad_pressure:
			pad.add_value_listener(self._light_pad, True)
	

	def _setup_navigation_lock(self):
		if(self._encoder_button[0].value_has_listener(self._nav_lock_value)):
			self._encoder_button[0].remove_value_listener(self._nav_lock_value)
		self._encoder_button[0].add_value_listener(self._nav_lock_value)
	

	def _setup_arrange_session_toggle(self):
		if(self._nav[1].value_has_listener(self._arrange_session_value)):
			self._nav[1].remove_value_listener(self._arrange_session_value)
		self._nav[1].add_value_listener(self._arrange_session_value)
	

	"""configuration methods"""
	def assign_main_configuration(self):
		for column in range(7):
			for row in range(3):
				self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])
		self._session.set_stop_track_clip_buttons(tuple([self._grid[index][3] for index in range(7)]))
		for row in range(3):
			self._scene[row].set_launch_button(self._grid[7][row])
		self._device[0].set_parameter_controls(tuple([self._encoder[index+1] for index in range(3)]))
		self._device[0].set_enabled(True)
		self._device[1].set_parameter_controls(tuple([self._encoder[index+4] for index in range(3)]))
		self._device[1].set_enabled(True)
		for track in range(2):
			self._mixer.channel_strip(track).set_volume_control(self._fader[track])
			self._mixer.channel_strip(track).set_solo_button(self._button[track*3])
			self._button[track*3].set_on_off_values(SOLO, 0)
			self._mixer.channel_strip(track).set_arm_button(self._button[1 + (track*3)])
			self._button[1 + (track*3)].set_on_off_values(ARM, 0)
			self._mixer.channel_strip(track).set_crossfade_toggle(self._button[2 + (track*3)])
		self._mixer.master_strip().set_volume_control(self._dial[1])
		self._mixer.set_prehear_volume_control(self._dial[0])
		self._session.set_track_bank_buttons(self._nav[4], self._nav[3])
		self._session.set_scene_bank_buttons(self._nav[2], self._nav[0])
		self._session_zoom.set_zoom_button(self._grid[7][3])
		self._session_zoom.set_nav_buttons(self._nav[0], self._nav[2], self._nav[3], self._nav[4])
		self._session_zoom.set_button_matrix(self._matrix)
		self._device[0].set_on_off_button(self._encoder_button[1])
		self._device_navigator[0].set_device_nav_buttons(self._encoder_button[2], self._encoder_button[3]) 
		self._device[1].set_on_off_button(self._encoder_button[4])
		self._device_navigator[1].set_device_nav_buttons(self._encoder_button[5], self._encoder_button[6]) 
		for track in range(2):
			self._update_device(self._mixer.channel_strip(track))
		#self._device.set_bank_nav_buttons(self._menu[0], self._menu[3])
		self.assign_track_selector(self._encoder[0])
		#for index in range(8):
		#	self._pad[index].send_value(1, True)
		#	self._pad[index].set_channel(1)
		#	self._pad[index].set_identifier(index)
		#	self._pad[index].set_enabled(False)	 #this has to happen for translate to work
		if not self._grid[7][3].value_has_listener(self._shift_value):
			self._grid[7][3].add_value_listener(self._shift_value)
		self._grid[7][3].send_value(127, True)
		self.request_rebuild_midi_map()	
	

	"""Tweaker custom methods"""
	def _shift_value(self, value):
		self._pad_offset.set_enabled(value>0)
		if value > 0:
			self._update_navigation_view()
			for pad in self._pad:
				pad.use_default_message()
				pad.set_enabled(True)
			self._pad_offset.set_mode_buttons(tuple(self._pad))
			self.schedule_message(1, self._pad_offset.update)
			if self._session.is_enabled():
				#self._update_navigation_view()
				#self.schedule_message(1, self._update_navigation_veiw)
				self._update_navigation_view()
			self._grid[7][3].send_value(SHIFT_ON)
			for track in range(2):
				self._mixer.channel_strip(track).set_crossfade_toggle(None)
				self._mixer.channel_strip(track).set_select_button(self._button[2 + (track*3)])
		else:
			self._pad_offset.set_mode_buttons(None)
			for index in range(4):
				self._pad[index].set_enabled(False)
				self._pad[index].set_channel(PAD_CHANNEL)
				self._pad[index].set_identifier(index + 4 + (self._pad_offset._mode_index * 8))
				self._pad[index+4].set_enabled(False)
				self._pad[index+4].set_channel(PAD_CHANNEL)
				self._pad[index+4].set_identifier(index + (self._pad_offset._mode_index * 8))
			self._grid[7][3].send_value(SHIFT_OFF)
			for track in range(2):
				self._mixer.channel_strip(track).set_select_button(None)
				self._mixer.channel_strip(track).set_crossfade_toggle(self._button[2 + (track*3)])
	

	def assign_track_selector(self, encoder):
		assert isinstance(encoder, EncoderElement)
		if not encoder.value_has_listener(self._track_selector_value):
			encoder.add_value_listener(self._track_selector_value)
	

	def deassign_track_selector(self, encoder):
		if encoder.value_has_listener(self._track_selector_value):
			encoder.remove_value_listener(self._track_selector_value)
	

	def _nav_lock_value(self, value):
		if value > 0:
			if self._nav_lock:
				self._mixer_offset = self._mixer_offset + self._session._track_offset
				self._mixer.set_track_offset(self._mixer_offset)
			else:
				if self._mixer_offset in range(self._session._track_offset, self._session._track_offset + 5):
					self._mixer_offset = self._mixer_offset - self._session._track_offset
				elif self._mixer_offset < self._session._track_offset:
					self._mixer_offset = 0
				else:
					self._mixer_offset = min(self._session._track_offset+5, len(self._session.tracks_to_use())-2)
				self._mixer.set_track_offset(self._session._track_offset + self._mixer_offset)
			self._nav_lock = not self._nav_lock
			self._session.update()
	

	def _arrange_session_value(self, value):
		if value > 0:
			if (self.application().view.is_view_visible('Arranger')):
				self.application().view.show_view('Session') 
			else:
				self.application().view.show_view('Arranger')	  
	

	def _track_selector_value(self, value):
		if(value is 1):
			if self._nav_lock:
				self._mixer_offset = min(self._mixer_offset + 1, min(NUM_TRACKS - 2, len(self._session.tracks_to_use())-self._session._track_offset-2))
			else:
				self._mixer_offset = min(self._mixer_offset + 1, len(self._session.tracks_to_use())-2)
		elif(value is 127):
				self._mixer_offset = max(self._mixer_offset - 1, 0)
		if self._nav_lock:
			self._mixer.set_track_offset(self._session._track_offset + self._mixer_offset)
			#self._session.set_offsets(self._session._track_offset)  ??
		else:
			self._mixer.set_track_offset(self._mixer_offset)
		self._session.update()
		if self._mixer.channel_strip(self._last_selected_strip_number)._track != None:
			self.song().view.selected_track = self._mixer.channel_strip(self._last_selected_strip_number)._track
		if self._linked_session != None:
			if self._linked_session._is_linked():
				self._linked_session._unlink()
			self._linked_session.set_offsets(self._mixer._track_offset, self._linked_session._scene_offset)
			self._linked_session._link()
	

	def _update_navigation_view(self):
		dif = self._mixer._track_offset - self._session._track_offset
		for index in range(7):
			#if (index + self._session._track_offset) in range(len(self._session.tracks_to_use())):
			if (index + self._session._track_offset) in range(0, len(self.song().visible_tracks)):
				self._grid[index][3].send_value(NAV_COLORS[int(index in range(dif, dif + 2))], True)
			elif (index + self._session._track_offset) in range(len(self.song().visible_tracks), len(self._session.tracks_to_use())):
				self._grid[index][3].send_value(RETURN_NAV_COLORS[int(index in range(dif, dif + 2))], True)
			else:
				self._grid[index][3].send_value(0, True)
		self._send_midi(tuple([240,0,1,106,01,07,21,21,247])) #set all pots to walk mode
		
	

	def _update_device(self, channelstrip):
		for control in channelstrip._device_component._parameter_controls:
			control.send_value(0, True)
		if channelstrip._device_component._on_off_button != None:
			channelstrip._device_component._on_off_button.turn_off()
		if not channelstrip._track is None:
			if not channelstrip._device_component._device in channelstrip._track.devices:
				track = channelstrip._track
				device_to_select = track.view.selected_device
				if (device_to_select == None) and (len(track.devices) > 0):
					device_to_select = track.devices[0]
				elif channelstrip._device_component and not type(channelstrip._device_component) is type(None):
					channelstrip._device_component.set_device(device_to_select)
				else:
					channelstrip._device_component.set_device(None)	
			else:
				pass
		else:
			channelstrip._device_component.set_device(None)	
		channelstrip._device_component._on_on_off_changed()	
	

	def _light_pad(self, value, sender):
		if not self._pad_offset.is_enabled():
			if value > sender._last_sent:
				if self._pad[self._pad_pressure.index(sender)]._last_sent_value < 1:
					self._pad[self._pad_pressure.index(sender)].send_value(127, True)
			else:
				self._pad[self._pad_pressure.index(sender)].send_value(0, True)
		sender._last_sent = value
	

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

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

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

		ret += ' '
		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._shift_mode._mode_index < 2):
			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._shift_mode._mode_index < 2):
			if self._touched > 5:
				self._touched = 5
			elif self._touched > 0:
				self._touched -= 1
			if self._touched is 0:
				self._monobridge._send('touch', 'off')
			else:
				self.schedule_message(2, self.check_touch)
	

	def	handle_sysex(self, midi_bytes):
		pass
	

	"""general functionality"""
	def disconnect(self):
		"""clean things up on disconnect"""
		#self._update_linked_device_selection = None
		if self._session.offset_has_listener(self._update_navigation_view):
			self._session.remove_offset_listener(self._update_navigation_view)
		if(self._nav[1].value_has_listener(self._arrange_session_value)):
			self._nav[1].remove_value_listener(self._arrange_session_value)
		if(self._encoder_button[0].value_has_listener(self._nav_lock_value)):
			self._encoder_button[0].remove_value_listener(self._nav_lock_value)
		for pad in self._pad_pressure:
			if pad.value_has_listener(self._light_pad):
				pad.remove_value_listener(self._light_pad)
		if self._grid[7][3].value_has_listener(self._shift_value):
			self._grid[7][3].remove_value_listener(self._shift_value)
		if self._session._is_linked():
			self._session._unlink()
		self.deassign_track_selector(self._encoder[0])
		self.log_message("--------------= Tweaker Session " + str(self._tweaker_version_check) + " log closed =--------------") #Create entry in log file
		super(Tweaker, self).disconnect()
		return None
	

	def _get_num_tracks(self):
		return self.num_tracks
	

 	def _on_selected_track_changed(self):
		super(Tweaker, self)._on_selected_track_changed()
		if self._session.is_enabled():
			self._session.update()
		for index in range(2):
			self._update_device(self._mixer.channel_strip(index))
			self._mixer.on_selected_track_changed()
	

	def connect_script_instances(self, instanciated_scripts):
		link = False
		for s in instanciated_scripts:
			if '_tweaker_version' in dir(s):
				if s._tweaker_version == self._tweaker_version_check:
					link = True
					break
		if link == True:
			if not self._session._is_linked():
				self._session._link()
	

	"""SessionComponent overrides"""
	def _session_update(self, session):
		def _update():
			SessionComponent.update(session)
			if session.is_enabled():
				self._update_navigation_view()
		return _update
		
	

	def _session_change_offsets(self, session): 
		def _change_offsets(track_increment, scene_increment):
			offsets_changed = (track_increment != 0) or (scene_increment != 0)
			if offsets_changed:
				session._track_offset += track_increment
				session._scene_offset += scene_increment
				assert (session._track_offset >= 0)
				assert (session._scene_offset >= 0)
				if (session._mixer != None):
					if(self._nav_lock):
						if (session.track_offset() + self._mixer_offset) > (len(session.tracks_to_use())-2):
							self._mixer_offset = max(len(session.tracks_to_use()) - session._track_offset - 2, 0)
						session._mixer.set_track_offset(max(0, session.track_offset() + self._mixer_offset))
			session._reassign_tracks()
			if offsets_changed:
				session._reassign_scenes()
				# this is replaced by notify_offset() in Live9 #for callback in session._offset_callbacks:
				# this is replaced by notify_offset() in Live9 #	callback()
				session.notify_offset()
				self._update_navigation_view()
				if self._mixer.channel_strip(self._last_selected_strip_number)._track != None:
					self.song().view.selected_track = self._mixer.channel_strip(self._last_selected_strip_number)._track
				if ((session.width() > 0) and (session.height() > 0)):
					session._do_show_highlight()
		return _change_offsets
		
	

	def _session_on_fired_slot_index_changed(self, session):
		def _on_fired_slot_index_changed(index):
			tracks_to_use = tuple(self.song().visible_tracks) + tuple(self.song().return_tracks)
			track_index = index + session.track_offset()
			if session.is_enabled() and session._stop_track_clip_buttons != None:
				if index < len(session._stop_track_clip_buttons):
					button = session._stop_track_clip_buttons[index]
					if button != None:
						if(track_index < len(tracks_to_use)) and (tracks_to_use[track_index].clip_slots) and (tracks_to_use[track_index].fired_slot_index == -2):
							button.send_value(session._stop_track_clip_value)
						#elif index in range(len(session.tracks_to_use())):
						#	dif = self._mixer._track_offset - self._session._track_offset
						#	button.send_value(NAV_COLORS[int(index in range(dif, dif + 2))], True)
						#else:
						#	button.turn_off()
						else:
							self._update_navigation_view()
		return _on_fired_slot_index_changed
		
	

	def _session_stop_track_value(self, session):
		def _stop_track_value(value, sender):
			assert (session._stop_track_clip_buttons != None)
			assert (list(session._stop_track_clip_buttons).count(sender) == 1)
			assert (value in range(128))
			if session.is_enabled():
				if ((value is not 0) or (not sender.is_momentary())):
					tracks = session.tracks_to_use()
					track_index = (list(session._stop_track_clip_buttons).index(sender) + session.track_offset())
					if (track_index in range(len(tracks))) and (tracks[track_index] in session.song().tracks):
						tracks[track_index].stop_all_clips()
					sender.send_value(3, True)
					self.schedule_message(10, self._update_navigation_view)
		
		return _stop_track_value
	

	"""ChannelStripComponent overrides"""
	def _channelstrip_update(self, channelstrip):
		def _update():
			ChannelStripComponent.update(channelstrip)
			self._update_device(channelstrip)
		return _update
		
	

	def _channelstrip_set_track(self, channelstrip, cb):
		def _set_track(track):
			assert ((track == None) or isinstance(track, Live.Track.Track))
			if channelstrip._track != None and isinstance(channelstrip._track, Live.Track.Track):
				if channelstrip._track.devices_has_listener(cb):
					channelstrip._track.remove_devices_listener(cb)
			if (track != None):
				track.add_devices_listener(cb)
			ChannelStripComponent.set_track(channelstrip, track)
		return _set_track
		
	

	def _channelstrip_select_value(self, channelstrip, index):  
		def _select_value(value):
			ChannelStripComponent._select_value(channelstrip, value)
			self._last_selected_strip_number = index
		return _select_value
		
	

	def _channelstrip_on_cf_assign_changed(self, channel_strip):
		def _on_cf_assign_changed():
			if (channel_strip.is_enabled() and (channel_strip._crossfade_toggle != None)):
				if (channel_strip._track != None) and (channel_strip._track in chain(self.song().tracks, self.song().return_tracks)):
					if channel_strip._track.mixer_device.crossfade_assign == 1: #modified
						channel_strip._crossfade_toggle.turn_off()
					elif channel_strip._track.mixer_device.crossfade_assign == 0:
						channel_strip._crossfade_toggle.send_value(CROSSFADE_A)
					else:
						channel_strip._crossfade_toggle.send_value(CROSSFADE_B)
		return _on_cf_assign_changed
		
	

	def _channelstrip1_cb(self):
		self._on_selected_track_changed()
	

	def _channelstrip2_cb(self):
		self._on_selected_track_changed()
	

	"""MixerComponent overrides"""
	def _mixer_tracks_to_use(self, mixer):
		def tracks_to_use():
			return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks)
		return tracks_to_use
		
	

	"""SessionComponent overrides"""
	def _device_number_of_parameter_banks(self, device):
		def _number_of_parameter_banks():
			return number_of_parameter_banks(device._device) #added
		return _number_of_parameter_banks
			
	

	def _device_assign_parameters(self, device):
		def _assign_parameters():
			assert device.is_enabled()
			assert (device._device != None)
			assert (device._parameter_controls != None)
			device._bank_name = ('Bank ' + str(device._bank_index + 1)) #added
			if (device._device.class_name in device._device_banks.keys()): #modified
				assert (device._device.class_name in device._device_best_banks.keys())
				banks = device._device_banks[device._device.class_name]
				bank = None
				if (not device._is_banking_enabled()):
					 banks = device._device_best_banks[device._device.class_name]
					 device._bank_name = 'Best of Parameters' #added
				if (len(banks) > device._bank_index):
					bank = banks[device._bank_index]
					if device._is_banking_enabled(): #added
						if device._device.class_name in device._device_bank_names.keys(): #added
							device._bank_name[device._bank_index] = device._device_bank_names[device._device.class_name] #added *recheck
				assert ((bank == None) or (len(bank) >= len(device._parameter_controls)))
				for index in range(len(device._parameter_controls)):
					parameter = None
					if (bank != None):
						parameter = get_parameter_by_name(device._device, bank[index])
					if (parameter != None):
						device._parameter_controls[index].connect_to(parameter)
					else:
						device._parameter_controls[index].release_parameter()
			else:
				parameters = device._device_parameters_to_map()
				num_controls = len(device._parameter_controls)
				index = (device._bank_index * num_controls)
				for control in device._parameter_controls:
					if (index < len(parameters)):
						control.connect_to(parameters[index])
					else:
						control.release_parameter()
					index += 1
		return _assign_parameters
class LaunchpadSimple(ControlSurface):
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self._session = None
        self._mixer = None

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

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

    def _delete_clip(self, midi_bytes):
        if midi_bytes[0] == MIDI_NOTE_ON_VALUE:
            row, col = launchpad_button_loc(midi_bytes[1])
            if row < SCENES_AMOUNT and col < 8:
                self._session.scene(row).clip_slot(col)._do_delete_clip()
                return True
        return False
Example #28
0
    def _setup_session_control(self):
        is_momentary = True
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87)
        right_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 107)  #78
        left_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 106)  #77
        right_button.name = 'Bank_Select_Right_Button'
        left_button.name = 'Bank_Select_Left_Button'
        global session
        session = SessionComponent(8, 40)
        session.name = 'Session_Control'
        session.set_track_bank_buttons(right_button, left_button)
        matrix = ButtonMatrixElement()
        matrix.name = 'Button_Matrix'
        scene_launch_notes = [56, 57, 58, 59, 60, 61, 62, 63]
        scene_launch_buttons = [
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                          scene_launch_notes[index]) for index in range(8)
        ]
        track_stop_buttons = [
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, (index + 28))
            for index in range(8)
        ]
        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'
        session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
        for scene_index in range(8):
            scene = 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(7):
                button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                                       (track_index * 8) + scene_index)
                button.name = str(track_index) + '_Clip_' + str(
                    scene_index) + '_Button'
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_stopped_value(0)
                clip_slot.set_started_value(64)
                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))
        session.selected_scene().name = 'Selected_Scene'
        #session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
        #session_zoom = SessionZoomingComponent(session)
        #session_zoom.name = 'Session_Overview'
        #session_zoom.set_button_matrix(matrix)
        #session_zoom.set_zoom_button(self._shift_button)
        #session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button)
        #session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
        #session_zoom.set_stopped_value(0)
        #session_zoom.set_selected_value(127)
        session.set_mixer(mixer)
        return None  #return session
class MidiFighterTwister(ControlSurface):
    __module__ = __name__
    __doc__ = "MidiFighterTwister class"

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            self.__c_instance = c_instance
            self.show_message('Script initiated')
            self.init()

    def init(self):
        # initialize listeners, caches and colors
        self.flush_all()
        self.mf_disable_bank_buttons()
        self.mf_init_page_config()
        self.mf_init_light_pages()

        # Start listeners to call dispatcher
        self.song().view.add_detail_clip_listener(
            self.dispatch_detail_clip_listener)
        self.song().add_current_song_time_listener(
            self.dispatch_current_song_time_listener)
        self.song().view.add_selected_track_listener(
            self.dispatch_selected_track_listener)
        self.device_listener_wrapper()

        # Initialize the sequencer buttons
        self.sequencer_init_buttons()
        self.sequencer_init_rotaries()
        self.init_clip_page()
        self.init_pad_page()
        self.init_device_params()

    def flush_all(self):
        for poti in range(64):
            for channel in range(4):
                self._send_midi((175 + channel, poti, 0))

    def mf_init_page_config(self):
        # Initialize configuration parameters
        # Sequencer configuration
        self.sequencer_page_default_color = 1
        self.sequencer_current_page_color_index = self.sequencer_page_default_color
        self.sequencer_base_default_note = 36
        self.sequencer_current_selected_note = self.sequencer_base_default_note
        self.sequencer_clip_position_16th = None

        # Midi Channels
        self.rotary_midi_channel = 175 + 1
        self.ring_midi_channel = 175 + 1
        self.switch_midi_channel = 175 + 2
        self.light_midi_channel = 175 + 2
        # Pages cc map
        self.clip_page_cc = range(0, 16)
        self.sequencer_page_cc = range(16, 32)
        self.note_page_cc = range(32, 48)
        self.control_page_cc = range(48, 64)
        # Pages init color
        self.clip_page_colors = [1] * 16
        self.sequencer_page_colors = [self.sequencer_page_default_color] * 16
        self.note_page_colors = range(1, 127, 16) * 2
        #self.note_page_colors = [0] * 16
        self.control_page_colors = [1] * 16
        # Status cache for sequencer
        self.switch_encoder_status_cache = [False] * 64
        # List to store ButtonElements in
        self.switch_encoder_buttons = [False] * 64
        # Status cache for rotaries
        self.rotary_encoder_potis = [False] * 64

    def mf_init_light_pages(self):
        sequencer_page_map = zip(self.sequencer_page_cc,
                                 self.sequencer_page_colors)
        for light_encoder_cc, light_color_cc in sequencer_page_map:
            self._mf_set_light(light_encoder_cc, light_color_cc, False)
        note_page_map = zip(self.note_page_cc,
                            self.note_page_colors)
        for light_encoder_cc, light_color_cc in note_page_map:
            self._mf_set_light(light_encoder_cc, light_color_cc, False)

    def _mf_set_light(self, light_encoder_cc, light_color_cc, status):
        # Sets color on midi channel 2 (177) end updates status cache
        # for sequencer to remember statuses
        self._send_midi((self.light_midi_channel, light_encoder_cc,
                         light_color_cc))
        self.switch_encoder_status_cache[light_encoder_cc] = status

    def mf_disable_bank_buttons(self):
        # Workaround for not sending values to track when pressing bank buttons
        self.padm0 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 0)
        self.padm1 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 1)
        self.padm2 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 2)
        self.padm3 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 3)
        self.padm0.add_value_listener(self.bank_buttons_dummy,
                                      identify_sender=True)
        self.padm1.add_value_listener(self.bank_buttons_dummy,
                                      identify_sender=True)
        self.padm2.add_value_listener(self.bank_buttons_dummy,
                                      identify_sender=True)
        self.padm3.add_value_listener(self.bank_buttons_dummy,
                                      identify_sender=True)

    def bank_buttons_dummy(self):
        pass

    def dispatch_detail_clip_listener(self):
        self.current_clip = self.song().view.highlighted_clip_slot.clip
        self.init_sequencer()
        try:
            if self.current_clip.is_midi_clip and not self.current_clip.notes_has_listener:
                # Update leds when notes are added or removed
                self.current_clip.add_notes_listener(
                    self._sequencer_update_notes_to_light)
                self.init_sequencer()
            else:
                self.sequencer_reset_colors()
        except AttributeError:
            pass

    def dispatch_current_song_time_listener(self):
        self.sequencer_light_follows_beat()

    def dispatch_selected_track_listener(self):
        self.device_auto_select()
        self.device_listener_wrapper()

    def device_listener_wrapper(self):
        selected_track = self.song().view.selected_track
        if not selected_track.devices_has_listener(self.device_auto_select):
            self.song().view.selected_track.add_devices_listener(
                self.device_auto_select)

    # Sequencer
    def init_sequencer(self):
        self.sequencer_current_selected_note = self.sequencer_base_default_note
        self.sequencer_current_page_color_index = self.sequencer_page_default_color
        self._sequencer_update_notes_to_light()

    def sequencer_init_buttons(self):
        for switch_encoder_cc in self.sequencer_page_cc:
            self.switch_encoder_buttons[switch_encoder_cc] = ButtonElement(
                IS_MOMENTARY, MIDI_CC_TYPE, 1, switch_encoder_cc)
            self.switch_encoder_buttons[switch_encoder_cc].add_value_listener(
                self.sequencer_button_press, identify_sender=True)
        self.padl14 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 14)
        self.padr17 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 17)
        self.padl16 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 16)
        self.padr19 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 19)
        self.padl14.add_value_listener(self.sequencer_side_button_press,
                                       identify_sender=True)
        self.padr17.add_value_listener(self.sequencer_side_button_press,
                                       identify_sender=True)
        self.padl16.add_value_listener(self.sequencer_side_button_press,
                                       identify_sender=True)
        self.padr19.add_value_listener(self.sequencer_side_button_press,
                                       identify_sender=True)

    def sequencer_init_rotaries(self):
        for rotary_encoder_cc in self.sequencer_page_cc:
            self.rotary_encoder_potis[rotary_encoder_cc] = EncoderElement( MIDI_CC_TYPE, 0, rotary_encoder_cc, Live.MidiMap.MapMode.absolute)
            self.rotary_encoder_potis[rotary_encoder_cc].add_value_listener(self.sequencer_rotary_change, identify_sender=True)

    def sequencer_rotary_change(self, value, sender):
        try:
            self.current_clip
        except AttributeError:
            return False
        if self.current_clip.is_midi_clip:
            cc_value = sender._msg_identifier
            if value > 0:
                if not self.switch_encoder_status_cache[cc_value]:
                    self._send_midi((self.light_midi_channel,
                                     cc_value,
                                     self.sequencer_current_light_on_color))
                    self._send_midi((
                        self.ring_midi_channel, cc_value, 100))
                    self.switch_encoder_status_cache[cc_value] = True
                self.current_clip.set_notes(((self.sequencer_current_selected_note, cc_value % 16 * 0.25, 0.25, value, False),))
            elif value == 0:
                self._send_midi((self.light_midi_channel,
                                cc_value, self.sequencer_current_page_color))
                self.current_clip.remove_notes(
                    cc_value % 16 * 0.25,
                    self.sequencer_current_selected_note,
                    0.25, 1)
                self.switch_encoder_status_cache[cc_value] = False

    def sequencer_button_press(self, value, sender):
        try:
            self.current_clip
        except AttributeError:
            return False
        if self.current_clip.is_midi_clip:
            cc_value = sender._msg_identifier
            if value > 0:
                if not self.switch_encoder_status_cache[cc_value]:
                    self._send_midi((self.light_midi_channel,
                                     cc_value,
                                     self.sequencer_current_light_on_color))
                    self.current_clip.set_notes(((
                        self.sequencer_current_selected_note, cc_value % 16 *
                        0.25, 0.25, 100, False),))
                    self.switch_encoder_status_cache[cc_value] = True
                    self._send_midi((self.ring_midi_channel, cc_value, 100))
                else:
                    self._send_midi((self.light_midi_channel,
                                     cc_value,
                                     self.sequencer_current_page_color))
                    self._send_midi((self.ring_midi_channel, cc_value, 0))
                    self.current_clip.remove_notes(
                        cc_value % 16 * 0.25,
                        self.sequencer_current_selected_note,
                        0.25, 1)
                    self.switch_encoder_status_cache[cc_value] = False

    def sequencer_side_button_press(self, value, sender):
            try:
                cc_value = sender._msg_identifier
                if value > 0:
                    # Note/clolor up/down
                    if cc_value == 14 and self.sequencer_current_selected_note > 0:
                        self.sequencer_current_selected_note = self.sequencer_current_selected_note - 1
                        self.sequencer_current_page_color_index = self.sequencer_current_page_color_index - 16
                        self._sequencer_update_notes_to_light()
                        self.sequencer_clip_position_16th = None
                        self.show_message("Selected Midi Note: "+str(self.sequencer_current_selected_note))
                    if cc_value == 17 and self.sequencer_current_selected_note < 127:
                        self.sequencer_current_selected_note = self.sequencer_current_selected_note + 1
                        self.sequencer_current_page_color_index = self.sequencer_current_page_color_index + 16
                        self._sequencer_update_notes_to_light()
                        self.sequencer_clip_position_16th = None
                        self.show_message("Selected Midi Note: "+str(self.sequencer_current_selected_note))
                    # New/duplicate clip
                    if cc_value == 16 and self.sequencer_current_selected_note > 0:
                        self.duplicate_clip()
                    if cc_value == 19 and self.sequencer_current_selected_note > 0:
                        self.session_record()
            except AttributeError:
                pass

    def sequencer_light_follows_beat(self):
        try:
            if self.current_clip.is_midi_clip:
                    if self.sequencer_clip_position_16th == None:
                        self.sequencer_clip_position_16th = int(self.current_clip.playing_position / 0.25)
                        if self.switch_encoder_status_cache[self.sequencer_page_cc[self.sequencer_clip_position_16th]]:
                            self._send_midi((177, self.sequencer_page_cc[self.sequencer_clip_position_16th], self.sequencer_current_light_on_color))
                        else:
                            self._send_midi((177, self.sequencer_page_cc[self.sequencer_clip_position_16th], self.sequencer_current_page_color))
                    elif self.sequencer_clip_position_16th != int(self.current_clip.playing_position/0.25):
                        if self.switch_encoder_status_cache[self.sequencer_page_cc[self.sequencer_clip_position_16th]]:
                            self._send_midi((177, self.sequencer_page_cc[self.sequencer_clip_position_16th], self.sequencer_current_light_on_color))
                        else:
                            self._send_midi((177, self.sequencer_page_cc[self.sequencer_clip_position_16th], self.sequencer_current_page_color))
                        self.sequencer_clip_position_16th = int(self.current_clip.playing_position/0.25)
                        self._send_midi((177, self.sequencer_page_cc[self.sequencer_clip_position_16th], self.sequencer_current_light_beat_color))
        except IndexError:
            pass

    @property
    def sequencer_current_light_on_color(self):
        # light on color to be relative to page color
        return self.sequencer_current_page_color + 32 % 128

    @property
    def sequencer_current_light_beat_color(self):
        # light on color to be relative to page color
        return self.sequencer_current_page_color + 64 % 128

    @property
    def sequencer_current_page_color(self):
        return self.sequencer_current_page_color_index % 128

    def _sequencer_get_midi_notes(self, note):
        # self.current_clip.get_notes(start, self.sequencer_current_selected_note,
        # selection_length, hight)
        try:
            return self.current_clip.get_notes(0, note, 4, 1)
        except AttributeError:
            return []

    def _sequencer_update_notes_to_light(self):
        self.sequencer_reset_colors()
        notes_for_current_selected_note = self._sequencer_get_midi_notes(
            self.sequencer_current_selected_note)
        for note in notes_for_current_selected_note:
            light_encoder_cc = int(note[1]*4+self.sequencer_page_cc[0])
            self._send_midi((self.ring_midi_channel, light_encoder_cc, note[3]))
            self._mf_set_light(light_encoder_cc,
                               self.sequencer_current_light_on_color, True)

    def sequencer_reset_colors(self):
        for light_encoder_cc in self.sequencer_page_cc:
            self._mf_set_light(light_encoder_cc,
                               self.sequencer_current_page_color, False)
            self._send_midi((self.ring_midi_channel, light_encoder_cc, 0))

    def duplicate_clip(self):
        self.log_message("duplicate clip")
        #if self._clip_slot and self._clip_slot.has_clip:
        #    slot_name = self._clip_slot.clip.name
        #    track = self._clip_slot.canonical_parent
        current_track = self.song().view.selected_track
        current_clip_slot = self.song().view.highlighted_clip_slot
        self.song().duplicate_scene(list(current_track.clip_slots).index(current_clip_slot))
        #new_clip = current_track.duplicate_clip_slot(
        #    list(current_track.clip_slots).index(current_clip_slot)+1)
        #self.log_message(new_clip)
        #selected_track = self.song().view.selected_track
        #selected_track.duplicate_clip_slot(selected_track)

    def session_record(self):
        self.log_message("session record")
        #self.song().trigger_session_record()

# Clip page setion

    def init_clip_page(self):
        num_tracks = 4
        num_scenes = 3
        self.flash_status = 1
        self.Mixer = MixerComponent(4, 3)

        # Volencoder
        self.volencoders = [None for index in range(num_tracks)]
        for index in range(num_tracks):
            self.volencoders[index] = EncoderElement(
                MIDI_CC_TYPE, 0, index, Live.MidiMap.MapMode.absolute)
            self.Mixer.channel_strip(index).set_volume_control(
                self.volencoders[index])

        # Sendencoder
        for index in range(num_tracks):
            encoder_cc_send_1 = index + num_tracks
            encoder_cc_send_2 = index + num_tracks * 2
            send1 = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_send_1,
                                   Live.MidiMap.MapMode.absolute)
            send2 = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_send_2,
                                   Live.MidiMap.MapMode.absolute)
            self.Mixer.channel_strip(index).set_send_controls((send1, send2))

        # Panencoder
        for index in range(num_tracks):
            encoder_cc_pan = index + num_tracks * 3
            pan = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_pan,
                                 Live.MidiMap.MapMode.absolute)
            self.Mixer.channel_strip(index).set_pan_control(pan)

        # Arm-/selectbuttons
        for index in range(num_tracks):
            armbutton = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1,
                                      index + 12)
            self.Mixer.channel_strip(index).set_arm_button(armbutton)
            self.Mixer.channel_strip(index).set_select_button(armbutton)

        # Navigation buttons
        self.padl11 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 11)
        self.padr8 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 8)
        self.padl10 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 10)
        self.padr13 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 13)

        self.grid = [None for index in range(num_tracks * 3)]
        for index in range(num_tracks * 3):
            self.grid[index] = ButtonElement(
                IS_MOMENTARY, MIDI_CC_TYPE, 1, index)
        self.matrix = ButtonMatrixElement()
        for row in range(num_scenes):
            button_row = []
            for column in range(num_tracks):
                button_row.append(self.grid[column+(row*4)])
                self.log_message(str(column+(row*4)))
            self.matrix.add_row(tuple(button_row))

        self.Session = SessionComponent(num_tracks, num_scenes)
        self.Session.name = "Session"
        self.Session.set_offsets(0, 0)
        self.Session.set_mixer(self.Mixer)
        self.Session._do_show_highlight()
        self.set_highlighting_session_component(self.Session)
        self.Session.set_track_bank_buttons(self.padl11, self.padr8)
        self.Session.set_scene_bank_buttons(self.padr13, self.padl10)

        self.scene = [None for index in range(num_scenes)]
        for row in range(num_scenes):
            self.scene[row] = self.Session.scene(row)
            self.scene[row].name = 'Scene_'+str(row)
            for column in range(num_tracks):
                clip_slot = self.scene[row].clip_slot(column)
                clip_slot.name = str(column)+'_Clip_Slot'+str(row)
                self.scene[row].clip_slot(column).set_triggered_to_play_value(35)
                self.scene[row].clip_slot(column).set_stopped_value(68)
                self.scene[row].clip_slot(column).set_started_value(45)
                self.scene[row].clip_slot(column).set_triggered_to_record_value(100)
                self.scene[row].clip_slot(column).set_recording_value(80)

        for column in range(num_tracks):
            for row in range(num_scenes):
                self.scene[row].clip_slot(column).set_launch_button(self.grid[column+(row*4)])
            for index in range(num_tracks*num_scenes):
                self.grid[index].clear_send_cache()

    def update_display(self):
        # Called every 100 ms
        ControlSurface.update_display(self)
        self.refresh_state()
        self.Session.set_enabled(True)
        self.Session.update()
        # Sequencer hack
        try:
            for light_encoder_cc in self.sequencer_page_cc:
                self._send_midi((self.ring_midi_channel, light_encoder_cc, 0))
            notes_for_current_selected_note = self._sequencer_get_midi_notes(
                self.sequencer_current_selected_note)
            for note in notes_for_current_selected_note:
                light_encoder_cc = int(note[1]*4+self.sequencer_page_cc[0])
                self._send_midi((self.ring_midi_channel, light_encoder_cc,
                                 note[3]))
        except AttributeError:
            pass

    # Pad Section
    def init_pad_page(self):
        self.pad_device_params()
        PAD_TRANSLATION = (
            (0, 0, 32, 1), (1, 0, 33, 1), (2, 0, 34, 1), (3, 0, 35, 1),
            (0, 1, 36, 1), (1, 1, 37, 1), (2, 1, 38, 1), (3, 1, 39, 1),
            (0, 2, 40, 1), (1, 2, 41, 1), (2, 2, 42, 1), (3, 2, 43, 1),
            (0, 3, 44, 1), (1, 3, 45, 1), (2, 3, 46, 1), (3, 3, 47, 1))
        self.set_pad_translations(PAD_TRANSLATION)
        self._device_selection_follows_track_selection = True

    def pad_device_params(self):
        device_param_controls = []
        for param in self.note_page_cc[:8]:
            self.rotary_encoder_potis[param] = EncoderElement(
                MIDI_CC_TYPE, 0, param, Live.MidiMap.MapMode.absolute)
            self.rotary_encoder_potis[param].release_parameter()
            self.rotary_encoder_potis[param].send_value(0, True)
            self.rotary_encoder_potis[param].clear_send_cache()
            device_param_controls.append(self.rotary_encoder_potis[param])

        device = DeviceComponent()
        device.name = 'Device_Component pad'
        device.set_parameter_controls(tuple(device_param_controls))
        self.set_device_component(device)

    #def scrolling(self):
    #    self.application().view.scroll_view(ndir, 'Detail/DeviceChain', True)

    # Live.Song.Song.View.selected_track
    #Live.Song.Song.View.select_device()[0]

    # Device parameter section
    def init_device_params(self):
        device_param_controls = []
        device_bank_buttons = []
        for param in self.control_page_cc[:8]:
            self.rotary_encoder_potis[param] = EncoderElement(
                MIDI_CC_TYPE, 0, param, Live.MidiMap.MapMode.absolute)
            self.switch_encoder_buttons[param] = ButtonElement(
                IS_MOMENTARY, MIDI_CC_TYPE, 1, param)
            self.rotary_encoder_potis[param].release_parameter()
            self.rotary_encoder_potis[param].send_value(0, True)
            self.rotary_encoder_potis[param].clear_send_cache()
            device_param_controls.append(self.rotary_encoder_potis[param])
            device_bank_buttons.append(self.switch_encoder_buttons[param])

        device = DeviceComponent()
        device.name = 'Device_Component'
        device.set_parameter_controls(tuple(device_param_controls))
        device.set_bank_buttons(tuple(device_bank_buttons))
        device.set_on_off_button(ButtonElement(
            IS_MOMENTARY, MIDI_CC_TYPE, 1, 56))
        self.set_device_component(device)

    def device_auto_select(self):
        # Iterates through devices within a track and assigns the first
        # DrumPad device to activate the individual drum's device.
        # Use first device in case none is a DrumPad device.
        selected_track = self.song().view.selected_track
        devices = selected_track.devices
        for device in devices:
            if device.can_have_drum_pads:
                self.current_drum_device = device
                pad_device = self.current_drum_device.view.selected_chain.devices[0]
                self.song().view.select_device(pad_device)
                if not self.current_drum_device.view.selected_drum_pad_has_listener(
                        self.device_update_current_note):
                    self.current_drum_device.view.add_selected_drum_pad_listener(
                            self.device_update_current_note)
                break
            else:
                self.song().view.select_device(devices[0])

    def device_update_current_note(self):
        current_note = self.current_drum_device.view.selected_drum_pad.note
        self.sequencer_current_selected_note = current_note

        # Update light of active pad
        #self._send_midi((self.light_midi_channel, light_encoder_cc, 63))
        try:
            self.current_clip = self.song().view.highlighted_clip_slot.clip
            self.current_clip.is_midi_clip
            self._sequencer_update_notes_to_light()
        except AttributeError:
            pass
class NanoKontrolShift(ControlSurface):
    __module__ = __name__
    __doc__ = " NanoKontrolShift controller script "

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

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

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

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

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

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

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

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


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

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

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

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

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

        self.log_message("Controls Cleared")

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


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


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

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

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

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

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

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

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

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

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

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

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

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

        self.set_device_component(None)
        ControlSurface.disconnect(self)
        return None
Example #31
0
	def _setup_session_control(self):
		is_momentary = True		  
		right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 43)
		left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 42)
		up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 44)
		down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 45)
		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'
		global session
		session = SessionComponent(4, 4)
		session.name = 'Session_Control'
		session.set_track_bank_buttons(right_button, left_button)
		session.set_scene_bank_buttons(down_button, up_button)
		self._session = session
		matrix = ButtonMatrixElement()
		matrix.name = 'Button_Matrix'
		scene_launch_notes = [33,34,35,36]
		scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, scene_launch_notes[index]) for index in range(4) ]
		#track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(4) ]
		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_clip_value(2)
		button_notes = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32]
		for scene_index in range(4):
			scene = 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(4):
				button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, (track_index * 4) + scene_index + 1)
				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(0)
				clip_slot.set_started_value(64)
				#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))
		session.selected_scene().name = 'Selected_Scene'
		#session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
		#session_zoom = SessionZoomingComponent(session)
		#session_zoom.name = 'Session_Overview'
		#session_zoom.set_button_matrix(matrix)
		#session_zoom.set_zoom_button(self._shift_button)
		#session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button)
		#session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
		#session_zoom.set_stopped_value(0)
		#session_zoom.set_selected_value(127)
		self.set_highlighting_session_component(session)
		session.set_mixer(mixer)
		return None #return session
Example #32
0
class XoneK2(ControlSurface):
    def __init__(self, instance):
        global g_logger
        g_logger = self.log_message
        super(XoneK2, self).__init__(instance, False)
        with self.component_guard():
            self._set_suppress_rebuild_requests(True)
            self.init_session()
            self.init_mixer()
            self.init_matrix()
            self.init_tempo()

            # connect mixer to session
            self.session.set_mixer(self.mixer)
            self.session.update()
            self.set_highlighting_session_component(self.session)
            self._set_suppress_rebuild_requests(False)

    def init_session(self):
        self.session = SessionComponent(NUM_TRACKS, NUM_SCENES)
        self.session.name = 'Session'
        self.session.set_scene_bank_buttons(button(BUTTON_LL),
                                            button(BUTTON_LR))
        self.session.update()

    def init_mixer(self):
        self.mixer = MixerWithDevices(num_tracks=NUM_TRACKS,
                                      device_select=[
                                          button(PUSH_ENCODERS[i])
                                          for i in range(NUM_TRACKS)
                                      ],
                                      device_encoders=ENCODERS)
        self.mixer.id = 'Mixer'

        self.song().view.selected_track = self.mixer.channel_strip(0)._track

        for i in range(NUM_TRACKS):
            self.mixer.channel_strip(i).set_volume_control(fader(FADERS[i]))
            self.mixer.channel_strip(i).set_solo_button(button(BUTTONS3[i]))
            self.mixer.set_eq_controls(
                i, (knob(KNOBS3[i]), knob(KNOBS2[i]), knob(KNOBS1[i])))
            self.mixer.set_device_controls(i, button(BUTTONS1[i]))

        self.master_encoder = DynamicEncoder(
            ENCODER_LR,
            self.song().master_track.mixer_device.volume)
        self.cue_encoder = DynamicEncoder(
            ENCODER_LL,
            self.song().master_track.mixer_device.cue_volume)
        self.mixer.update()

    def init_matrix(self):
        self.matrix = ButtonMatrixElement()

        for scene_index in range(NUM_SCENES):
            scene = self.session.scene(scene_index)
            scene.name = 'Scene ' + str(scene_index)
            button_row = []
            for track_index in range(NUM_TRACKS):
                note_nr = GRID[scene_index][track_index]
                b = button(note_nr,
                           name='Clip %d, %d button' %
                           (scene_index, track_index))
                button_row.append(b)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = 'Clip slot %d, %d' % (scene_index,
                                                       track_index)
                clip_slot.set_stopped_value(0)
                clip_slot.set_started_value(64)
                clip_slot.set_launch_button(b)
            self.matrix.add_row(tuple(button_row))
        stop_buttons = [button(note_nr) for note_nr in BUTTONS2]
        self.session.set_stop_track_clip_buttons(stop_buttons)

    def init_tempo(self):
        self.transport = CustomTransportComponent()
        self.transport.set_tempo_bumpers(button(PUSH_ENCODER_LR),
                                         button(PUSH_ENCODER_LL))
Example #33
0
class NanoKontrolShift(ControlSurface):
    __module__ = __name__
    __doc__ = " NanoKontrolShift controller script "

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.log_message("Controls Cleared")

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.session.set_stop_track_clip_buttons(tuple(stop_track_buttons))

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

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

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

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

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

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

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

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

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

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

        ControlSurface.disconnect(self)
        return None
Example #35
0
class LemurPad(MonOhm):
	__module__ = __name__
	__doc__ = " Lemur version of the MonOhm companion controller script "


	def __init__(self, *a, **k):
		self._timer_callbacks = []		#Used for _monobridge, which uses L8 method for registering timer callbacks.  deprecated, needs to be replaced by new L9 Task class.
		self._osc_registry = {}
		self._display_button_names = DISPLAY_BUTTON_NAMES		
		super(LemurPad, self).__init__(*a, **k)
		self._host_name = "LemurPad"
		self._color_type = 'AumPad'
		self.connected = 0
		with self.component_guard():
			self._setup_touchosc()
			self._assign_host2()
			self._assign_session_colors()
	

	def query_ohm(self):
		pass
	


	"""script initialization methods"""
	def _setup_monobridge(self):
		self._monobridge = OSCMonoBridgeElement(self)
		self._monobridge.name = 'MonoBridge'
	

	def _setup_controls(self):
		is_momentary = True
		self._fader = [None for index in range(8)]
		self._dial = [None for index in range(16)]
		self._button = [None for index in range(8)]
		self._menu = [None for index in range(6)]
		for index in range(8):
			self._fader[index] = OSCMonoEncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_FADERS[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, '/Fader_'+str(index)+'/x', '/Strip'+str(index+8)+'/set', '/Strip'+str(index)+'/set', self)
		for index in range(8):
			self._button[index] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_'+str(index), '/Select_'+str(index)+'/value', '/Select/set '+str(index),  '/Select/text '+str(index), self)
		for index in range(16):
			self._dial[index] = OSCMonoEncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_DIALS[index], Live.MidiMap.MapMode.absolute, 'Dial_' + str(index), index + 8, '/Dial_'+str(index)+'/x', '/Dial'+str(index)+'val/set', '/Dial'+str(index)+'name/set', self)
		for index in range(6):
			self._menu[index] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_MENU[index], 'Menu_' + str(index), '/Function_'+str(index)+'/value', '/Function/set '+str(index), '/Function/text '+str(index), self)	
		self._crossfader = OSCMonoEncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute, "Crossfader", 24, '/XFader/x', '/XFader/none', None, self)
		self._livid = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', '/Livid/x', '/Livid/x', None, self)
		self._shift_l = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Shift_Button_Left', '/ShiftL/x', '/ShiftL/x', None, self)
		self._shift_r = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Shift_Button_Right', '/ShiftR/x', '/ShiftR/x', None, self)
		self._matrix = ButtonMatrixElement()
		self._matrix.name = 'Matrix'
		self._monomod = ButtonMatrixElement()
		self._monomod.name = 'Monomod'
		self._grid = [None for index in range(8)]
		for column in range(8):
			self._grid[column] = [None for index in range(8)]
			for row in range(8):
				self._grid[column][row] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, (column * 8) + row, 'Grid_' + str(column) + '_' + str(row), '/ClipGrid_'+str(column)+'_'+str(row)+'/value', '/ClipGrid/set '+str(column)+' '+str(row), '/ClipGrid/text '+str(column)+' '+str(row), self)
		for row in range(5):
			button_row = []
			for column in range(7):
				button_row.append(self._grid[column][row])
			self._matrix.add_row(tuple(button_row)) 
		for row in range(8):
			button_row = []
			for column in range(8):
				button_row.append(self._grid[column][row])
			self._monomod.add_row(tuple(button_row))
		self._dummy_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, 125)
		self._dummy_button.name = 'Dummy1'
		self._dummy_button2 = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, 126)
		self._dummy_button2.name = 'Dummy2'
		self._dummy_button3 = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, 127)
		self._dummy_button2.name = 'Dummy3'
		self._monomod256 = ButtonMatrixElement()
		self._monomod256.name = 'Monomod256'
		self._square = [None for index in range(16)]
		for column in range(16):
			self._square[column] = [None for index in range(16)]
			for row in range(16):
				self._square[column][row] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, int(column/8) + 1, row + ((column%8) * 16), '256Grid_' + str(column) + '_' + str(row), '/Grid_'+str(column)+'_'+str(row)+'/value', '/Grid/set '+str(column)+' '+str(row), None, self)
				#self._square[column][row] = FlashingButtonElement(is_momentary, 0, 15, -1, '256Grid_' + str(column) + '_' + str(row), '/1/p_grid/'+str(column)+'/'+str(row), '/1/c_grid/'+str(column)+'/'+str(row), self)
		for row in range(16):
			button_row = []
			for column in range(16):
				button_row.append(self._square[column][row])
			self._monomod256.add_row(tuple(button_row))
		self._bank_buttons = ButtonMatrixElement()
		self._key_buttons = ButtonMatrixElement()
		self._bank_button = [None for index in range(2)]
		for index in range(2):
			self._bank_button[index] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, index, '256Grid_Bank_' + str(index), '/Shift_'+str(index)+'/value', '/Shift/set '+str(index), None, self)
		button_row = []
		for index in range(2):
			button_row.append(self._bank_button[index])
		self._bank_buttons.add_row(tuple(button_row))
		button_row = []
		self._key_button = [None for index in range(8)]
		for index in range(8):
			self._key_button[index] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, index+8, '256Grid_Key_' + str(index), '/Keys_'+str(index)+'/value', '/Keys/set '+str(index), None, self)
		for index in range(8):
			button_row.append(self._key_button[index])
		self._key_buttons.add_row(tuple(button_row))

		self._pedal = [None for index in range(8)]
		if self._use_pedal is True:
			for index in range(8):
					self._pedal[index] = EncoderElement(MIDI_CC_TYPE, 0, 25+index, Live.MidiMap.MapMode.absolute)
					self._pedal[index].name = 'Pedal_'+str(index)
					self._pedal[index]._report = False
	

	def _setup_session_control(self):
		is_momentary = True
		num_tracks = 4
		num_scenes = 5 
		self._session = NameServerSessionComponent(num_tracks, num_scenes, self)
		self._session.name = "Left_Session"
		self._session.set_offsets(0, 0)	 
		self._session.set_stop_clip_value(self._color_defs['STOP_CLIP'])
		self._scene = [None for index in range(5)]
		for row in range(num_scenes):
			self._scene[row] = self._session.scene(row)
			self._scene[row].name = 'L_Scene_' + str(row)
			for column in range(num_tracks):
				clip_slot = self._scene[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_L_' + str(row)
				clip_slot.set_triggered_to_play_value(self._color_defs['CLIP_TRG_PLAY'])
				clip_slot.set_triggered_to_record_value(self._color_defs['CLIP_TRG_REC'])
				clip_slot.set_stopped_value(self._color_defs['CLIP_STOP'])
				clip_slot.set_started_value(self._color_defs['CLIP_STARTED'])
				clip_slot.set_recording_value(self._color_defs['CLIP_RECORDING'])
		self._session.set_mixer(self._mixer)
		self._session_zoom = SessionZoomingComponent(self._session)	 
		self._session_zoom.name = 'L_Session_Overview'
		self._session_zoom.set_stopped_value(self._color_defs['ZOOM_STOPPED'])
		self._session_zoom.set_playing_value(self._color_defs['ZOOM_PLAYING'])
		self._session_zoom.set_selected_value(self._color_defs['ZOOM_SELECTED'])
		self._session_zoom._zoom_button = (self._dummy_button)
		self._session_zoom.set_enabled(True) 
		self._session2 = SessionComponent(num_tracks, num_scenes)
		self._session2.name = 'Right_Session'
		self._session2.set_offsets(4, 0)
		self._session2.set_stop_clip_value(self._color_defs['STOP_CLIP'])
		self._scene2 = [None for index in range(5)]
		for row in range(num_scenes):
			self._scene2[row] = self._session2.scene(row)
			self._scene2[row].name = 'R_Scene_' + str(row)
			for column in range(num_tracks):
				clip_slot = self._scene2[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_R_' + str(row)
				clip_slot.set_triggered_to_play_value(self._color_defs['CLIP_TRG_PLAY'])
				clip_slot.set_triggered_to_record_value(self._color_defs['CLIP_TRG_REC'])
				clip_slot.set_stopped_value(self._color_defs['CLIP_STOP'])
				clip_slot.set_started_value(self._color_defs['CLIP_STARTED'])
				clip_slot.set_recording_value(self._color_defs['CLIP_RECORDING'])
		self._session2.set_mixer(self._mixer2)
		self._session2.add_offset_listener(self._on_session_offset_changes)
		self._session_zoom2 = SessionZoomingComponent(self._session2)	   
		self._session_zoom2.name = 'R_Session_Overview'
		self._session_zoom2.set_stopped_value(self._color_defs['ZOOM_STOPPED'])
		self._session_zoom2.set_playing_value(self._color_defs['ZOOM_PLAYING'])
		self._session_zoom2.set_selected_value(self._color_defs['ZOOM_SELECTED'])
		self._session_zoom.set_enabled(True) 
		self._session_zoom2._zoom_button = (self._dummy_button2)
		self._session_main = SessionComponent(8, num_scenes)
		self._session_main.name = 'Main_Session'
		self._session_main.set_stop_clip_value(self._color_defs['STOP_CLIP'])
		self._scene_main = [None for index in range(5)]
		for row in range(num_scenes):
			self._scene_main[row] = self._session_main.scene(row)
			self._scene_main[row].name = 'M_Scene_' + str(row)
			for column in range(8):
				clip_slot = self._scene_main[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_M_' + str(row)
				clip_slot.set_triggered_to_play_value(self._color_defs['CLIP_TRG_PLAY'])
				clip_slot.set_triggered_to_record_value(self._color_defs['CLIP_TRG_REC'])
				clip_slot.set_stopped_value(self._color_defs['CLIP_STOP'])
				clip_slot.set_started_value(self._color_defs['CLIP_STARTED'])
				clip_slot.set_recording_value(self._color_defs['CLIP_RECORDING'])
		self._session_main.set_mixer(self._mixer)
		self._session_zoom_main = SessionZoomingComponent(self._session_main)
		self._session_zoom_main.name = 'M_Session_Overview'
		self._session_zoom_main.set_stopped_value(self._color_defs['ZOOM_STOPPED'])
		self._session_zoom_main.set_playing_value(self._color_defs['ZOOM_PLAYING'])
		self._session_zoom_main.set_selected_value(self._color_defs['ZOOM_SELECTED'])
		self._session_zoom_main.set_enabled(True)
		self._session_zoom_main._zoom_button = (self._dummy_button3)
		self._sessions = [self._session, self._session2, self._session_main]
		self._zooms = [self._session_zoom, self._session_zoom2, self._session_zoom_main]
	

	def _setup_monomod(self):
		self._host = MonomodComponent(self)
		self._host.name = 'Monomod_Host'
		self._host2 = SpecialMonomodComponent(self)
		self._host2.name = '256_Monomod_Host'
		self.hosts = [self._host, self._host2]
	

	def _assign_host2(self):
		self._host2._set_shift_button(self._bank_button[0])
		self._host2._set_alt_button(self._bank_button[1])
		self._host2._set_button_matrix(self._monomod256)
		self._host2._set_key_buttons(self._key_button)
		self._host2.set_enabled(True)
	

	def _setup_touchosc(self):
		self._osc_registry = {}
		#self._osc_registry['/ping'] = self._monobridge.ping
		#self._osc_registry['/1'] = self._monobridge.page1
		#self._osc_registry['/2'] = self._monobridge.page2
		for control in self.controls:
			if hasattr(control, 'osc'):
				self._osc_registry[control.osc] = control.set_value
			#if hasattr(control, 'osc_alt'):
			#	self._osc_registry[control.osc_alt] = control.set_value
				#self.log_message('create dict key: ' + str(control.osc) + str(control.name))
	


	"""shift/zoom methods"""
	def deassign_matrix(self):
		super(LemurPad, self).deassign_matrix()
		self.clear_grid_names()
	


	"""menu button management methods"""
	def deassign_menu(self):
		super(LemurPad, self).deassign_menu()
		for index in range(6):
			self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(' '))
	

	def assign_device_nav_to_menu(self):
		super(LemurPad, self).assign_device_nav_to_menu()
		for index in range(6):
			self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(DEVICE_NAV_NAMES[index])))
	

	def assign_transport_to_menu(self):
		super(LemurPad, self).assign_transport_to_menu()
		for index in range(6):
			self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(TRANSPORT_NAMES[index])))
	

	def assign_session_nav_to_menu(self):
		super(LemurPad, self).assign_session_nav_to_menu()
		for index in range(6):
			self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(SESSION_NAV_NAMES[index])))
	

	def assign_session_main_nav_to_menu(self):
		super(LemurPad, self).assign_session_main_nav_to_menu()
		for index in range(6):
			self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(SESSION_NAV_NAMES[index])))
	

	def assign_monomod_shift_to_menu(self):
		super(LemurPad, self).assign_monomod_shift_to_menu()
		for index in range(6):
			self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(MONOMOD_SHIFT_NAMES[index])))
	

	def assign_monomod_to_menu(self):
		super(LemurPad, self).assign_monomod_shift_to_menu()
		for index in range(6):
			self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(MONOMOD_NAMES[index])))
	

	def assign_session_bank_to_menu(self):
		super(LemurPad, self).assign_session_bank_to_menu()
		for index in range(6):
			self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(SESSION_BANK_NAMES[index])))
	

	def assign_session2_bank_to_menu(self):
		super(LemurPad, self).assign_session2_bank_to_menu()
		for index in range(6):
			self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(SESSION_BANK2_NAMES[index])))
	

	def assign_session_main_nav_to_menu(self):
		super(LemurPad, self).assign_session_main_nav_to_menu()
		for index in range(6):
			self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(SESSION_MAIN_BANK_NAMES[index])))
	


	"""m4l bridge"""
	def generate_strip_string(self, display_string):
		NUM_CHARS_PER_DISPLAY_STRIP = 9
		if (not display_string):
			return ('`_')
		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.replace(' ', '_')
	

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

	def clip_name(self, sender, name):
		#self.log_message('clip name ' + str(sender.osc_name) + ' ' + str(self.generate_strip_string(str(name))))
		self._monobridge._send_osc(sender.osc_name, self.generate_strip_string(str(name)))
	

	"""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():
					clip_names.append(clip_slot._clip_slot)##.clip.name)
					#return clip_slot._clip_slot
					#self.log_message('clip name' + str(clip_slot._clip_slot.clip.name))
		return clip_names"""
	


	"""called on timer"""
	def update_display(self):
		super(LemurPad, self).update_display()
		for callback in self._timer_callbacks:
			callback()	
	

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

	def strobe(self):
		pass
	


	"""general functionality"""
	def disconnect(self):
		super(MonOhm, self).disconnect()
	

	def clear_grid_names(self):
		#self.log_message('clear grid names' + str(self))
		for column in range(8):
			for row in range(8):
				self._monobridge._send_osc(self._grid[column][row].osc_name, '`_')	
	

	def _register_timer_callback(self, callback):
		""" Registers a callback that is triggerd on every call of update_display """		 
		assert (callback != None)
		assert (dir(callback).count('im_func') is 1)
		assert (self._timer_callbacks.count(callback) == 0)
		self._timer_callbacks.append(callback)
		return None
	

	def _unregister_timer_callback(self, callback):
		""" Unregisters a timer callback """		
		assert (callback != None)
		assert (dir(callback).count('im_func') is 1)
		assert (self._timer_callbacks.count(callback) == 1)
		self._timer_callbacks.remove(callback)
		return None
	

	def _set_brightness(self, value):
		#self._bright = (value != 0)
		#for control in self.controls:
		#	if isinstance(control, OSCMonoButtonElement):
		#		self._monobridge._send_osc(control.osc_alt, int(self._bright), True)
		pass
	

	def reset(self):
		#self._monobridge._send_osc('/reset')
		for control in self.controls:
			control.reset()
	

	def assign_lower_grid_names(self, mode):
		if self._display_button_names is True:
			for column in range(8):
				for row in range(3):
					self._monobridge._send_osc(self._grid[column][row+5].osc_name, self.generate_strip_string(str(GRID_NAMES[mode][row][column])))
	

	def reset_and_refresh_state(self, *a, **k):
		self.schedule_message(1, self.reset)
		self.schedule_message(2, self.refresh_state)
Example #36
0
class MidiFighterTwister(ControlSurface):
    __module__ = __name__
    __doc__ = "MidiFighterTwister class"

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            self.__c_instance = c_instance
            self.show_message('Script initiated')
            self.init()

    def init(self):
        # initialize listeners, caches and colors
        self.flush_all()
        self.mf_disable_bank_buttons()
        self.mf_init_page_config()
        self.mf_init_light_pages()

        # Start listeners to call dispatcher
        self.song().view.add_detail_clip_listener(
            self.dispatch_detail_clip_listener)
        self.song().add_current_song_time_listener(
            self.dispatch_current_song_time_listener)
        self.song().view.add_selected_track_listener(
            self.dispatch_selected_track_listener)
        self.device_listener_wrapper()

        # Initialize the sequencer buttons
        self.sequencer_init_buttons()
        self.sequencer_init_rotaries()
        self.init_clip_page()
        self.init_pad_page()
        self.init_device_params()

    def flush_all(self):
        for poti in range(64):
            for channel in range(4):
                self._send_midi((175 + channel, poti, 0))

    def mf_init_page_config(self):
        # Initialize configuration parameters
        # Sequencer configuration
        self.sequencer_page_default_color = 1
        self.sequencer_current_page_color_index = self.sequencer_page_default_color
        self.sequencer_base_default_note = 36
        self.sequencer_current_selected_note = self.sequencer_base_default_note
        self.sequencer_clip_position_16th = None

        # Midi Channels
        self.rotary_midi_channel = 175 + 1
        self.ring_midi_channel = 175 + 1
        self.switch_midi_channel = 175 + 2
        self.light_midi_channel = 175 + 2
        # Pages cc map
        self.clip_page_cc = range(0, 16)
        self.sequencer_page_cc = range(16, 32)
        self.note_page_cc = range(32, 48)
        self.control_page_cc = range(48, 64)
        # Pages init color
        self.clip_page_colors = [1] * 16
        self.sequencer_page_colors = [self.sequencer_page_default_color] * 16
        self.note_page_colors = range(1, 127, 16) * 2
        #self.note_page_colors = [0] * 16
        self.control_page_colors = [1] * 16
        # Status cache for sequencer
        self.switch_encoder_status_cache = [False] * 64
        # List to store ButtonElements in
        self.switch_encoder_buttons = [False] * 64
        # Status cache for rotaries
        self.rotary_encoder_potis = [False] * 64

    def mf_init_light_pages(self):
        sequencer_page_map = zip(self.sequencer_page_cc,
                                 self.sequencer_page_colors)
        for light_encoder_cc, light_color_cc in sequencer_page_map:
            self._mf_set_light(light_encoder_cc, light_color_cc, False)
        note_page_map = zip(self.note_page_cc, self.note_page_colors)
        for light_encoder_cc, light_color_cc in note_page_map:
            self._mf_set_light(light_encoder_cc, light_color_cc, False)

    def _mf_set_light(self, light_encoder_cc, light_color_cc, status):
        # Sets color on midi channel 2 (177) end updates status cache
        # for sequencer to remember statuses
        self._send_midi(
            (self.light_midi_channel, light_encoder_cc, light_color_cc))
        self.switch_encoder_status_cache[light_encoder_cc] = status

    def mf_disable_bank_buttons(self):
        # Workaround for not sending values to track when pressing bank buttons
        self.padm0 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 0)
        self.padm1 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 1)
        self.padm2 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 2)
        self.padm3 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 3)
        self.padm0.add_value_listener(self.bank_buttons_dummy,
                                      identify_sender=True)
        self.padm1.add_value_listener(self.bank_buttons_dummy,
                                      identify_sender=True)
        self.padm2.add_value_listener(self.bank_buttons_dummy,
                                      identify_sender=True)
        self.padm3.add_value_listener(self.bank_buttons_dummy,
                                      identify_sender=True)

    def bank_buttons_dummy(self):
        pass

    def dispatch_detail_clip_listener(self):
        self.current_clip = self.song().view.highlighted_clip_slot.clip
        self.init_sequencer()
        try:
            if self.current_clip.is_midi_clip and not self.current_clip.notes_has_listener:
                # Update leds when notes are added or removed
                self.current_clip.add_notes_listener(
                    self._sequencer_update_notes_to_light)
                self.init_sequencer()
            else:
                self.sequencer_reset_colors()
        except AttributeError:
            pass

    def dispatch_current_song_time_listener(self):
        self.sequencer_light_follows_beat()

    def dispatch_selected_track_listener(self):
        self.device_auto_select()
        self.device_listener_wrapper()

    def device_listener_wrapper(self):
        selected_track = self.song().view.selected_track
        if not selected_track.devices_has_listener(self.device_auto_select):
            self.song().view.selected_track.add_devices_listener(
                self.device_auto_select)

    # Sequencer
    def init_sequencer(self):
        self.sequencer_current_selected_note = self.sequencer_base_default_note
        self.sequencer_current_page_color_index = self.sequencer_page_default_color
        self._sequencer_update_notes_to_light()

    def sequencer_init_buttons(self):
        for switch_encoder_cc in self.sequencer_page_cc:
            self.switch_encoder_buttons[switch_encoder_cc] = ButtonElement(
                IS_MOMENTARY, MIDI_CC_TYPE, 1, switch_encoder_cc)
            self.switch_encoder_buttons[switch_encoder_cc].add_value_listener(
                self.sequencer_button_press, identify_sender=True)
        self.padl14 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 14)
        self.padr17 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 17)
        self.padl16 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 16)
        self.padr19 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 19)
        self.padl14.add_value_listener(self.sequencer_side_button_press,
                                       identify_sender=True)
        self.padr17.add_value_listener(self.sequencer_side_button_press,
                                       identify_sender=True)
        self.padl16.add_value_listener(self.sequencer_side_button_press,
                                       identify_sender=True)
        self.padr19.add_value_listener(self.sequencer_side_button_press,
                                       identify_sender=True)

    def sequencer_init_rotaries(self):
        for rotary_encoder_cc in self.sequencer_page_cc:
            self.rotary_encoder_potis[rotary_encoder_cc] = EncoderElement(
                MIDI_CC_TYPE, 0, rotary_encoder_cc,
                Live.MidiMap.MapMode.absolute)
            self.rotary_encoder_potis[rotary_encoder_cc].add_value_listener(
                self.sequencer_rotary_change, identify_sender=True)

    def sequencer_rotary_change(self, value, sender):
        try:
            self.current_clip
        except AttributeError:
            return False
        if self.current_clip.is_midi_clip:
            cc_value = sender._msg_identifier
            if value > 0:
                if not self.switch_encoder_status_cache[cc_value]:
                    self._send_midi((self.light_midi_channel, cc_value,
                                     self.sequencer_current_light_on_color))
                    self._send_midi((self.ring_midi_channel, cc_value, 100))
                    self.switch_encoder_status_cache[cc_value] = True
                self.current_clip.set_notes(
                    ((self.sequencer_current_selected_note,
                      cc_value % 16 * 0.25, 0.25, value, False), ))
            elif value == 0:
                self._send_midi((self.light_midi_channel, cc_value,
                                 self.sequencer_current_page_color))
                self.current_clip.remove_notes(
                    cc_value % 16 * 0.25, self.sequencer_current_selected_note,
                    0.25, 1)
                self.switch_encoder_status_cache[cc_value] = False

    def sequencer_button_press(self, value, sender):
        try:
            self.current_clip
        except AttributeError:
            return False
        if self.current_clip.is_midi_clip:
            cc_value = sender._msg_identifier
            if value > 0:
                if not self.switch_encoder_status_cache[cc_value]:
                    self._send_midi((self.light_midi_channel, cc_value,
                                     self.sequencer_current_light_on_color))
                    self.current_clip.set_notes(
                        ((self.sequencer_current_selected_note,
                          cc_value % 16 * 0.25, 0.25, 100, False), ))
                    self.switch_encoder_status_cache[cc_value] = True
                    self._send_midi((self.ring_midi_channel, cc_value, 100))
                else:
                    self._send_midi((self.light_midi_channel, cc_value,
                                     self.sequencer_current_page_color))
                    self._send_midi((self.ring_midi_channel, cc_value, 0))
                    self.current_clip.remove_notes(
                        cc_value % 16 * 0.25,
                        self.sequencer_current_selected_note, 0.25, 1)
                    self.switch_encoder_status_cache[cc_value] = False

    def sequencer_side_button_press(self, value, sender):
        try:
            cc_value = sender._msg_identifier
            if value > 0:
                # Note/clolor up/down
                if cc_value == 14 and self.sequencer_current_selected_note > 0:
                    self.sequencer_current_selected_note = self.sequencer_current_selected_note - 1
                    self.sequencer_current_page_color_index = self.sequencer_current_page_color_index - 16
                    self._sequencer_update_notes_to_light()
                    self.sequencer_clip_position_16th = None
                    self.show_message(
                        "Selected Midi Note: " +
                        str(self.sequencer_current_selected_note))
                if cc_value == 17 and self.sequencer_current_selected_note < 127:
                    self.sequencer_current_selected_note = self.sequencer_current_selected_note + 1
                    self.sequencer_current_page_color_index = self.sequencer_current_page_color_index + 16
                    self._sequencer_update_notes_to_light()
                    self.sequencer_clip_position_16th = None
                    self.show_message(
                        "Selected Midi Note: " +
                        str(self.sequencer_current_selected_note))
                # New/duplicate clip
                if cc_value == 16 and self.sequencer_current_selected_note > 0:
                    self.duplicate_clip()
                if cc_value == 19 and self.sequencer_current_selected_note > 0:
                    self.session_record()
        except AttributeError:
            pass

    def sequencer_light_follows_beat(self):
        try:
            if self.current_clip.is_midi_clip:
                if self.sequencer_clip_position_16th == None:
                    self.sequencer_clip_position_16th = int(
                        self.current_clip.playing_position / 0.25)
                    if self.switch_encoder_status_cache[self.sequencer_page_cc[
                            self.sequencer_clip_position_16th]]:
                        self._send_midi(
                            (177, self.sequencer_page_cc[
                                self.sequencer_clip_position_16th],
                             self.sequencer_current_light_on_color))
                    else:
                        self._send_midi((177, self.sequencer_page_cc[
                            self.sequencer_clip_position_16th],
                                         self.sequencer_current_page_color))
                elif self.sequencer_clip_position_16th != int(
                        self.current_clip.playing_position / 0.25):
                    if self.switch_encoder_status_cache[self.sequencer_page_cc[
                            self.sequencer_clip_position_16th]]:
                        self._send_midi(
                            (177, self.sequencer_page_cc[
                                self.sequencer_clip_position_16th],
                             self.sequencer_current_light_on_color))
                    else:
                        self._send_midi((177, self.sequencer_page_cc[
                            self.sequencer_clip_position_16th],
                                         self.sequencer_current_page_color))
                    self.sequencer_clip_position_16th = int(
                        self.current_clip.playing_position / 0.25)
                    self._send_midi((177, self.sequencer_page_cc[
                        self.sequencer_clip_position_16th],
                                     self.sequencer_current_light_beat_color))
        except IndexError:
            pass

    @property
    def sequencer_current_light_on_color(self):
        # light on color to be relative to page color
        return self.sequencer_current_page_color + 32 % 128

    @property
    def sequencer_current_light_beat_color(self):
        # light on color to be relative to page color
        return self.sequencer_current_page_color + 64 % 128

    @property
    def sequencer_current_page_color(self):
        return self.sequencer_current_page_color_index % 128

    def _sequencer_get_midi_notes(self, note):
        # self.current_clip.get_notes(start, self.sequencer_current_selected_note,
        # selection_length, hight)
        try:
            return self.current_clip.get_notes(0, note, 4, 1)
        except AttributeError:
            return []

    def _sequencer_update_notes_to_light(self):
        self.sequencer_reset_colors()
        notes_for_current_selected_note = self._sequencer_get_midi_notes(
            self.sequencer_current_selected_note)
        for note in notes_for_current_selected_note:
            light_encoder_cc = int(note[1] * 4 + self.sequencer_page_cc[0])
            self._send_midi(
                (self.ring_midi_channel, light_encoder_cc, note[3]))
            self._mf_set_light(light_encoder_cc,
                               self.sequencer_current_light_on_color, True)

    def sequencer_reset_colors(self):
        for light_encoder_cc in self.sequencer_page_cc:
            self._mf_set_light(light_encoder_cc,
                               self.sequencer_current_page_color, False)
            self._send_midi((self.ring_midi_channel, light_encoder_cc, 0))

    def duplicate_clip(self):
        self.log_message("duplicate clip")
        #if self._clip_slot and self._clip_slot.has_clip:
        #    slot_name = self._clip_slot.clip.name
        #    track = self._clip_slot.canonical_parent
        current_track = self.song().view.selected_track
        current_clip_slot = self.song().view.highlighted_clip_slot
        self.song().duplicate_scene(
            list(current_track.clip_slots).index(current_clip_slot))
        #new_clip = current_track.duplicate_clip_slot(
        #    list(current_track.clip_slots).index(current_clip_slot)+1)
        #self.log_message(new_clip)
        #selected_track = self.song().view.selected_track
        #selected_track.duplicate_clip_slot(selected_track)

    def session_record(self):
        self.log_message("session record")
        #self.song().trigger_session_record()

# Clip page setion

    def init_clip_page(self):
        num_tracks = 4
        num_scenes = 3
        self.flash_status = 1
        self.Mixer = MixerComponent(4, 3)

        # Volencoder
        self.volencoders = [None for index in range(num_tracks)]
        for index in range(num_tracks):
            self.volencoders[index] = EncoderElement(
                MIDI_CC_TYPE, 0, index, Live.MidiMap.MapMode.absolute)
            self.Mixer.channel_strip(index).set_volume_control(
                self.volencoders[index])

        # Sendencoder
        for index in range(num_tracks):
            encoder_cc_send_1 = index + num_tracks
            encoder_cc_send_2 = index + num_tracks * 2
            send1 = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_send_1,
                                   Live.MidiMap.MapMode.absolute)
            send2 = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_send_2,
                                   Live.MidiMap.MapMode.absolute)
            self.Mixer.channel_strip(index).set_send_controls((send1, send2))

        # Panencoder
        for index in range(num_tracks):
            encoder_cc_pan = index + num_tracks * 3
            pan = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_pan,
                                 Live.MidiMap.MapMode.absolute)
            self.Mixer.channel_strip(index).set_pan_control(pan)

        # Arm-/selectbuttons
        for index in range(num_tracks):
            armbutton = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1,
                                      index + 12)
            self.Mixer.channel_strip(index).set_arm_button(armbutton)
            self.Mixer.channel_strip(index).set_select_button(armbutton)

        # Navigation buttons
        self.padl11 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 11)
        self.padr8 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 8)
        self.padl10 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 10)
        self.padr13 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 13)

        self.grid = [None for index in range(num_tracks * 3)]
        for index in range(num_tracks * 3):
            self.grid[index] = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1,
                                             index)
        self.matrix = ButtonMatrixElement()
        for row in range(num_scenes):
            button_row = []
            for column in range(num_tracks):
                button_row.append(self.grid[column + (row * 4)])
                self.log_message(str(column + (row * 4)))
            self.matrix.add_row(tuple(button_row))

        self.Session = SessionComponent(num_tracks, num_scenes)
        self.Session.name = "Session"
        self.Session.set_offsets(0, 0)
        self.Session.set_mixer(self.Mixer)
        self.Session._do_show_highlight()
        self.set_highlighting_session_component(self.Session)
        self.Session.set_track_bank_buttons(self.padl11, self.padr8)
        self.Session.set_scene_bank_buttons(self.padr13, self.padl10)

        self.scene = [None for index in range(num_scenes)]
        for row in range(num_scenes):
            self.scene[row] = self.Session.scene(row)
            self.scene[row].name = 'Scene_' + str(row)
            for column in range(num_tracks):
                clip_slot = self.scene[row].clip_slot(column)
                clip_slot.name = str(column) + '_Clip_Slot' + str(row)
                self.scene[row].clip_slot(column).set_triggered_to_play_value(
                    35)
                self.scene[row].clip_slot(column).set_stopped_value(68)
                self.scene[row].clip_slot(column).set_started_value(45)
                self.scene[row].clip_slot(
                    column).set_triggered_to_record_value(100)
                self.scene[row].clip_slot(column).set_recording_value(80)

        for column in range(num_tracks):
            for row in range(num_scenes):
                self.scene[row].clip_slot(column).set_launch_button(
                    self.grid[column + (row * 4)])
            for index in range(num_tracks * num_scenes):
                self.grid[index].clear_send_cache()

    def update_display(self):
        # Called every 100 ms
        ControlSurface.update_display(self)
        self.refresh_state()
        self.Session.set_enabled(True)
        self.Session.update()
        # Sequencer hack
        try:
            for light_encoder_cc in self.sequencer_page_cc:
                self._send_midi((self.ring_midi_channel, light_encoder_cc, 0))
            notes_for_current_selected_note = self._sequencer_get_midi_notes(
                self.sequencer_current_selected_note)
            for note in notes_for_current_selected_note:
                light_encoder_cc = int(note[1] * 4 + self.sequencer_page_cc[0])
                self._send_midi(
                    (self.ring_midi_channel, light_encoder_cc, note[3]))
        except AttributeError:
            pass

    # Pad Section
    def init_pad_page(self):
        self.pad_device_params()
        PAD_TRANSLATION = ((0, 0, 32, 1), (1, 0, 33, 1), (2, 0, 34, 1),
                           (3, 0, 35, 1), (0, 1, 36, 1), (1, 1, 37, 1),
                           (2, 1, 38, 1), (3, 1, 39, 1), (0, 2, 40, 1),
                           (1, 2, 41, 1), (2, 2, 42, 1), (3, 2, 43, 1),
                           (0, 3, 44, 1), (1, 3, 45, 1), (2, 3, 46,
                                                          1), (3, 3, 47, 1))
        self.set_pad_translations(PAD_TRANSLATION)
        self._device_selection_follows_track_selection = True

    def pad_device_params(self):
        device_param_controls = []
        for param in self.note_page_cc[:8]:
            self.rotary_encoder_potis[param] = EncoderElement(
                MIDI_CC_TYPE, 0, param, Live.MidiMap.MapMode.absolute)
            self.rotary_encoder_potis[param].release_parameter()
            self.rotary_encoder_potis[param].send_value(0, True)
            self.rotary_encoder_potis[param].clear_send_cache()
            device_param_controls.append(self.rotary_encoder_potis[param])

        device = DeviceComponent()
        device.name = 'Device_Component pad'
        device.set_parameter_controls(tuple(device_param_controls))
        self.set_device_component(device)

    #def scrolling(self):
    #    self.application().view.scroll_view(ndir, 'Detail/DeviceChain', True)

    # Live.Song.Song.View.selected_track
    #Live.Song.Song.View.select_device()[0]

    # Device parameter section
    def init_device_params(self):
        device_param_controls = []
        device_bank_buttons = []
        for param in self.control_page_cc[:8]:
            self.rotary_encoder_potis[param] = EncoderElement(
                MIDI_CC_TYPE, 0, param, Live.MidiMap.MapMode.absolute)
            self.switch_encoder_buttons[param] = ButtonElement(
                IS_MOMENTARY, MIDI_CC_TYPE, 1, param)
            self.rotary_encoder_potis[param].release_parameter()
            self.rotary_encoder_potis[param].send_value(0, True)
            self.rotary_encoder_potis[param].clear_send_cache()
            device_param_controls.append(self.rotary_encoder_potis[param])
            device_bank_buttons.append(self.switch_encoder_buttons[param])

        device = DeviceComponent()
        device.name = 'Device_Component'
        device.set_parameter_controls(tuple(device_param_controls))
        device.set_bank_buttons(tuple(device_bank_buttons))
        device.set_on_off_button(
            ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 56))
        self.set_device_component(device)

    def device_auto_select(self):
        # Iterates through devices within a track and assigns the first
        # DrumPad device to activate the individual drum's device.
        # Use first device in case none is a DrumPad device.
        selected_track = self.song().view.selected_track
        devices = selected_track.devices
        for device in devices:
            if device.can_have_drum_pads:
                self.current_drum_device = device
                pad_device = self.current_drum_device.view.selected_chain.devices[
                    0]
                self.song().view.select_device(pad_device)
                if not self.current_drum_device.view.selected_drum_pad_has_listener(
                        self.device_update_current_note):
                    self.current_drum_device.view.add_selected_drum_pad_listener(
                        self.device_update_current_note)
                break
            else:
                self.song().view.select_device(devices[0])

    def device_update_current_note(self):
        current_note = self.current_drum_device.view.selected_drum_pad.note
        self.sequencer_current_selected_note = current_note

        # Update light of active pad
        #self._send_midi((self.light_midi_channel, light_encoder_cc, 63))
        try:
            self.current_clip = self.song().view.highlighted_clip_slot.clip
            self.current_clip.is_midi_clip
            self._sequencer_update_notes_to_light()
        except AttributeError:
            pass
Example #37
0
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self._device_selection_follows_track_selection = True
        with self.component_guard():
            self._suppress_send_midi = True
            self._suppress_session_highlight = True
            self._control_is_with_automap = False
            is_momentary = True
            self._suggested_input_port = 'Akai MPK26'
            self._suggested_output_port = 'Akai MPK26'
            self.log("BEFORE mixer")
            self._setup_mixer_control()
            self._setup_device_control()


            # self.clipcontrol(8)

            self.log("AFTER MIXER")
            """SESSION ViEW"""
            global session
            session = SessionComponent(GRIDSIZE[0],GRIDSIZE[1])
            session.name = 'Session_Control'
            matrix = ButtonMatrixElement()
            matrix.name = 'Button_Matrix'
            up_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, UP_BUTTON)
            down_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, DOWN_BUTTON)
            left_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, LEFT_BUTTON)
            right_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, RIGHT_BUTTON)

            session.set_scene_bank_buttons(down_button, up_button)
            session.set_track_bank_buttons(right_button, left_button)

            # session_zoom = SessionZoomingComponent(session)
            # session_zoom.set_nav_buttons(up_button,down_button,left_button,right_button)
            session_stop_buttons = []
            self.log("SETTING UP GRID")
            for row in xrange(GRIDSIZE[1]):
                button_row = []
                self.log("CZ ROW")
                self.log(str(row))
                scene = session.scene(row)
                scene.name = 'Scene_' + str(row)
                scene.set_launch_button(ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, SCENE_BUTTONS[row]))
                scene.set_triggered_value(2)

                for column in xrange(GRIDSIZE[0]):
                    self.log("CZ COLUMN")
                    self.log(str(column))
                    button = ConfigurableButtonElement(True, MIDI_NOTE_TYPE, CHANNEL_MIXER, LAUNCH_BUTTONS[row][column])
                    button.name = str(column) + '_Clip_' + str(row) + '_Button'
                    button_row.append(button)
                    clip_slot = scene.clip_slot(column)
                    clip_slot.name = str(column) + '_Clip_Slot_' + str(row)
                    clip_slot.set_launch_button(button)

                matrix.add_row(tuple(button_row))

            for column in xrange(GRIDSIZE[0]):
                session_stop_buttons.append((ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL_MIXER, TRACK_STOPS[column])))

            self._suppress_session_highlight = False
            self._suppress_send_midi = False
            self.set_highlighting_session_component(session)
            session.set_stop_track_clip_buttons(tuple(session_stop_buttons))
            session.set_mixer(mixer)
Example #38
0
class LemurPad(MonOhm):
    __module__ = __name__
    __doc__ = " Lemur version of the MonOhm companion controller script "

    def __init__(self, *a, **k):
        self._timer_callbacks = [
        ]  #Used for _monobridge, which uses L8 method for registering timer callbacks.  deprecated, needs to be replaced by new L9 Task class.
        self._osc_registry = {}
        self._display_button_names = DISPLAY_BUTTON_NAMES
        super(LemurPad, self).__init__(*a, **k)
        self._host_name = "LemurPad"
        self._color_type = 'AumPad'
        self.connected = 0
        with self.component_guard():
            self._setup_touchosc()
            self._assign_host2()
            self._assign_session_colors()

    def query_ohm(self):
        pass

    """script initialization methods"""

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

    def _setup_controls(self):
        is_momentary = True
        self._fader = [None for index in range(8)]
        self._dial = [None for index in range(16)]
        self._button = [None for index in range(8)]
        self._menu = [None for index in range(6)]
        for index in range(8):
            self._fader[index] = OSCMonoEncoderElement(
                MIDI_CC_TYPE,
                CHANNEL,
                OHM_FADERS[index],
                Live.MidiMap.MapMode.absolute,
                'Fader_' + str(index),
                index,
                self,
                osc='/Fader_' + str(index) + '/x',
                osc_parameter='/Strip' + str(index + 8) + '/set',
                osc_name='/Strip' + str(index) + '/set')
        for index in range(8):
            self._button[index] = OSCMonoButtonElement(
                is_momentary,
                MIDI_NOTE_TYPE,
                CHANNEL,
                OHM_BUTTONS[index],
                'Button_' + str(index),
                self,
                osc='/Select_' + str(index) + '/value',
                osc_alt='/Select/set ' + str(index),
                osc_name='/Select/text ' + str(index))
        for index in range(16):
            self._dial[index] = OSCMonoEncoderElement(
                MIDI_CC_TYPE,
                CHANNEL,
                OHM_DIALS[index],
                Live.MidiMap.MapMode.absolute,
                'Dial_' + str(index),
                index + 8,
                self,
                osc='/Dial_' + str(index) + '/x',
                osc_parameter='/Dial' + str(index) + 'val/set',
                osc_name='/Dial' + str(index) + 'name/set')
        for index in range(6):
            self._menu[index] = OSCMonoButtonElement(
                is_momentary,
                MIDI_NOTE_TYPE,
                CHANNEL,
                OHM_MENU[index],
                'Menu_' + str(index),
                self,
                osc='/Function_' + str(index) + '/value',
                osc_alt='/Function/set ' + str(index),
                osc_name='/Function/text ' + str(index))
        self._crossfader = OSCMonoEncoderElement(MIDI_CC_TYPE,
                                                 CHANNEL,
                                                 CROSSFADER,
                                                 Live.MidiMap.MapMode.absolute,
                                                 "Crossfader",
                                                 24,
                                                 self,
                                                 osc='/XFader/x',
                                                 osc_parameter='/XFader/none',
                                                 osc_name=None)
        self._livid = OSCMonoButtonElement(is_momentary,
                                           MIDI_NOTE_TYPE,
                                           CHANNEL,
                                           LIVID,
                                           'Livid_Button',
                                           self,
                                           osc='/Livid/x',
                                           osc_alt='/Livid/x',
                                           osc_name=None)
        self._shift_l = OSCMonoButtonElement(is_momentary,
                                             MIDI_NOTE_TYPE,
                                             CHANNEL,
                                             SHIFT_L,
                                             'Shift_Button_Left',
                                             self,
                                             osc='/ShiftL/x',
                                             osc_alt='/ShiftL/x',
                                             osc_name=None)
        self._shift_r = OSCMonoButtonElement(is_momentary,
                                             MIDI_NOTE_TYPE,
                                             CHANNEL,
                                             SHIFT_R,
                                             'Shift_Button_Right',
                                             self,
                                             osc='/ShiftR/x',
                                             osc_alt='/ShiftR/x',
                                             osc_name=None)
        self._matrix = ButtonMatrixElement()
        self._matrix.name = 'Matrix'
        self._monomod = ButtonMatrixElement()
        self._monomod.name = 'Monomod'
        self._grid = [None for index in range(8)]
        for column in range(8):
            self._grid[column] = [None for index in range(8)]
            for row in range(8):
                self._grid[column][row] = OSCMonoButtonElement(
                    is_momentary,
                    MIDI_NOTE_TYPE,
                    CHANNEL, (column * 8) + row,
                    'Grid_' + str(column) + '_' + str(row),
                    self,
                    osc='/ClipGrid_' + str(column) + '_' + str(row) + '/value',
                    osc_alt='/ClipGrid/set ' + str(column) + ' ' + str(row),
                    osc_name='/ClipGrid/text ' + str(column) + ' ' + str(row))
        for row in range(5):
            button_row = []
            for column in range(7):
                button_row.append(self._grid[column][row])
            self._matrix.add_row(tuple(button_row))
        for row in range(8):
            button_row = []
            for column in range(8):
                button_row.append(self._grid[column][row])
            self._monomod.add_row(tuple(button_row))
        self._dummy_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15,
                                           125)
        self._dummy_button.name = 'Dummy1'
        self._dummy_button2 = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15,
                                            126)
        self._dummy_button2.name = 'Dummy2'
        self._dummy_button3 = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15,
                                            127)
        self._dummy_button2.name = 'Dummy3'
        self._monomod256 = ButtonMatrixElement()
        self._monomod256.name = 'Monomod256'
        self._square = [None for index in range(16)]
        for column in range(16):
            self._square[column] = [None for index in range(16)]
            for row in range(16):
                self._square[column][row] = OSCMonoButtonElement(
                    is_momentary,
                    MIDI_NOTE_TYPE,
                    int(column / 8) + 1,
                    row + ((column % 8) * 16),
                    '256Grid_' + str(column) + '_' + str(row),
                    self,
                    osc='/Grid_' + str(column) + '_' + str(row) + '/value',
                    osc_alt='/Grid/set ' + str(column) + ' ' + str(row),
                    osc_name=None)
                #self._square[column][row] = FlashingButtonElement(is_momentary, 0, 15, -1, '256Grid_' + str(column) + '_' + str(row), '/1/p_grid/'+str(column)+'/'+str(row), '/1/c_grid/'+str(column)+'/'+str(row), self)
        for row in range(16):
            button_row = []
            for column in range(16):
                button_row.append(self._square[column][row])
            self._monomod256.add_row(tuple(button_row))
        self._bank_buttons = ButtonMatrixElement()
        self._key_buttons = ButtonMatrixElement()
        self._bank_button = [None for index in range(2)]
        for index in range(2):
            self._bank_button[index] = OSCMonoButtonElement(
                is_momentary,
                MIDI_NOTE_TYPE,
                15,
                index,
                '256Grid_Bank_' + str(index),
                self,
                osc='/Shift_' + str(index) + '/value',
                osc_alt='/Shift/set ' + str(index),
                osc_name=None)
        button_row = []
        for index in range(2):
            button_row.append(self._bank_button[index])
        self._bank_buttons.add_row(tuple(button_row))
        button_row = []
        self._key_button = [None for index in range(8)]
        for index in range(8):
            self._key_button[index] = OSCMonoButtonElement(
                is_momentary,
                MIDI_NOTE_TYPE,
                15,
                index + 8,
                '256Grid_Key_' + str(index),
                self,
                osc='/Keys_' + str(index) + '/value',
                osc_alt='/Keys/set ' + str(index),
                osc_name=None)
        for index in range(8):
            button_row.append(self._key_button[index])
        self._key_buttons.add_row(tuple(button_row))

    def _setup_session_control(self):
        is_momentary = True
        num_tracks = 4
        num_scenes = 5
        self._session = NameServerSessionComponent(num_tracks, num_scenes,
                                                   self)
        self._session.name = "Left_Session"
        self._session.set_offsets(0, 0)
        self._session.set_stop_clip_value(self._color_defs['STOP_CLIP'])
        self._scene = [None for index in range(5)]
        for row in range(num_scenes):
            self._scene[row] = self._session.scene(row)
            self._scene[row].name = 'L_Scene_' + str(row)
            for column in range(num_tracks):
                clip_slot = self._scene[row].clip_slot(column)
                clip_slot.name = str(column) + '_Clip_Slot_L_' + str(row)
                clip_slot.set_triggered_to_play_value(
                    self._color_defs['CLIP_TRG_PLAY'])
                clip_slot.set_triggered_to_record_value(
                    self._color_defs['CLIP_TRG_REC'])
                clip_slot.set_stopped_value(self._color_defs['CLIP_STOP'])
                clip_slot.set_started_value(self._color_defs['CLIP_STARTED'])
                clip_slot.set_recording_value(
                    self._color_defs['CLIP_RECORDING'])
        self._session.set_mixer(self._mixer)
        self._session_zoom = SessionZoomingComponent(self._session)
        self._session_zoom.name = 'L_Session_Overview'
        self._session_zoom.set_stopped_value(self._color_defs['ZOOM_STOPPED'])
        self._session_zoom.set_playing_value(self._color_defs['ZOOM_PLAYING'])
        self._session_zoom.set_selected_value(
            self._color_defs['ZOOM_SELECTED'])
        self._session_zoom._zoom_button = (self._dummy_button)
        self._session_zoom.set_enabled(True)
        self._session2 = SessionComponent(num_tracks, num_scenes)
        self._session2.name = 'Right_Session'
        self._session2.set_offsets(4, 0)
        self._session2.set_stop_clip_value(self._color_defs['STOP_CLIP'])
        self._scene2 = [None for index in range(5)]
        for row in range(num_scenes):
            self._scene2[row] = self._session2.scene(row)
            self._scene2[row].name = 'R_Scene_' + str(row)
            for column in range(num_tracks):
                clip_slot = self._scene2[row].clip_slot(column)
                clip_slot.name = str(column) + '_Clip_Slot_R_' + str(row)
                clip_slot.set_triggered_to_play_value(
                    self._color_defs['CLIP_TRG_PLAY'])
                clip_slot.set_triggered_to_record_value(
                    self._color_defs['CLIP_TRG_REC'])
                clip_slot.set_stopped_value(self._color_defs['CLIP_STOP'])
                clip_slot.set_started_value(self._color_defs['CLIP_STARTED'])
                clip_slot.set_recording_value(
                    self._color_defs['CLIP_RECORDING'])
        self._session2.set_mixer(self._mixer2)
        self._session2.add_offset_listener(self._on_session_offset_changes)
        self._session_zoom2 = SessionZoomingComponent(self._session2)
        self._session_zoom2.name = 'R_Session_Overview'
        self._session_zoom2.set_stopped_value(self._color_defs['ZOOM_STOPPED'])
        self._session_zoom2.set_playing_value(self._color_defs['ZOOM_PLAYING'])
        self._session_zoom2.set_selected_value(
            self._color_defs['ZOOM_SELECTED'])
        self._session_zoom.set_enabled(True)
        self._session_zoom2._zoom_button = (self._dummy_button2)
        self._session_main = SessionComponent(8, num_scenes)
        self._session_main.name = 'Main_Session'
        self._session_main.set_stop_clip_value(self._color_defs['STOP_CLIP'])
        self._scene_main = [None for index in range(5)]
        for row in range(num_scenes):
            self._scene_main[row] = self._session_main.scene(row)
            self._scene_main[row].name = 'M_Scene_' + str(row)
            for column in range(8):
                clip_slot = self._scene_main[row].clip_slot(column)
                clip_slot.name = str(column) + '_Clip_Slot_M_' + str(row)
                clip_slot.set_triggered_to_play_value(
                    self._color_defs['CLIP_TRG_PLAY'])
                clip_slot.set_triggered_to_record_value(
                    self._color_defs['CLIP_TRG_REC'])
                clip_slot.set_stopped_value(self._color_defs['CLIP_STOP'])
                clip_slot.set_started_value(self._color_defs['CLIP_STARTED'])
                clip_slot.set_recording_value(
                    self._color_defs['CLIP_RECORDING'])
        self._session_main.set_mixer(self._mixer)
        self._session_zoom_main = SessionZoomingComponent(self._session_main)
        self._session_zoom_main.name = 'M_Session_Overview'
        self._session_zoom_main.set_stopped_value(
            self._color_defs['ZOOM_STOPPED'])
        self._session_zoom_main.set_playing_value(
            self._color_defs['ZOOM_PLAYING'])
        self._session_zoom_main.set_selected_value(
            self._color_defs['ZOOM_SELECTED'])
        self._session_zoom_main.set_enabled(True)
        self._session_zoom_main._zoom_button = (self._dummy_button3)
        self._sessions = [self._session, self._session2, self._session_main]
        self._zooms = [
            self._session_zoom, self._session_zoom2, self._session_zoom_main
        ]

    def _setup_mod(self):
        self.monomodular = get_monomodular(self)
        self.monomodular.name = 'monomodular_switcher'
        self.modhandler = LemurOhmModHandler(self)
        self.modhandler.name = 'ModHandler'
        self.modhandler256 = LemurModHandler(self)
        self.modhandler256.name = 'ModHandler256'

    def _assign_host2(self):
        self.modhandler256.set_shift_button(self._bank_button[0])
        self.modhandler256.set_alt_button(self._bank_button[1])
        self.modhandler256.set_grid(self._monomod256)
        self.modhandler256.set_key_buttons(self._key_buttons)
        self.modhandler256.set_enabled(True)

    def _setup_touchosc(self):
        self._osc_registry = {}
        #self._osc_registry['/ping'] = self._monobridge.ping
        #self._osc_registry['/1'] = self._monobridge.page1
        #self._osc_registry['/2'] = self._monobridge.page2
        for control in self.controls:
            if hasattr(control, 'osc'):
                self._osc_registry[control.osc] = control.set_value
            #if hasattr(control, 'osc_alt'):
            #	self._osc_registry[control.osc_alt] = control.set_value
            #self.log_message('create dict key: ' + str(control.osc) + str(control.name))

    """shift/zoom methods"""

    def deassign_matrix(self):
        super(LemurPad, self).deassign_matrix()
        self.clear_grid_names()

    """menu button management methods"""

    def deassign_menu(self):
        super(LemurPad, self).deassign_menu()
        for index in range(6):
            self._monobridge._send_osc(self._menu[index].osc_name,
                                       self.generate_strip_string(' '))

    def assign_device_nav_to_menu(self):
        super(LemurPad, self).assign_device_nav_to_menu()
        for index in range(6):
            self._monobridge._send_osc(
                self._menu[index].osc_name,
                self.generate_strip_string(str(DEVICE_NAV_NAMES[index])))

    def assign_transport_to_menu(self):
        super(LemurPad, self).assign_transport_to_menu()
        for index in range(6):
            self._monobridge._send_osc(
                self._menu[index].osc_name,
                self.generate_strip_string(str(TRANSPORT_NAMES[index])))

    def assign_session_nav_to_menu(self):
        super(LemurPad, self).assign_session_nav_to_menu()
        for index in range(6):
            self._monobridge._send_osc(
                self._menu[index].osc_name,
                self.generate_strip_string(str(SESSION_NAV_NAMES[index])))

    def assign_session_main_nav_to_menu(self):
        super(LemurPad, self).assign_session_main_nav_to_menu()
        for index in range(6):
            self._monobridge._send_osc(
                self._menu[index].osc_name,
                self.generate_strip_string(str(SESSION_NAV_NAMES[index])))

    def assign_monomod_shift_to_menu(self):
        super(LemurPad, self).assign_monomod_shift_to_menu()
        for index in range(6):
            self._monobridge._send_osc(
                self._menu[index].osc_name,
                self.generate_strip_string(str(MONOMOD_SHIFT_NAMES[index])))

    def assign_monomod_to_menu(self):
        super(LemurPad, self).assign_monomod_shift_to_menu()
        for index in range(6):
            self._monobridge._send_osc(
                self._menu[index].osc_name,
                self.generate_strip_string(str(MONOMOD_NAMES[index])))

    def assign_session_bank_to_menu(self):
        super(LemurPad, self).assign_session_bank_to_menu()
        for index in range(6):
            self._monobridge._send_osc(
                self._menu[index].osc_name,
                self.generate_strip_string(str(SESSION_BANK_NAMES[index])))

    def assign_session2_bank_to_menu(self):
        super(LemurPad, self).assign_session2_bank_to_menu()
        for index in range(6):
            self._monobridge._send_osc(
                self._menu[index].osc_name,
                self.generate_strip_string(str(SESSION_BANK2_NAMES[index])))

    def assign_session_main_nav_to_menu(self):
        super(LemurPad, self).assign_session_main_nav_to_menu()
        for index in range(6):
            self._monobridge._send_osc(
                self._menu[index].osc_name,
                self.generate_strip_string(str(
                    SESSION_MAIN_BANK_NAMES[index])))

    """m4l bridge"""

    def generate_strip_string(self, display_string):
        NUM_CHARS_PER_DISPLAY_STRIP = 9
        if (not display_string):
            return ('`_')
        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.replace(' ', '_')

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

    def clip_name(self, sender, name):
        #self.log_message('clip name ' + str(sender.osc_name) + ' ' + str(self.generate_strip_string(str(name))))
        self._monobridge._send_osc(sender.osc_name,
                                   self.generate_strip_string(str(name)))

    """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():
					clip_names.append(clip_slot._clip_slot)##.clip.name)
					#return clip_slot._clip_slot
					#self.log_message('clip name' + str(clip_slot._clip_slot.clip.name))
		return clip_names"""
    """called on timer"""

    def update_display(self):
        super(LemurPad, self).update_display()
        for callback in self._timer_callbacks:
            callback()

    def strobe(self):
        pass

    """general functionality"""

    def disconnect(self):
        super(MonOhm, self).disconnect()

    def clear_grid_names(self):
        #self.log_message('clear grid names' + str(self))
        for column in range(8):
            for row in range(8):
                self._monobridge._send_osc(self._grid[column][row].osc_name,
                                           '`_')

    def _register_timer_callback(self, callback):
        """ Registers a callback that is triggerd on every call of update_display """
        assert (callback != None)
        assert (dir(callback).count('im_func') is 1)
        assert (self._timer_callbacks.count(callback) == 0)
        self._timer_callbacks.append(callback)
        return None

    def _unregister_timer_callback(self, callback):
        """ Unregisters a timer callback """
        assert (callback != None)
        assert (dir(callback).count('im_func') is 1)
        assert (self._timer_callbacks.count(callback) == 1)
        self._timer_callbacks.remove(callback)
        return None

    def _set_brightness(self, value):
        #self._bright = (value != 0)
        #for control in self.controls:
        #	if isinstance(control, OSCMonoButtonElement):
        #		self._monobridge._send_osc(control.osc_alt, int(self._bright), True)
        pass

    def reset(self):
        #self._monobridge._send_osc('/reset')
        for control in self.controls:
            control.reset()

    def assign_lower_grid_names(self, mode):
        if self._display_button_names is True:
            for column in range(8):
                for row in range(3):
                    self._monobridge._send_osc(
                        self._grid[column][row + 5].osc_name,
                        self.generate_strip_string(
                            str(GRID_NAMES[mode][row][column])))

    def reset_and_refresh_state(self, *a, **k):
        self.schedule_message(1, self.reset)
        self.schedule_message(2, self.refresh_state)
Example #39
0
class OP1(ControlSurface):
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self.c_instance = c_instance

        self.retries_count = 0
        self.device_connected = False

        self.clip_color_callbacks = {}
        self.slot_callbacks = {}

        self.text_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x03)
        self.text_end_sequence = (0xf7, )
        self.enable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x02, 0xf7)
        self.disable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x00,
                                 0xf7)

        self.id_sequence = (0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7)

        self.text_color_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x04)

        self.log('INITIALIZING')

        self.app = Live.Application.get_application()

        #maj = self.app.get_major_version()
        #min = self.app.get_minor_version()
        #bug = self.app.get_bugfix_version()
        #self.show_message(str(1) + "." + str(0) + "." + str(9))

        self.show_message("Version " + VERSION)

        # reseting text
        self.write_text(' ')

        # reset display clips
        self.reset_display_clips()

        # getting browser visible state
        self.session_browser_visible = self.app.view.is_view_visible("Browser")

        # getting browser visible state
        self.arrange_browser_visible = self.app.view.is_view_visible("Browser")

        # getting session view visible state
        self.session_visible = self.app.view.is_view_visible("Session")

        # getting arrange view visible state
        self.arrange_visible = self.app.view.is_view_visible("Arranger")

        # getting detail view visible state
        self.detail_visible = self.app.view.is_view_visible("Detail")

        # getting back to arranger state
        self.back_to_arranger_state = self.song().back_to_arranger

        # initializing channel strip to null
        self._channel_strip = None

        # initializing transport component
        self._transport = TransportComponent()

        # initializing mixer component
        self._mixer = MixerComponent(NUM_TRACKS, 2)

        # initializing session component
        self._session = SessionComponent(NUM_TRACKS, NUM_ROWS)
        self._session.add_offset_listener(self.session_offset_changed)

        # configuring operation mode selector buttons
        self._operation_mode_buttons = ButtonElement(
            True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_1_BUTTON), ButtonElement(
                True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_2_BUTTON), ButtonElement(
                    True, MIDI_CC_TYPE, CHANNEL,
                    OP1_MODE_3_BUTTON), ButtonElement(True, MIDI_CC_TYPE,
                                                      CHANNEL,
                                                      OP1_MODE_4_BUTTON),

        # initializing operation mode selector
        self._operation_mode_selector = OP1ModeSelectorComponent(
            self, self._transport, self._mixer, self._session)

        # setting operation mode selector buttons
        self._operation_mode_selector.set_mode_buttons(
            self._operation_mode_buttons)

        # adding value listener for operation mode index
        self._operation_mode_selector.add_mode_index_listener(
            self.mode_index_changed)

        # setting global transport assignments
        self._transport.set_record_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_REC_BUTTON))
        self._transport.set_play_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_PLAY_BUTTON))
        self._transport.set_stop_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_STOP_BUTTON))
        self._transport.set_metronome_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_METRONOME_BUTTON))
        self._transport.set_tap_tempo_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_HELP_BUTTON))
        self._transport.set_punch_buttons(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS1_BUTTON),
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS2_BUTTON))
        self._transport.set_loop_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS3_BUTTON))
        self._transport.set_overdub_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS4_BUTTON))

        # setting global session assignments
        self._session.set_scene_bank_buttons(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_COM),
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MICRO))

        # setting misc listeners
        self.browser_toggle_button = ButtonElement(False, MIDI_CC_TYPE,
                                                   CHANNEL, 15)
        self.browser_toggle_button.add_value_listener(
            self.browser_toggle_button_callback)

        self.mainview_toggle_button = ButtonElement(False, MIDI_CC_TYPE,
                                                    CHANNEL, 16)
        self.mainview_toggle_button.add_value_listener(
            self.mainview_toggle_button_callback)

        self.detailview_toggle_button = ButtonElement(False, MIDI_CC_TYPE,
                                                      CHANNEL, 17)
        self.detailview_toggle_button.add_value_listener(
            self.detailview_toggle_button_callback)

        self.clear_track_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL,
                                                25)
        self.clear_track_button.add_value_listener(
            self.clear_track_button_callback)

        self.back_to_arranger_button = ButtonElement(True, MIDI_CC_TYPE,
                                                     CHANNEL, 26)
        self.back_to_arranger_button.add_value_listener(
            self.back_to_arranger_button_callback)

        # adding value listener for selected track change
        self.song().view.add_selected_track_listener(
            self.selected_track_changed)

        # adding value listener for selected scene change
        self.song().view.add_selected_scene_listener(
            self.selected_scene_changed)

        # setting assignments for currently selected track
        self.selected_track_changed()

        # setting assignments for currently selected scene
        self.selected_scene_changed()

    def handle_sysex(self, midi_bytes):
        if ((midi_bytes[6] == 32) and (midi_bytes[7] == 118)):
            self.device_connected = True
            self.log("OP-1 CONNECTED. SENDING ABLETON LIVE MODE INIT SEQUENCE")
            self._send_midi(self.enable_sequence)

    def add_clip_slot_listeners(self):
        #self.log('ADDING CLIP SLOT LISTENERS')

        # creating an empty list for all clip slots
        clip_slots = []

        # getting a reference to all tracks
        tracks = self.song().tracks

        # appending all tracks clip slots to clip_slots
        for track in tracks:
            clip_slots.append(track.clip_slots)

        # iterating over all clip slots
        for t in range(len(clip_slots)):
            for c in range(len(clip_slots[t])):
                clip_slot = clip_slots[t][c]

                # adding has clip listener to clip slot
                self.add_slot_listener(clip_slot)

                # if clip slot has clip
                if clip_slot.has_clip:
                    # adding clip listeners
                    self.add_clip_listener(clip_slot.clip)

    def rem_clip_slot_listeners(self):
        #self.log('REMOVING CLIP SLOT LISTENERS')

        # iterate over all clip color change callbacks
        for c in self.clip_color_callbacks:
            # if clip still exists
            if c != None:
                # and it has a has clip listener
                if c.color_has_listener(self.clip_color_callbacks[c]) == 1:
                    # remove it
                    c.remove_color_listener(self.clip_color_callbacks[c])

        # iterate over all clip slot callbacks
        for cs in self.slot_callbacks:
            # if clip slot still exists
            if cs != None:
                # and it has a has clip listener
                if cs.has_clip_has_listener(self.slot_callbacks[cs]) == 1:
                    # remove it
                    cs.remove_has_clip_listener(self.slot_callbacks[cs])

    def add_slot_listener(self, cs):
        # setting has clip listener
        callback = lambda: self.has_clip_listener(cs)

        # if we don't have a clip slot has clip listener for this clip slot yet
        if not (self.slot_callbacks.has_key(cs)):
            # adding has clip callback to clip slot
            cs.add_has_clip_listener(callback)

            # saving callback for future release
            self.slot_callbacks[cs] = callback

    def add_clip_listener(self, clip):
        # setting callback for clip color change
        color_callback = lambda: self.update_display_clips()

        # if we don't have a clip color change callback for this clip yet
        if not (self.clip_color_callbacks.has_key(clip)):
            # adding clip color change callback
            clip.add_color_listener(color_callback)

            # saving callback for future release
            self.clip_color_callbacks[clip] = color_callback

    def has_clip_listener(self, cs):
        # clip slot has clip listener callback
        if cs.has_clip:
            # add clip listener
            self.add_clip_listener(cs.clip)
        else:
            # update display if clip slot was removed
            self.update_display_clips()

    def session_offset_changed(self):
        # if session component offset changes, update display
        self.update_display_clips()

    def selected_scene_changed(self):
        # if on clip mode update display
        if (self._operation_mode_selector.mode_index == OP1_MODE_CLIP):
            self.update_display_clip_mode()

    def mode_index_changed(self):
        # update display to current mode info
        if (self._operation_mode_selector.mode_index == OP1_MODE_PERFORM):
            self.update_display_perform_mode()
        elif (self._operation_mode_selector.mode_index == OP1_MODE_CLIP):
            self.update_display_clip_mode()
        elif (self._operation_mode_selector.mode_index == OP1_MODE_TRANSPORT):
            self.update_display_transport_mode()
        elif (self._operation_mode_selector.mode_index == OP1_MODE_MIXER):
            self.update_display_mixer_mode()

    def clear_track_button_callback(self, value):
        # if clear track button was called, reset track
        if (value == 127):
            for i in range(len(self.song().tracks)):
                self.song().tracks[i].arm = 0
                self.song().tracks[i].solo = 0
                self.song().tracks[i].mute = 0

            for i in range(len(self.song().return_tracks)):
                self.song().tracks[i].solo = 0
                self.song().tracks[i].mute = 0

    def clear_return_track_assignment(self, strip):
        # clear return track assingments
        strip.set_volume_control(None)
        strip.set_pan_control(None)
        strip.set_mute_button(None)
        strip.set_solo_button(None)

    def clear_track_assignment(self, strip):
        # clear track assignments
        strip.set_volume_control(None)
        strip.set_pan_control(None)
        strip.set_mute_button(None)
        strip.set_solo_button(None)
        strip.set_arm_button(None)

    def clear_tracks_assigments(self):
        # for all normal tracks, clear assignments
        for i in range(NUM_TRACKS):
            strip = self._mixer.channel_strip(i)
            if (strip != None):
                self.clear_track_assignment(strip)

        # for all return tracks, clear assignments
        for i in range(2):
            return_strip = self._mixer.return_strip(i)
            if (return_strip != None):
                self.clear_return_track_assignment(return_strip)

    def selected_track_changed(self):
        # if on mixer mode update display
        if (self._operation_mode_selector.mode_index == OP1_MODE_MIXER):
            self.update_display_mixer_mode()

        # clear track assignments
        self.clear_tracks_assigments()

        # getting selected strip
        self._channel_strip = self._mixer.selected_strip()

        # perform track assignments
        self._channel_strip.set_volume_control(
            EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_1,
                           Live.MidiMap.MapMode.relative_two_compliment))
        self._channel_strip.set_pan_control(
            EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_2,
                           Live.MidiMap.MapMode.relative_two_compliment))

        # setting a tuple of encoders to control sends
        send_controls = EncoderElement(
            MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_3,
            Live.MidiMap.MapMode.relative_two_compliment), EncoderElement(
                MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_4,
                Live.MidiMap.MapMode.relative_two_compliment),

        # setting send encoders
        self._channel_strip.set_send_controls(tuple(send_controls))

        # setting solo button
        self._channel_strip.set_solo_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS6_BUTTON))

        # if track can be armed, set arm button
        if (self._channel_strip._track.can_be_armed):
            self._channel_strip.set_arm_button(
                ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS7_BUTTON))

        # if track is no master, set mute button
        if (self._channel_strip._track != self.song().master_track):
            self._channel_strip.set_mute_button(
                ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS5_BUTTON))

    def browser_toggle_button_callback(self, value):
        if (value == 127):
            if (self.session_visible):
                if (self.session_browser_visible == True):
                    self.session_browser_visible = False
                    self.app.view.hide_view("Browser")
                else:
                    self.session_browser_visible = True
                    self.app.view.show_view("Browser")

            if (self.arrange_visible):
                if (self.arrange_browser_visible == True):
                    self.arrange_browser_visible = False
                    self.app.view.hide_view("Browser")
                else:
                    self.arrange_browser_visible = True
                    self.app.view.show_view("Browser")

    def back_to_arranger_button_callback(self, value):
        if (value == 127):
            self.song().back_to_arranger = False

    def mainview_toggle_button_callback(self, value):
        if (value == 127):
            if (self.session_visible == True):
                self.session_visible = False
                self.arrange_visible = True
                self.app.view.show_view("Arranger")
                self.arrange_browser_visible = self.app.view.is_view_visible(
                    "Browser")
            else:
                self.session_visible = True
                self.arrange_visible = False
                self.app.view.show_view("Session")
                self.session_browser_visible = self.app.view.is_view_visible(
                    "Browser")

    def detailview_toggle_button_callback(self, value):
        if (value == 127):
            if (self.detail_visible == True):
                self.detail_visible = False
                self.app.view.hide_view("Detail")
            else:
                self.detail_visible = True
                self.app.view.show_view("Detail")

    def write_text(self, msg):
        text_list = []
        sequence = ()

        text_list.append(len(msg.strip()))

        for i in msg.strip():
            text_list.append(ord(i))

        sequence = self.text_start_sequence + tuple(
            text_list) + self.text_end_sequence

        self._send_midi(sequence)

    def suggest_input_port(self):
        return "OP-1 Midi Device"

    def suggest_output_port(self):
        return "OP-1 Midi Device"

    def update_display_perform_mode(self):
        self.write_text("perform\rmode")

    def reset_display_clips(self):
        count = 0
        colors = []
        length = []
        sequence = ()

        for i in range(NUM_TRACKS):
            count += 1

            colors.append(0x00)
            colors.append(0x00)
            colors.append(0x00)

        length.append(count)
        sequence = self.text_color_start_sequence + tuple(length) + tuple(
            colors) + self.text_end_sequence
        self._send_midi(sequence)

    def update_display_clips(self):
        #self.log("UPDATING DISPLAY CLIPS")
        count = 0
        colors = []
        length = []
        sequence = ()

        tracks_len = len(self.song().tracks) - self._session._track_offset

        if (tracks_len > NUM_TRACKS):
            tracks_len = NUM_TRACKS

        for i in range(tracks_len):
            count += 1

            clip_slot = self._session.scene(0).clip_slot(i)

            if (clip_slot != None):
                if (clip_slot.has_clip() != False):
                    clip_color = clip_slot._clip_slot.clip.color
                    colors.append(((clip_color >> 16) & 0x000000ff) >> 1)
                    colors.append(((clip_color >> 8) & 0x000000ff) >> 1)
                    colors.append((clip_color & 0x000000ff) >> 1)
                else:
                    colors.append(0x00)
                    colors.append(0x00)
                    colors.append(0x00)
            else:
                colors.append(0x00)
                colors.append(0x00)
                colors.append(0x00)

        length.append(count)
        sequence = self.text_color_start_sequence + tuple(length) + tuple(
            colors) + self.text_end_sequence
        self._send_midi(sequence)

    def update_display_clip_mode(self):
        self.write_text(
            "sel. scene\r" +
            str(self.song().view.selected_scene.name.lower().strip()))

    def update_display_transport_mode(self):
        song_time = str(self.song().get_current_beats_song_time())
        self.write_text("song pos.\r" + song_time[:len(song_time) - 4])

    def update_display_mixer_mode(self):
        self.write_text("sel. track\r" +
                        str(self.song().view.selected_track.name.lower()))

    def update_display(self):
        if not (self.device_connected):
            if (self.retries_count < 5):
                self.log("TRYING OP-1 CONNECTION")
                self.retries_count += 1
                self._send_midi(self.id_sequence)
                time.sleep(1)

        # if in transport mode, update display with song position
        if (self._operation_mode_selector.mode_index == OP1_MODE_TRANSPORT):
            self.update_display_transport_mode()

        # checking if app current view is session
        if (self.app.view.is_view_visible("Session")):
            # checking if session browser state is diferent from the internal
            if (self.session_browser_visible !=
                    self.app.view.is_view_visible("Browser")):
                self.session_browser_visible = self.app.view.is_view_visible(
                    "Browser")

        # checking if app current view is arrange
        if (self.app.view.is_view_visible("Arranger")):
            # checking if arrange browser state is diferent from the internal
            if (self.arrange_browser_visible !=
                    self.app.view.is_view_visible("Browser")):
                self.arrange_browser_visible = self.app.view.is_view_visible(
                    "Browser")

        # checking if app current view is detail
        if (self.app.view.is_view_visible("Detail")):
            # checking if detail state is diferent from the internal
            if (self.detail_visible !=
                    self.app.view.is_view_visible("Detail")):
                self.detail_visible = self.app.view.is_view_visible("Detail")

    def refresh_state(self):
        self.log("REFRESH STATE")
        self.retries_count = 0
        self.device_connected = False

    def build_midi_map(self, midi_map_handle):
        #self.log("BUILD MIDI MAP")

        assert (self._suppress_requests_counter == 0)
        self._in_build_midi_map = True
        self._midi_map_handle = midi_map_handle
        self._forwarding_registry = {}
        for control in self.controls:
            if isinstance(control, InputControlElement):
                control.install_connections()
        self._midi_map_handle = None
        self._in_build_midi_map = False
        if (self._pad_translations != None):
            self._c_instance.set_pad_translation(self._pad_translations)

        # remove clip listeners
        self.rem_clip_slot_listeners()

        # add clip listeners
        self.add_clip_slot_listeners()

        # update display
        self.update_display_clips()

    def log(self, msg):
        self.c_instance.log_message("[TE OP-1] " + msg)

    def disconnect(self):
        # removing clip slots listeners
        self.rem_clip_slot_listeners()

        # removing value listener for track changed
        self.song().view.remove_selected_track_listener(
            self.selected_track_changed)

        # removing value listener for scene changed
        self.song().view.remove_selected_scene_listener(
            self.selected_scene_changed)

        # removing value listener for operation mode index
        self._operation_mode_selector.remove_mode_index_listener(
            self.mode_index_changed)

        # removing global transport assignments
        self._transport.set_punch_buttons(None, None)
        self._transport.set_loop_button(None)
        self._transport.set_overdub_button(None)
        self._transport.set_record_button(None)
        self._transport.set_play_button(None)
        self._transport.set_stop_button(None)
        self._transport.set_metronome_button(None)
        self._transport.set_tap_tempo_button(None)

        # removing global session assignments
        self._session.set_scene_bank_buttons(None, None)

        # removing misc listeners
        self.browser_toggle_button.remove_value_listener(
            self.browser_toggle_button_callback)
        self.mainview_toggle_button.remove_value_listener(
            self.mainview_toggle_button_callback)
        self.detailview_toggle_button.remove_value_listener(
            self.detailview_toggle_button_callback)
        self.clear_track_button.remove_value_listener(
            self.clear_track_button_callback)
        self.back_to_arranger_button.remove_value_listener(
            self.back_to_arranger_button_callback)

        # sending special ableton mode disable sequence
        self._send_midi(self.disable_sequence)

        # disconnecting control surface
        ControlSurface.disconnect(self)

        self.log("DISCONNECTED")
Example #40
0
    def _setup_session_control(self):
        is_momentary = True
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87)        
        right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 78)
        left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 77)
        up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 71)
        down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 79)
        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'
        global session
        session = SessionComponent(7, 8)
        session.name = 'Session_Control'
        session.set_track_bank_buttons(right_button, left_button)
        session.set_scene_bank_buttons(down_button, up_button)
        matrix = ButtonMatrixElement()
        matrix.name = 'Button_Matrix'
        scene_launch_notes = [56,57,58,59,60,61,62,63]
        scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, scene_launch_notes[index]) for index in range(8) ]
        #track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ]
        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)
        #button_notes = [0,8,16,24,32,40,48,56,1,9,17,25,33,41,49,57,2,10,18,26,34,42,50,58,3,11,19,27,35,43,51,59,4,12,20,28,36,44,52,60,5,13,21,29,37,45,53,61,6,14,22,30,38,46,54,62]
        for scene_index in range(8):
            scene = 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(7):
                button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, (track_index * 8) + scene_index)
                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(0)
                clip_slot.set_started_value(64)
                #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))
        session.selected_scene().name = 'Selected_Scene'
        #session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
        #session_zoom = SessionZoomingComponent(session)
        #session_zoom.name = 'Session_Overview'
        #session_zoom.set_button_matrix(matrix)
        #session_zoom.set_zoom_button(self._shift_button)
        #session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button)
        #session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
        #session_zoom.set_stopped_value(0)
        #session_zoom.set_selected_value(127)
        session.set_mixer(mixer)
        return None #return session