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

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

        return

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

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

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

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

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

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

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

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

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

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

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

        self._session.set_stop_track_clip_buttons(tuple(clip_stop_buttons))

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

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

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

    def _dummy_listener(self, value):
        pass

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

    def _update_mixer_offset(self):
        all_tracks = self._session.tracks_to_use()
        selected_track = self.song().view.selected_track
        num_strips = self._session.width()
        if selected_track in all_tracks:
            track_index = list(all_tracks).index(selected_track)
            new_offset = track_index - track_index % num_strips
            self._session.set_offsets(new_offset, self._session.scene_offset())
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
class Launchkey(ControlSurface):
    """ Script for Novation's Launchkey 25/49/61 keyboards """

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

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

        return

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

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

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

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

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

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

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

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

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

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

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

        self._session.set_stop_track_clip_buttons(tuple(clip_stop_buttons))

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

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

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

    def _dummy_listener(self, value):
        pass

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

    def _update_mixer_offset(self):
        all_tracks = self._session.tracks_to_use()
        selected_track = self.song().view.selected_track
        num_strips = self._session.width()
        if selected_track in all_tracks:
            track_index = list(all_tracks).index(selected_track)
            new_offset = track_index - track_index % num_strips
            self._session.set_offsets(new_offset, self._session.scene_offset())
Ejemplo n.º 5
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
Ejemplo n.º 6
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)
Ejemplo n.º 7
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
Ejemplo n.º 8
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
Ejemplo n.º 9
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_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