Exemple #1
0
	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		self._monomod_version = 'b994'
		self.hosts = []
		self._host_name = 'BlockPad'
		self._color_type = 'Monochrome'
		self._timer = 0
		is_momentary = True
		self._suggested_input_port = 'block (Controls)'
		self._suggested_output_port = 'block (Controls)'
		self._wrote_user_byte = False
		matrix = ButtonMatrixElement()
		for row in range(8):
			button_row = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((column * 8) + row), 'Button_'+str(column)+'_'+str(row), self) for column in range(8) ]
			matrix.add_row(tuple(button_row))
		knobs = [ EncoderElement(MIDI_CC_TYPE, 0, KNOB_CC[index], Live.MidiMap.MapMode.absolute) for index in range(8) ]
		sliders = [ EncoderElement(MIDI_CC_TYPE, 0, SLIDER_CC[index], Live.MidiMap.MapMode.absolute) for index in range(2) ]
		self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0)
		self._config_button.add_value_listener(self._config_value)
		top_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, TOP_NOTES[index], 'Top_Button'+str(index), self) for index in range(8) ]
		side_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index], 'Side_Button'+str(index), self) for index in range(8) ]
		self._setup_monobridge()
		self._setup_monomod()
		self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, tuple(knobs), tuple(sliders), self)
		self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16)
		self._user_byte_value(1)
		self._user_byte_write_button.add_value_listener(self._user_byte_value)
		self.set_enabled(True)
		self.log_message("--------------= BlockPad log opened =--------------") #Create entry in log file
		self.refresh_state()
Exemple #2
0
	def _setup_session_control(self):
		is_momentary = True
		self._shift_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98, 'Shift_Button', self)		   
		right_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96, 'Right_Button', self)
		self._right_button = right_button
		left_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97, 'Left_Button', self)
		self._left_button = left_button
		up_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94, 'Up_Button', self)
		self._up_button = up_button
		down_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95, 'Down_Button', self)
		self._down_button = down_button
		self._session = PedaledSessionComponent(8, 5)
		self._session.name = 'Session_Control'
		self._session.set_track_bank_buttons(right_button, left_button)
		self._session.set_scene_bank_buttons(down_button, up_button)
		matrix = ButtonMatrixElement()
		self._matrix = matrix  # added a
		matrix.name = 'Button_Matrix'
		scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82)) for index in range(5) ]
		track_stop_buttons = [ AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52, 'Track_' + str(index) + '_Stop_Button', self) for index in range(8) ]
		self._track_stop_buttons = track_stop_buttons  # added a
		for index in range(len(scene_launch_buttons)):
			scene_launch_buttons[index].name = 'Scene_'+ str(index) + '_Launch_Button'
		stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81)
		stop_all_button.name = 'Stop_All_Clips_Button'
		self._session.set_stop_all_clips_button(stop_all_button)
		self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		self._session.set_stop_track_clip_value(2)
		for scene_index in range(5):
			scene = self._session.scene(scene_index)
			scene.name = 'Scene_' + str(scene_index)
			button_row = []
			scene.set_launch_button(scene_launch_buttons[scene_index])
			scene.set_triggered_value(2)
			for track_index in range(8):
				button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53), str(track_index) + '_Clip_' + str(scene_index) + '_Button', self)
				#button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button'
				button_row.append(button)
				clip_slot = scene.clip_slot(track_index)
				clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index)
				clip_slot.set_triggered_to_play_value(2)
				clip_slot.set_triggered_to_record_value(4)
				clip_slot.set_stopped_value(5)
				clip_slot.set_started_value(1)
				clip_slot.set_recording_value(3)
				clip_slot.set_launch_button(button)
			matrix.add_row(tuple(button_row))
		self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67))
		self._session.selected_scene().name = 'Selected_Scene'
		self._session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
		self._session_zoom = SessionZoomingComponent(self._session)
		self._session_zoom.name = 'Session_Overview'
		self._session_zoom.set_button_matrix(matrix)
		self._session_zoom.set_zoom_button(self._shift_button)
		self._session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button)
		self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
		self._session_zoom.set_stopped_value(3)
		self._session_zoom.set_selected_value(5)
Exemple #3
0
	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		with self.component_guard():
			self._suppress_send_midi = True
			self._suppress_session_highlight = True
			is_momentary = True
			self._suggested_input_port = 'Launchpad'
			self._suggested_output_port = 'Launchpad'
			self._control_is_with_automap = False
			self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16)
			self._user_byte_write_button.name = 'User_Byte_Button'
			self._user_byte_write_button.send_value(1)
			self._user_byte_write_button.add_value_listener(self._user_byte_value)
			self._wrote_user_byte = False
			self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143
			matrix = ButtonMatrixElement()
			matrix.name = 'Button_Matrix'
			for row in range(8):
				button_row = []
				for column in range(8):
					button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, row * 16 + column)
					button.name = str(column) + '_Clip_' + str(row) + '_Button'
					button_row.append(button)

				matrix.add_row(tuple(button_row))

			self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False)
			self._config_button.add_value_listener(self._config_value)
			top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index) for index in range(8) ]
			side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index]) for index in range(8) ]
			top_buttons[0].name = 'Bank_Select_Up_Button'
			top_buttons[1].name = 'Bank_Select_Down_Button'
			top_buttons[2].name = 'Bank_Select_Left_Button'
			top_buttons[3].name = 'Bank_Select_Right_Button'
			top_buttons[4].name = 'Session_Button'
			top_buttons[5].name = 'User1_Button'
			top_buttons[6].name = 'User2_Button'
			top_buttons[7].name = 'Mixer_Button'
			side_buttons[0].name = 'Vol_Button'
			side_buttons[1].name = 'Pan_Button'
			side_buttons[2].name = 'SndA_Button'
			side_buttons[3].name = 'SndB_Button'
			side_buttons[4].name = 'Stop_Button'
			side_buttons[5].name = 'Trk_On_Button'
			side_buttons[6].name = 'Solo_Button'
			side_buttons[7].name = 'Arm_Button'
			self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self)
			self._selector.name = 'Main_Modes'
			self._do_combine()
			for control in self.controls:
				if isinstance(control, ConfigurableButtonElement):
					control.add_value_listener(self._button_value)

			self.set_highlighting_session_component(self._selector.session_component())
			self._suppress_session_highlight = False
			#self.set_suppress_rebuild_requests(False)

			self.log_message("LaunchPad95 Loaded !")
Exemple #4
0
	def __init__(self, *a, **k):
		ControlSurface.__init__(self, *a, **k)
		with self.component_guard():
			self._monomod_version = 'b996'
			self._host_name = 'LaunchMod'
			self._color_type = 'Launchpad'
			self._timer = 0
			self._suppress_send_midi = True
			self._suppress_session_highlight = True
			self._suppress_highlight = False
			is_momentary = True
			self._suggested_input_port = 'Launchpad'
			self._suggested_output_port = 'Launchpad'
			self._control_is_with_automap = False
			self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16)
			self._user_byte_write_button.name = 'User_Byte_Button'
			self._user_byte_write_button.send_value(1)
			self._user_byte_write_button.add_value_listener(self._user_byte_value)
			self._wrote_user_byte = False
			self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143
			matrix = ButtonMatrixElement()
			matrix.name = 'Button_Matrix'
			for row in range(8):
				button_row = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, row * 16 + column, str(column) + '_Clip_' + str(row) + '_Button', self) for column in range(8) ]
				matrix.add_row(tuple(button_row))

			self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False)
			self._config_button.add_value_listener(self._config_value)
			top_button_names = ['Bank_Select_Up_Button',
			 'Bank_Select_Down_Button',
			 'Bank_Select_Left_Button',
			 'Bank_Select_Right_Button',
			 'Session_Button',
			 'User1_Button',
			 'User2_Button',
			 'Mixer_Button']
			side_button_names = ['Vol_Button',
			 'Pan_Button',
			 'SndA_Button',
			 'SndB_Button',
			 'Stop_Button',
			 'Trk_On_Button',
			 'Solo_Button',
			 'Arm_Button']
			top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, top_button_names[index], self) for index in range(8) ]
			side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index], side_button_names[index], self) for index in range(8) ]
			self._side_buttons = ButtonMatrixElement()
			self._side_buttons.add_row(side_buttons)
			self._setup_monobridge()
			self._setup_mod()
			self._selector = MainSelectorComponent(self, matrix, tuple(top_buttons), tuple(side_buttons), self._config_button)
			self._selector.name = 'Main_Modes'
			for control in self.controls:
				isinstance(control, MonoButtonElement) and control.add_value_listener(self._button_value)
			self.set_highlighting_session_component(self._selector.session_component())
			self._suppress_session_highlight = False
		self.log_message('--------------= ' + str(self._monomod_version) + ' log opened =--------------')	
Exemple #5
0
	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		self.set_suppress_rebuild_requests(True)
		self._suppress_send_midi = True
		self._suppress_session_highlight = True
		is_momentary = True
		self._suggested_input_port = "Launchpad"
		self._suggested_output_port = "Launchpad"
		self._control_is_with_automap = False
		self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16)
		self._user_byte_write_button.name = "User_Byte_Button"
		self._user_byte_write_button.send_value(1)
		self._user_byte_write_button.add_value_listener(self._user_byte_value)
		self._wrote_user_byte = False
		self._challenge = (Live.Application.get_random_int(0, 400000000) & 2139062143)
		matrix = ButtonMatrixElement()
		matrix.name = "Button_Matrix"
		for row in range(8):
			button_row = []
			for column in range(8):
				button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((row * 16) + column))
				button.name = (((str(column) + "_Clip_") + str(row)) + "_Button")
				button_row.append(button)

			matrix.add_row(tuple(button_row))

		self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0)
		self._config_button.add_value_listener(self._config_value)
		top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, (104 + index)) for index in range(8) ]
		side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index]) for index in range(8) ]
		top_buttons[0].name = "Bank_Select_Up_Button"
		top_buttons[1].name = "Bank_Select_Down_Button"
		top_buttons[2].name = "Bank_Select_Left_Button"
		top_buttons[3].name = "Bank_Select_Right_Button"
		top_buttons[4].name = "Session_Button"
		top_buttons[5].name = "User1_Button"
		top_buttons[6].name = "User2_Button"
		top_buttons[7].name = "Mixer_Button"
		side_buttons[0].name = "Vol_Button"
		side_buttons[1].name = "Pan_Button"
		side_buttons[2].name = "SndA_Button"
		side_buttons[3].name = "SndB_Button"
		side_buttons[4].name = "Stop_Button"
		side_buttons[5].name = "Trk_On_Button"
		side_buttons[6].name = "Solo_Button"
		side_buttons[7].name = "Arm_Button"
		self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self)
		self._selector.name = "Main_Modes"
		for control in self.controls:
			if isinstance(control, ConfigurableButtonElement):
				control.add_value_listener(self._button_value)

		self._suppress_session_highlight = False
		self.set_suppress_rebuild_requests(False)

		self.log_message("LaunchPad85 Loaded !")
Exemple #6
0
	def _setup_session_control(self):
		is_momentary = True
		num_tracks = 4
		num_scenes = 4
		
		self.session = SessionComponent(num_tracks, num_scenes)
		self.session.name = 'MaschinAble_session_control'
		matrix = ButtonMatrixElement()
		
		self.session.set_offsets(0, 0)
		
		up_button = ButtonElement(is_momentary, 1, 1, 108)
		down_button = ButtonElement(is_momentary, 1, 1, 109)
		left_button = ButtonElement(is_momentary, 1, 1, 110)
		right_button = ButtonElement(is_momentary, 1, 1, 111)
		
		self.session.set_track_bank_buttons(right_button, left_button)
		self.session.set_scene_bank_buttons(down_button, up_button)
		
		launch_notes_start_from = 112
		launch_notes = range(launch_notes_start_from, launch_notes_start_from + 16)
		current_scene = list(
			self.song().scenes).index(self.song().view.selected_scene)
		current_track = list(
			self.song().tracks).index(self.song().view.selected_track)
		for scene_index in range(num_scenes):
			button_row = []
			for track_index in range(num_tracks):
				clip_slot = self.session.scene(num_scenes - 1 - scene_index + current_scene).clip_slot(track_index + current_track)
				button = ButtonElement(is_momentary, 0, 1, launch_notes[track_index+(4*scene_index)])
				button_row.append(button)
				if clip_slot.has_clip:
					clip_slot.set_stopped_value(1)
				else:
					clip_slot.set_stopped_value(0)
				clip_slot.set_triggered_to_play_value(2)
				clip_slot.set_triggered_to_record_value(2)
				clip_slot.set_launch_button(button)
			matrix.add_row(tuple(button_row))
Exemple #7
0
	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		self._monomod_version = 'b994'
		self._host_name = 'LaunchMod'
		self._color_type = 'Launchpad'
		self.hosts = []
		self._timer = 0
		self.set_suppress_rebuild_requests(True)
		self._suppress_send_midi = True
		self._suppress_session_highlight = True
		is_momentary = True
		self._suggested_input_port = 'Launchpad'
		self._suggested_output_port = 'Launchpad'
		self._wrote_user_byte = False
		self._control_is_with_automap = False
		self._challenge = (Live.Application.get_random_int(0, 400000000) & 2139062143)
		matrix = ButtonMatrixElement()
		matrix.name = 'ButtonMatrix'
		for row in range(8):
			#button_row = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((row * 16) + column)) for column in range(8) ]
			button_row = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((row * 16) + column), 'Button_'+str(row)+'_'+str(column), self) for column in range(8) ]
			matrix.add_row(tuple(button_row))
		self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0)
		self._config_button.add_value_listener(self._config_value)
		top_buttons = [ FlashingButtonElement(is_momentary, MIDI_CC_TYPE, 0, (104 + index), 'Top_Button'+str(index), self) for index in range(8) ]
		side_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index], 'Side_Button'+str(index), self) for index in range(8) ]
		self._setup_monobridge()
		self._setup_monomod()
		self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self)
		self._suppress_session_highlight = False
		self._suppress_send_midi = False
		self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16)
		self._user_byte_write_button.send_value(1)
		self._user_byte_write_button.add_value_listener(self._user_byte_value)
		self._suppress_send_midi = True
		self.set_suppress_rebuild_requests(False)
		self.log_message("--------------= LaunchMod log opened =--------------") #Create entry in log file
		self.refresh_state()
class Maschine(ControlSurface):
    __module__ = __name__
    '''Basic Control Script for All Maschine Modell Mikro, Mikro Mk2, Mk1, Mk2, Studio'''
    def __init__(self, c_instance):
        super(Maschine, self).__init__(c_instance)
        self.component_guard().__enter__()

        try:
            register_sender(self)
            self._diplay_cache = ['', '', '', '']
            self._suppress_send_midi = True
            is_momentary = True
            self._c_ref = c_instance
            self.display_task = DisplayTask()
            self._challenge = Live.Application.get_random_int(
                0, 400000000) & 2139062143
            self._active = False
            self._midi_pause_count = 0
            self.blink_state = 0
            self.send_slider_index = 0
            self.nav_index = 0
            self.arm_selected_track = False
            self.undo_state = 0
            self.redo_state = 0
            self._set_suppress_rebuild_requests(True)
            self._modeselect = ModeSelector(self.is_monochrome())
            self._device = self._set_up_device_control()
            self._set_up_session(self._modeselect)
            self._set_up_mixer()
            self._setup_transport()
            self._set_global_buttons()
            self._editsection = EditSection()
            self._editsection.connect_session(self._session)
            self._editsection.set_mode_selector(self._modeselect)
            self._session.set_mode(self._modeselect._clip_mode)
            self._audio_clip_editor = AudioClipEditComponent()
            self._note_repeater = NoteRepeatComponent(c_instance.note_repeat)
            self._midi_edit = MidiEditSection()
            self._init_settings()
            self._init_maschine()
            self.set_highlighting_session_component(self._session)
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._on_selected_track_changed()
            self.set_up_function_buttons()
            self.show_message(str(''))
            self.request_rebuild_midi_map()
            self._set_suppress_rebuild_requests(False)
            self._active = True
            self._display_device_param = False
            self.set_feedback_channels(FEEDBACK_CHANNELS)
            self._final_init()
            self._suppress_send_midi = False
            self.apply_preferences()
            self.init_text_display()
            self._on_appointed_device_changed.subject = self.song()
        finally:
            pass

    def _init_maschine(self):
        pass

    def _final_init(self):
        pass

    def create_pad_button(self, scene_index, track_index, color_source):
        pass

    def create_gated_button(self, identifier, hue):
        pass

    def apply_preferences(self):
        pref_dict = self._pref_dict
        if 'step_advance' in pref_dict:
            self._session.set_step_advance(pref_dict['step_advance'])

        if 'solo_exclusive' in pref_dict:
            self._modeselect.set_solo_exclusive(pref_dict['solo_exclusive'])
        else:
            self._modeselect.set_solo_exclusive(True)
        if 'arm_exclusive' in pref_dict:
            self._modeselect.set_arm_exclusive(pref_dict['arm_exclusive'])
        else:
            self._modeselect.set_arm_exclusive(True)
        if 'quantize_val' in pref_dict:
            self._editsection.quantize = pref_dict['quantize_val']
        else:
            self._editsection.quantize = 5
        if 'initial_cliplen' in pref_dict:
            self._editsection.initial_clip_len = pref_dict['initial_cliplen']
        else:
            self._editsection.initial_clip_len = 4
        if 'auto_arm_sel_track' in pref_dict:
            self.arm_selected_track = pref_dict['auto_arm_sel_track']
        else:
            self.arm_selected_track = False
        if 'note_color_mode' in pref_dict:
            self._modeselect._pad_mode._note_display_mode = pref_dict[
                'note_color_mode']
        else:
            self._modeselect._pad_mode._note_display_mode = ND_KEYBOARD1
        self._pref_dict[
            'note_color_mode'] = self._modeselect._pad_mode._note_display_mode
        if not self.arm_selected_track or 127:
            pass
        self.set_sel_arm_button.send_value(0, True)
        self._note_repeater.recall_values(self._pref_dict)

    def store_preferences(self):
        self._pref_dict['step_advance'] = self._session.get_step_advance()
        self._pref_dict['solo_exclusive'] = self._modeselect.is_solo_exclusive(
        )
        self._pref_dict['arm_exclusive'] = self._modeselect.is_arm_exclusive()
        self._pref_dict['quantize_val'] = self._editsection.quantize
        self._pref_dict['initial_cliplen'] = self._editsection.initial_clip_len
        self._pref_dict['auto_arm_sel_track'] = self.arm_selected_track
        self._pref_dict[
            'note_color_mode'] = self._modeselect._pad_mode._note_display_mode
        self._note_repeater.store_values(self._pref_dict)

    def _init_settings(self):
        loads = loads
        dumps = dumps
        import pickle
        ascii = ascii
        import encodings
        nop(ascii)
        preferences = self._c_instance.preferences(self.preferences_name())
        self._pref_dict = {}

        try:
            self._pref_dict = loads(str(preferences))
        except Exception:
            pass

        pref_dict = self._pref_dict
        (None, preferences.set_serializer)(lambda: dumps(pref_dict))

    def preferences_name(self):
        return 'Maschine'

    def _pre_serialize(self):
        dumps = dumps
        import pickle
        ascii = ascii
        import encodings
        nop(ascii)
        preferences = self._c_instance.preferences('Maschine')
        self.store_preferences()
        dump = dumps(self._pref_dict)
        (preferences.set_serializer, )(lambda: dump)

    def toggle_nav_mode(self):
        self._session.switch_step_advance()
        self.show_message(' View Navigation in steps of ' +
                          str(self._session.get_step_advance()))

    def _set_up_session(self, mode_selector):
        is_momentary = True
        self._session = MaschineSessionComponent()
        self._session.set_color_manager(mode_selector.get_color_manager())
        self.nav_buttons = (self.create_gated_button(92, COLOR_HUE_NAV),
                            self.create_gated_button(81, COLOR_HUE_NAV),
                            self.create_gated_button(93, COLOR_HUE_NAV),
                            self.create_gated_button(91, COLOR_HUE_NAV))
        self._session.set_scene_bank_buttons(self.nav_buttons[0],
                                             self.nav_buttons[1])
        self._session.set_track_bank_buttons(self.nav_buttons[2],
                                             self.nav_buttons[3])
        continue
        track_stop_buttons = [
            StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL,
                        index + STOP_CC_OFF) for index in range(4)
        ]
        self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
        self._matrix = []
        self._bmatrix = ButtonMatrixElement()
        for scene_index in range(4):
            button_row = []
            for track_index in range(4):
                button = self.create_pad_button(scene_index, track_index,
                                                mode_selector)
                button_row.append(button)

            self._matrix.append(tuple(button_row))
            self._bmatrix.add_row(tuple(button_row))

        self._session.set_matrix(self._matrix)
        for (track_index, scene_index) in self._bmatrix.iterbuttons():
            if button:
                scene = self._session.scene(scene_index)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(button)
                clip_slot.set_triggered_to_play_value(1)
                clip_slot.set_triggered_to_record_value(1)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(1)
                clip_slot.set_stopped_value(1)
                continue

        self._session._link()

    def _set_up_mixer(self):
        is_momentary = True
        self._mixer = MaschineMixerComponent(8)
        self.send_sliders = []
        for track in range(8):
            self.send_sliders.append(
                SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL,
                              SEND_CC_OFF + track))

        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.set_arm_button(
                StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL,
                            ARM_CC_OFF + track))
            strip.set_solo_button(
                StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL,
                            SOLO_CC_OFF + track))
            strip.set_mute_button(
                StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL,
                            MUTE_CC_OFF + track))
            strip.set_volume_control(
                SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL,
                              LEVEL_CC_OFF + track))
            strip.set_pan_control(
                SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, PAN_CC_OFF + track))
            strip.set_select_button(
                StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL,
                            SELECT_CC_OFF + track))
            st = tuple([self.send_sliders[track]])
            strip.set_send_controls(st)

        self.send_slider_toggle_button = StateButton(False, MIDI_CC_TYPE, 0,
                                                     90)
        self._do_toggle_send.subject = self.send_slider_toggle_button
        self._session.set_mixer(self._mixer)

    def _set_global_buttons(self):
        is_momentary = True
        self._undo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 85)
        self._do_undo.subject = self._undo_button
        self._redo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 87)
        self._do_redo.subject = self._redo_button
        self._stop_all_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 111)
        self._do_stop_all.subject = self._stop_all_button
        self._toggle_detail_button = ButtonElement(is_momentary, MIDI_CC_TYPE,
                                                   1, 121)
        self._action_toogle_detail_view.subject = self._toggle_detail_button
        self._fire_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 9)
        self._do_fire_button.subject = self._fire_button
        self._g_clear_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1,
                                             106)
        self._hold_clear_action.subject = self._g_clear_button
        self._g_duplicate_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1,
                                                 107)
        self._hold_duplicate_action.subject = self._g_duplicate_button
        self.track_left_button = StateButton(is_momentary, MIDI_CC_TYPE, 0,
                                             120)
        self.track_right_button = StateButton(is_momentary, MIDI_CC_TYPE, 0,
                                              121)
        self.set_sel_arm_button = StateButton(is_momentary, MIDI_CC_TYPE, 2,
                                              56)
        self._reenable_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1,
                                              120)
        self._do_auto_reenable.subject = self._reenable_button
        self._on_change_reenabled.subject = self.song()
        self._on_change_reenabled()
        self._a_trk_left.subject = self.track_left_button
        self._a_trk_right.subject = self.track_right_button
        self._a_sel_arm.subject = self.set_sel_arm_button

    def _set_up_device_control(self):
        is_momentary = True
        device = MaschineDeviceComponent()
        param_controls = []
        for index in range(8):
            param_controls.append(
                SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL,
                              DEVICE_CC_OFF + index))

        device.set_parameter_controls(tuple(param_controls))
        self.device_control = param_controls
        device.set_on_off_button(
            StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL,
                        DEVICE_BUTTON_CC_OFF))
        device.set_bank_nav_buttons(
            StateButton(is_momentary, MIDI_CC_TYPE, 3, 104),
            ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 105))
        self._device_nav_button_left = StateButton(is_momentary, MIDI_CC_TYPE,
                                                   3, 106)
        self._device_nav_button_right = StateButton(is_momentary, MIDI_CC_TYPE,
                                                    3, 107)
        self._navigate_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 127)
        self._nav_value_left.subject = self._device_nav_button_left
        self._nav_value_right.subject = self._device_nav_button_right
        self._do_focus_navigate.subject = self._navigate_button
        self.set_device_component(device)
        return device

    def _setup_transport(self):
        is_momentary = True
        transport = TransportComponent()
        studiotransport = MaschineTransport()
        playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108)
        stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110)
        recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109)
        overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107)
        metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104)
        eventRecButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 98)
        playButton.name = 'Play'
        stopButton.name = 'Stop'
        recordButton.name = 'Record'
        overdubButton.name = 'Overdub'
        metrononmeButton.name = 'Metronome'
        transport.set_play_button(playButton)
        transport.set_stop_button(stopButton)
        transport.set_record_button(recordButton)
        transport.set_overdub_button(overdubButton)
        transport.set_metronome_button(metrononmeButton)
        studiotransport.set_session_auto_button(eventRecButton)
        studiotransport.set_arrangement_overdub_button(
            StateButton(is_momentary, MIDI_CC_TYPE, 0, 106))
        studiotransport.set_back_arrange_button(
            StateButton(is_momentary, MIDI_CC_TYPE, 0, 105))
        transport.set_nudge_buttons(
            StateButton(is_momentary, MIDI_CC_TYPE, 1, 51),
            StateButton(is_momentary, MIDI_CC_TYPE, 1, 50))
        punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52)
        punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53)
        punchinbutton.name = 'Punch In'
        punchoutbutton.name = 'Punch Out'
        transport.set_punch_buttons(punchinbutton, punchoutbutton)
        transport.set_loop_button(
            StateButton(is_momentary, MIDI_CC_TYPE, 1, 54))
        self.song_follow_button = ButtonElement(True, MIDI_CC_TYPE, 2, 98)
        self._do_song_follow.subject = self.song_follow_button
        self._song_follow_changed.subject = self.song().view
        self._song_follow_changed()
        self.prehear_knob = SliderElement(MIDI_CC_TYPE, 0, 41)
        self.prehear_knob.connect_to(
            self.song().master_track.mixer_device.cue_volume)
        self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59)
        self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58)
        transport.set_seek_buttons(self.transp_ff_button,
                                   self.transp_rw_button)
        self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 105)
        self.xfadeKnob.connect_to(
            self.song().master_track.mixer_device.crossfader)
        self.master_knob = SliderElement(MIDI_CC_TYPE, 0, 99)
        self.master_knob.connect_to(
            self.song().master_track.mixer_device.volume)
        self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88)
        self._do_tap_tempo.subject = self.tap_button
        self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1,
                                                 55)
        self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56)
        self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57)
        self._do_toggle_cue.subject = self.cue_add_delete_button
        self._do_toggle_prev_cue.subject = self.cue_prev_button
        self._do_toggle_next_cue.subject = self.cue_next_button

    def set_up_function_buttons(self):
        is_momentary = True
        self.keycolor_mod_button = StateButton(is_momentary, MIDI_CC_TYPE, 1,
                                               73)
        self._do_key_color.subject = self.keycolor_mod_button
        self._update_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 86)
        self._do_update_display.subject = self._update_button

    def _on_appointed_device_changed(self):
        self._modeselect._device_changed()

    _on_appointed_device_changed = subject_slot('appointed_device')(
        _on_appointed_device_changed)

    def _update_hardware(self):
        self._session.update()
        self._modeselect.refresh()
        self.update_undo_redo(True)

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

    def _send_midi(self, midi_bytes, **keys):
        self._c_ref.send_midi(midi_bytes)
        return True

    def init_text_display(self):
        if USE_DISPLAY:
            self._modeselect._pad_mode.update_text_display()

    def _on_selected_track_changed(self):
        super(Maschine, self)._on_selected_track_changed()
        self.set_controlled_track(self.song().view.selected_track)
        self._on_devices_changed.subject = self.song().view.selected_track

    def _on_devices_changed(self):
        pass

    _on_devices_changed = subject_slot('devices')(_on_devices_changed)

    def update(self):
        self.set_feedback_channels(FEEDBACK_CHANNELS)
        super(Maschine, self).update()

    def is_monochrome(self):
        return False

    def _deassign_matrix(self):
        for scene_index in range(4):
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(None)

    def update_display(self):
        self.component_guard().__enter__()

        try:
            self._is_sending_scheduled_messages().__enter__()

            try:
                self._task_group.update(0.1)
            finally:
                pass

            self._modeselect.notify(self.blink_state)
            self.blink_state = (self.blink_state + 1) % 4
            self.display_task.tick()
            self.update_undo_redo(False)
        finally:
            pass

    def update_undo_redo(self, force=False):
        if force:
            self.undo_state = self.song().can_undo
            self.redo_state = self.song().can_redo

        if self.song().can_undo != self.undo_state:
            self.undo_state = self.song().can_undo
            if not self.undo_state == 1 or 127:
                pass
            self._undo_button.send_value(0)

        if self.song().can_redo != self.redo_state:
            self.redo_state = self.song().can_redo
            if not self.redo_state == 1 or 127:
                pass
            self._redo_button.send_value(0)

    def adjust_loop_start(self, delta):
        loopval = self.song().loop_start
        self.song().loop_start = min(self.song().song_length,
                                     max(0, loopval + delta))

    def adjust_loop_length(self, delta):
        loopval = self.song().loop_length
        self.song().loop_length = min(self.song().song_length,
                                      max(abs(delta), loopval + delta))

    def _do_armsolo_mode(self, value):
        pass

    def _do_fire_button(self, value):
        if not self._fire_button != None:
            raise AssertionError
        if not value in range(128):
            raise AssertionError
        if value != 0:
            if self.isShiftDown():
                self.song().tap_tempo()
            else:
                clip_slot = self.song().view.highlighted_clip_slot
                if clip_slot:
                    clip_slot.fire()

    _do_fire_button = subject_slot('value')(_do_fire_button)

    def _do_undo(self, value):
        if value != 0:
            if self.use_layered_buttons() and self.isShiftDown():
                if self.song().can_redo == 1:
                    self.song().redo()
                    self.show_message(str('REDO'))

            elif self.song().can_undo == 1:
                self.song().undo()
                self.show_message(str('UNDO'))

    _do_undo = subject_slot('value')(_do_undo)

    def _do_redo(self, value):
        if value != 0:
            if self.song().can_redo == 1:
                self.song().redo()
                self.show_message(str('REDO'))

    _do_redo = subject_slot('value')(_do_redo)

    def _do_stop_all(self, value):
        if value != 0:
            if self.use_layered_buttons() and self.isShiftDown():
                self.song().stop_all_clips(0)
            else:
                self.song().stop_all_clips(1)

    _do_stop_all = subject_slot('value')(_do_stop_all)

    def isShiftDown(self):
        return self._editsection.isShiftdown()

    def modifiers(self):
        return self._editsection.modifiers()

    def use_layered_buttons(self):
        return False

    def _handle_base_note(self, diff):
        self._modeselect._pad_mode.inc_base_note(diff)

    def _handle_octave(self, diff):
        self._modeselect._pad_mode.inc_octave(diff)
        octave_val = self._modeselect._pad_mode

    def _handle_scale(self, diff):
        self._modeselect._pad_mode.inc_scale(diff)

    def _do_update_display(self, value):
        if value != 0:
            self.refresh_state()

    _do_update_display = subject_slot('value')(_do_update_display)

    def _do_key_color(self, value):
        if not value in range(128):
            raise AssertionError
        if value != 0:
            self._modeselect._pad_mode.step_key_color_mode()

    _do_key_color = subject_slot('value')(_do_key_color)

    def _do_tap_tempo(self, value):
        if not value in range(128):
            raise AssertionError
        if value != 0:
            self.song().tap_tempo()

    _do_tap_tempo = subject_slot('value')(_do_tap_tempo)

    def _do_toggle_cue(self, value):
        if not value in range(128):
            raise AssertionError
        if value != 0:
            self.song().set_or_delete_cue()

    _do_toggle_cue = subject_slot('value')(_do_toggle_cue)

    def _do_toggle_prev_cue(self, value):
        if not value in range(128):
            raise AssertionError
        if value != 0:
            self.song().jump_to_prev_cue()

    _do_toggle_prev_cue = subject_slot('value')(_do_toggle_prev_cue)

    def _do_toggle_next_cue(self, value):
        if not value in range(128):
            raise AssertionError
        if value != 0:
            self.song().jump_to_next_cue()

    _do_toggle_next_cue = subject_slot('value')(_do_toggle_next_cue)

    def _do_toggle_send(self, value):
        if not value in range(128):
            raise AssertionError
        if self.isShiftDown():
            if value != 0:
                self.refresh_state()
                self.show_message('Refresh Display')

        else:
            nr_of_tracks = len(self.song().return_tracks)
            if value == 0 or nr_of_tracks < 1:
                return None

            prev = self.send_slider_index
            self.send_slider_index += 1
            if self.send_slider_index >= nr_of_tracks:
                self.send_slider_index = 0

            self.show_message(' Set Send ' +
                              str(SENDS[self.send_slider_index]))
            self.timed_message(
                2, ' Set Send ' + str(SENDS[self.send_slider_index]))
            if prev != self.send_slider_index:
                for track in range(8):
                    strip = self._mixer.channel_strip(track)
                    slider_list = []
                    for index in range(self.send_slider_index + 1):
                        if index < self.send_slider_index - 1:
                            slider_list.append(None)
                        else:
                            slider_list.append(self.send_sliders[track])
                        strip.set_send_controls(tuple(slider_list))

    _do_toggle_send = subject_slot('value')(_do_toggle_send)

    def _a_trk_left(self, value):
        if not value in range(128):
            raise AssertionError
        if value != 0:
            if self.application().view.is_view_visible('Session'):
                direction = Live.Application.Application.View.NavDirection.left
                self.application().view.scroll_view(direction, 'Session', True)
                track = self.song().view.selected_track
                self.timed_message(2, 'T:' + track.name, False)
                if self.arm_selected_track and track.can_be_armed:
                    arm_exclusive(self.song(), track)

    _a_trk_left = subject_slot('value')(_a_trk_left)

    def _a_trk_right(self, value):
        if not value in range(128):
            raise AssertionError
        if value != 0:
            if self.application().view.is_view_visible('Session'):
                direction = Live.Application.Application.View.NavDirection.right
                self.application().view.scroll_view(direction, 'Session', True)
                track = self.song().view.selected_track
                self.timed_message(2, 'T:' + track.name, False)
                if self.arm_selected_track and track.can_be_armed:
                    arm_exclusive(self.song(), track)

    _a_trk_right = subject_slot('value')(_a_trk_right)

    def _a_sel_arm(self, value):
        if value != 0:
            if self.arm_selected_track:
                self.arm_selected_track = False
                self.set_sel_arm_button.send_value(0, True)
            else:
                self.arm_selected_track = True
                self.set_sel_arm_button.send_value(127, True)

    _a_sel_arm = subject_slot('value')(_a_sel_arm)

    def _nav_value_left(self, value):
        if not self._device_nav_button_left != None:
            raise AssertionError
        if not value in range(128):
            raise AssertionError
        modifier_pressed = True
        if value != 0:
            if not self.application().view.is_view_visible(
                    'Detail') or not self.application().view.is_view_visible(
                        'Detail/DeviceChain'):
                self.application().view.show_view('Detail')
                self.application().view.show_view('Detail/DeviceChain')
            else:
                direction = Live.Application.Application.View.NavDirection.left
                self.application().view.scroll_view(direction,
                                                    'Detail/DeviceChain',
                                                    not modifier_pressed)

    _nav_value_left = subject_slot('value')(_nav_value_left)

    def _nav_value_right(self, value):
        if not self._device_nav_button_right != None:
            raise AssertionError
        if not value in range(128):
            raise AssertionError
        if value != 0:
            modifier_pressed = True
            if not self.application().view.is_view_visible(
                    'Detail') or not self.application().view.is_view_visible(
                        'Detail/DeviceChain'):
                self.application().view.show_view('Detail')
                self.application().view.show_view('Detail/DeviceChain')
            else:
                direction = Live.Application.Application.View.NavDirection.right
                self.application().view.scroll_view(direction,
                                                    'Detail/DeviceChain',
                                                    not modifier_pressed)

    _nav_value_right = subject_slot('value')(_nav_value_right)

    def _do_focus_navigate(self, value):
        if not self._navigate_button != None:
            raise AssertionError
        if not value in range(128):
            raise AssertionError
        if value != 0:
            self.nav_index = (self.nav_index + 1) % len(VIEWS_ALL)
            self.application().view.focus_view(VIEWS_ALL[self.nav_index])
            self.show_message('Focus on : ' + str(VIEWS_ALL[self.nav_index]))

    _do_focus_navigate = subject_slot('value')(_do_focus_navigate)

    def focus_clip_detail(self):
        self.application().view.focus_view('Detail/Clip')

    def _song_follow_changed(self):
        view = self.song().view
        if view.follow_song:
            self.song_follow_button.send_value(1, True)
        else:
            self.song_follow_button.send_value(0, True)

    _song_follow_changed = subject_slot('follow_song')(_song_follow_changed)

    def _do_song_follow(self, value):
        if value != 0:
            view = self.song().view
            if view.follow_song:
                view.follow_song = False
                self.song_follow_button.send_value(0, True)
            else:
                view.follow_song = True
                self.song_follow_button.send_value(1, True)

    _do_song_follow = subject_slot('value')(_do_song_follow)

    def _hold_duplicate_action(self, value):
        if value != 0:
            pass
        1

    _hold_duplicate_action = subject_slot('value')(_hold_duplicate_action)

    def _hold_clear_action(self, value):
        if value != 0:
            self._mixer.enter_clear_mode()
            self._device_component.enter_clear_mode()
        else:
            self._mixer.exit_clear_mode()
            self._device_component.exit_clear_mode()

    _hold_clear_action = subject_slot('value')(_hold_clear_action)

    def _action_toogle_main_view(self, value):
        if value != 0:
            appv = self.application().view
            if appv.is_view_visible('Arranger'):
                appv.show_view('Session')
            else:
                appv.show_view('Arranger')

    _action_toogle_main_view = subject_slot('value')(_action_toogle_main_view)

    def _action_toogle_detail_view(self, value):
        if value != 0:
            appv = self.application().view
            if self.isShiftDown():
                if appv.is_view_visible('Arranger'):
                    appv.show_view('Session')
                else:
                    appv.show_view('Arranger')
            elif appv.is_view_visible('Detail/Clip'):
                appv.show_view('Detail/DeviceChain')
            else:
                appv.show_view('Detail/Clip')

    _action_toogle_detail_view = subject_slot('value')(
        _action_toogle_detail_view)

    def _on_change_reenabled(self):
        if self.song().re_enable_automation_enabled:
            self._reenable_button.turn_on()
        else:
            self._reenable_button.turn_off()

    _on_change_reenabled = subject_slot('re_enable_automation_enabled')(
        _on_change_reenabled)

    def _do_auto_reenable(self, value):
        if value != 0:
            self.song().re_enable_automation()

    _do_auto_reenable = subject_slot('value')(_do_auto_reenable)

    def to_color_edit_mode(self, active):
        pass

    def clear_display_all(self):
        self.send_to_display('', 0)
        self.send_to_display('', 1)
        self.send_to_display('', 2)
        self.send_to_display('', 3)

    def clear_display(self, grid):
        self.send_to_display('', grid)

    def timed_message(self, grid, text, hold=False):
        if USE_DISPLAY == False:
            self.show_message(text)
        else:
            self.display_task.set_func(self.clear_display, grid)
            self.send_to_display(text, grid)
            if hold:
                self.display_task.hold()

            self.display_task.start()

    def timed_message_release(self):
        self.display_task.release()

    def update_bank_display(self):
        if USE_DISPLAY:
            (name, bank) = self._device._current_bank_details()
            if self._display_device_param:
                prms = len(bank)
                d1 = ''
                for i in range(4):
                    parm = bank[i]
                    if parm:
                        name = parm.name
                        if not i < 3 or '|':
                            pass
                        d1 += name[:6] + ''
                        continue
                    if not i < 3 or '|':
                        pass
                    d1 += '      ' + ''

                self.send_to_display(d1, 2)
                d1 = ''
                for i in range(4):
                    parm = bank[i + 4]
                    if parm:
                        name = parm.name
                        if not i < 3 or '|':
                            pass
                        d1 += name[:6] + ''
                        continue
                    if not i < 3 or '|':
                        pass
                    d1 += '      ' + ''

                self.send_to_display(d1, 4)
            else:
                self.timed_message(2, 'Bank: ' + name)

    def display_parameters(self, paramlist):
        if USE_DISPLAY == False:
            return None

    def send_to_display(self, text, grid=0):
        if USE_DISPLAY == False:
            return None

        if self._diplay_cache[grid] == text:
            return None

        self._diplay_cache[grid] = text
        if len(text) > 28:
            text = text[:27]

        msgsysex = [240, 0, 0, 102, 23, 18, min(grid, 3) * 28]
        filled = text.ljust(28)
        for c in filled:
            msgsysex.append(ord(c))

        msgsysex.append(247)
        self._send_midi(tuple(msgsysex))

    def cleanup(self):
        pass

    def disconnect(self):
        self._pre_serialize()
        self.clear_display_all()
        for (track_index, scene_index) in self._bmatrix.iterbuttons():
            if button:
                button.send_color_direct(PColor.OFF[0])
                continue

        time.sleep(0.2)
        self._active = False
        self._suppress_send_midi = True
        super(Maschine, self).disconnect()
Exemple #9
0
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self._device_selection_follows_track_selection = True
        with self.component_guard():
            self._suppress_send_midi = True
            self._suppress_session_highlight = True
            self._control_is_with_automap = False
            is_momentary = True
            self._suggested_input_port = 'Akai MPK26'
            self._suggested_output_port = 'Akai MPK26'
            # self.log("BEFORE mixer")
            self._setup_mixer_control()
            self._setup_device_control()

            # self.clipcontrol(8)

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

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

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

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

                matrix.add_row(tuple(button_row))

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

            self._suppress_session_highlight = False
            self._suppress_send_midi = False
            self.set_highlighting_session_component(session)
            session.set_stop_track_clip_buttons(tuple(session_stop_buttons))
            session.set_mixer(mixer)
class APC40plus22(APC):
    __doc__ = " Script for Akai's APC40 Controller with extra features added "
    def __init__(self, c_instance):
        self._c_instance = c_instance
        self._shift_modes = None #added from APC20 script
        self._encoder_modes = None #added
        self._slider_modes = None #added
        APC.__init__(self, c_instance)
        self.show_message("APC40_22 script loaded")
        
        # Disabling the scene launch buttons and assigning them to the first 5 repeats on Master
        self._device_buttons = []
        self.setup_device_buttons()

    def disconnect(self): #this is from the APC20 script
        for button in self._device_buttons:
            button.remove_value_listener(self._device_toggle)
        self._device_buttons = None
        self._shift_modes = None
        self._encoder_modes = None
        self._slider_modes = None
        APC.disconnect(self)        

    def setup_device_buttons(self):
      repeat = RepeatComponent(self)
      repeat.set_shift_button(self._shift_button)

    def _setup_session_control(self):
        is_momentary = True
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98)        
        right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96)
        left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97)
        up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94)
        down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95)
        right_button.name = 'Bank_Select_Right_Button'
        left_button.name = 'Bank_Select_Left_Button'
        up_button.name = 'Bank_Select_Up_Button'
        down_button.name = 'Bank_Select_Down_Button'
        self._session = PedaledSessionComponent(8, 5)
        self._session.name = 'Session_Control'
        self._session.set_track_bank_buttons(right_button, left_button)
        self._session.set_scene_bank_buttons(down_button, up_button)
        self._matrix = ButtonMatrixElement() #was: matrix = ButtonMatrixElement()
        self._matrix.name = 'Button_Matrix' #was: matrix.name = 'Button_Matrix'
        scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82)) for index in range(5) ]
        #self._track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ]
        self._track_stop_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ]
        for index in range(len(scene_launch_buttons)):
            scene_launch_buttons[index].name = 'Scene_'+ str(index) + '_Launch_Button'
        for index in range(len(self._track_stop_buttons)):
            self._track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button'
        stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81)
        stop_all_button.name = 'Stop_All_Clips_Button'
        self._session.set_stop_all_clips_button(stop_all_button)
        self._session.set_stop_track_clip_buttons(tuple(self._track_stop_buttons))
        self._session.set_stop_track_clip_value(2)
        for scene_index in range(5):
            scene = self._session.scene(scene_index)
            scene.name = 'Scene_' + str(scene_index)
            button_row = []
            scene.set_launch_button(scene_launch_buttons[scene_index])
            scene.set_triggered_value(2)
            for track_index in range(8):
                #button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53)) 
                button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53)) #use Launchpad configurable button instead
                button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button'
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index)
                clip_slot.set_triggered_to_play_value(2)
                clip_slot.set_triggered_to_record_value(4)
                clip_slot.set_stopped_value(3)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(5)
                clip_slot.set_launch_button(button)
            self._matrix.add_row(tuple(button_row)) #matrix.add_row(tuple(button_row))

        # Removing the launch selected clip footpedal option
        #self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67))


        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
        self._session_zoom = SessionZoomingComponent(self._session) #use APC20 Zooming instead      
        self._session_zoom.name = 'Session_Overview'
        self._session_zoom.set_button_matrix(self._matrix) #was: self._session_zoom.set_button_matrix(matrix)
        self._session_zoom.set_zoom_button(self._shift_button) #set in MatrixModesComponent instead
        self._session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button)
        self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
        self._session_zoom.set_stopped_value(3)
        self._session_zoom.set_selected_value(5)
        return None

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(self, 8) #added self for parent
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80)
        master_select_button.name = 'Master_Select_Button'
        self._mixer.master_strip().set_select_button(master_select_button) #set in ShiftableSelectorComponent instead if used for Note Mode
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        select_buttons = [] #added
        arm_buttons = [] #added
        sliders = [] #added     
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            #volume_control = SliderElement(MIDI_CC_TYPE, track, 7) #set in ShiftableSelectorComponent instead
            #arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) #see below
            solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)
            solo_button.name = str(track) + '_Solo_Button'
            strip.set_solo_button(solo_button)

            if track < 4:
              mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50)
              mute_button.name = str(track) + '_Mute_Button'
              strip.set_mute_button(mute_button)
              strip.set_invert_mute_feedback(True)

            strip.set_shift_button(self._shift_button)
            select_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) #added
            select_buttons[-1].name = str(track) + '_Select_Button' #added            
            #strip.set_select_button(select_buttons[-1]) #added 
            arm_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) #added
            arm_buttons[-1].name = str(track) + '_Arm_Button' #added
            sliders.append(SliderElement(MIDI_CC_TYPE, track, 7)) #added
            sliders[-1].name = str(track) + '_Volume_Control' #added

        self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        self._prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
        self._crossfader.name = 'Crossfader' #not used in APC20
        master_volume_control.name = 'Master_Volume_Control'
        self._prehear_control.name = 'Prehear_Volume_Control'
        self._mixer.set_shift_button(self._shift_button) #added for shifting prehear
        self._mixer.set_crossfader_control(self._crossfader) #not used in APC20
        self._mixer.set_prehear_volume_control(self._prehear_control) #functionality overridden in SpecialMixerComponent
        self._mixer.master_strip().set_volume_control(master_volume_control)
        self._slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) #added from APC20 script
        self._slider_modes.name = 'Slider_Modes' #added from APC20 script
        matrix_modes = MatrixModesComponent(self._matrix, self._session, self._session_zoom, tuple(self._track_stop_buttons), self) #added new
        matrix_modes.name = 'Matrix_Modes' #added new
        # Original method args for ShiftableSelectorComponent: (self, select_buttons, master_button, arm_buttons, matrix, session, zooming, mixer, transport, slider_modes, mode_callback)
        #self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message)
        self._shift_modes = ShiftableSelectorComponent(self, tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, self._slider_modes, matrix_modes) #, self._send_introduction_message) #also added self for _parent
        self._shift_modes.name = 'Shift_Modes'
        self._shift_modes.set_mode_toggle(self._shift_button)

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

    def _setup_looper_control(self):
        is_momentary = True
        #pedal = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)
        loop_on = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 4, 50)
        loop_start = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 5, 50)
        halve = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 6, 50)
        double = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 7, 50)
        looper = LooperComponent(self)
        looper.set_shift_button(self._shift_button)
        looper.set_loop_toggle_button(loop_on)
        looper.set_loop_start_button(loop_start)
        looper.set_loop_double_button(double) 
        looper.set_loop_halve_button(halve) 

    def _setup_device_and_transport_control(self):
        is_momentary = True
        device_bank_buttons = []
        device_param_controls = []
        bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Device_Lock_Button', 'Metronome_Button')
        for index in range(8):
            device_bank_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 58 + index))
            device_bank_buttons[-1].name = bank_button_labels[index]
            ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 24 + index)
            ringed_encoder = RingedEncoderElement(MIDI_CC_TYPE, 0, 16 + index, Live.MidiMap.MapMode.absolute)
            ringed_encoder.set_ring_mode_button(ring_mode_button)
            ringed_encoder.set_feedback_delay(-1) #added from Axiom DirectLink example
            ringed_encoder.name = 'Device_Control_' + str(index)
            ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button'
            device_param_controls.append(ringed_encoder)
        self._device = ShiftableDeviceComponent()
        self._device.name = 'Device_Component'
        self._device.set_bank_buttons(tuple(device_bank_buttons))
        self._device.set_shift_button(self._shift_button)
        self._device.set_parameter_controls(tuple(device_param_controls))
        self._device.set_on_off_button(device_bank_buttons[1])
        self.set_device_component(self._device)
        detail_view_toggler = DetailViewControllerComponent()
        detail_view_toggler.name = 'Detail_View_Control'
        detail_view_toggler.set_shift_button(self._shift_button)
        detail_view_toggler.set_device_clip_toggle_button(device_bank_buttons[0])
        detail_view_toggler.set_detail_toggle_button(device_bank_buttons[4])
        detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3])
        transport = ShiftableTransportComponent()
        transport.name = 'Transport'
        play_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 91)
        stop_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 92)
        record_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 93)
        nudge_up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 100)
        nudge_down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 101)
        tap_tempo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99)
        play_button.name = 'Play_Button'
        stop_button.name = 'Stop_Button'
        record_button.name = 'Record_Button'
        nudge_up_button.name = 'Nudge_Up_Button'
        nudge_down_button.name = 'Nudge_Down_Button'
        tap_tempo_button.name = 'Tap_Tempo_Button'
        transport.set_shift_button(self._shift_button)
        transport.set_play_button(play_button)
        transport.set_stop_button(stop_button)
        transport.set_record_button(record_button)
        transport.set_nudge_buttons(nudge_up_button, nudge_down_button)
        transport.set_undo_button(nudge_down_button) #shifted nudge
        transport.set_redo_button(nudge_up_button) #shifted nudge
        transport.set_tap_tempo_button(tap_tempo_button)
        self._device.set_lock_button(tap_tempo_button) #shifted tap tempo
        transport.set_quant_toggle_button(device_bank_buttons[5])
        transport.set_overdub_button(device_bank_buttons[6])
        transport.set_metronome_button(device_bank_buttons[7])
        transport.set_tempo_encoder(self._prehear_control) #shifted prehear
        bank_button_translator = ShiftableTranslatorComponent()
        bank_button_translator.set_controls_to_translate(tuple(device_bank_buttons))
        bank_button_translator.set_shift_button(self._shift_button)


    def _setup_global_control(self):
        is_momentary = True
        self._global_bank_buttons = []
        self._global_param_controls = []
        for index in range(8):
            ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 56 + index)
            ringed_encoder = RingedEncoderElement(MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute)
            ringed_encoder.name = 'Track_Control_' + str(index)
            ringed_encoder.set_feedback_delay(-1)
            ring_button.name = ringed_encoder.name + '_Ring_Mode_Button'
            ringed_encoder.set_ring_mode_button(ring_button)
            self._global_param_controls.append(ringed_encoder)
        self._global_bank_buttons = []
        global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button')
        for index in range(4):
            self._global_bank_buttons.append(ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87 + index))#(not is_momentary, MIDI_NOTE_TYPE, 0, 87 + index))
            self._global_bank_buttons[-1].name = global_bank_labels[index]
        self._encoder_modes = EncoderMixerModeSelectorComponent(self._mixer)
        self._encoder_modes.name = 'Track_Control_Modes'
        #self._encoder_modes.set_modes_buttons(self._global_bank_buttons) # set in ShiftableEncoderSelectorComponent
        self._encoder_modes.set_controls(tuple(self._global_param_controls))
        #self._encoder_device_modes = EncoderDeviceModeSelectorComponent(self._mixer, self._device) #new
        self._encoder_device_modes = EncoderDeviceComponent(self._mixer, self._device, self)
        self._encoder_device_modes.name = 'Alt_Device_Control_Modes' #new
        self._encoder_eq_modes = EncoderEQComponent(self._mixer, self)#EncoderEQModeSelectorComponent(self._mixer) #new
        self._encoder_eq_modes.name = 'EQ_Control_Modes' #new
        global_translation_selector = ChannelTranslationSelector() #translate track encoders to channels 1 through 4, based on button selection (pan = 1, send A = 2, send B = 3, send C = 4)
        global_translation_selector.name = 'Global_Translations'
        global_translation_selector.set_controls_to_translate(tuple(self._global_param_controls))
        global_translation_selector.set_mode_buttons(tuple(self._global_bank_buttons))
        encoder_user_modes = EncoderUserModesComponent(self, self._encoder_modes, tuple(self._global_param_controls), tuple(self._global_bank_buttons), self._mixer, self._device, self._encoder_device_modes, self._encoder_eq_modes) #self._mixer, tuple(sliders)) #added
        encoder_user_modes.name = 'Encoder_User_Modes' #added   
        self._encoder_shift_modes = ShiftableEncoderSelectorComponent(self, tuple(self._global_bank_buttons), encoder_user_modes, self._encoder_modes, self._encoder_eq_modes, self._encoder_device_modes) #tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, slider_modes, matrix_modes) #, self._send_introduction_message) #also added self for _parent
        self._encoder_shift_modes.name = 'Encoder_Shift_Modes'
        self._encoder_shift_modes.set_mode_toggle(self._shift_button)     


    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        #self._slider_modes.update() #added to update alternate slider assignments
        track = self.song().view.selected_track
        device_to_select = track.view.selected_device
        if device_to_select == None and len(track.devices) > 0:
            device_to_select = track.devices[0]
        if device_to_select != None:
            self.song().view.select_device(device_to_select)
        self._device_component.set_device(device_to_select)
        return None

    def _product_model_id_byte(self):
        return 115
Exemple #11
0
class Serato(ControlSurface):

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

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

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

    def build_midi_map(self, midi_map_handle):
        pass

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

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

            self._matrix.add_row(tuple(button_row))

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

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

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

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

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

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

    def _move_device_focus(self, increment):
        if not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain'):
            self.application().view.show_view('Detail')
            self.application().view.show_view('Detail/DeviceChain')
        else:
            modifier_pressed = True
            direction = Live.Application.Application.View.NavDirection.left
            if increment > 0:
                direction = Live.Application.Application.View.NavDirection.right
            self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)
class DC1(ControlSurface):
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        is_momentary = True
        self._timer = 0                             #used for flashing states, and is incremented by each call from self._update_display()
        self._touched = 0    
        self.flash_status = 1 # Used in FlashingButtonElement (kludge for our purposes)       
        self._device_selection_follows_track_selection = True
        
        with self.component_guard():
            self._setup_transport_control()

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


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


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

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



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

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

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

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

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

        self.refresh_state()
        self.session.set_enabled(True)
        self.session.update()  
              
    def setup_device_control(self):
        is_momentary = True
        device_bank_buttons = []
        device_param_controls = []
        bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button')
        for index in range(4):
            device_bank_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 16 + index))
            device_bank_buttons[-1].name = bank_button_labels[index]
        for index in range(8):
            #ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, 21 + index)
            ringed_encoder = CMDEncoderElement(MIDI_CC_TYPE, CHANNEL, 16 + index, Live.MidiMap.MapMode.relative_binary_offset, 20)
            #ringed_encoder.set_ring_mode_button(ring_mode_button)
            ringed_encoder.name = 'Device_Control_' + str(index)
            #ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button'
            device_param_controls.append(ringed_encoder)

        device = ShiftableDeviceComponent()
        device.name = 'Device_Component'
        device.set_bank_buttons(tuple(device_bank_buttons))
        device.set_shift_button(self._shift_button)
        device.set_parameter_controls(tuple(device_param_controls))
        device.set_on_off_button(device_bank_buttons[1])
        self.set_device_component(device)
        detail_view_toggler = DetailViewControllerComponent(self)
        detail_view_toggler.name = 'Detail_View_Control'
        detail_view_toggler.set_shift_button(self._shift_button)
        detail_view_toggler.set_device_clip_toggle_button(device_bank_buttons[0])
        detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3])
        
    def update_display(self):
        ControlSurface.update_display(self)
        self._timer = (self._timer + 1) % 256
  
    def disconnect(self):
        self._hosts = []
        ControlSurface.disconnect(self)
        return None        
class APC20(APC):
    """ Script for Akai's APC20 Controller """

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

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

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

    def _setup_session_control(self):
        is_momentary = True
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81)
        self._session = APCSessionComponent(8, 5)
        self._session.name = 'Session_Control'
        self._matrix = ButtonMatrixElement()
        self._matrix.name = 'Button_Matrix'
        scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, index + 82) for index in range(5) ]
        track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ]
        for index in range(len(scene_launch_buttons)):
            scene_launch_buttons[index].name = 'Scene_' + str(index) + '_Launch_Button'

        for index in range(len(track_stop_buttons)):
            track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button'

        self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
        self._session.set_stop_track_clip_value(2)
        for scene_index in range(5):
            scene = self._session.scene(scene_index)
            scene.name = 'Scene_' + str(scene_index)
            button_row = []
            scene.set_launch_button(scene_launch_buttons[scene_index])
            scene.set_triggered_value(2)
            for track_index in range(8):
                button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, scene_index + 53)
                button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button'
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index)
                clip_slot.set_triggered_to_play_value(2)
                clip_slot.set_triggered_to_record_value(4)
                clip_slot.set_stopped_value(5)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(3)
                clip_slot.set_launch_button(button)

            self._matrix.add_row(tuple(button_row))

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

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)
            mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50)
            solo_button.name = str(track) + '_Solo_Button'
            mute_button.name = str(track) + '_Mute_Button'
            strip.set_solo_button(solo_button)
            strip.set_mute_button(mute_button)
            strip.set_shift_button(self._shift_button)
            strip.set_invert_mute_feedback(True)

        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
        master_volume_control.name = 'Master_Volume_Control'
        prehear_control.name = 'Prehear_Volume_Control'
        self._mixer.set_prehear_volume_control(prehear_control)
        self._mixer.master_strip().set_volume_control(master_volume_control)

    def _setup_custom_components(self):
        is_momentary = True
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80)
        master_select_button.name = 'Master_Select_Button'
        select_buttons = []
        arm_buttons = []
        sliders = []
        for track in range(8):
            select_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51))
            arm_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48))
            sliders.append(SliderElement(MIDI_CC_TYPE, track, 7))
            select_buttons[-1].name = str(track) + '_Select_Button'
            arm_buttons[-1].name = str(track) + '_Arm_Button'
            sliders[-1].name = str(track) + '_Volume_Control'

        transport = TransportComponent()
        transport.name = 'Transport'
        slider_modes = SliderModesComponent(self._mixer, tuple(sliders))
        slider_modes.name = 'Slider_Modes'
        self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message)
        self._shift_modes.name = 'Shift_Modes'
        self._shift_modes.set_mode_toggle(self._shift_button)

    def _product_model_id_byte(self):
        return 123
class APC40(APC, OptimizedControlSurface):
    """ Script for Akai's APC40 Controller """

    def __init__(self, *a, **k):
        super(APC40, self).__init__(*a, **k)
        self._color_skin = make_biled_skin()
        self._default_skin = make_default_skin()
        with self.component_guard():
            self._create_controls()
            self._create_session()
            self._create_mixer()
            self._create_device()
            self._create_detail_view_control()
            self._create_transport()
            self._create_global_control()
            self._create_fallback_control_owner()
            self._session.set_mixer(self._mixer)
            self.set_highlighting_session_component(self._session)
            self.set_device_component(self._device)
            for component in self.components:
                component.set_enabled(False)

        self._device_selection_follows_track_selection = True

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

    def _create_controls(self):
        make_on_off_button = partial(make_button, skin=self._default_skin)
        make_color_button = partial(make_button, skin=self._color_skin)
        self._shift_button = make_button(0, 98, resource_type=PrioritizedResource, name='Shift_Button')
        self._right_button = make_button(0, 96, name='Bank_Select_Right_Button')
        self._left_button = make_button(0, 97, name='Bank_Select_Left_Button')
        self._up_button = make_button(0, 94, name='Bank_Select_Up_Button')
        self._down_button = make_button(0, 95, name='Bank_Select_Down_Button')
        self._session_matrix = ButtonMatrixElement(name='Button_Matrix')
        self._scene_launch_buttons_raw = [ make_color_button(0, index + 82, name='Scene_%d_Launch_Button' % index) for index in xrange(SESSION_HEIGHT) ]
        self._track_stop_buttons = [ make_color_button(index, 52, name='Track_%d_Stop_Button' % index) for index in xrange(SESSION_WIDTH) ]
        self._stop_all_button = make_color_button(0, 81, name='Stop_All_Clips_Button')
        self._matrix_rows_raw = [ [ make_color_button(track_index, scene_index + 53, name='%d_Clip_%d_Button' % (track_index, scene_index)) for track_index in xrange(SESSION_WIDTH) ] for scene_index in xrange(SESSION_HEIGHT) ]
        for row in self._matrix_rows_raw:
            self._session_matrix.add_row(row)

        self._selected_slot_launch_button = make_pedal_button(67, name='Selected_Slot_Launch_Button')
        self._selected_scene_launch_button = make_pedal_button(64, name='Selected_Scene_Launch_Button')
        self._volume_controls = []
        self._arm_buttons = []
        self._solo_buttons = []
        self._mute_buttons = []
        self._select_buttons = []
        for index in xrange(MIXER_SIZE):
            self._volume_controls.append(make_slider(index, 7, name='%d_Volume_Control' % index))
            self._arm_buttons.append(make_on_off_button(index, 48, name='%d_Arm_Button' % index))
            self._solo_buttons.append(make_on_off_button(index, 49, name='%d_Solo_Button' % index))
            self._mute_buttons.append(make_on_off_button(index, 50, name='%d_Mute_Button' % index))
            self._select_buttons.append(make_on_off_button(index, 51, name='%d_Select_Button' % index))

        self._crossfader_control = make_slider(0, 15, name='Crossfader')
        self._master_volume_control = make_slider(0, 14, name='Master_Volume_Control')
        self._master_select_button = make_on_off_button(0, 80, name='Master_Select_Button')
        self._prehear_control = make_encoder(0, 47, name='Prehear_Volume_Control')
        self._device_bank_buttons = []
        self._device_param_controls_raw = []
        bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Metronome_Button')
        for index in range(8):
            self._device_bank_buttons.append(make_on_off_button(0, 58 + index, name=bank_button_labels[index]))
            encoder_name = 'Device_Control_%d' % index
            ringed_encoder = make_ring_encoder(16 + index, 24 + index, name=encoder_name)
            self._device_param_controls_raw.append(ringed_encoder)

        self._play_button = make_button(0, 91, name='Play_Button')
        self._stop_button = make_button(0, 92, name='Stop_Button')
        self._record_button = make_button(0, 93, name='Record_Button')
        self._nudge_up_button = make_button(0, 100, name='Nudge_Up_Button')
        self._nudge_down_button = make_button(0, 101, name='Nudge_Down_Button')
        self._tap_tempo_button = make_button(0, 99, name='Tap_Tempo_Button')
        self._global_bank_buttons = []
        self._global_param_controls = []
        for index in range(8):
            encoder_name = 'Track_Control_%d' % index
            ringed_encoder = make_ring_encoder(48 + index, 56 + index, name=encoder_name)
            self._global_param_controls.append(ringed_encoder)

        self._global_bank_buttons = [ make_on_off_button(0, 87 + index, name=name) for index, name in enumerate(('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button')) ]
        self._device_clip_toggle_button = self._device_bank_buttons[0]
        self._device_on_off_button = self._device_bank_buttons[1]
        self._detail_left_button = self._device_bank_buttons[2]
        self._detail_right_button = self._device_bank_buttons[3]
        self._detail_toggle_button = self._device_bank_buttons[4]
        self._rec_quantization_button = self._device_bank_buttons[5]
        self._overdub_button = self._device_bank_buttons[6]
        self._metronome_button = self._device_bank_buttons[7]

        def wrap_matrix(control_list, wrapper = nop):
            return ButtonMatrixElement(rows=[map(wrapper, control_list)])

        self._scene_launch_buttons = wrap_matrix(self._scene_launch_buttons_raw)
        self._track_stop_buttons = wrap_matrix(self._track_stop_buttons)
        self._volume_controls = wrap_matrix(self._volume_controls)
        self._arm_buttons = wrap_matrix(self._arm_buttons)
        self._solo_buttons = wrap_matrix(self._solo_buttons)
        self._mute_buttons = wrap_matrix(self._mute_buttons)
        self._select_buttons = wrap_matrix(self._select_buttons)
        self._device_param_controls = wrap_matrix(self._device_param_controls_raw)
        self._device_bank_buttons = wrap_matrix(self._device_bank_buttons, partial(DeviceBankButtonElement, modifiers=[self._shift_button]))
        self._shifted_matrix = ButtonMatrixElement(rows=recursive_map(self._with_shift, self._matrix_rows_raw))
        self._shifted_scene_buttons = ButtonMatrixElement(rows=[[ self._with_shift(button) for button in self._scene_launch_buttons_raw ]])

    def _create_session(self):
        self._session = SessionComponent(SESSION_WIDTH, SESSION_HEIGHT, auto_name=True, enable_skinning=True, is_enabled=False, layer=Layer(track_bank_left_button=self._left_button, track_bank_right_button=self._right_button, scene_bank_up_button=self._up_button, scene_bank_down_button=self._down_button, stop_all_clips_button=self._stop_all_button, stop_track_clip_buttons=self._track_stop_buttons, scene_launch_buttons=self._scene_launch_buttons, clip_launch_buttons=self._session_matrix, slot_launch_button=self._selected_slot_launch_button, selected_scene_launch_button=self._selected_scene_launch_button))
        self._session_zoom = SessionZoomingComponent(self._session, name='Session_Overview', enable_skinning=True, is_enabled=False, layer=Layer(button_matrix=self._shifted_matrix, nav_up_button=self._with_shift(self._up_button), nav_down_button=self._with_shift(self._down_button), nav_left_button=self._with_shift(self._left_button), nav_right_button=self._with_shift(self._right_button), scene_bank_buttons=self._shifted_scene_buttons))

    def _create_mixer(self):
        self._mixer = MixerComponent(MIXER_SIZE, auto_name=True, is_enabled=False, invert_mute_feedback=True, layer=Layer(volume_controls=self._volume_controls, arm_buttons=self._arm_buttons, solo_buttons=self._solo_buttons, mute_buttons=self._mute_buttons, track_select_buttons=self._select_buttons, shift_button=self._shift_button, crossfader_control=self._crossfader_control, prehear_volume_control=self._prehear_control))
        self._mixer.master_strip().layer = Layer(volume_control=self._master_volume_control, select_button=self._master_select_button)

    def _create_device(self):
        self._device = DeviceComponent(name='Device_Component', is_enabled=False, layer=Layer(bank_buttons=self._device_bank_buttons, on_off_button=self._device_on_off_button), use_fake_banks=True)
        ChannelTranslationSelector(8, name='Control_Translations')
        self._device.set_parameter_controls(tuple(self._device_param_controls_raw))

    def _create_detail_view_control(self):
        self._detail_view_toggler = DetailViewCntrlComponent(name='Detail_View_Control', is_enabled=False, layer=Layer(device_clip_toggle_button=self._device_clip_toggle_button, detail_toggle_button=self._detail_toggle_button, device_nav_left_button=self._detail_left_button, device_nav_right_button=self._detail_right_button))

    def _create_transport(self):
        self._transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=self._play_button, stop_button=self._stop_button, record_button=self._record_button, nudge_up_button=self._nudge_up_button, nudge_down_button=self._nudge_down_button, tap_tempo_button=self._tap_tempo_button, quant_toggle_button=self._rec_quantization_button, overdub_button=self._overdub_button, metronome_button=self._metronome_button))
        self._bank_button_translator = ChannelTranslationSelector(name='Bank_Button_Translations', is_enabled=False)

    def _create_global_control(self):

        def set_pan_controls():
            for index, control in enumerate(self._global_param_controls):
                self._mixer.channel_strip(index).set_pan_control(control)
                self._mixer.channel_strip(index).set_send_controls((None, None, None))
                control.set_channel(0)

        def set_send_controls(send_index):
            for index, control in enumerate(self._global_param_controls):
                self._mixer.channel_strip(index).set_pan_control(None)
                send_controls = [None] * 3
                send_controls[send_index] = control
                self._mixer.channel_strip(index).set_send_controls(send_controls)
                control.set_channel(send_index + 1)

        encoder_modes = ModesComponent(name='Track_Control_Modes', is_enabled=False)
        encoder_modes.add_mode('pan', [set_pan_controls])
        encoder_modes.add_mode('send_a', [partial(set_send_controls, 0)])
        encoder_modes.add_mode('send_b', [partial(set_send_controls, 1)])
        encoder_modes.add_mode('send_c', [partial(set_send_controls, 2)])
        encoder_modes.selected_mode = 'pan'
        encoder_modes.layer = Layer(pan_button=self._global_bank_buttons[0], send_a_button=self._global_bank_buttons[1], send_b_button=self._global_bank_buttons[2], send_c_button=self._global_bank_buttons[3])
        self._translation_selector = ChannelTranslationSelector(name='Global_Translations')

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

    def get_matrix_button(self, column, row):
        return self._matrix_rows_raw[row][column]

    def _product_model_id_byte(self):
        return 115
Exemple #15
0
class BlockMod(MonOhm):
	__module__ = __name__
	__doc__ = " Monomodular controller script for Livid Block "


	def __init__(self, *a, **k):
		self._shift_button = None
		super(BlockMod, self).__init__(*a, **k)
		self._host_name = 'BlockMod'
		self._color_type = 'Monochrome'
		self._link_mixer = LINK_MIXER
		self._rgb = 1
		self._ohm = 127
		self._ohm_type = 'static'
		self._pad_translations = PAD_TRANSLATION
		self._mem = [4, 8, 12, 16]
		self.modhandler._color_type = 'Monochrome'
	

	"""script initialization methods"""
	def _setup_monobridge(self):
		self._monobridge = MonoBridgeElement(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(8)]
		self._button = [None for index in range(8)]
		self._menu = [None for index in range(6)]
		for index in range(2):
			self._fader[index] = MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, SLIDER_CC[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self)
		#for index in range(8):
		#	self._button[index] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_' + str(index), self)
		for index in range(8):
			self._dial[index] = MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, KNOB_CC[index], Live.MidiMap.MapMode.absolute, 'Dial_' + str(index), index + 8, self)
		for index in range(4):
			self._menu[index] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, FUNCTION_NOTES[index], 'Menu_' + str(index), self)	
		#self._livid = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self)
		self._livid = DoublePressElement(MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self))
		self._shift_l = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Shift_Button_Left', self)
		self._shift_r = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Shift_Button_Right', 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] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, (column * 8) + row, 'Grid_' + 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._dial_matrix = ButtonMatrixElement()
		self._dial_matrix.add_row(self._dial)
	

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

	def _setup_crossfader(self):
		pass
	

	def _setup_mod(self):
		super(BlockMod, self)._setup_mod()
		self.modhandler.nav_box.on_value = 8
	

	def _setup_layers(self):
		self._device_navigator.layer = Layer(priority = 5, prev_button = self._menu[2], next_button = self._menu[3])
		self._device.mod_layer = AddLayerMode(self._device, Layer(priority = 5, bank_prev_button = self._menu[0], bank_next_button = self._menu[1]))
		self._transport.mod_layer = AddLayerMode(self._transport, Layer(priority = 5, play_button = self._menu[2], stop_button = self._menu[3]))
		self.modhandler.set_mod_button(self._livid)
		self.modhandler.layer = Layer(priority = 5, 
									grid = self._monomod,
									nav_up_button = self._menu[0],
									nav_down_button = self._menu[1],
									nav_left_button = self._menu[2],
									nav_right_button =  self._menu[3],
									shift_button = self._shift_r,
									alt_button = self._shift_l,
									parameter_controls = self._dial_matrix)
		self.modhandler.legacy_shift_mode = AddLayerMode(self.modhandler, Layer(priority = 6,
									channel_buttons = self._monomod.submatrix[:, 1:2],
									nav_matrix = self._monomod.submatrix[:4, 2:6]))
		self.modhandler.shift_mode = AddLayerMode(self.modhandler, Layer(priority = 6, 
									lock_button = self._livid,
									device_selector_matrix = self._monomod.submatrix[:, :1],
									key_buttons = self._monomod.submatrix[:, 7:8]))
		self.modhandler.shiftlock_mode = AddLayerMode(self.modhandler, Layer(priority = 6, 
									key_buttons = self._monomod.submatrix[:, 7:8]))
	

	def _setup_modes(self):
		self._monomod_mode = MonomodModeComponent(self, self.monomod_mode_update)
		self._monomod_mode.name = 'Monomod_Mode'
		self._monomod_mode.layer = Layer(priority = 5, mode_toggle = self._livid)
		self._monomod_mode.set_enabled(True)
		self._on_shift_doublepress_value.subject = self._livid.double_press
		self._shift_mode = BlockModShiftModeComponent(self, self.shift_update) 
		self._shift_mode.name = 'Shift_Mode'
		#self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r)
		self._shift_mode.layer = Layer(priority = 3, toggle1 = self._shift_l, toggle2 = self._shift_r)
		self._shift_mode.set_enabled(True)
		self._l_function_mode = FunctionModeComponent(self, self.l_function_update)
		self._l_function_mode.name = 'Left_Function_Mode'
		self._r_function_mode = FunctionModeComponent(self, self.r_function_update)
		self._r_function_mode.name = 'Right_Function_Mode'
		self._m_function_mode = FunctionModeComponent(self, self.m_function_update)
		self._m_function_mode.name = 'Main_Function_Mode'
		self._function_modes = [self._l_function_mode, self._r_function_mode, self._m_function_mode]
	

	@subject_slot('value')
	def _on_shift_doublepress_value(self, value):
		#self._monomod_mode.set_mode(abs(self._monomod_mode._mode_index -1))
		pass
	

	"""shift/zoom methods"""
	def deassign_matrix(self):
		self._session_zoom.set_button_matrix(None)
		self._session_zoom2.set_button_matrix(None)
		#self._session.set_stop_track_clip_buttons(None)
		#self._session2.set_stop_track_clip_buttons(None)
		self._session_zoom_main.set_button_matrix(None)
		#self._session_main.set_stop_track_clip_buttons(None)
		for column in range(4):
			self._mixer2.channel_strip(column).set_select_button(None)
			self._mixer2.return_strip(column).set_mute_button(None)
			self._mixer2.return_strip(column).set_solo_button(None)
			self._mixer2.return_strip(column).set_arm_button(None)
			self._mixer2.return_strip(column).set_crossfade_toggle(None)
			self._mixer2.return_strip(column).set_select_button(None)			#shouldn't this be somewhere else?
			self._mixer2.channel_strip(column).set_crossfade_toggle(None)
			self._mixer2.channel_strip(column).set_mute_button(None)
			self._mixer2.channel_strip(column).set_solo_button(None)
			self._mixer2.channel_strip(column).set_arm_button(None)
			for row in range(5):
				self._scene[row].clip_slot(column).set_launch_button(None)
				self._scene2[row].clip_slot(column).set_launch_button(None)
		for index in range(5):
			self._scene[index].set_launch_button(None)
			self._scene2[index].set_launch_button(None)
			self._scene_main[index].set_launch_button(None)
		self._session_zoom.set_nav_buttons(None, None, None, None)
		self._session_zoom2.set_nav_buttons(None, None, None, None)
		self._session_zoom_main.set_nav_buttons(None, None, None, None)
		self._session.set_track_bank_buttons(None, None)
		self._session.set_scene_bank_buttons(None, None)
		self._session2.set_track_bank_buttons(None, None)
		self._session2.set_scene_bank_buttons(None, None)
		self._session_main.set_track_bank_buttons(None, None)
		self._session_main.set_scene_bank_buttons(None, None)
		for column in range(8):
			self._mixer.channel_strip(column).set_select_button(None)
			self._mixer.channel_strip(column).set_crossfade_toggle(None)
			self._mixer.channel_strip(column).set_mute_button(None)
			self._mixer.channel_strip(column).set_solo_button(None)
			self._mixer.channel_strip(column).set_arm_button(None)
			for row in range(5):
				self._scene_main[row].clip_slot(column).set_launch_button(None)
			for row in range(8):
				self._grid[column][row].set_channel(0)
				self._grid[column][row].release_parameter()
				self._grid[column][row].use_default_message()
				self._grid[column][row].set_enabled(True)
				self._grid[column][row].set_on_off_values(127, 0)
				self._grid[column][row].send_value(0, True)
		#self._send_reset.set_buttons(tuple(None for index in range(4)))
	

	def zoom_off(self):
		for column in range(4):
			self._grid[column][5].set_on_value(MUTE[self._rgb])
			self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
			self._grid[column][6].set_on_value(ARM[self._rgb])
			self._mixer.channel_strip(column).set_arm_button(self._grid[column][6])
			for row in range(5):
				self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])
			if(self._r_function_mode._mode_index in range(0,3)):
				self._grid[column + 4][5].set_on_value(MUTE[self._rgb])
				self._mixer2.channel_strip(column).set_mute_button(self._grid[column + 4][5])
				self._grid[column + 4][6].set_on_value(ARM[self._rgb])
				self._mixer2.channel_strip(column).set_arm_button(self._grid[column + 4][6])
				for row in range(5):
					self._scene2[row].clip_slot(column).set_launch_button(self._grid[column + 4][row])
			elif(self._r_function_mode._mode_index is 3):
				self._grid[column + 4][5].set_on_value(MUTE[self._rgb])
				self._mixer2.return_strip(column).set_mute_button(self._grid[column + 4][5])
				for row in range(5):
					self._grid[column + 4][row].send_value(USER1_COLOR[self._rgb], True)
					self._grid[column + 4][row].set_channel(RIGHT_USER1_CHANNEL)
					self._grid[column + 4][row].set_identifier(RIGHT_USER1_MAP[column][row])
					self._grid[column + 4][row].set_enabled(False)	 #this has to happen for translate to work
				#self._session_zoom2.set_ignore_buttons(True)
		if(self._r_function_mode._mode_index is 0):
			for index in range(4):
				self._grid[index + 4][7].send_value(SEND_RESET[self._rgb], True)
			#self._send_reset.set_buttons(tuple(self._grid[index + 4][7] for index in range(4)))
	

	def zoom_off_m(self):
		self.deassign_dials()
		for column in range(8):
			self._grid[column][5].set_on_value(MUTE[self._rgb])
			self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
			self._grid[column][6].set_on_value(ARM[self._rgb])
			self._mixer.channel_strip(column).set_arm_button(self._grid[column][6])
			for row in range(5):
				self._scene_main[row].clip_slot(column).set_launch_button(self._grid[column][row])
		#self._session_zoom.set_button_matrix(self._matrix)
	

	def zoom_left(self):
		track_stop_buttons = []
		track_stop_buttons2 = []
		for index in range(4):
			self._grid[index][6].set_off_value(TRACK_STOP[self._rgb])
			track_stop_buttons.append(self._grid[index][6])
			self._grid[index + 4][6].set_off_value(TRACK_STOP[self._rgb])
			track_stop_buttons2.append(self._grid[index + 4][6])
		for index in range(5):
			self._grid[7][index].set_off_value(SCENE_LAUNCH[self._rgb])
			self._scene[index].set_launch_button(self._grid[7][index])
		#self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		#self._session.set_stop_track_clip_buttons(self._matrix.submatrix[:4][7:])
		#self._session2.set_stop_track_clip_buttons(tuple(track_stop_buttons2))
		#self._session2.set_stop_track_clip_buttons(self._matrix.submatrix[4:8][7:])
		self._session_zoom.set_button_matrix(self._matrix)
		self._grid[0][5].set_on_value(RECORD[self._rgb])
		self._transport.set_record_button(self._grid[0][5])
		self._grid[1][5].set_on_value(OVERDUB[self._rgb])
		self._transport.set_overdub_button(self._grid[1][5])
		self._grid[2][5].set_on_value(LOOP[self._rgb])
		self._transport.set_loop_button(self._grid[2][5])
		self._grid[3][5].set_on_value(STOP_ALL[self._rgb])	
		self._session.set_stop_all_clips_button(self._grid[3][5])
		for index in range(4):
			self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True)
		#self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4)))
		for index in range(4):
			self._grid[index + 4][7].set_off_value(DEVICE_SELECT[self._rgb])
		self._device_selector.set_matrix(self._monomod.submatrix[4:8][7:])
		self._device_selector.set_offset(4)
	

	def zoom_right(self):
		track_stop_buttons = []
		track_stop_buttons2 = []
		for index in range(4):
			self._grid[index][6].set_off_value(TRACK_STOP[self._rgb])
			track_stop_buttons.append(self._grid[index][6])
		for index in range(5):
			self._grid[7][index].set_off_value(SCENE_LAUNCH[self._rgb])
			self._scene2[index].set_launch_button(self._grid[7][index])
		#self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		#self._session.set_stop_track_clip_buttons(self._matrix.submatrix[:4][7:])
		if(self._r_function_mode._mode_index < 3):
			for index in range(4):
				self._grid[index + 4][6].set_off_value(TRACK_STOP[self._rgb])
				track_stop_buttons2.append(self._grid[index + 4][6])
			#self._session2.set_stop_track_clip_buttons(self._matrix.submatrix[4:8][7:])
			#self._session2.set_stop_track_clip_buttons(tuple(track_stop_buttons2))
		self._session_zoom2.set_button_matrix(self._matrix)
		self._grid[0][5].set_on_value(RECORD[self._rgb])
		self._transport.set_record_button(self._grid[0][5])
		self._grid[1][5].set_on_value(OVERDUB[self._rgb])
		self._transport.set_overdub_button(self._grid[1][5])
		self._grid[2][5].set_on_value(LOOP[self._rgb])
		self._transport.set_loop_button(self._grid[2][5])
		self._grid[3][5].set_on_value(STOP_ALL[self._rgb])
		self._session.set_stop_all_clips_button(self._grid[3][5])
		for index in range(4):
			self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True)
		#self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4)))
		for index in range(4):
			self._grid[index][7].set_off_value(DEVICE_SELECT[self._rgb])
		self._device_selector.set_matrix(self._monomod.submatrix[:4][7:])
		self._device_selector.set_offset(0)
	

	def zoom_main(self):
		track_stop_buttons = []
		for index in range(8):
			self._grid[index][6].set_on_value(TRACK_STOP[self._rgb])
			track_stop_buttons.append(self._grid[index][6])
		for index in range(5):
			self._grid[7][index].set_on_value(SCENE_LAUNCH[self._rgb])
			self._scene_main[index].set_launch_button(self._grid[7][index])
		#self._session_main.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		#self._session_main.set_stop_track_clip_buttons(self._matrix[0:8][7:])
		self._session_zoom_main.set_button_matrix(self._matrix)
		self._grid[0][5].set_on_value(RECORD[self._rgb])
		self._transport.set_record_button(self._grid[0][5])
		self._grid[1][5].set_on_value(OVERDUB[self._rgb])
		self._transport.set_overdub_button(self._grid[1][5])
		self._grid[2][5].set_on_value(LOOP[self._rgb])
		self._transport.set_loop_button(self._grid[2][5])
		self._grid[3][5].set_on_value(STOP_ALL[self._rgb])	
		self._session.set_stop_all_clips_button(self._grid[3][5])
		for index in range(4):
			self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True)
		#self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4)))
		for index in range(4):
			self._grid[index + 4][7].set_off_value(DEVICE_SELECT[self._rgb])
		self._device_selector.set_matrix(self._monomod.submatrix[4:8][7:])
		self._device_selector.set_offset(4)
	


	"""function mode callbacks"""
	def l_function_update(self):
		mode = self._l_function_mode._mode_index
		if(self._l_function_mode.is_enabled() is False):
			self._l_function_mode.set_mode_buttons(None)
		if not self.modhandler.is_enabled():
			if(self._l_function_mode.is_enabled() is True):
				if(len(self._l_function_mode._modes_buttons) is 0):
					for index in range(4):
						self._mixer.channel_strip(index).set_select_button(None)
					buttons = []
					for index in range(4):
						buttons.append(self._grid[index][7]) 
					self._l_function_mode.set_mode_buttons(tuple(buttons))
				if(self._shift_mode._mode_index is 2):
					for index in range(4):
						if(mode != index):
							self._grid[index][7].turn_off()
						else:
							self._grid[index][7].turn_on()
			if(mode is 0):
				self.assign_device_dials()
				self.show_message('Mixer Split:Dials Device Mode')
			elif(mode is 1):
				self.assign_send_dials()
				self.show_message('Mixer Split:Dials Send Mode')
			elif(mode is 2):
				self.assign_split_volume_dials()
				self.show_message('Mixer Split:Dials Volume Mode')
			elif(mode is 3):
				self.assign_user_dials()
				self.show_message('Mixer Split:Dials User Map Mode')
	

	def r_function_update(self):
		mode = self._r_function_mode._mode_index
		if(self._r_function_mode.is_enabled() is False):
			self._r_function_mode.set_mode_buttons(None)
			#self._session2.set_show_highlight(False)
			#self._session._highlighting_callback(self._session._track_offset, self._session._scene_offset, 4, 5, 1)
		if not self.modhandler.is_enabled():
			if(self._r_function_mode.is_enabled() is True):
				if(len(self._r_function_mode._modes_buttons) is 0):
					for index in range(4):
						self._mixer2.channel_strip(index).set_select_button(None)
					buttons = []
					for index in range(4):
						buttons.append(self._grid[index + 4][7]) 
					self._r_function_mode.set_mode_buttons(tuple(buttons))
				if(self._shift_mode._mode_index is 3):
					for index in range(4):
						if(mode != index):
							self._grid[index + 4][7].turn_off()
						else:
							self._grid[index + 4][7].turn_on()
			self._session2.set_offsets(int(self._mem[mode]), self._session2._scene_offset)
			self.show_message('Mixer Split: Track Offset' + str(RIGHT_MODE_OFFSETS[mode]))
	

	def m_function_update(self):
		mode = self._m_function_mode._mode_index
		if(self._m_function_mode.is_enabled() is False):
			self._m_function_mode.set_mode_buttons(None)
			#self._session.set_show_highlight(False)
			#self._session2.set_show_highlight(False)
			#self._session_main._highlighting_callback(self._session_main._track_offset, self._session_main._scene_offset, 8, 5, 1)
		if not self.modhandler.is_enabled():
			if(self._m_function_mode.is_enabled() is True):
				if(len(self._m_function_mode._modes_buttons) is 0):
					for index in range(8):
						self._mixer.channel_strip(index).set_select_button(None)
					buttons = []
					for index in range(4):
						buttons.append(self._grid[index][7]) 
					self._m_function_mode.set_mode_buttons(tuple(buttons))
				if(self._shift_mode._mode_index is 4):
					for index in range(4):
						if(mode != index):
							self._grid[index][7].turn_off()
						else:
							self._grid[index][7].turn_on()
			if(mode is 0):
				self.assign_device_dials()
				self.show_message('Mixer Linked:Dials Device Mode')
			elif(mode is 1):
				self.assign_send_dials()
				self.show_message('Mixer Linked:Dials Send Mode')
			elif(mode is 2):
				self.assign_volume_dials()
				self.show_message('Mixer Linked:Dials Volume Mode')
			elif(mode is 3):
				self.assign_user_dials()
				self.show_message('Mixer Linked:Dials User Map Mode')
	

	def shift_update(self):
		self._clutch_device_selection = True
		#self.allow_updates(False)
		#if(not self._in_build_midi_map):
		#	self.set_suppress_rebuild_requests(True)
		self.deassign_channel_select_buttons()
		self.deassign_matrix()
		self.deassign_menu()
		if(self._monomod_mode._mode_index is 0):		#if monomod is not on
			if(self._shift_mode._mode_index is 0):							#if no shift is pressed
				#self._shift_mode._mode_toggle1.turn_off()
				#self._shift_mode._mode_toggle2.turn_off()
				if(self.split_mixer() is False):
					self.set_split_mixer(True)
				for zoom in self._zooms:
					zoom._on_zoom_value(0)
				self.zoom_off()
				self._device_selector.set_enabled(False)
				for mode in self._function_modes:
					mode.set_enabled(False)
				self.assign_channel_select_buttons()
				#self._recalculate_selected_channel()
				#self.assign_transport_to_menu()
				self.assign_session_nav_to_menu()
				self.l_function_update()
				self.r_function_update()
				self.assign_crossfader()
				self.set_highlighting_session_component(self._session)
				self._session._do_show_highlight()	
				#self._session.set_show_highlight(True)
			elif(self._shift_mode._mode_index is 1):						#if no shift is pressed, but mixer is linked
				#self._shift_mode._mode_toggle1.turn_on()
				#self._shift_mode._mode_toggle2.turn_on()
				if(self.split_mixer() is True):
					self.set_split_mixer(False)
				for zoom in self._zooms:
					zoom._on_zoom_value(0)
				self.zoom_off_m()
				self._device_selector.set_enabled(False)
				for mode in self._function_modes:
					mode.set_enabled(False)
				self.assign_main_channel_select_buttons()
				self.assign_session_main_nav_to_menu()
				self.m_function_update()
				self.assign_crossfader()
				self.set_highlighting_session_component(self._session_main)
				self._session_main._do_show_highlight()
			elif(self._shift_mode._mode_index > 1):						#if a shift is pressed
				self.assign_device_nav_to_menu()
				self.deassign_channel_select_buttons()
				if(self._shift_mode._mode_index is 2):					#if shift left
					#self._shift_mode._mode_toggle1.turn_on()
					self.zoom_left()
					self._session_zoom._on_zoom_value(1)
					self._session.set_enabled(True) #this is a workaround so that the stop buttons still function
					self._l_function_mode.set_enabled(True)
					self.set_highlighting_session_component(self._session)
					self._session._do_show_highlight()
				elif(self._shift_mode._mode_index is 3):				#if shift right
					#self._shift_mode._mode_toggle2.turn_on()
					self.zoom_right()
					self._session_zoom2._on_zoom_value(1)
					self._session2.set_enabled(True)  #this is a workaround so that the stop buttons still function
					self._r_function_mode.set_enabled(True)
					self.assign_master_fader()
					if(self._r_function_mode._mode_index < 4):
						self.set_highlighting_session_component(self._session2)
						self._session2._do_show_highlight()
				elif(self._shift_mode._mode_index is 4):				#if either shift pressed while mixer is linked
					#self._shift_mode._mode_toggle1.turn_on()
					#self._shift_mode._mode_toggle2.turn_on()
					self.zoom_main()
					self._session_zoom_main._on_zoom_value(1)
					self._session_main.set_enabled(True) #this is a workaround so that the stop buttons still function
					self._m_function_mode.set_enabled(True)
					self.assign_master_fader()
					self.set_highlighting_session_component(self._session_main)
					self._session_main._do_show_highlight()
				self._device_selector.set_enabled(True)
		else:
			for mode in self._function_modes:
				mode.set_enabled(False)
			#self.modhandler._shift_value(int(self._shift_mode._mode_index>1))
		self.allow_updates(True)
		#self.set_suppress_rebuild_requests(False)
		self._clutch_device_selection = False
		if(self._shift_mode._mode_index < 2):
			self._monobridge._send('touch', 'off')
		else:
			self._monobridge._send('touch', 'on')
	

	"""left control management methods"""
	def deassign_dials(self):
		for index in range(8):
			self._dial[index].use_default_message()
			self._dial[index].release_parameter()
			self._dial[index].set_enabled(True)
		if(self._device._parameter_controls != None):
			for control in self._device._parameter_controls:
				control.release_parameter()
			self._device._parameter_controls = None
		self._mixer.selected_strip().set_send_controls(None)
		self._mixer.selected_strip().set_volume_control(None)
		for track in range(4):
			self._mixer.channel_strip(track).set_volume_control(None)
			self._mixer.channel_strip(track+4).set_volume_control(None)
			self._mixer2.channel_strip(track).set_volume_control(None)
			self._mixer2.return_strip(track).set_volume_control(None)
	

	def assign_device_dials(self):
		self._ohm_type = OHM_TYPE[0]
		self._ohm = OHM_VALUE[0]
		self.deassign_dials()
		self._device.set_enabled(True)
		device_param_controls = []
		for index in range(8):
			device_param_controls.append(self._dial[index])
		self._device.set_parameter_controls(tuple(device_param_controls))
		self._mixer.selected_strip().set_volume_control(self._fader[0])
	

	def assign_send_dials(self):
		self._ohm_type = OHM_TYPE[1]
		self._ohm = OHM_VALUE[1]
		self.deassign_dials()
		dials = []
		for index in range(4):
			dials.append(self._dial[index])
		for index in range(4):
			if(self._mixer2.return_strip(index)):
				self._mixer2.return_strip(index).set_volume_control(self._dial[index + 4])
		self._mixer.selected_strip().set_send_controls(tuple(dials))
		self._mixer.selected_strip().set_volume_control(self._fader[0])
	

	def assign_volume_dials(self):
		self._ohm_type = OHM_TYPE[2]
		self._ohm = OHM_VALUE[2]
		self.deassign_dials()
		for track in range(8):
			self._mixer.channel_strip(track).set_volume_control(self._dial[track])
		self._mixer.selected_strip().set_volume_control(self._fader[0])
	

	def assign_split_volume_dials(self):
		self._ohm_type = OHM_TYPE[2]
		self._ohm = OHM_VALUE[2]
		self.deassign_dials()
		for track in range(4):
			self._mixer.channel_strip(track).set_volume_control(self._dial[track])
			self._mixer2.channel_strip(track).set_volume_control(self._dial[track+4])
		self._mixer.selected_strip().set_volume_control(self._fader[0])
	

	def assign_user_dials(self):
		self._ohm_type = OHM_TYPE[3]
		self._ohm = OHM_VALUE[3]
		self.deassign_dials()
		for index in range(8):
			self._dial[index].set_channel(L_USER_DIAL_CHAN)
			self._dial[index].set_identifier(L_USER_DIAL_MAP[index])
			self._dial[index].set_enabled(False)
		self._mixer.selected_strip().set_volume_control(self._fader[0])
	


	"""menu button management methods"""
	def deassign_menu(self):
		self._device.set_lock_button(None)
		self._device.set_on_off_button(None)
		#self._device_navigator.set_device_nav_buttons(None, None)	
		self._device_navigator.set_enabled(False)
		self._device.set_bank_nav_buttons(None, None)
		self._transport.set_play_button(None)	
		self._transport.set_record_button(None) 
		self._transport.set_stop_button(None)
		self._transport.set_loop_button(None)	
		self._transport.set_overdub_button(None)	
		self._session.set_stop_all_clips_button(None)
		self._session_main.set_track_bank_buttons(None, None)
		self._session_main.set_scene_bank_buttons(None, None)
	

	def assign_device_nav_to_menu(self):
		#self._device_navigator.set_device_nav_buttons(self._menu[2], self._menu[3]) 
		self._device_navigator.set_enabled(True)
		self._device.set_bank_nav_buttons(self._menu[0], self._menu[1])
	

	def assign_transport_to_menu(self):
		self._transport.set_play_button(self._menu[0])	
		self._transport.set_record_button(self._menu[2])
		self._transport.set_stop_button(self._menu[1])
		session.set_stop_all_clips_button(self._menu[3])
	

	def assign_session_nav_to_menu(self):
		self._session.set_track_bank_buttons(self._menu[3], self._menu[2])
		self._session.set_scene_bank_buttons(self._menu[1], self._menu[0])
	

	def assign_monomod_shift_to_menu(self):
		#self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[2])
		self._device_navigator.set_enabled(True)
		self._device.set_bank_nav_buttons(self._menu[1], self._menu[0])
	

	def assign_session_bank_to_menu(self):
		self._session.set_track_bank_buttons(self._menu[3], self._menu[2])
		self._session.set_scene_bank_buttons(self._menu[1], self._menu[0])
	

	def assign_session2_bank_to_menu(self):
		self._session2.set_track_bank_buttons(self._menu[3], self._menu[2])
		self._session2.set_scene_bank_buttons(self._menu[1], self._menu[0])
	

	def assign_session_main_nav_to_menu(self):
		self._session_main.set_track_bank_buttons(self._menu[3], self._menu[2])
		self._session_main.set_scene_bank_buttons(self._menu[1], self._menu[0])
	


	"""channel selection management methods"""
	def deassign_channel_select_buttons(self):
		for index in range(8):
			if(self._mixer.channel_strip(index)):
				self._mixer.channel_strip(index).set_select_button(None)
			self._grid[index][7].release_parameter()
		for index in range(4):
			self._mixer2.channel_strip(index).set_select_button(None)
			self._mixer2.return_strip(index).set_select_button(None)
			self._mixer2.master_strip().set_select_button(None)
			self._grid[index + 4][7].release_parameter()
	

	def assign_channel_select_buttons(self):
		for index in range(4):
			#if(self._mixer.channel_strip(index)):
			self._grid[index][7].set_on_off_values(127, 0)
			self._mixer.channel_strip(index).set_select_button(self._grid[index][7])
		if(self._r_function_mode._mode_index < 3):
			for index in range(4):
				self._grid[index][7].set_on_off_values(127, 0)
				self._mixer2.channel_strip(index).set_select_button(self._grid[index + 4][7])	
		else:
			for index in range(4):
				self._grid[index][7].set_on_off_values(1, 0)
				self._mixer2.return_strip(index).set_select_button(self._grid[index + 4][7])
	

	def assign_return_select_buttons(self):
		for index in range(4):
			self._grid[index + 4][7].set_off_value(0) 
			if(self._mixer.channel_strip(index)):
				self._grid[index + 4][7].set_on_value(1)
				self._mixer.channel_strip(index).set_select_button(self._grid[index + 4][7])
	

	def assign_l_channel_select_buttons(self):
		self._mixer.set_select_buttons(None, None)
		self._session.set_select_buttons(None, None)
		for index in range(4):
			self._grid[index][7].set_off_value(0)
			if(self._mixer.channel_strip(index)):
				self._mixer.channel_strip(index).set_select_button(self._grid[index][7])
	

	def assign_r_channel_select_buttons(self):
		self._mixer2.set_select_buttons(None, None)
		self._session2.set_select_buttons(None, None)
		for index in range(4):
			self._grid[index + 4][7].set_off_value(0)
			if(self._mixer2.channel_strip(index)):
				self._mixer2.channel_strip(index).set_select_button(self._grid[index + 4][7])
	

	def assign_main_channel_select_buttons(self):
		for index in range(8):
			self._grid[index][7].set_off_value(0)
			if(self._mixer.channel_strip(index)):
				self._grid[index][7].set_on_value(127)
				self._mixer.channel_strip(index).set_select_button(self._grid[index][7])
	

	def assign_master_fader(self):
		self._mixer.set_crossfader_control(None)
		self._mixer.master_strip().set_volume_control(self._fader[1])
	

	def assign_crossfader(self):
		self._mixer.master_strip().set_volume_control(None)
		self._mixer.set_crossfader_control(self._fader[1])
	


	"""called on timer"""
	def update_display(self):
		super(BlockMod, self).update_display()
		if(self._timer == 0):
			self._shift_pressed_timer = -12
	

	def strobe(self):
		if(self._ohm_type != 'static'):
			if(self._ohm_type is 'pulse'):
				self._ohm = int(math.fabs(((self._timer * 8) % 64) -32) +32)
			if(self._ohm_type is 'up'):
				self._ohm = int(((self._timer * 4) % 64) + 16)
			if(self._ohm_type is 'down'):
				self._ohm = int(math.fabs(int(((self._timer * 4) % 64) - 64)) + 16)
		self._send_midi(tuple([176, 63, int(self._ohm)]))
		self._send_midi(tuple([176, 31, int(self._ohm)]))	
	

	def handle_sysex(self, midi_bytes):
		pass
	

	def _on_session_offset_changes(self):
		if self._r_function_mode._mode_index in range(0,4):
			self._mem[int(self._r_function_mode._mode_index)] = self._session2.track_offset()
	



#	a
Exemple #16
0
class AumPC20(APC):
    """ Monomodular script for Akai's APC20 Controller """
    def __init__(self, c_instance, *a, **k):
        self._shift_modes = None
        super(AumPC20, self).__init__(c_instance, *a, **k)

    def disconnect(self):
        self._shift_modes = None
        super(AumPC20, self).disconnect()

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

    def _setup_session_control(self):
        is_momentary = True
        self._shift_button = AumPCMonoButtonElement(is_momentary,
                                                    MIDI_NOTE_TYPE, 0, 81,
                                                    'Shift_Button', self)
        self._session = APCSessionComponent(8, 5)
        self._session.name = 'Session_Control'
        self._matrix = ButtonMatrixElement()
        self._matrix.name = 'Button_Matrix'
        scene_launch_buttons = [
            AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                   (index + 82),
                                   'Scene_' + str(index) + '_Launch_Button',
                                   self) for index in range(5)
        ]
        self._scene_launch_buttons = scene_launch_buttons
        track_stop_buttons = [
            AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52,
                                   'Track_' + str(index) + '_Stop_Button',
                                   self) for index in range(8)
        ]
        self._track_stop_buttons = track_stop_buttons
        for index in range(len(scene_launch_buttons)):
            scene_launch_buttons[index].name = 'Scene_' + str(
                index) + '_Launch_Button'

        for index in range(len(track_stop_buttons)):
            track_stop_buttons[index].name = 'Track_' + str(
                index) + '_Stop_Button'

        self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
        self._session.set_stop_track_clip_value(2)
        for scene_index in range(5):
            scene = self._session.scene(scene_index)
            scene.name = 'Scene_' + str(scene_index)
            button_row = []
            scene.set_launch_button(scene_launch_buttons[scene_index])
            scene.set_triggered_value(2)
            for track_index in range(8):
                button = AumPCMonoButtonElement(
                    is_momentary, MIDI_NOTE_TYPE, track_index,
                    (scene_index + 53),
                    '_Clip_' + str(scene_index) + '_Button', self)
                button.name = str(track_index) + '_Clip_' + str(
                    scene_index) + '_Button'
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                    scene_index)
                clip_slot.set_triggered_to_play_value(2)
                clip_slot.set_triggered_to_record_value(4)
                clip_slot.set_stopped_value(5)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(3)
                clip_slot.set_launch_button(button)

            self._matrix.add_row(tuple(button_row))

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

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._solo_buttons = []
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            solo_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                                 track, 49,
                                                 str(track) + '_Solo_Button',
                                                 self)
            self._solo_buttons.append(solo_button)
            mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        50)
            solo_button.name = str(track) + '_Solo_Button'
            mute_button.name = str(track) + '_Mute_Button'
            strip.set_solo_button(solo_button)
            strip.set_mute_button(mute_button)
            strip.set_shift_button(self._shift_button)
            strip.set_invert_mute_feedback(True)

        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        prehear_control = EncoderElement(
            MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
        master_volume_control.name = 'Master_Volume_Control'
        prehear_control.name = 'Prehear_Volume_Control'
        self._mixer.set_prehear_volume_control(prehear_control)
        self._mixer.master_strip().set_volume_control(master_volume_control)

    def _setup_custom_components(self):
        is_momentary = True
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                             80)
        master_select_button.name = 'Master_Select_Button'
        self._master_select_button = master_select_button
        select_buttons = []
        arm_buttons = []
        sliders = []
        for track in range(8):
            select_buttons.append(
                AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51,
                                       str(track) + '_Select_Button', self))
            arm_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48))
            sliders.append(
                MonoEncoderElement(MIDI_CC_TYPE, track, 7,
                                   Live.MidiMap.MapMode.absolute,
                                   'Slider_' + str(track), track, self))
            select_buttons[-1].name = str(track) + '_Select_Button'
            arm_buttons[-1].name = str(track) + '_Arm_Button'
            #sliders[-1].name = str(track) + '_Volume_Control'
        self._select_buttons = select_buttons

        transport = TransportComponent()
        transport.name = 'Transport'
        slider_modes = SliderModesComponent(self._mixer, tuple(sliders))
        slider_modes.name = 'Slider_Modes'
        self._shift_modes = AumPC20ShiftableSelectorComponent(
            tuple(select_buttons), master_select_button, tuple(arm_buttons),
            self._matrix, self._session, self._session_zoom, self._mixer,
            transport, slider_modes, self._send_introduction_message, self)
        self._shift_modes.name = 'Shift_Modes'
        self._shift_modes.set_mode_toggle(self._shift_button)
        self._device = DeviceComponent()

    def _product_model_id_byte(self):
        return 123

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

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

    def _shift_value(self, value):
        if value > 0:
            self._mixer.master_strip().set_select_button(None)
            self._monomod_mode.set_mode_toggle(self._master_select_button)
        else:
            self._mixer.master_strip().set_select_button(
                self._master_select_button)
            self._monomod_mode.set_mode_toggle(None)

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

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

    """m4l bridge"""

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

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

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

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

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

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

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

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

    def set_appointed_device(self, *a, **k):
        pass
    def _setup_session_control(self):
        self.session = CustomSessionComponent(self.box_width, self.box_height,
                                              self)  # subclass from _Framework
        is_momentary = True  # what exactly does this do in the _Framework?
        if up_button_note_number >= 0 and down_button_note_number >= 0:  # opt in enable UP/DOWN nav
            up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                      midi_channel, up_button_note_number)
            up_button.name = 'Bank_Select_Up_Button'  # sure, why not
            down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                        midi_channel, down_button_note_number)
            down_button.name = 'Bank_Select_Down_Button'  #sure, why not
            self.session.set_scene_bank_buttons(down_button, up_button)
        if right_button_note_number >= 0 and left_button_note_number >= 0:  # opt in enable LEFT/RIGHT nav
            right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                         midi_channel,
                                         right_button_note_number)
            right_button.name = 'Bank_Select_Right_Button'  #sure, why not
            left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                        midi_channel, left_button_note_number)
            left_button.name = 'Bank_Select_Left_Button'  #sure, why not
            self.session.set_track_bank_buttons(right_button, left_button)
        self.session.name = 'Session_Control'  #sure, why not
        matrix = ButtonMatrixElement(
        )  # @todo subclass this via established new patterns
        matrix.name = 'Button_Matrix'  #sure, why not
        # I loop a little different. The goal is readbility, flexibility, and the web app...incase you did not notice yet
        if len(scene_launch_notes) > 0 and len(
                scene_launch_notes
        ) == self.box_height:  # logic check have launch notes and scene = box height
            for index in range(self.box_height):
                self.session.scene(index).set_launch_button(
                    ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel,
                                  scene_launch_notes[index]))
        else:
            self.log_message(
                "..::|| Scene launch not in use or error on case of use. Modern.DJ ||::.."
            )
        if len(stop_track_buttons) > 0 and len(
                stop_track_buttons
        ) == self.box_width:  #logic check have track stop assignments and
            track_stop_buttons = [
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel,
                              stop_track_buttons[index])
                for index in range(len(stop_track_buttons))
            ]
            for index in range(len(track_stop_buttons)):
                track_stop_buttons[index].name = 'Track_' + str(
                    index) + '_Stop_Button'  # sure, why not
            self.session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
        else:
            self.log_message(
                "..::|| Stop notes not in use or error found Modern.DJ ||::..")
        # Check for stop all clips option
        if stop_all_clips >= 0:
            self.session.set_stop_all_clips_button(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel,
                              stop_all_clips))
        # creating the matrix of buttons from the launch_button_list (tuple)
        launch_button_list_len = len(
            launch_button_list
        )  # var used multiple times. This is a performance modification
        if (
                self.box_height * self.box_width
        ) == launch_button_list_len:  # check box size against number of button vars sent
            launch_ctr = launch_button_list_len - 1  # decrement for zero offset in list/tuple
            launch_button_list.reverse(
            )  #reverse list from human readable for decrement use (performance tweak)
            ## check for use of RGB
            if use_velocity_for_RGB != 1:  # if not enabled use these defaults
                self.log_message(
                    "..::|| RGB not in effect assigning defaults ||::..")
                self.clip_loaded_stopped = 1
                self.clip_currently_playing = 127
                self.clip_triggered_to_play = 64
            else:  # yes RGB in effect...assign per the parameters script
                self.clip_loaded_stopped = clip_loaded_stopped
                self.clip_currently_playing = clip_currently_playing
                self.clip_triggered_to_play = clip_triggered_to_play

            for scene_index in range(
                    self.box_height):  # loop on the notes matrix
                scene = self.session.scene(
                    scene_index)  # part of the martix built, think rows
                scene.name = 'Scene_' + str(scene_index)  # sure, why not
                button_row = []  # create recepticle
                # loop across the tracks
                for track_index in range(self.box_width):
                    button = ButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                           midi_channel,
                                           launch_button_list[launch_ctr]
                                           )  # button instance for _Framework
                    launch_ctr = launch_ctr - 1  # decrement is faster than increment
                    button.name = str(track_index) + '_Clip_' + str(
                        scene_index) + '_Button'  # sure, why not
                    button_row.append(button)  # add to our growing list
                    clip_slot = scene.clip_slot(
                        track_index
                    )  # clips slot and buttons are not the same thing, this aligns these ideas in the red box
                    clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                        scene_index)  # sure, why not
                    # assign the button and and status in th refrech update
                    clip_slot.set_stopped_value(
                        self.clip_loaded_stopped
                    )  # this number is sent back to the machine allowing diff colors for stopped
                    clip_slot.set_started_value(
                        self.clip_currently_playing
                    )  # this number is sent back to the machine allowing diff colors for started/is-playing
                    clip_slot.set_triggered_to_play_value(
                        self.clip_triggered_to_play
                    )  # this number is sent back to the machine allowing diff colors for cued, will play next
                    clip_slot.set_launch_button(
                        button)  # part of the slit+button = go time paradigm
                matrix.add_row(
                    tuple(button_row)
                )  # close out the matrix build. @todo - possible subclass here?
        else:  # log message
            self.log_message(
                "..::|| Number of notes defined does not match box height and width Modern.DJ ||::.."
            )
        ''' live 9 only
        self.set_highlighting_session_component(self.session) # new for live9 -- this is for the box. via aumhaa/bitnomad
        '''
        return None
class APC40(APC, OptimizedControlSurface):
    """ Script for Akai's APC40 Controller """
    def __init__(self, *a, **k):
        super(APC40, self).__init__(*a, **k)
        self._color_skin = make_biled_skin()
        self._default_skin = make_default_skin()
        with self.component_guard():
            self._create_controls()
            self._create_session()
            self._create_mixer()
            self._create_device()
            self._create_detail_view_control()
            self._create_transport()
            self._create_global_control()
            self._create_fallback_control_owner()
            self._session.set_mixer(self._mixer)
            self.set_highlighting_session_component(self._session)
            self.set_device_component(self._device)
            for component in self.components:
                component.set_enabled(False)

        self._device_selection_follows_track_selection = True

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

    def _create_controls(self):
        make_on_off_button = partial(make_button, skin=self._default_skin)
        make_color_button = partial(make_button, skin=self._color_skin)
        self._shift_button = make_button(0,
                                         98,
                                         resource_type=PrioritizedResource,
                                         name='Shift_Button')
        self._right_button = make_button(0,
                                         96,
                                         name='Bank_Select_Right_Button')
        self._left_button = make_button(0, 97, name='Bank_Select_Left_Button')
        self._up_button = make_button(0, 94, name='Bank_Select_Up_Button')
        self._down_button = make_button(0, 95, name='Bank_Select_Down_Button')
        self._session_matrix = ButtonMatrixElement(name='Button_Matrix')
        self._scene_launch_buttons_raw = [
            make_color_button(0,
                              index + 82,
                              name='Scene_%d_Launch_Button' % index)
            for index in xrange(SESSION_HEIGHT)
        ]
        self._track_stop_buttons = [
            make_color_button(index, 52, name='Track_%d_Stop_Button' % index)
            for index in xrange(SESSION_WIDTH)
        ]
        self._stop_all_button = make_color_button(0,
                                                  81,
                                                  name='Stop_All_Clips_Button')
        self._matrix_rows_raw = [[
            make_color_button(track_index,
                              scene_index + 53,
                              name='%d_Clip_%d_Button' %
                              (track_index, scene_index))
            for track_index in xrange(SESSION_WIDTH)
        ] for scene_index in xrange(SESSION_HEIGHT)]
        for row in self._matrix_rows_raw:
            self._session_matrix.add_row(row)

        self._selected_slot_launch_button = make_pedal_button(
            67, name='Selected_Slot_Launch_Button')
        self._selected_scene_launch_button = make_pedal_button(
            64, name='Selected_Scene_Launch_Button')
        self._volume_controls = []
        self._arm_buttons = []
        self._solo_buttons = []
        self._mute_buttons = []
        self._select_buttons = []
        for index in xrange(MIXER_SIZE):
            self._volume_controls.append(
                make_slider(index, 7, name='%d_Volume_Control' % index))
            self._arm_buttons.append(
                make_on_off_button(index, 48, name='%d_Arm_Button' % index))
            self._solo_buttons.append(
                make_on_off_button(index, 49, name='%d_Solo_Button' % index))
            self._mute_buttons.append(
                make_on_off_button(index, 50, name='%d_Mute_Button' % index))
            self._select_buttons.append(
                make_on_off_button(index, 51, name='%d_Select_Button' % index))

        self._crossfader_control = make_slider(0, 15, name='Crossfader')
        self._master_volume_control = make_slider(0,
                                                  14,
                                                  name='Master_Volume_Control')
        self._master_select_button = make_on_off_button(
            0, 80, name='Master_Select_Button')
        self._prehear_control = make_encoder(0,
                                             47,
                                             name='Prehear_Volume_Control')
        self._device_bank_buttons = []
        self._device_param_controls_raw = []
        bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button',
                              'Previous_Device_Button', 'Next_Device_Button',
                              'Detail_View_Button', 'Rec_Quantization_Button',
                              'Midi_Overdub_Button', 'Metronome_Button')
        for index in range(8):
            self._device_bank_buttons.append(
                make_on_off_button(0,
                                   58 + index,
                                   name=bank_button_labels[index]))
            encoder_name = 'Device_Control_%d' % index
            ringed_encoder = make_ring_encoder(16 + index,
                                               24 + index,
                                               name=encoder_name)
            self._device_param_controls_raw.append(ringed_encoder)

        self._play_button = make_button(0, 91, name='Play_Button')
        self._stop_button = make_button(0, 92, name='Stop_Button')
        self._record_button = make_button(0, 93, name='Record_Button')
        self._nudge_up_button = make_button(0, 100, name='Nudge_Up_Button')
        self._nudge_down_button = make_button(0, 101, name='Nudge_Down_Button')
        self._tap_tempo_button = make_button(0, 99, name='Tap_Tempo_Button')
        self._global_bank_buttons = []
        self._global_param_controls = []
        for index in range(8):
            encoder_name = 'Track_Control_%d' % index
            ringed_encoder = make_ring_encoder(48 + index,
                                               56 + index,
                                               name=encoder_name)
            self._global_param_controls.append(ringed_encoder)

        self._global_bank_buttons = [
            make_on_off_button(0, 87 + index, name=name)
            for index, name in enumerate(('Pan_Button', 'Send_A_Button',
                                          'Send_B_Button', 'Send_C_Button'))
        ]
        self._device_clip_toggle_button = self._device_bank_buttons[0]
        self._device_on_off_button = self._device_bank_buttons[1]
        self._detail_left_button = self._device_bank_buttons[2]
        self._detail_right_button = self._device_bank_buttons[3]
        self._detail_toggle_button = self._device_bank_buttons[4]
        self._rec_quantization_button = self._device_bank_buttons[5]
        self._overdub_button = self._device_bank_buttons[6]
        self._metronome_button = self._device_bank_buttons[7]

        def wrap_matrix(control_list, wrapper=nop):
            return ButtonMatrixElement(rows=[map(wrapper, control_list)])

        self._scene_launch_buttons = wrap_matrix(
            self._scene_launch_buttons_raw)
        self._track_stop_buttons = wrap_matrix(self._track_stop_buttons)
        self._volume_controls = wrap_matrix(self._volume_controls)
        self._arm_buttons = wrap_matrix(self._arm_buttons)
        self._solo_buttons = wrap_matrix(self._solo_buttons)
        self._mute_buttons = wrap_matrix(self._mute_buttons)
        self._select_buttons = wrap_matrix(self._select_buttons)
        self._device_param_controls = wrap_matrix(
            self._device_param_controls_raw)
        self._device_bank_buttons = wrap_matrix(
            self._device_bank_buttons,
            partial(DeviceBankButtonElement, modifiers=[self._shift_button]))
        self._shifted_matrix = ButtonMatrixElement(
            rows=recursive_map(self._with_shift, self._matrix_rows_raw))
        self._shifted_scene_buttons = ButtonMatrixElement(rows=[[
            self._with_shift(button)
            for button in self._scene_launch_buttons_raw
        ]])

    def _create_session(self):
        self._session = SessionComponent(
            SESSION_WIDTH,
            SESSION_HEIGHT,
            auto_name=True,
            enable_skinning=True,
            is_enabled=False,
            layer=Layer(track_bank_left_button=self._left_button,
                        track_bank_right_button=self._right_button,
                        scene_bank_up_button=self._up_button,
                        scene_bank_down_button=self._down_button,
                        stop_all_clips_button=self._stop_all_button,
                        stop_track_clip_buttons=self._track_stop_buttons,
                        scene_launch_buttons=self._scene_launch_buttons,
                        clip_launch_buttons=self._session_matrix,
                        slot_launch_button=self._selected_slot_launch_button,
                        selected_scene_launch_button=self.
                        _selected_scene_launch_button))
        self._session_zoom = SessionZoomingComponent(
            self._session,
            name='Session_Overview',
            enable_skinning=True,
            is_enabled=False,
            layer=Layer(button_matrix=self._shifted_matrix,
                        nav_up_button=self._with_shift(self._up_button),
                        nav_down_button=self._with_shift(self._down_button),
                        nav_left_button=self._with_shift(self._left_button),
                        nav_right_button=self._with_shift(self._right_button),
                        scene_bank_buttons=self._shifted_scene_buttons))

    def _create_mixer(self):
        self._mixer = MixerComponent(
            MIXER_SIZE,
            auto_name=True,
            is_enabled=False,
            invert_mute_feedback=True,
            layer=Layer(volume_controls=self._volume_controls,
                        arm_buttons=self._arm_buttons,
                        solo_buttons=self._solo_buttons,
                        mute_buttons=self._mute_buttons,
                        track_select_buttons=self._select_buttons,
                        shift_button=self._shift_button,
                        crossfader_control=self._crossfader_control,
                        prehear_volume_control=self._prehear_control))
        self._mixer.master_strip().layer = Layer(
            volume_control=self._master_volume_control,
            select_button=self._master_select_button)

    def _create_device(self):
        self._device = DeviceComponent(
            name='Device_Component',
            is_enabled=False,
            layer=Layer(bank_buttons=self._device_bank_buttons,
                        on_off_button=self._device_on_off_button),
            use_fake_banks=True)
        ChannelTranslationSelector(8, name='Control_Translations')
        self._device.set_parameter_controls(
            tuple(self._device_param_controls_raw))

    def _create_detail_view_control(self):
        self._detail_view_toggler = DetailViewCntrlComponent(
            name='Detail_View_Control',
            is_enabled=False,
            layer=Layer(
                device_clip_toggle_button=self._device_clip_toggle_button,
                detail_toggle_button=self._detail_toggle_button,
                device_nav_left_button=self._detail_left_button,
                device_nav_right_button=self._detail_right_button))

    def _create_transport(self):
        self._transport = TransportComponent(
            name='Transport',
            is_enabled=False,
            layer=Layer(play_button=self._play_button,
                        stop_button=self._stop_button,
                        record_button=self._record_button,
                        nudge_up_button=self._nudge_up_button,
                        nudge_down_button=self._nudge_down_button,
                        tap_tempo_button=self._tap_tempo_button,
                        quant_toggle_button=self._rec_quantization_button,
                        overdub_button=self._overdub_button,
                        metronome_button=self._metronome_button))
        self._bank_button_translator = ChannelTranslationSelector(
            name='Bank_Button_Translations', is_enabled=False)

    def _create_global_control(self):
        def set_pan_controls():
            for index, control in enumerate(self._global_param_controls):
                self._mixer.channel_strip(index).set_pan_control(control)
                self._mixer.channel_strip(index).set_send_controls(
                    (None, None, None))
                control.set_channel(0)

        def set_send_controls(send_index):
            for index, control in enumerate(self._global_param_controls):
                self._mixer.channel_strip(index).set_pan_control(None)
                send_controls = [None] * 3
                send_controls[send_index] = control
                self._mixer.channel_strip(index).set_send_controls(
                    send_controls)
                control.set_channel(send_index + 1)

        encoder_modes = ModesComponent(name='Track_Control_Modes',
                                       is_enabled=False)
        encoder_modes.add_mode('pan', [set_pan_controls])
        encoder_modes.add_mode('send_a', [partial(set_send_controls, 0)])
        encoder_modes.add_mode('send_b', [partial(set_send_controls, 1)])
        encoder_modes.add_mode('send_c', [partial(set_send_controls, 2)])
        encoder_modes.selected_mode = 'pan'
        encoder_modes.layer = Layer(pan_button=self._global_bank_buttons[0],
                                    send_a_button=self._global_bank_buttons[1],
                                    send_b_button=self._global_bank_buttons[2],
                                    send_c_button=self._global_bank_buttons[3])
        self._translation_selector = ChannelTranslationSelector(
            name='Global_Translations')

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

    def get_matrix_button(self, column, row):
        return self._matrix_rows_raw[row][column]

    def _product_model_id_byte(self):
        return 115
Exemple #19
0
class Tweaker(ControlSurface):
	__module__ = __name__
	__doc__ = " MonOhmod companion controller script "


	def __init__(self, c_instance):
		"""everything except the '_on_selected_track_changed' override and 'disconnect' runs from here"""
		ControlSurface.__init__(self, c_instance)
		with self.component_guard():
			self._update_linked_device_selection = None
			self._tweaker_version = '0.2'
			self.log_message("--------------= Tweaker Mixer " + str(self._tweaker_version) + " log opened =--------------") 
			self._update_linked_device_selection = None
			self._setup_mixer_control()
			self._setup_session_control()
	

	"""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] = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, column + (row * 8), 'Grid_' + str(column) + '_' + str(row), self) for row in range(4)]
		self._button = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_BUTTONS[index], 'Button_' + str(index), self) for index in range(len(TWEAKER_BUTTONS))]
		self._nav = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_NAVS[index], 'Nav_' + str(index), self) for index in range(len(TWEAKER_NAVS))]
		self._encoder_buttons = [FlashingButtonElement(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 = [FlashingButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, TWEAKER_PADS[index], 'Pad_' + str(index), self) for index in range(len(TWEAKER_PADS))]
		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)) 	
	

	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, True)
		self._mixer.name = 'Mixer'
		self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer)
		self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
	

	def _setup_session_control(self):
		is_momentary = True
		num_tracks = 2
		num_scenes = 3 
		self._session = SessionComponent(num_tracks, num_scenes)
		self._session.name = "Session"
		self._session.set_offsets(0, 0)
		self._session.set_mixer(self._mixer)
		self.set_highlighting_session_component(self._session)
	

	"""general functionality"""
	
	def allow_updates(self, allow_updates):
		for component in self.components:
			component.set_allow_update(int(allow_updates!=0))
	

	def disconnect(self):
		"""clean things up on disconnect"""
		if self._session._is_linked():
			self._session._unlink()
		self.log_message("--------------= Tweaker Mixer " + str(self._tweaker_version) + " log closed =--------------") #Create entry in log file
		ControlSurface.disconnect(self)
		return None
	

	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:
					link = True
			if not s is self:
				s._linked_session = self._session
					#break	
		if link is True:
			if not self._session._is_linked():
				#self._session.set_offsets(0, 0)
				self._session._link()
	

	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

#	a
class OhmModes(ControlSurface):
	__module__ = __name__
	__doc__ = ' OhmModes controller script '

	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		with self.component_guard():
			self._version_check = 'b994'
			self._host_name = 'Ohm'
			self._color_type = 'OhmRGB'
			self._hosts = []
			self.hosts = []
			self._client = [ None for index in range(6) ]
			self._active_client = None
			self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< OhmModes ' + str(self._version_check) + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>')
			self._rgb = 0
			self._timer = 0
			self._touched = 0
			self.flash_status = 1
			self._backlight = 127
			self._backlight_type = 'static'
			self._ohm = 127
			self._ohm_type = 'static'
			self._pad_translations = PAD_TRANSLATION
			self._device_selection_follows_track_selection = FOLLOW
			self._keys_octave = 5
			self._keys_scale = 0
			self._tempo_buttons = None
			self._setup_monobridge()
			self._setup_controls()
			self._setup_transport_control()
			self._setup_mixer_control()
			self._setup_session_control()
			self._setup_device_control()
			self._setup_crossfader()
			self._setup_ohmmod()
			self._setup_switchboard()
			self._setup_modes()
			self._assign_page_constants()
			self._last_device = None
			self.song().view.add_selected_track_listener(self._update_selected_device)
			self.show_message('OhmModes Control Surface Loaded')
			self._send_midi(tuple(switchxfader))
			if FORCE_TYPE is True:
				self._rgb = FORCE_COLOR_TYPE
			else:
				self.schedule_message(10, self.query_ohm, None)
			self.log_message(str(self._highlighting_session_component))

	def query_ohm(self):
		self._send_midi(tuple(check_model))

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

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

	def get_device_bank(self):
		return self._device._bank_index

	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] = MonoEncoderElement2(MIDI_CC_TYPE, CHANNEL, OHM_FADERS[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self)

		for index in range(8):
			self._button[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_' + str(index), self)

		for index in range(16):
			self._dial[index] = CodecEncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_DIALS[index], Live.MidiMap.MapMode.absolute, 'Encoder_' + str(index), index, self)

		self._knobs = []
		for index in range(12):
			self._knobs.append(self._dial[index])

		for index in range(6):
			self._menu[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_MENU[index], 'Menu_' + str(index), self)

		self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute)
		self._crossfader.name = 'Crossfader'
		self._livid = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self)
		self._shift_l = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Page_Button_Left', self)
		self._shift_r = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Page_Button_Right', self)
		self._matrix = ButtonMatrixElement()
		self._matrix.name = 'Matrix'
		self._grid = [ None for index in range(8) ]
		self._monomod = ButtonMatrixElement()
		self._monomod.name = 'Monomod'
		for column in range(8):
			self._grid[column] = [ None for index in range(8) ]
			for row in range(8):
				self._grid[column][row] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, column * 8 + row, 'Grid_' + 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._mod_matrix = ButtonMatrixElement()
		self._mod_matrix.name = 'Matrix'
		self._dial_matrix = EncoderMatrixElement(self)
		self._dial_matrix.name = 'Dial_Matrix'
		self._dial_button_matrix = ButtonMatrixElement()
		self._dial_button_matrix.name = 'Dial_Button_Matrix'
		for row in range(4):
			button_row = []
			for column in range(4):
				button_row.append(self._grid[column + 4][row])

			self._mod_matrix.add_row(tuple(button_row))

		for row in range(3):
			dial_row = []
			for column in range(4):
				dial_row.append(self._dial[row * 4 + column])

			self._dial_matrix.add_row(tuple(dial_row))

		for row in range(3):
			dial_button_row = []
			for column in range(4):
				dial_button_row.append(self._grid[column][row])

			self._dial_button_matrix.add_row(tuple(dial_button_row))

		self._key = [ self._grid[KEYS[index][1]][KEYS[index][0]] for index in range(32) ]
		self._encoder = [ self._dial[index] for index in range(12) ]
		self._key_matrix = ButtonMatrixElement()
		button_row = []
		for column in range(16):
			button_row.append(self._key[16 + column])

		self._key_matrix.add_row(tuple(button_row))

	def _setup_ohmmod(self):
		self._host = MonomodComponent(self)
		self._host.name = 'Monomod_Host'
		self.hosts = [self._host]
		self._hosts = [self._host]
		for index in range(6):
			self._client[index] = MonoClient(self, index)
			self._client[index].name = 'Client_' + str(index)
			self._client[index]._device_component.set_parameter_controls(tuple([ self._dial[num] for num in range(12) ]))
			self._client[index]._control_defs = {'dials': self._dial_matrix,
			 'buttons': self._dial_button_matrix,
			 'grid': self._mod_matrix,
			 'keys': self._key,
			 'knobs': [ self._dial[num + 12] for num in range(4) ]}

		self._host._active_client = self._client[0]
		self._host._active_client._is_active = True
		self._host.connect_to_clients(self)

	def _setup_switchboard(self):
		self._switchboard = SwitchboardElement(self, self._client)
		self._switchboard.name = 'Switchboard'

	def _setup_modes(self):
		self._shift_mode = ShiftModeComponent(self)
		self._shift_mode.name = 'Shift_Mode'
		self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r, self._livid)
		self._scale_mode = ScaleModeComponent(self)
		self._scale_mode.name = 'Scale_Mode'
		self._octave_mode = OctaveModeComponent(self)
		self._octave_mode.name = 'Octave_Mode'
		self._modNum = ModNumModeComponent(self, self.modNum_update)
		self._modNum.name = 'Mod_Number'
		self._modNum.set_mode = self._modNum_set_mode(self._modNum)
		self._modNum.set_mode_buttons([ self._menu[index] for index in range(6) ])

	def _modNum_set_mode(self, modNum):
		def set_mode(mode):
			if modNum._is_enabled == True:
				assert isinstance(mode, int)
				assert (mode in range(modNum.number_of_modes()))
				if (modNum._mode_index != mode):
					modNum._mode_index = mode
					modNum.update()
		return set_mode
	

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

	def _setup_mixer_control(self):
		global mixer
		is_momentary = True
		self._num_tracks = 7
		mixer = SpecialMixerComponent(7, 0, True, False)
		mixer.name = 'Mixer'
		self._mixer = mixer
		for index in range(7):
			mixer.channel_strip(index).set_volume_control(self._fader[index])

		for index in range(7):
			mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index)
			mixer.track_eq(index).name = 'Mixer_EQ_' + str(index)
			mixer.channel_strip(index)._invert_mute_feedback = True

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

	def _setup_session_control(self):
		global session
		is_momentary = True
		num_tracks = 7
		num_scenes = 5
		session = SessionComponent(num_tracks, num_scenes)
		session.name = 'Session'
		self._session = session
		session.set_offsets(0, 0)
		self._scene = [ None for index in range(6) ]
		for row in range(num_scenes):
			self._scene[row] = session.scene(row)
			self._scene[row].name = 'Scene_' + str(row)
			for column in range(num_tracks):
				clip_slot = self._scene[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_' + str(row)

		session.set_mixer(self._mixer)
		session.set_show_highlight(True)
		self._session_zoom = SessionZoomingComponent(session)
		self._session_zoom.name = 'Session_Overview'
		self.set_highlighting_session_component(self._session)

	def _assign_session_colors(self):
		self.log_message('assign session colors')
		num_tracks = 7
		num_scenes = 5
		self._session.set_stop_track_clip_value(STOP_CLIP_COLOR[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_TRIGD_TO_PLAY_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_triggered_to_record_value(CLIP_TRIGD_TO_RECORD_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_stopped_value(CLIP_STOPPED_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_started_value(CLIP_STARTED_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_recording_value(CLIP_RECORDING_COLOR[self._rgb])

		self._session_zoom.set_stopped_value(ZOOM_STOPPED_COLOR[self._rgb])
		self._session_zoom.set_playing_value(ZOOM_PLAYING_COLOR[self._rgb])
		self._session_zoom.set_selected_value(ZOOM_SELECTED_COLOR[self._rgb])
		for row in range(8):
			for column in range(8):
				self._grid[column][row].set_force_next_value()

		self._session.on_scene_list_changed()
		self._shift_mode.update()

	def _setup_device_control(self):
		self._device = DeviceComponent()
		self._device.name = 'Device_Component'
		self.set_device_component(self._device)
		self._device_navigator = DetailViewControllerComponent()
		self._device_navigator.name = 'Device_Navigator'
		self._device_selection_follows_track_selection = FOLLOW

	def device_follows_track(self, val):
		self._device_selection_follows_track_selection = val == 1
		return self

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

	def disconnect(self):
		"""clean things up on disconnect"""
		self.song().view.remove_selected_track_listener(self._update_selected_device)
		self.log_message(time.strftime('%d.%m.%Y %H:%M:%S', time.localtime()) + '--------------= OhmModes log closed =--------------')
		ControlSurface.disconnect(self)

	def _get_num_tracks(self):
		return self.num_tracks

	def flash(self):
		for row in range(8):
			if self._button[row]._flash_state > 0:
				self._button[row].flash(self._timer)
			for column in range(8):
				button = self._grid[column][row]
				if button._flash_state > 0:
					button.flash(self._timer)

	def strobe(self):
		if self._backlight_type != 'static':
			if self._backlight_type is 'pulse':
				self._backlight = int(math.fabs(self._timer * 16 % 64 - 32) + 32)
			if self._backlight_type is 'up':
				self._backlight = int(self._timer * 8 % 64 + 16)
			if self._backlight_type is 'down':
				self._backlight = int(math.fabs(int(self._timer * 8 % 64 - 64)) + 16)
		self._send_midi(tuple([176, 27, int(self._backlight)]))
		if self._ohm_type != 'static':
			if self._ohm_type is 'pulse':
				self._ohm = int(math.fabs(self._timer * 16 % 64 - 32) + 32)
			if self._ohm_type is 'up':
				self._ohm = int(self._timer * 8 % 64 + 16)
			if self._ohm_type is 'down':
				self._ohm = int(math.fabs(int(self._timer * 8 % 64 - 64)) + 16)
		self._send_midi(tuple([176, 63, int(self._ohm)]))
		self._send_midi(tuple([176, 31, int(self._ohm)]))

	def deassign_matrix(self):
		with self.component_guard():
			self._host._set_knobs(None)
			self._host._set_button_matrix(None)
			self._host.set_enabled(False)
			self._modNum.set_enabled(False)
			self.assign_alternate_mappings(0)
			self._scale_mode.set_mode_buttons(None)
			self._scale_mode.set_enabled(False)
			self._octave_mode.set_mode_buttons(None)
			self._octave_mode.set_enabled(False)
			self._session_zoom.set_enabled(False)
			self._session_zoom.set_nav_buttons(None, None, None, None)
			self._session.set_track_bank_buttons(None, None)
			self._session.set_scene_bank_buttons(None, None)
			self._transport.set_enabled(False)
			for column in range(4):
				self._mixer.track_eq(column)._gain_controls = None
				self._mixer.track_eq(column).set_enabled(False)

			for column in range(7):
				self._mixer.channel_strip(column).set_crossfade_toggle(None)
				self._mixer.channel_strip(column).set_mute_button(None)
				self._mixer.channel_strip(column).set_solo_button(None)
				self._mixer.channel_strip(column).set_arm_button(None)
				self._mixer.channel_strip(column).set_send_controls(None)
				self._mixer.channel_strip(column).set_pan_control(None)
				self._mixer.track_eq(column).set_enabled(False)
				for row in range(5):
					self._scene[row].clip_slot(column).set_launch_button(None)

			"""for column in range(8):
				self._button[column]._on_value = SELECT_COLOR[self._rgb]
				for row in range(8):
					self._grid[column][row].set_enabled(True)
					self._grid[column][row].release_parameter()
					self._grid[column][row].use_default_message()
					self._grid[column][row].set_on_off_values(127, 0)
					self._grid[column][row].send_value(0, True)"""
			for column in range(8):
				self._button[column]._on_value = SELECT_COLOR[self._rgb]
				for row in range(8):
					#self._grid[column][row].set_channel(0)
					self._grid[column][row].release_parameter()
					self._grid[column][row].use_default_message()
					self._grid[column][row].set_enabled(True)
					self._grid[column][row].send_value(0, True)
					self._grid[column][row]._on_value = 127
					self._grid[column][row]._off_value = 0
					self._grid[column][row].force_next_send()


			for index in range(6):
				self._menu[index]._on_value = 127
				self._menu[index]._off_value = 0

			for index in range(16):
				self._dial[index].use_default_message()
				self._dial[index].release_parameter()

			self._device.set_parameter_controls(None)
			self._device.set_enabled(False)
			self._device_navigator.set_enabled(False)
			self._mixer.update()
			self._matrix.reset()
		self.request_rebuild_midi_map()

	def _assign_page_constants(self):
		with self.component_guard():
			self._session_zoom.set_zoom_button(self._grid[7][7])
			self._session_zoom.set_button_matrix(self._matrix)
			for column in range(7):
				self._mixer.channel_strip(column).set_select_button(self._button[column])
				self._mixer.channel_strip(column).set_volume_control(self._fader[column])

			self._mixer.master_strip().set_volume_control(self._fader[7])
			self._mixer.master_strip().set_select_button(self._button[7])
			self._mixer.set_prehear_volume_control(self._dial[15])
			self._transport.set_play_button(self._menu[0])
			self._menu[0].send_value(PLAY_COLOR[self._rgb], True)
			self._menu[0]._on_value = PLAY_COLOR[self._rgb]
			self._transport.set_stop_button(self._menu[1])
			self._menu[1]._off_value = STOP_COLOR[self._rgb]
			self._menu[1]._on_value = STOP_COLOR[self._rgb]
			self._menu[1].send_value(STOP_COLOR[self._rgb], True)
			self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[4])

	def assign_page_0(self):
		with self.component_guard():
			self._backlight_type = 'static'
			self._session_zoom.set_enabled(True)
			for column in range(7):	
				self._grid[column][5]._on_value = MUTE_COLOR[self._rgb]
				self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
				self._grid[column][6]._on_value = SOLO_COLOR[self._rgb]
				self._mixer.channel_strip(column).set_solo_button(self._grid[column][6])
				self._grid[column][7]._on_value = ARM_COLOR[self._rgb]
				self._mixer.channel_strip(column).set_arm_button(self._grid[column][7])
				self._mixer.channel_strip(column).set_pan_control(self._dial[column + 8])
				for row in range(5):
					self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])

			for column in range(4):
				self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column], self._dial[column + 4]]))

			for index in range(5):
				self._grid[7][index]._off_value = SCENE_LAUNCH_COLOR[self._rgb]
				self._scene[index].set_launch_button(self._grid[7][index])
				self._grid[7][index].set_force_next_value()
				self._grid[7][index].turn_off()

			for index in range(4):
				self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb]

			self._session.set_track_bank_buttons(self._menu[4], self._menu[3])
			self._session.set_scene_bank_buttons(self._menu[5], self._menu[2])
			self._menu[0]._on_value = PLAY_COLOR[self._rgb]
			self._menu[1]._off_value = STOP_COLOR[self._rgb]
			self._menu[1]._on_value = STOP_COLOR[self._rgb]
			self._transport.set_enabled(True)
			#self._mixer.update_all()
		self.request_rebuild_midi_map()
		#self.log_message('assign_page_0')

	def assign_page_1(self):
		with self.component_guard():
			self._backlight_type = 'pulse'
			self._session_zoom.set_enabled(False)
			for column in range(4):
				for row in range(4):
					self._grid[column][row].send_value(DRUM_COLOR[self._rgb], True)
					self._grid[column + 4][row].send_value(BASS_COLOR[self._rgb], True)
					self._grid[column][row].set_enabled(False)
					self._grid[column][row]._msg_channel = PAGE1_DRUM_CHANNEL
					self._grid[column][row].set_identifier(PAGE1_DRUM_MAP[column][row])
					self._grid[column + 4][row].set_enabled(False)
					self._grid[column + 4][row]._msg_channel = PAGE1_BASS_CHANNEL
					self._grid[column + 4][row].set_identifier(PAGE1_BASS_MAP[column][row])

			scale_mode_buttons = []
			for column in range(8):
				for row in range(3):
					self._grid[column][row + 4].set_enabled(False)
					self._grid[column][row + 4].send_value(KEYS_COLOR[self._rgb], True)
					self._grid[column][row + 4]._msg_channel = PAGE1_KEYS_CHANNEL
					self._grid[column][row + 4].set_identifier(int(PAGE1_KEYS_MAP[column][row]) + int(PAGE1_MODES_MAP[self._scale_mode._mode_index][column]) + int(self._octave_mode._mode_index * 12))

				for row in range(1):
					scale_mode_buttons.append(self._grid[column][7])

			self._scale_mode.set_mode_buttons(tuple(scale_mode_buttons))
			self._scale_mode.set_enabled(True)
			self._octave_mode.set_mode_buttons(tuple([self._menu[5], self._menu[2]]))
			self._octave_mode.set_enabled(True)
			for column in range(7):
				self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column + 8]]))
				self._mixer.channel_strip(column).set_arm_button(self._button[column])

			self._device.set_enabled(True)
			device_param_controls = []
			for index in range(8):
				device_param_controls.append(self._dial[index])

			self._device.set_parameter_controls(tuple(device_param_controls))
			self._menu[0]._on_value = PLAY_COLOR[self._rgb]
			for index in range(4):
				self._menu[2 + index]._on_value = DEVICE_NAV_COLOR[self._rgb]

			self._device_navigator.set_enabled(True)
			self._menu[0]._on_value = PLAY_COLOR[self._rgb]
			self._menu[1]._off_value = STOP_COLOR[self._rgb]
			self._menu[1]._on_value = STOP_COLOR[self._rgb]
			self._transport.set_enabled(True)
		self.request_rebuild_midi_map()

	def assign_page_2(self):
		with self.component_guard():
			self._backlight_type = 'up'
			self._session_zoom.set_enabled(True)
			for column in range(7):
				self._grid[column][5]._on_value = MUTE_COLOR[self._rgb]
				self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
				self._grid[column][6]._on_value = CROSSFADE_ASSIGN_COLOR[self._rgb]
				self._mixer.channel_strip(column).set_crossfade_toggle(self._grid[column][6])
				self._grid[column][7]._msg_channel = 2
				self._grid[column][7].set_identifier(column)
				self._grid[column][7].reset()
				self._grid[column][7].set_enabled(False)
				self._grid[column][7].send_value(4, True)
				for row in range(5):
					self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])

			for row in range(5):
				self._grid[7][row]._off_value = SCENE_LAUNCH_COLOR[self._rgb]
				self._scene[row].set_launch_button(self._grid[7][row])
				self._grid[7][row].set_force_next_value()
				self._grid[7][row].turn_off()

			for column in range(4):
				self._mixer.track_eq(column).set_gain_controls(tuple([self._dial[column + 8], self._dial[column + 4], self._dial[column]]))
				self._mixer.track_eq(column).set_enabled(True)

			for column in range(3):
				self._mixer.channel_strip(column + 4).set_pan_control(self._dial[column + 12])

			for index in range(4):
				self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb]

			self._session.set_track_bank_buttons(self._menu[4], self._menu[3])
			self._session.set_scene_bank_buttons(self._menu[5], self._menu[2])
			self._set_tempo_buttons([self._grid[7][5], self._grid[7][6]])
			self._menu[0]._on_value = PLAY_COLOR[self._rgb]
			self._menu[1]._off_value = STOP_COLOR[self._rgb]
			self._menu[1]._on_value = STOP_COLOR[self._rgb]
			self._transport.set_enabled(True)
			#self._mixer.update()
		self.request_rebuild_midi_map()

	def assign_mod(self):
		with self.component_guard():
			self.deassign_matrix()
			self._host.set_enabled(True)
			self._modNum.set_enabled(True)
			self._host._set_dial_matrix(self._dial_matrix, self._dial_button_matrix)
			self._host._set_button_matrix(self._mod_matrix)
			self._host._set_key_buttons(tuple(self._key))
			if not self._host._active_client.is_connected():
				self.assign_alternate_mappings(self._modNum._mode_index + 1)

	def modNum_update(self):
		if self._modNum._is_enabled == True:
			self.assign_alternate_mappings(0)
			self._host._select_client(int(self._modNum._mode_index))
			self._host.display_active_client()
			if not self._host._active_client.is_connected():
				self.assign_alternate_mappings(self._modNum._mode_index + 1)
			for button in self._modNum._modes_buttons:
				if self._modNum._mode_index == self._modNum._modes_buttons.index(button):
					button.send_value(1)
				else:
					button.send_value(self._client[self._modNum._modes_buttons.index(button)]._mod_color)

	def assign_alternate_mappings(self, chan):
		for column in range(8):
			for row in range(8):
				self._grid[column][row].set_channel(chan)
		for knob in self._encoder:
			knob.set_channel(chan)
			knob.set_enabled(chan is 0)

		self.request_rebuild_midi_map()

	def display_mod_colors(self):
		pass

	def _update_selected_device(self):
		if self._device_selection_follows_track_selection is True:
			track = self.song().view.selected_track
			device_to_select = track.view.selected_device
			if device_to_select == None and len(track.devices) > 0:
				device_to_select = track.devices[0]
			if device_to_select != None:
				self.song().view.select_device(device_to_select)
			self.set_appointed_device(device_to_select)
			self.request_rebuild_midi_map()

	def handle_sysex(self, midi_bytes):
		if len(midi_bytes) > 10:
			if midi_bytes[:11] == tuple([240,
			 126,
			 0,
			 6,
			 2,
			 0,
			 1,
			 97,
			 1,
			 0,
			 7]):
				self.log_message(str('>>>color detected'))
				self._rgb = 0
			elif midi_bytes[:11] == tuple([240,
			 126,
			 0,
			 6,
			 2,
			 0,
			 1,
			 97,
			 1,
			 0,
			 2]):
				self.log_message(str('>>>mono detected'))
				self._rgb = 1
		self._assign_session_colors()

	def to_encoder(self, num, val):
		rv = int(val * 127)
		self._device._parameter_controls[num].receive_value(rv)
		p = self._device._parameter_controls[num]._parameter_to_map_to
		newval = val * (p.max - p.min) + p.min
		p.value = newval

	def set_local_ring_control(self, val = 1):
		self._local_ring_control = val != 0

	def set_absolute_mode(self, val = 1):
		self._absolute_mode = val != 0

	def send_ring_leds(self):
		"""if self._host._is_enabled == True:
		leds = [240, 0, 1, 97, 8, 31]
		for index in range(12):
				wheel = self._encoder[index]
				bytes = wheel._get_ring()
				leds.append(bytes[0])
				leds.append(int(bytes[1]) + int(bytes[2]))
		leds.append(247)
		self._send_midi(tuple(leds))"""
		pass


	def _set_tempo_buttons(self, buttons):
		if self._tempo_buttons != None:
			self._tempo_buttons[0].remove_value_listener(self._tempo_value)
			self._tempo_buttons[1].remove_value_listener(self._tempo_value)
		self._tempo_buttons = buttons
		if buttons != None:
			for button in buttons:
				 assert isinstance(button, FlashingButtonElement)
			self._tempo_buttons[0].set_on_off_values(4, 0)
			self._tempo_buttons[0].add_value_listener(self._tempo_value, True)
			self._tempo_buttons[1].set_on_off_values(4, 0)
			self._tempo_buttons[1].add_value_listener(self._tempo_value, True)
			self._tempo_buttons[0].turn_on()
			self._tempo_buttons[1].turn_on()

	def _tempo_value(self, value, sender):
		if value > 0 and self._tempo_buttons.index(sender) == 0:
			self.song().tempo = round(min(self.song().tempo + 1, 999))
		elif value > 0 and self._tempo_buttons.index(sender) == 1:
			self.song().tempo = round(max(self.song().tempo - 1, 20))

	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, tuple([MonoEncoderElement2, CodecEncoderElement])):
			self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name)))
			self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value)))

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

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

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

		return clip_names

	def shift_update(self):
		pass
Exemple #21
0
class Lemaur256(ControlSurface):
	__module__ = __name__
	__doc__ = " Lemaur256 controller script "


	def __init__(self, c_instance):
		"""everything except the '_on_selected_track_changed' override and 'disconnect' runs from here"""
		ControlSurface.__init__(self, c_instance)
		self.log_message("--------------= Lemaur256 log opened =--------------") 
		self._suggested_input_port = 'None'
		self._suggested_output_port = 'None'
		self.set_suppress_rebuild_requests(True)
		self._monomod_version = 'b994'
		self._host_name = 'AumPad'
		self._color_type = 'AumPad'
		self.connected = 0
		self.hosts = []
		self._osc_registry = {}
		self._bright = True
		self._rgb = 0
		self._timer = 0
		self.flash_status = 1
		self._setup_monobridge()
		self._setup_controls()
		self._setup_monomod()
		self._setup_touchosc()
		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)
		self.set_suppress_rebuild_requests(False)
		self.reset()
		self.refresh_state()
		self.show_message('Aum256 Control Surface Loaded')
	

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

	def _setup_controls(self):
		is_momentary = True
		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] = OSCFlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, int(column/8) + 1, row + ((column%8) * 16), '256Grid_' + str(column) + '_' + str(row), '/Grid_'+str(column)+'_'+str(row), '/Grid/set '+str(column)+' '+str(row), None, 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] = OSCFlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, index, '256Grid_Bank_' + str(index), '/Shift_'+str(index), '/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] = OSCFlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, index+8, '256Grid_Key_' + str(index), '/Keys_'+str(index), '/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))
	

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

	def _setup_touchosc(self):
		self._osc_registry = {}
		self._osc_registry['/ping'] = self._monobridge.ping
		self._osc_registry['/1'] = self._monobridge.page1
		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
	

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

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


	"""m4l bridge"""
	def generate_strip_string(self, display_string):
		NUM_CHARS_PER_DISPLAY_STRIP = 9
		if (not display_string):
			#return (' ' * NUM_CHARS_PER_DISPLAY_STRIP)
			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._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(str(clip_slot._clip_slot.clip.name))
		return clip_names
	


	"""midi functionality"""
	def max_to_midi(self, message): #takes a 'tosymbol' list from Max, such as "240 126 0 6 1 247"
		msg_str = str(message) #gets rid of the quotation marks which 'tosymbol' has added
		midi_msg = tuple(int(s) for s in msg_str.split()) #converts to a tuple 
		self._send_midi(midi_msg) #sends to controller
	

	def max_from_midi(self, message): #takes a 'tosymbol' list from Max, such as "240 126 0 6 1 247"
		msg_str = str(message) #gets rid of the quotation marks which 'tosymbol' has added
		midi_msg = tuple(int(s) for s in msg_str.split()) #converts to a tuple 
		self.receive_external_midi(midi_msg) #sends to controller
	

	def to_encoder(self, num, val):
		rv=int(val*127)
		self._device._parameter_controls[num].receive_value(rv)
		p = self._device._parameter_controls[num]._parameter_to_map_to
		newval = (val * (p.max - p.min)) + p.min
		p.value = newval
	

	def receive_external_midi(self, midi_bytes):
		#self.log_message('receive_external_midi' + str(midi_bytes))
		assert (midi_bytes != None)
		assert isinstance(midi_bytes, tuple)
		self.set_suppress_rebuild_requests(True)
		if (len(midi_bytes) is 3):
			msg_type = (midi_bytes[0] & 240)
			forwarding_key = [midi_bytes[0]]
			self.log_message(str(self._forwarding_registry))
			if (msg_type is not MIDI_PB_TYPE):
				forwarding_key.append(midi_bytes[1])
			recipient = self._forwarding_registry[tuple(forwarding_key)]
			self.log_message('receive_midi recipient ' + str(recipient))
			if (recipient != None):
				recipient.receive_value(midi_bytes[2])
		else:
			self.handle_sysex(midi_bytes)
		self.set_suppress_rebuild_requests(False)
	


	"""general functionality"""
	def disconnect(self):
		"""clean things up on disconnect"""
		#self._disconnect_notifier.set_mode(0)
		self.log_message("--------------= Lemaur256 log closed =--------------") #Create entry in log file
		ControlSurface.disconnect(self)
		return None
	
	
	def allow_updates(self, allow_updates):
		for component in self.components:
			component.set_allow_update(int(allow_updates!=0))
	

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

	def reset(self):
		for control in self.controls:
			control.reset()
Exemple #22
0
class MonoWing(ControlSurface):


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

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

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

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

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

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

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

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

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

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

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

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

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

	def flash(self):
		if(self.flash_status > 0):
			for control in self.controls:
				if isinstance(control, MonoButtonElement):
					control.flash(self._timer)
class MidiFighterTwister(ControlSurface):
    __module__ = __name__
    __doc__ = "MidiFighterTwister class"

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

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

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

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

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

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

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

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

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

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

    def bank_buttons_dummy(self):
        pass

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

    def dispatch_current_song_time_listener(self):
        self.sequencer_light_follows_beat()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

# Clip page setion

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # Update light of active pad
        #self._send_midi((self.light_midi_channel, light_encoder_cc, 63))
        try:
            self.current_clip = self.song().view.highlighted_clip_slot.clip
            self.current_clip.is_midi_clip
            self._sequencer_update_notes_to_light()
        except AttributeError:
            pass
Exemple #24
0
 def __init__(self, c_instance):
     ControlSurface.__init__(self, c_instance)
     with self.component_guard():
         self._monomod_version = 'b995'
         self._host_name = 'LaunchMod'
         self._color_type = 'Launchpad'
         self.hosts = []
         self._timer = 0
         self._suppress_send_midi = True
         self._suppress_session_highlight = True
         self._suppress_highlight = False
         is_momentary = True
         self._suggested_input_port = 'Launchpad'
         self._suggested_output_port = 'Launchpad'
         self._control_is_with_automap = False
         self._user_byte_write_button = ButtonElement(
             is_momentary, MIDI_CC_TYPE, 0, 16)
         self._user_byte_write_button.name = 'User_Byte_Button'
         self._user_byte_write_button.send_value(1)
         self._user_byte_write_button.add_value_listener(
             self._user_byte_value)
         self._wrote_user_byte = False
         self._challenge = Live.Application.get_random_int(
             0, 400000000) & 2139062143
         matrix = ButtonMatrixElement()
         matrix.name = 'Button_Matrix'
         for row in range(8):
             button_row = [
                 ConfigurableButtonElement(
                     is_momentary, MIDI_NOTE_TYPE, 0, ((row * 16) + column),
                     str(column) + '_Clip_' + str(row) + '_Button', self)
                 for column in range(8)
             ]
             matrix.add_row(tuple(button_row))
         self._config_button = ButtonElement(is_momentary,
                                             MIDI_CC_TYPE,
                                             0,
                                             0,
                                             optimized_send_midi=False)
         self._config_button.add_value_listener(self._config_value)
         top_button_names = [
             'Bank_Select_Up_Button', 'Bank_Select_Down_Button',
             'Bank_Select_Left_Button', 'Bank_Select_Right_Button',
             'Session_Button', 'User1_Button', 'User2_Button',
             'Mixer_Button'
         ]
         side_button_names = [
             'Vol_Button', 'Pan_Button', 'SndA_Button', 'SndB_Button',
             'Stop_Button', 'Trk_On_Button', 'Solo_Button', 'Arm_Button'
         ]
         top_buttons = [
             ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0,
                                       (104 + index),
                                       top_button_names[index], self)
             for index in range(8)
         ]
         side_buttons = [
             ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                       SIDE_NOTES[index],
                                       side_button_names[index], self)
             for index in range(8)
         ]
         self._setup_monobridge()
         self._setup_monomod()
         self._selector = MainSelectorComponent(matrix, tuple(top_buttons),
                                                tuple(side_buttons),
                                                self._config_button, self)
         self._selector.name = 'Main_Modes'
         for control in self.controls:
             if isinstance(control, MonoButtonElement):
                 control.add_value_listener(self._button_value)
         self.set_highlighting_session_component(
             self._selector.session_component())
         self._suppress_session_highlight = False
     self.log_message(
         "--------------= " + str(self._monomod_version) +
         " log opened =--------------")  #Create entry in log file
    def _setup_session_control(self):
        is_momentary = True
        num_tracks = 4
        num_scenes = 4
        global session #We want to instantiate the global session as a SessionComponent object (it was a global "None" type up until now...)
        session = MaschineSessionComponent(num_tracks, num_scenes) #(num_tracks, num_scenes)
        session.set_offsets(0, 0) #(track_offset, scene_offset) Sets the initial offset of the red box from top left

        matrix = ButtonMatrixElement()

        self._register_timer_callback(session.flash_clip_slots)

        """set up the session buttons"""
        left_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 91)
        right_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 93)
        session.set_track_bank_buttons(right_button, left_button)

        # Stop buttons
        track_stop_buttons = [ ButtonElement(is_momentary, MIDI_CC_TYPE, 4, (55 + index)) for index in range(num_tracks) ]
        session.set_stop_track_clip_buttons(tuple(track_stop_buttons))

        up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 81)
        down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 92)
        session.set_scene_bank_buttons(down_button, up_button) # (up_button, down_button) This is to move the "red box" up or down (increment track up or down, not screen up or down, so they are inversed)

        session.set_mixer(mixer) #Bind the mixer to the session so that they move together
        selected_scene = self.song().view.selected_scene #this is from the Live API
        all_scenes = self.song().scenes
        index = list(all_scenes).index(selected_scene)
        session.set_offsets(0, index) #(track_offset, scene_offset)

        scene_launch_buttons = []
            
        for scene_index in range(4):
          scene = session.scene(scene_index)
          launch_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, (124 + scene_index))
          scene.set_launch_button(launch_button)
          scene_launch_buttons.append(launch_button)

        clip_launch_notes = [
          [24, 25, 26, 27],
          [20, 21, 22, 23],
          [16, 17, 18, 19],
          [12, 13, 14, 15],
        ]

        for scene_index in range(num_scenes):
          button_row = []
          for track_index in range(num_tracks):
            clip_slot = session.scene(scene_index).clip_slot(track_index)
            clip_slot.set_triggered_to_record_value(127)
            clip_slot.set_recording_value(127)
            clip_slot.set_started_value(127)
            clip_slot.set_stopped_value(127)
            button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 2, clip_launch_notes[scene_index][track_index])
            clip_slot.set_launch_button(button)
            button_row.append(button)
          matrix.add_row(tuple(button_row))

        session_zoom = SessionZoomingComponent(session)
        session_zoom.set_zoom_button(self.shift_button)
        session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button)
        session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
        session_zoom.set_button_matrix(matrix)
        session_zoom.set_stopped_value(0)
        session_zoom.set_selected_value(127)
Exemple #26
0
	def init(self):
		#skip init if already done.
		if self._init_done:
			return
		self._init_done = True
		
		# second part of the __init__ after model has been identified using its challenge response
		if self._mk3_rgb or self._lpx:
			from .SkinMK2 import make_skin
			self._skin = make_skin()
			self._side_notes = (89, 79, 69, 59, 49, 39, 29, 19)
			self._drum_notes = (20, 30, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126)
		elif self._mk2_rgb:
			from .SkinMK2 import make_skin
			self._skin = make_skin()
			self._side_notes = (89, 79, 69, 59, 49, 39, 29, 19)
			#self._drum_notes = (20, 30, 31, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126)
			self._drum_notes = (20, 30, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126)
		else:
			from .SkinMK1 import make_skin # @Reimport
			self._skin = make_skin()
			self._side_notes = (8, 24, 40, 56, 72, 88, 104, 120)
			self._drum_notes = (41, 42, 43, 44, 45, 46, 47, 57, 58, 59, 60, 61, 62, 63, 73, 74, 75, 76, 77, 78, 79, 89, 90, 91, 92, 93, 94, 95, 105, 106, 107)
		
		with self.component_guard():
			is_momentary = True
			self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False)
			self._config_button.add_value_listener(self._config_value)
			self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16)
			self._user_byte_write_button.name = 'User_Byte_Button'
			self._user_byte_write_button.send_value(1)
			self._user_byte_write_button.add_value_listener(self._user_byte_value)
			matrix = ButtonMatrixElement()
			matrix.name = 'Button_Matrix'
			for row in range(8):
				button_row = []
				for column in range(8):
					if self._mk2_rgb or self._mk3_rgb or self._lpx:
						# for mk2 buttons are assigned "top to bottom"
						midi_note = (81 - (10 * row)) + column
					else:
						midi_note = row * 16 + column
					button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, midi_note, skin = self._skin, control_surface = self)
					button.name = str(column) + '_Clip_' + str(row) + '_Button'
					button_row.append(button)
				matrix.add_row(tuple(button_row))

			if self._mk3_rgb or self._lpx :
				top_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 91 + index, skin = self._skin) for index in range(8)]
				side_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, self._side_notes[index], skin = self._skin) for index in range(8)]
			else:
				top_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, skin = self._skin) for index in range(8)]
				side_buttons = [ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, self._side_notes[index], skin = self._skin) for index in range(8)]
				
			top_buttons[0].name = 'Bank_Select_Up_Button'
			top_buttons[1].name = 'Bank_Select_Down_Button'
			top_buttons[2].name = 'Bank_Select_Left_Button'
			top_buttons[3].name = 'Bank_Select_Right_Button'
			top_buttons[4].name = 'Session_Button'
			top_buttons[5].name = 'User1_Button'
			top_buttons[6].name = 'User2_Button'
			top_buttons[7].name = 'Mixer_Button'
			side_buttons[0].name = 'Vol_Button'
			side_buttons[1].name = 'Pan_Button'
			side_buttons[2].name = 'SndA_Button'
			side_buttons[3].name = 'SndB_Button'
			side_buttons[4].name = 'Stop_Button'
			side_buttons[5].name = 'Trk_On_Button'
			side_buttons[6].name = 'Solo_Button'
			side_buttons[7].name = 'Arm_Button'
			self._osd = M4LInterface()
			self._osd.name = "OSD"
			self._init_note_repeat()
			self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self._osd, self, self._note_repeat)
			self._selector.name = 'Main_Modes'
			self._do_combine()
			for control in self.controls:
				if isinstance(control, ConfigurableButtonElement):
					control.add_value_listener(self._button_value)
		  
			self._suppress_session_highlight = False
			self.set_highlighting_session_component(self._selector.session_component())
			# due to our 2 stage init, we need to rebuild midi map 
			self.request_rebuild_midi_map()
			# and request update 
			self._selector.update()
			if self._lpx:
				self.log_message("LaunchPad95 (LPX) Loaded !")
			elif self._mk3_rgb:
				self.log_message("LaunchPad95 (mk3) Loaded !")
			elif self._mk2_rgb:
				self.log_message("LaunchPad95 (mk2) Loaded !")
			else:
				self.log_message("LaunchPad95 (classic) Loaded !")
Exemple #27
0
class AumPC20(APC):
	__doc__ = " Script for Akai's APC20 Controller "


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

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

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

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

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

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

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

	def _product_model_id_byte(self):
		return 123
	

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

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

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

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

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

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

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

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

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



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

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

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


### Mod Overrides ####

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

	def _mod_update_nav_buttons(self, mod):
		def _update_nav_buttons():
			if mod._nav_buttons != None:
				if(mod._y > 0):
					mod._nav_buttons[0].turn_on()
				else:
					mod._nav_buttons[0].turn_off()
				if(mod._y < 8):
					mod._nav_buttons[1].turn_on()
				else:
					mod._nav_buttons[1].turn_off() 
		return _update_nav_buttons
Exemple #28
0
class AumPC20(APC20):
    def __init__(self, c_instance, *a, **k):
        self._monomod_version = 'b996'
        self._host_name = 'AumPC'
        self._color_type = 'APC'
        self._timer = 0
        self._touched = 0
        self.flash_status = False
        super(AumPC20, self).__init__(c_instance, *a, **k)
        with self.component_guard():
            self._setup_mod()

    def disconnect(self):
        super(AumPC20, self).disconnect()
        rebuild_sys()

    def _create_controls(self):
        make_color_button = partial(make_button, skin=self._skin)
        self._shift_button = make_button(0,
                                         81,
                                         name='Shift_Button',
                                         num=0,
                                         cs=self)
        self._matrix = ButtonMatrixElement(name='Button_Matrix')
        self._scene_launch_buttons_raw = [
            make_color_button(0,
                              index + 82,
                              name='Scene_%d_Launch_Button' % index,
                              num=index,
                              cs=self) for index in xrange(SESSION_HEIGHT)
        ]
        self._track_stop_buttons = [
            make_color_button(index,
                              52,
                              name='Track_%d_Stop_Button' % index,
                              num=index,
                              cs=self) for index in xrange(SESSION_WIDTH)
        ]
        self._matrix_rows_raw = []
        for scene_index in xrange(SESSION_HEIGHT):
            row = [
                make_color_button(
                    track_index,
                    scene_index + 53,
                    name='%d_Clip_%d_Button' % (track_index, scene_index),
                    num=index,
                    cs=self) for track_index in xrange(SESSION_WIDTH)
            ]
            self._matrix_rows_raw.append(row)
            self._matrix.add_row(row)

        self._selected_scene_launch_button = make_pedal_button(
            64, name='Selected_Scene_Launch_Button')
        self._scene_launch_buttons = ButtonMatrixElement(
            rows=[self._scene_launch_buttons_raw])
        self._solo_buttons = [
            make_button(track_index,
                        49,
                        name='%d_Solo_Button' % track_index,
                        num=track_index,
                        cs=self) for track_index in xrange(MIXER_SIZE)
        ]
        self._mute_buttons = [
            make_button(track_index,
                        50,
                        name='%d_Mute_Button' % track_index,
                        num=track_index,
                        cs=self) for track_index in xrange(MIXER_SIZE)
        ]
        self._master_volume_control = make_slider(0,
                                                  14,
                                                  name='Master_Volume_Control',
                                                  num=0,
                                                  script=self)
        self._prehear_control = EncoderElement(MIDI_CC_TYPE,
                                               0,
                                               47,
                                               MapMode.relative_two_compliment,
                                               name='Prehear_Volume_Control',
                                               num=0,
                                               script=self)
        self._master_select_button = make_button(0,
                                                 80,
                                                 name='Master_Select_Button',
                                                 num=index,
                                                 cs=self)
        self._select_buttons = [
            make_button(track_index,
                        51,
                        name='%d_Select_Button' % track_index,
                        num=track_index,
                        cs=self) for track_index in xrange(8)
        ]
        self._arm_buttons = [
            make_button(track_index,
                        48,
                        name='%d_Arm_Button' % track_index,
                        num=track_index,
                        cs=self) for track_index in xrange(8)
        ]
        self._sliders = [
            make_slider(track_index,
                        7,
                        name='%d_Volume_Control' % track_index,
                        num=track_index,
                        script=self) for track_index in xrange(8)
        ]

        self._monomod = ButtonMatrixElement(name='Monomod')
        for row in self._matrix_rows_raw:
            self._monomod.add_row(row)
        self._monomod.add_row(self._track_stop_buttons)
        self._monomod.add_row(self._select_buttons)
        self._monomod.add_row(self._mute_buttons)

        self._setup_monobridge(
        )  #had to put this here b/c the original author foolishly placed assignment methods inside of creation methods...argh.

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

    def _setup_mod(self):
        self.monomodular = get_monomodular(self)
        self.monomodular.name = 'monomodular_switcher'
        self.modhandler = APCModHandler(self)
        self.modhandler.name = 'ModHandler'
        self.modhandler.layer = Layer(
            priority=5,
            grid=self._monomod,
            nav_up_button=self._scene_launch_buttons_raw[2],
            nav_down_button=self._scene_launch_buttons_raw[3],
            lock_button=self._scene_launch_buttons_raw[4],
            shiftlock_button=self._scene_launch_buttons_raw[0],
            alt_button=self._scene_launch_buttons_raw[1],
            shift_button=self._shift_button)
        self.modhandler.set_enabled(False)
        self._monomod_mode = MonomodModeComponent(self._monomod_mode_update,
                                                  self)
        self._monomod_mode.name = "Monomod_Mode_Component"
        self._monomod_mode.layer = Layer(
            priority=5, mode_toggle=self._master_select_button)
        self._on_shift_value.subject = self._shift_button
        self._on_master_value.subject = self._master_select_button

    @subject_slot('value')
    def _on_shift_value(self, value):
        self._monomod_mode.set_enabled(value > 0)

    @subject_slot('value')
    def _on_master_value(self, value):
        if not self._shift_button.is_pressed(
        ) and not self.modhandler.is_enabled():
            self.schedule_message(1, self._shift_modes.update)

    def _monomod_mode_update(self):
        #self.log_message('mode update: ' + str(self._monomod_mode._mode_index))
        if (self._monomod_mode._mode_index == 0):
            self.flash_status = False
            self.modhandler.set_enabled(False)
            self._slider_modes.set_enabled(True)
            self._shift_modes.set_enabled(True)
            self._scene_launch_buttons[2].set_on_off_values(127, 0)
            self._scene_launch_buttons[3].set_on_off_values(127, 0)
            self._monomod.reset()
            self._shift_modes.set_enabled(True)
            for track in range(8):
                self._mixer.channel_strip(track).set_mute_button(
                    self._mute_buttons[track])
            self._session.set_enabled(True)
            self._session_zoom._is_zoomed_out = False
            self._session_zoom.set_enabled(True)
            self._transport.set_enabled(True)
            self.request_rebuild_midi_map()
            self.schedule_message(1, self._shift_modes.update)
        elif (self._monomod_mode._mode_index == 1):
            self._slider_modes.set_enabled(False)
            if self._shift_modes._note_mode_active is True:
                self._shift_modes._mode_callback(ABLETON_MODE)
                self._shift_modes._note_mode_active = False
                self._session_zoom.set_ignore_buttons(False)
                self._shift_modes._transport.update()
                self._shift_modes._on_note_mode_changed()
            self._shift_modes.set_enabled(False)
            self._session.set_clip_launch_buttons(None)
            for track in range(8):
                self._mixer.channel_strip(track).set_select_button(None)
                self._mixer.channel_strip(track).set_mute_button(None)
            self._session.set_track_bank_buttons(None, None)
            self._session.set_scene_bank_buttons(None, None)
            for scene in range(5):
                self._scene_launch_buttons[scene].turn_off()
            self._transport.set_enabled(False)
            self._session.set_enabled(False)
            self._session_zoom.set_enabled(False)
            self.flash_status = True
            self._monomod.reset()
            self.modhandler.set_enabled(True)
        self._master_select_button.send_value(self._monomod_mode._mode_index)

    """m4l bridge"""

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

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

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

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

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

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

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

    def flash(self):
        if self.flash_status:
            for control, _ in self._monomod.iterbuttons():
                if isinstance(control, MonoButtonElement):
                    control.flash(self._timer)
Exemple #29
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)
class MatrixModesComponent(ModeSelectorComponent):
    ' SelectorComponent that assigns matrix to different functions '
    __module__ = __name__

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

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

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

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

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

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

    def number_of_modes(self):
        return 8

    def update(self):
        pass

    def get_mode_index_value(self):
        return self._mode_index

    def _set_modes(self):
        if self.is_enabled():
            if self._vu != None:
                self._vu.disconnect()

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

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

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

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

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

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

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

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

    def _update_vu_meters(self):
        if self._vu == None:
            self._vu = VUMeters(self._parent)
        else:
            self._vu.disconnect()
        self._vu.observe(int(self._session_zoom._session.track_offset()))
Exemple #31
0
    def _setup_session_control(self):
        Live.Base.log("LOG: AAAMatrix _setup_session_control")
        is_momentary = True

        # Set Highlight Grid Size
        session = CustomSessionComponent(num_tracks, num_scenes)

        # Set Session Name
        session.name = 'AAAMatrix Session'

        # Set Highlight Grid Size
        session.set_offsets(offset_tracks, offset_scenes)

        # SESSION NAVIGATION BUTTONS
        right_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                     right_button_CC)
        left_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                    left_button_CC)
        right_button.name = 'Bank_Select_Right_Button'
        left_button.name = 'Bank_Select_Left_Button'
        session.set_track_bank_buttons(right_button, left_button)
        up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                  up_button_CC)
        down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                    down_button_CC)
        up_button.name = 'Bank_Select_Up_Button'
        down_button.name = 'Bank_Select_Down_Button'
        session.set_scene_bank_buttons(down_button, up_button)

        #SCENE NAVIGATION BUTTONS
        prev_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                    left_select_CC)
        next_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                    right_select_CC)
        next_button.name = 'Next_Select_Button'
        prev_button.name = 'Prev_Select__Button'
        session.set_select_buttons(next_button, prev_button)

        #STOP ALL CLIP BUTTON
        stop_all_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                        stop_all_clips_CC)
        stop_all_button.name = 'Stop_All_Button'
        session.set_stop_all_clips_button(stop_all_button)

        #SCENE LAUCH BUTTONS
        scene_launch_buttons = [
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL,
                          scene_launch_column_CCs[index])
            for index in xrange(num_scenes)
        ]
        scene_launch_buttons = ButtonMatrixElement(name='Scene_Launch_Buttons',
                                                   rows=[scene_launch_buttons])
        session.set_scene_launch_buttons(scene_launch_buttons)

        #CLIP STOP BUTTONS
        scene_stop_buttons = [
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL,
                          clip_stop_row_CCs[index])
            for index in xrange(num_tracks)
        ]
        scene_stop_buttons = ButtonMatrixElement(name='Scene_Stop_Buttons',
                                                 rows=[scene_stop_buttons])
        session.set_stop_track_clip_buttons(scene_stop_buttons)

        #CLIP LAUCH BUTTONS
        matrix = ButtonMatrixElement(name='Button_Matrix')
        for scene_index in xrange(num_scenes):
            row = [
                ButtonElement(True, MIDI_CC_TYPE, CHANNEL,
                              clip_CCs[scene_index][track_index])
                for track_index in xrange(num_tracks)
            ]
            matrix.add_row(row)
        session.set_clip_launch_buttons(matrix)

        self.set_highlighting_session_component(session)
Exemple #32
0
class APC_64_40_9(APC):
    """ Script for Akai's APC40 Controller """
    def __init__(self, c_instance):
        self._c_instance = c_instance
        self._shift_modes = None
        self._encoder_modes = None
        self._slider_modes = None
        self._sequencer = None
        APC.__init__(self, c_instance)
        self._device_selection_follows_track_selection = True

    def disconnect(self):
        self._shift_modes = None
        self._encoder_modes = None
        self._slider_modes = None
        self._sequencer = None
        APC.disconnect(self)

    def _setup_session_control(self):
        is_momentary = True
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98)
        self._right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96)
        self._left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97)
        self._up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94)
        self._down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95)
        self._right_button.name = 'Bank_Select_Right_button'
        self._left_button.name = 'Bank_Select_Left_button'
        self._up_button.name = 'Bank_Select_Up_button'
        self._down_button.name = 'Bank_Select_Down_button'
        self._session = PedaledSessionComponent(8, 5)
        self._session.name = 'Session_Control'
        self._session.set_track_bank_buttons(self._right_button,
                                             self._left_button)
        self._session.set_scene_bank_buttons(self._down_button,
                                             self._up_button)
        self._matrix = ButtonMatrixElement()
        self._matrix.name = 'Button_Matrix'
        self._scene_launch_buttons = [
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, index + 82)
            for index in range(5)
        ]
        self._track_stop_buttons = [
            ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52)
            for index in range(8)
        ]
        for index in range(len(self._scene_launch_buttons)):
            self._scene_launch_buttons[index].name = 'Scene_' + str(
                index) + '_Launch_Button'
        for index in range(len(self._track_stop_buttons)):
            self._track_stop_buttons[index].name = 'Track_' + str(
                index) + '_Stop_Button'
        self._stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                              81)
        self._stop_all_button.name = 'Stop_All_Clips_Button'
        self._session.set_stop_all_clips_button(self._stop_all_button)
        self._session.set_stop_track_clip_buttons(
            tuple(self._track_stop_buttons))
        self._session.set_stop_clip_value(0)
        self._session.set_stop_clip_triggered_value(2)

        for scene_index in range(5):
            scene = self._session.scene(scene_index)
            scene.name = 'Scene_' + str(scene_index)
            button_row = []
            scene.set_launch_button(self._scene_launch_buttons[scene_index])
            scene.set_triggered_value(2)
            for track_index in range(8):
                button = ConfigurableButtonElement(is_momentary,
                                                   MIDI_NOTE_TYPE, track_index,
                                                   (scene_index + 53))
                button.name = str(track_index) + '_Clip_' + str(
                    scene_index) + '_Button'
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                    scene_index)
                clip_slot.set_triggered_to_play_value(2)
                clip_slot.set_triggered_to_record_value(4)
                clip_slot.set_stopped_value(5)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(3)
                clip_slot.set_launch_button(button)
            self._matrix.add_row(tuple(button_row))
        self._session.set_slot_launch_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67))
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
        self._session_zoom = ShiftableZoomingComponent(
            self._session, tuple(self._track_stop_buttons))
        self._session_zoom.name = 'Session_Overview'
        self._session_zoom.set_button_matrix(self._matrix)
        self._session_zoom.set_zoom_button(self._shift_button)
        self._session_zoom.set_nav_buttons(self._up_button, self._down_button,
                                           self._left_button,
                                           self._right_button)
        self._session_zoom.set_scene_bank_buttons(
            tuple(self._scene_launch_buttons))
        self._session_zoom.set_stopped_value(3)
        self._session_zoom.set_selected_value(5)

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(self, 8)
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                             80)
        master_select_button.name = 'Master_Select_Button'
        self._mixer.master_strip().set_select_button(master_select_button)
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        select_buttons = []
        arm_buttons = []
        solo_buttons = []
        mute_buttons = []
        sliders = []
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        49)
            solo_buttons.append(solo_button)
            mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        50)
            mute_buttons.append(mute_button)
            solo_button.name = str(track) + '_Solo_Button'
            mute_button.name = str(track) + '_Mute_Button'
            strip.set_solo_button(solo_button)
            strip.set_mute_button(mute_button)
            strip.set_shift_button(self._shift_button)
            strip.set_invert_mute_feedback(True)
            select_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51))
            select_buttons[-1].name = str(track) + '_Select_Button'
            arm_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48))
            arm_buttons[-1].name = str(track) + '_Arm_Button'
            sliders.append(SliderElement(MIDI_CC_TYPE, track, 7))
            sliders[-1].name = str(track) + '_Volume_Control'

        self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        self._prehear_control = EncoderElement(
            MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
        self._crossfader.name = 'Crossfader'
        master_volume_control.name = 'Master_Volume_Control'
        self._prehear_control.name = 'Prehear_Volume_Control'
        self._mixer.set_shift_button(self._shift_button)
        self._mixer.set_crossfader_control(self._crossfader)
        self._mixer.set_prehear_volume_control(self._prehear_control)
        self._mixer.master_strip().set_volume_control(master_volume_control)
        self._slider_modes = SliderModesComponent(self._mixer, tuple(sliders))
        self._slider_modes.name = 'Slider_Modes'
        matrix_modes = MatrixModesComponent(self._matrix, self._session,
                                            self._session_zoom,
                                            tuple(self._track_stop_buttons),
                                            self)
        matrix_modes.name = 'Matrix_Modes'
        self._sequencer = StepSequencerComponent(
            self, self._session, self._matrix, tuple(self._track_stop_buttons))
        self._sequencer.set_bank_buttons(tuple(select_buttons))
        self._sequencer.set_nav_buttons(self._up_button, self._down_button,
                                        self._left_button, self._right_button)
        self._sequencer.set_button_matrix(self._matrix)
        self._sequencer.set_follow_button(master_select_button)
        self._sequencer.set_velocity_buttons(tuple(arm_buttons))
        self._sequencer.set_shift_button(self._shift_button)
        self._sequencer.set_lane_mute_buttons(tuple(
            self._scene_launch_buttons))
        self._sequencer.set_loop_start_buttons(tuple(mute_buttons))
        self._sequencer.set_loop_length_buttons(tuple(solo_buttons))
        self._shift_modes = ShiftableSelectorComponent(
            self, tuple(select_buttons), master_select_button,
            tuple(self._track_stop_buttons), self._stop_all_button,
            tuple(mute_buttons), tuple(solo_buttons), tuple(arm_buttons),
            tuple(self._scene_launch_buttons), self._matrix, self._session,
            self._session_zoom, self._mixer, self._slider_modes, matrix_modes,
            self._sequencer)
        self._shift_modes.name = 'Shift_Modes'
        self._shift_modes.set_mode_toggle(self._shift_button)

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

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

    def _setup_global_control(self):
        is_momentary = True
        self._global_bank_buttons = []
        self._global_param_controls = []
        for index in range(8):
            ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0,
                                        56 + index)
            ringed_encoder = RingedEncoderElement(
                MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute)
            ringed_encoder.name = 'Track_Control_' + str(index)
            ringed_encoder.set_feedback_delay(-1)
            ring_button.name = ringed_encoder.name + '_Ring_Mode_Button'
            ringed_encoder.set_ring_mode_button(ring_button)
            self._global_param_controls.append(ringed_encoder)
        self._global_bank_buttons = []
        global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button',
                              'Send_C_Button')
        for index in range(4):
            self._global_bank_buttons.append(
                ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                          87 + index))
            self._global_bank_buttons[-1].name = global_bank_labels[index]
        self._encoder_modes = EncModeSelectorComponent(self._mixer)
        self._encoder_modes.name = 'Track_Control_Modes'
        self._encoder_modes.set_controls(tuple(self._global_param_controls))
        self._encoder_device_modes = EncoderDeviceComponent(
            self._mixer, self._device, self)
        self._encoder_device_modes.name = 'Alt_Device_Control_Modes'
        self._encoder_eq_modes = EncoderEQComponent(self._mixer, self)
        self._encoder_eq_modes.name = 'EQ_Control_Modes'
        global_translation_selector = ChannelTranslationSelector()
        global_translation_selector.name = 'Global_Translations'
        global_translation_selector.set_controls_to_translate(
            tuple(self._global_param_controls))
        global_translation_selector.set_mode_buttons(
            tuple(self._global_bank_buttons))
        encoder_user_modes = EncoderUserModesComponent(
            self, self._encoder_modes, tuple(self._global_param_controls),
            tuple(self._global_bank_buttons), self._mixer, self._device,
            self._encoder_device_modes, self._encoder_eq_modes)
        encoder_user_modes.name = 'Encoder_User_Modes'
        self._encoder_shift_modes = ShiftableEncoderSelectorComponent(
            self, tuple(self._global_bank_buttons), encoder_user_modes,
            self._encoder_modes, self._encoder_eq_modes,
            self._encoder_device_modes)
        self._encoder_shift_modes.name = 'Encoder_Shift_Modes'
        self._encoder_shift_modes.set_mode_toggle(self._shift_button)

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        track = self.song().view.selected_track
        device_to_select = track.view.selected_device
        if device_to_select == None and len(track.devices) > 0:
            device_to_select = track.devices[0]
        if device_to_select != None:
            self.song().view.select_device(device_to_select)
        self._device_component.set_device(device_to_select)
        return None

    def _product_model_id_byte(self):
        return 115
Exemple #33
0
class AumPC40(APC40):


	def __init__(self, c_instance, *a, **k):
		super(AumPC40, self).__init__(c_instance, *a, **k)
		self._monomod_version = 'b996'
		self._host_name = 'AumPC'
		self._color_type = 'APC'
		self._timer = 0
		self._touched = 0
		self.flash_status = False
		with self.component_guard():
			self._setup_monobridge()
			self._setup_mod()
			self._device_component._current_bank_details = self._make_current_bank_details(self._device_component)
	

	def disconnect(self):
		super(AumPC40, self).disconnect()
		rebuild_sys()
	

	def _create_controls(self):
		make_on_off_button = partial(make_button, skin=self._default_skin)
		make_color_button = partial(make_button, skin=self._color_skin)
		self._shift_button = make_button(0, 98, resource_type=PrioritizedResource, name='Shift_Button')
		self._right_button = make_button(0, 96, name='Bank_Select_Right_Button')
		self._left_button = make_button(0, 97, name='Bank_Select_Left_Button')
		self._up_button = make_button(0, 94, name='Bank_Select_Up_Button')
		self._down_button = make_button(0, 95, name='Bank_Select_Down_Button')
		self._session_matrix = ButtonMatrixElement(name='Button_Matrix')
		self._scene_launch_buttons = [ make_color_button(0, index + 82, name='Scene_%d_Launch_Button' % index, cs = self) for index in xrange(SESSION_HEIGHT) ]
		self._track_stop_buttons = [ make_color_button(index, 52, name='Track_%d_Stop_Button' % index, cs = self) for index in xrange(SESSION_WIDTH) ]
		self._stop_all_button = make_color_button(0, 81, name='Stop_All_Clips_Button', cs = self)
		self._matrix_rows_raw = [ [ make_color_button(track_index, scene_index + 53, name='%d_Clip_%d_Button' % (track_index, scene_index), cs = self) for track_index in xrange(SESSION_WIDTH) ] for scene_index in xrange(SESSION_HEIGHT) ]
		for row in self._matrix_rows_raw:
			self._session_matrix.add_row(row)

		self._selected_slot_launch_button = make_pedal_button(67, name='Selected_Slot_Launch_Button')
		self._selected_scene_launch_button = make_pedal_button(64, name='Selected_Scene_Launch_Button')
		self._volume_controls = []
		self._arm_buttons = []
		self._original_solo_buttons = []
		self._original_mute_buttons = []
		self._select_buttons = []
		for index in xrange(MIXER_SIZE):
			self._volume_controls.append(make_slider(index, 7, name='%d_Volume_Control' % index, num=index, script = self))
			self._arm_buttons.append(make_on_off_button(index, 48, name='%d_Arm_Button' % index, cs = self))
			self._original_solo_buttons.append(make_on_off_button(index, 49, name='%d_Solo_Button' % index, cs = self))
			self._original_mute_buttons.append(make_on_off_button(index, 50, name='%d_Mute_Button' % index, cs = self))
			self._select_buttons.append(make_on_off_button(index, 51, name='%d_Select_Button' % index, cs = self))

		self._crossfader_control = make_slider(0, 15, name='Crossfader', script = self)
		self._master_volume_control = make_slider(0, 14, name='Master_Volume_Control', script = self)
		self._master_select_button = make_on_off_button(0, 80, name='Master_Select_Button', cs = self)
		self._prehear_control = make_encoder(0, 47, name='Prehear_Volume_Control', script = self)
		self._device_bank_buttons = []
		self._device_param_controls_raw = []
		bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Metronome_Button')
		for index in range(8):
			self._device_bank_buttons.append(make_on_off_button(0, 58 + index, name=bank_button_labels[index]))
			encoder_name = 'Device_Control_%d' % index
			ringed_encoder = make_ring_encoder(16 + index, 24 + index, name=encoder_name, num = index + 8, script = self)
			self._device_param_controls_raw.append(ringed_encoder)

		self._play_button = make_button(0, 91, name='Play_Button')
		self._stop_button = make_button(0, 92, name='Stop_Button')
		self._record_button = make_button(0, 93, name='Record_Button')
		self._nudge_up_button = make_button(0, 100, name='Nudge_Up_Button')
		self._nudge_down_button = make_button(0, 101, name='Nudge_Down_Button')
		self._tap_tempo_button = make_button(0, 99, name='Tap_Tempo_Button')
		self._global_bank_buttons = []
		self._global_param_controls = []
		for index in range(8):
			encoder_name = 'Track_Control_%d' % index
			ringed_encoder = make_ring_encoder(48 + index, 56 + index, name=encoder_name, num = index, script = self)
			self._global_param_controls.append(ringed_encoder)

		self._global_bank_buttons = [ make_on_off_button(0, 87 + index, name=name) for index, name in enumerate(('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button')) ]
		self._device_clip_toggle_button = self._device_bank_buttons[0]
		self._device_on_off_button = self._device_bank_buttons[1]
		self._detail_left_button = self._device_bank_buttons[2]
		self._detail_right_button = self._device_bank_buttons[3]
		self._detail_toggle_button = self._device_bank_buttons[4]
		self._rec_quantization_button = self._device_bank_buttons[5]
		self._overdub_button = self._device_bank_buttons[6]
		self._metronome_button = self._device_bank_buttons[7]

		self._monomod = ButtonMatrixElement(name = 'Monomod')
		for row in self._matrix_rows_raw:
			self._monomod.add_row(row)
		self._monomod.add_row(self._track_stop_buttons)
		self._monomod.add_row(self._select_buttons)
		self._monomod.add_row(self._original_mute_buttons)
		#self._doublepress_detail_button = DoublePressElement(self._detail_toggle_button)

		def wrap_matrix(control_list, wrapper = nop):
			return ButtonMatrixElement(rows=[map(wrapper, control_list)])

		self._scene_launch_buttons = wrap_matrix(self._scene_launch_buttons)
		self._track_stop_buttons = wrap_matrix(self._track_stop_buttons)
		self._volume_controls = wrap_matrix(self._volume_controls)
		self._arm_buttons = wrap_matrix(self._arm_buttons)
		self._original_solo_buttons = wrap_matrix(self._original_solo_buttons)
		self._original_mute_buttons = wrap_matrix(self._original_mute_buttons)
		self._select_buttons = wrap_matrix(self._select_buttons)
		self._device_param_controls = wrap_matrix(self._device_param_controls_raw)
		self._device_bank_buttons = wrap_matrix(self._device_bank_buttons, partial(DeviceBankButtonElement, modifiers=[self._shift_button]))

		self._solo_buttons = self._original_solo_buttons
		self._mute_buttons = self._original_mute_buttons

	

	def _create_detail_view_control(self):
		self._detail_view_toggler = DetailViewCntrlComponent(name='Detail_View_Control', is_enabled=False, layer=Layer(device_clip_toggle_button=self._device_clip_toggle_button, device_nav_left_button=self._detail_left_button, device_nav_right_button=self._detail_right_button))  #detail_toggle_button=self._detail_toggle_button

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

	def _setup_mod(self):
		self.monomodular = get_monomodular(self)
		self.monomodular.name = 'monomodular_switcher'
		self.modhandler = APCModHandler(self)
		self.modhandler.name = 'ModHandler' 
		self.modhandler.layer = Layer(priority = 5,
										grid = self._monomod, 
										nav_up_button = self._up_button, 
										nav_down_button = self._down_button, 
										nav_left_button = self._left_button, 
										nav_right_button = self._right_button,
										shiftlock_button = self._nudge_up_button,
										alt_button = self._nudge_down_button,
										shift_button = self._shift_button)
		self.modhandler.set_device_component(self._device_component)
		self.modhandler.set_enabled(False)
		self._monomod_mode = MonomodModeComponent(self._monomod_mode_update, self)
		self._monomod_mode.name = "Monomod_Mode_Component"
		self._monomod_mode.layer = Layer(priority = 5, mode_toggle = self._detail_toggle_button)
		self._on_shift_value.subject = self._shift_button
	

	@subject_slot('value')
	def _on_shift_value(self, value):
		#self._monomod_mode.set_enabled(value>0)
		self._monomod_mode.set_enabled(value is 0)
		#self.modhandler.is_enabled() and self.modhanlder._shift_value(value)
		if value:
			self.modhandler.set_lock_button(self._detail_toggle_button)
		else:
			self.modhandler.set_lock_button(None)
	

	def _monomod_mode_update(self):
		#self.log_message('mode update: ' + str(self._monomod_mode._mode_index))
		if(self._monomod_mode._mode_index == 0):
			self.flash_status = False
			self.modhandler.set_enabled(False)
			self._monomod.reset()
			self._on_selected_track_changed()		
		elif(self._monomod_mode._mode_index == 1):
			self.flash_status = True
			self._monomod.reset()
			self.modhandler.set_enabled(True)
		self._detail_toggle_button.send_value(self._monomod_mode._mode_index)
	

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

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

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

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

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

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

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

	def flash(self):
		if self.flash_status:
			for control, _ in self._monomod.iterbuttons():
				if isinstance(control, MonoButtonElement):
					control.flash(self._timer)
	

	def _make_current_bank_details(self, device_component):
		def _current_bank_details():
			if not self.modhandler.active_mod() is None:
				if self.modhandler.active_mod() and self.modhandler.active_mod()._param_component._device_parent != None:
					bank_name = self.modhandler.active_mod()._param_component._bank_name
					bank = [param._parameter for param in self.modhandler.active_mod()._param_component._params]
					if self.modhandler._alt_value.subject and self.modhandler._alt_value.subject.is_pressed():
						bank = bank[8:]
					#self.log_message('current mod bank details: ' + str(bank_name) + ' ' + str(bank))
					return (bank_name, bank)
				else:
					return DeviceComponent._current_bank_details(device_component)
			else:
				return DeviceComponent._current_bank_details(device_component)
		return _current_bank_details
class Serato(ControlSurface):
    def __init__(self, c_instance):
        publish_in_cs_list = True
        ControlSurface.__init__(self, c_instance, not publish_in_cs_list)
        self._device_selection_follows_track_selection = True
        with self.component_guard():
            self._matrix = None
            self._session = None
            self._mixer = None
            self._device = None
            self._scene_launch_buttons = None
            self._track_arm_buttons = None
            self._track_solo_buttons = None
            self._track_mute_buttons = None
            self._track_stop_buttons = None
            self._track_select_buttons = None
            self._device_on_off_button = None
            self._shift_button = None
            self._serato_interface = PySCAClipControl()
            self._serato_interface.PySCA_InitializeClipControl()
            self._setup_session_control()
            self._setup_mixer_control()
            self._setup_device_control()
            self._session.set_mixer(self._mixer)
            self.set_highlighting_session_component(self._session)
        return

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

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

    def build_midi_map(self, midi_map_handle):
        pass

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

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

            self._matrix.add_row(tuple(button_row))

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

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

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

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

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

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

    def _move_device_focus(self, increment):
        if not self.application().view.is_view_visible(
                'Detail') or not self.application().view.is_view_visible(
                    'Detail/DeviceChain'):
            self.application().view.show_view('Detail')
            self.application().view.show_view('Detail/DeviceChain')
        else:
            modifier_pressed = True
            direction = Live.Application.Application.View.NavDirection.left
            if increment > 0:
                direction = Live.Application.Application.View.NavDirection.right
            self.application().view.scroll_view(direction,
                                                'Detail/DeviceChain',
                                                not modifier_pressed)
Exemple #35
0
class Codec(ControlSurface):
    __module__ = __name__
    __doc__ = " MonoCode controller script "

    def __init__(self, c_instance, *a, **k):
        super(Codec, self).__init__(c_instance, *a, **k)
        self._monomod_version = 'b995'
        self._version_check = 'b995'
        self._host_name = 'Codec'
        self._color_type = 'Monochrome'
        self._link_mixer = LINK_MIXER
        self._hosts = []
        self._linked_script = None
        self._local_ring_control = True
        self._last_device = None
        self._device_list = [None, None, None, None]
        self._device_select_buttons = None
        self._last_device_component = None
        self._timer = 0
        self._touched = 0
        self._locked = False
        self.flash_status = 1
        self._shift_button = None
        self._shift_pressed = 0
        self._shift_pressed_timer = 0
        self._shift_thresh = SHIFT_THRESH
        self._use_device_selector = USE_DEVICE_SELECTOR
        self._device_selection_follows_track_selection = FOLLOW
        with self.component_guard():
            #self.local_ring_control(True)
            #self.set_absolute_mode(True)
            self._setup_controls()
            self._setup_monobridge()
            self._setup_device_controls()
            self._setup_special_device_control()
            self._device.append(
                self._special_device
            )  #necessary for device browsing to work with special device
            self._setup_device_chooser()
            self._setup_mixer_controls()
            self._setup_monomod()
            self._setup_modes()
            self._setup_device_selector()
            self._setup_send_reset()
            self._setup_default_buttons()
            self.set_local_ring_control(1)
            self.song().view.add_selected_track_listener(
                self._update_selected_device)
            self._initialize_code()
            #self._shift_mode.set_mode(0)
            #self._monomod_mode.set_mode(0)
        self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Codec ' +
                         str(self._monomod_version) +
                         ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>')
        self.show_message('Codec Control Surface Loaded')
        self.request_rebuild_midi_map()

    """script initialization methods"""

    def _initialize_code(self):
        self._send_midi(factoryreset)
        self._send_midi(btn_channels)
        self._send_midi(enc_channels)

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

    def _setup_controls(self):
        is_momentary = True
        self._livid = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                             CHANNEL, LIVID, 'Livid_Button',
                                             self)

        self._dial = [None for index in range(8)]
        for column in range(8):
            self._dial[column] = [None for index in range(4)]
            for row in range(4):
                self._dial[column][row] = CodecEncoderElement(
                    MIDI_CC_TYPE, CHANNEL, CODE_DIALS[row][column],
                    Live.MidiMap.MapMode.absolute,
                    'Dial_' + str(column) + '_' + str(row),
                    (column + (row * 8)), self)  #CODE_DIALS[row][column]

        self._button = [None for index in range(8)]
        for column in range(8):
            self._button[column] = [None for index in range(4)]
            for row in range(4):
                self._button[column][row] = CodecMonoButtonElement(
                    is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                    CODE_BUTTONS[row][column],
                    'Button_' + str(column) + '_' + str(row), self)

        self._column_button = [None for index in range(8)]
        for index in range(8):
            self._column_button[index] = CodecMonoButtonElement(
                is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                CODE_COLUMN_BUTTONS[index], 'Column_Button_' + str(index),
                self)

        self._row_button = [None for index in range(4)]
        for index in range(4):
            self._row_button[index] = CodecMonoButtonElement(
                is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_ROW_BUTTONS[index],
                'Row_Button_' + str(index), self)

        self._dial_matrix = EncoderMatrixElement(self)
        self._dial_matrix.name = 'Encoder_Matrix'
        for row in range(4):
            dial_row = tuple([self._dial[column][row] for column in range(8)])
            self._dial_matrix.add_row(dial_row)

        self._button_matrix = ButtonMatrixElement()
        self._button_matrix.name = 'Button_Matrix'
        for row in range(4):
            button_row = [self._button[column][row] for column in range(8)]
            button_row.append(self._row_button[row])
            self._button_matrix.add_row(tuple(button_row))
        self._button_matrix.add_row(tuple(self._column_button + [self._livid]))

    def _setup_modes(self):
        self._monomod_mode = MonomodModeComponent(self._mod_mode_update, self)
        self._monomod_mode.name = 'Monomod_Mode'
        self.set_shift_button(self._livid)
        self._shift_mode = ShiftModeComponent(self._shift_update, self)
        self._shift_mode.name = 'Shift_Mode'
        self._shift_mode.set_mode_buttons(
            tuple([
                self._row_button[0], self._row_button[1], self._row_button[2],
                self._row_button[3]
            ]))

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

    def _setup_monomod(self):
        self._host = CodecMonomodComponent(self)
        self._host.name = 'Monomod_Host'
        self._host._set_dial_matrix(self._dial_matrix, self._button_matrix)
        self.hosts = [self._host]
        encs = []
        for row in range(4):
            for col in range(8):
                encs.append(self._dial[col][row])
        self._host._set_parameter_controls(encs)

    def _setup_mixer_controls(self):
        is_momentary = True
        self._num_tracks = (8)
        self._session = SessionComponent(self._num_tracks, 0)
        self._session.name = 'Session'
        self._mixer = MixerComponent(self._num_tracks, 0, False, False)
        self._mixer.name = 'Mixer'
        self._mixer._next_track_value = self._mixer_next_track_value(
            self._mixer)
        self._mixer._prev_track_value = self._mixer_prev_track_value(
            self._mixer)
        self._mixer.set_track_offset(
            0)  #Sets start point for mixer strip (offset from left)
        #for index in range(8):
        #use the bottom row of encoders for volume, so add 24 to offset the index
        #	self._mixer.channel_strip(index).set_volume_control(self._dial[index+24])
        for index in range(8):
            self._mixer.channel_strip(
                index).name = 'Mixer_ChannelStrip_' + str(index)
            self._mixer.channel_strip(index)._invert_mute_feedback = True
            self._mixer.channel_strip(
                index)._mute_value = self._channelstrip_mute_value(
                    self._mixer.channel_strip(index))
            self._mixer.channel_strip(
                index)._solo_value = self._channelstrip_solo_value(
                    self._mixer.channel_strip(index))
            #mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index]))
        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._session.set_mixer(self._mixer)

    def _setup_device_controls(self):
        self._device = [None for index in range(4)]
        for index in range(4):
            self._device[index] = CodecDeviceComponent(self)
            self._device[index].name = 'CodecDevice_Component_' + str(index)
            device_param_controls = []
            for control in range(8):
                device_param_controls.append(self._dial[control][index])
            self._device[index].set_on_off_button(self._button[1][index])
            self._device[index].set_lock_button(self._button[2][index])
            self._device[index].set_bank_nav_buttons(self._button[4][index],
                                                     self._button[5][index])
            self._device[index].set_nav_buttons(self._button[6][index],
                                                self._button[7][index])
            self._device[index].set_parameter_controls(
                tuple(device_param_controls))
        self.set_device_component(self._device[0])
        self._last_device_component = self._device[0]

    def _setup_special_device_control(self):
        self._special_device = SpecialCodecDeviceComponent(self)
        self._special_device.name = 'SpecialCodecDeviceComponent'
        self._special_device.set_on_off_button(self._button[1][0])
        self._special_device.set_lock_button(self._button[2][0])
        self._special_device.set_bank_nav_buttons(self._button[4][0],
                                                  self._button[5][0])
        self._special_device.set_nav_buttons(self._button[6][0],
                                             self._button[7][0])
        device_param_controls = []
        for row in range(4):
            for column in range(8):
                device_param_controls.append(self._dial[column][row])
        self._special_device.set_parameter_controls(
            tuple(device_param_controls))

    def _setup_device_chooser(self):
        self._selected_device = self._device[0]
        self._last_selected_device = self._device[0]
        self._device_select_buttons = [
            self._button[0][index] for index in range(4)
        ]
        for button in self._device_select_buttons:
            button.add_value_listener(self._device_select_value, True)

    def _setup_device_selector(self):
        self._device_selector = CodecDeviceSelectorComponent(
            self, 'c', self._device + [self._special_device])
        self._device_selector.name = 'Device_Selector'
        self._device_selector.set_mode_buttons(self._column_button)
        #self._device_selector.set_mode_toggle(self._livid)

    def _setup_send_reset(self):
        self._send_reset = CodecResetSendsComponent(self)
        self._send_reset.set_buttons(self._button)

    def _setup_default_buttons(self):
        self._value_default = ParameterDefaultComponent(self)
        buttons = []
        dials = []
        for column in self._button:
            for button in column:
                buttons.append(button)
        for column in self._dial:
            for dial in column:
                dials.append(dial)
        self._value_default.set_buttons(buttons)
        self._value_default.set_dials(dials)

    """multiple device support"""

    def _device_select_value(self, value, sender):
        #self.log_message('device_select_value ' + str(value) + ' ' + str(self._device_select_buttons.index(sender)))
        if not self._shift_pressed:
            if sender.is_momentary or value > 0:
                if self._shift_mode._mode_index == 2:
                    self.set_device_component(self._device[
                        self._device_select_buttons.index(sender)])
                    self._last_device_component = self._device_component
                    if self._device_component != None and isinstance(
                            self._device_component._device,
                            Live.Device.Device):
                        if self._device_component.find_track(
                                self._device_component._device) == self.song(
                                ).view.selected_track:
                            self._device_component.display_device()

    """livid double press mechanism"""

    def set_shift_button(self, button):
        assert ((button == None) or (isinstance(button, MonoButtonElement)))
        if self._shift_button != None:
            self._shift_button.remove_value_listener(self._shift_value)
        self._shift_button = button
        if self._shift_button != None:
            self._shift_button.add_value_listener(self._shift_value)

    def _shift_value(self, value):
        self._shift_pressed = int(value != 0)
        if self._shift_pressed > 0:
            self._send_midi(SLOWENCODER)
            if (self._shift_pressed_timer + self._shift_thresh) > self._timer:
                #if(self._host.is_enabled() != True)
                self.log_message('mod mode: ' +
                                 str(abs(self._monomod_mode._mode_index - 1)))
                self._monomod_mode.set_mode(
                    max(0, min(1, abs(self._monomod_mode._mode_index - 1))))
                #else:
                #	self._monomod_mode.set_mode(0)
            self._shift_pressed_timer = self._timer % 256
        else:
            self._send_midi(NORMALENCODER)

    def _mod_mode_update(self):
        if (self._monomod_mode._mode_index == 0):
            self._host._set_shift_button(None)
            self._host.set_enabled(False)
            self._dial_matrix.reset()
            self._shift_mode.set_enabled(True)
            self._shift_update()
            self.request_rebuild_midi_map()
            self._livid.turn_off()
        elif (self._monomod_mode._mode_index == 1):
            self._shift_mode.set_enabled(False)
            self._deassign_all()
            self._dial_matrix.reset()
            self._button_matrix.reset()
            self._livid.turn_on()
            if not self._host._active_client == None:
                self._host.set_enabled(True)
                self._host._set_shift_button(self._livid)
            else:
                self._assign_alternate_mappings(1)
            self.request_rebuild_midi_map()

    """Mode Functions"""

    def _shift_update(self):
        if (self._shift_mode.is_enabled()):
            with self.component_guard():
                self.allow_updates(False)
                #if(not self._in_build_midi_map):
                #	self.set_suppress_rebuild_requests(True)
                self._deassign_all()
                if (self._shift_mode._mode_index is 0):
                    self._assign_volume()
                elif (self._shift_mode._mode_index is 1):
                    self._assign_sends()
                elif (self._shift_mode._mode_index is 2):
                    self._assign_devices()
                elif (self._shift_mode._mode_index is 3):
                    self._assign_special_device()
                for index in range(self._shift_mode.number_of_modes()):
                    if index == self._shift_mode._mode_index:
                        self._shift_mode._modes_buttons[index].turn_on()
                    else:
                        self._shift_mode._modes_buttons[index].turn_off()
                self.allow_updates(True)
                #self.set_suppress_rebuild_requests(False)
                self.request_rebuild_midi_map()

    def _deassign_all(self):
        self._assign_alternate_mappings(0)
        self._device_selector.set_enabled(False)
        for index in range(8):
            self._mixer.channel_strip(index).set_volume_control(None)
            self._mixer.channel_strip(index).set_pan_control(None)
            self._mixer.channel_strip(index).set_send_controls(
                tuple([None, None, None, None]))
        for index in range(4):
            self._device[index].set_enabled(False)
            self._device[index]._parameter_controls = None
            #self._device_navigator[index].set_enabled(False)
        self._special_device.set_enabled(False)
        self._special_device._parameter_controls = None
        self._device_selector.set_enabled(False)
        self._deassign_buttons()
        for control in self.controls:
            control.reset()
        self.request_rebuild_midi_map()

    def _deassign_buttons(self):
        for index in range(8):
            self._mixer.channel_strip(index).set_select_button(None)
            self._mixer.channel_strip(index).set_solo_button(None)
            self._mixer.channel_strip(index).set_mute_button(None)
        self._mixer.set_select_buttons(None, None)
        self._send_reset.set_enabled(False)

    def _assign_volume(self):
        for index in range(8):
            self._mixer.channel_strip(index).set_volume_control(
                self._dial[index][3])
            self._mixer.channel_strip(index).set_pan_control(
                self._dial[index][2])
            self._mixer.channel_strip(index).set_send_controls(
                tuple([self._dial[index][0], self._dial[index][1]]))
            self._mixer.channel_strip(index).set_select_button(
                self._column_button[index])
            self._mixer.channel_strip(index).set_solo_button(
                self._button[index][2])
            self._mixer.channel_strip(index).set_mute_button(
                self._button[index][3])
        self._mixer.set_select_buttons(self._button[7][0], self._button[6][0])

    def _assign_sends(self):
        for index in range(8):
            self._mixer.channel_strip(index).set_send_controls(
                tuple([
                    self._dial[index][0], self._dial[index][1],
                    self._dial[index][2], self._dial[index][3]
                ]))
            self._mixer.channel_strip(index).set_select_button(
                self._column_button[index])
            self._send_reset.set_enabled(True)

    def _assign_devices(self):
        self.set_device_component(self._last_device_component)
        self._device_select_value(
            1, self._device_select_buttons[self._device.index(
                self._device_component)])
        for index in range(4):
            device_param_controls = []
            for control in range(8):
                device_param_controls.append(self._dial[control][index])
            self._device[index].set_parameter_controls(
                tuple(device_param_controls))
            self._device[index].set_enabled(True)
        self._device_selector.set_enabled(self._use_device_selector)
        if not self._use_device_selector:
            for index in range(8):
                self._mixer.channel_strip(index).set_select_button(
                    self._column_button[index])

    def _assign_special_device(self):
        self.set_device_component(self._special_device)
        device_param_controls = []
        for row in range(4):
            for column in range(8):
                device_param_controls.append(self._dial[column][row])
        self._special_device.set_parameter_controls(
            tuple(device_param_controls))
        self._special_device.set_enabled(True)
        self._device_selector.set_enabled(self._use_device_selector)
        if not self._use_device_selector:
            for index in range(8):
                self._mixer.channel_strip(index).set_select_button(
                    self._column_button[index])

    def _assign_alternate_mappings(self, chan):
        for column in self._dial:
            for control in column:
                control.set_channel(chan)
                control.set_enabled(chan is 0)
        for column in self._button:
            for control in column:
                control.set_channel(chan)
                control.set_enabled(chan is 0)
        for control in self._column_button:
            control.set_channel(chan)
            control.set_enabled(chan is 0)
        for control in self._row_button:
            control.set_channel(chan)
            control.set_enabled(chan is 0)

    """general functionality"""

    def disconnect(self):
        """clean things up on disconnect"""
        if not self._shift_button is None:
            if self._shift_button.value_has_listener(self._shift_value):
                self._shift_button.remove_value_listener(self._shift_value)
        for button in self._device_select_buttons:
            if button.value_has_listener(self._device_select_value):
                button.remove_value_listener(self._device_select_value)
        if self._session._is_linked():
            self._session._unlink()
        self.song().view.remove_selected_track_listener(
            self._update_selected_device)
        """for cs in self._control_surfaces():
			for host in self._hosts:
				self.log_message('installed: ' + str(cs) + ' vs. ' + str(host))
				if str(type(cs)) == str(type(host)):
					self.log_message('disconnecting: ' + str(type(cs)))
					cs.disconnect(cs)"""
        #self._host._set_parameter_controls(None)
        self._hosts = []
        if self._linked_script != None:
            self._linked_script._update_linked_device_selection = None
        self._linked_script = None
        #self._disconnect_notifier.set_mode(0)
        self.log_message(
            '<<<<<<<<<<<<<<<<<<<<<<<<< Codec log closed >>>>>>>>>>>>>>>>>>>>>>>>>'
        )
        ControlSurface.disconnect(self)
        return None

    def connect_script_instances(self, instanciated_scripts):
        found = False
        for s in instanciated_scripts:
            if '_codec_version' in dir(s):
                if s._codec_version == self._version_check:
                    if s._host_name == ('MonOhm'):
                        self.log_message('found codec version ' +
                                         str(s._codec_version) +
                                         ' in script ' + str(s._host_name))
                        found = True
                        self._linked_script = s
                        self._linked_script._update_linked_device_selection = self._update_linked_device_selection
                        if not self._session._is_linked(
                        ) and self._link_mixer is True:
                            self._session.set_offsets(LINK_OFFSET[0],
                                                      LINK_OFFSET[1])
                            self._session._link()
                else:
                    self.log_message('version mismatch: Monomod version ' +
                                     str(self._version_check) +
                                     ' vs. Host version ' +
                                     str(s._codec_version))

        if found == False:
            for s in instanciated_scripts:
                if '_codec_version' in dir(s):
                    if s._codec_version == self._version_check:
                        if s._host_name == 'BlockMod':
                            self.log_message('found codec version ' +
                                             str(s._codec_version) +
                                             ' in script ' + str(s._host_name))
                            self._linked_script = s
                            self._linked_script._update_linked_device_selection = self._update_linked_device_selection
                        if not self._session._is_linked(
                        ) and self._link_mixer is True:
                            self._session.set_offsets(LINK_OFFSET[0],
                                                      LINK_OFFSET[1])
                            self._session._link()
                    else:
                        self.log_message('version mismatch: Monomod version ' +
                                         str(self._version_check) +
                                         ' vs. Host version ' +
                                         str(s._codec_version))
        #self.log_message('hosts: ' + str(self._hosts))"""

    def update_display(self):
        ControlSurface.update_display(
            self
        )  #since we are overriding this from the inherited method, we need to call the original routine as well
        self._timer = (self._timer + 1) % 256
        if (self._timer == 0):
            self._shift_pressed_timer = -12
        if (self._local_ring_control is False):
            self.send_ring_leds()
        self.flash()

    def handle_sysex(self, midi_bytes):
        #self._send_midi(tuple([240, 00, 01, 97, 04, 15, 01, 247]))
        #response = [long(0),long(0)]
        #self.log_message(response)
        pass

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

    def send_ring_leds(self):
        leds = [240, 0, 1, 97, 4, 31]
        for column in range(8):
            for row in range(4):
                wheel = self._dial[column][row]
                bytes = wheel._get_ring()
                leds.append(bytes[0])
                leds.append(int(bytes[1]) + int(bytes[2]))
                #if(row == 1 and column == 0):
                #	self.log_message(str(leds) + ' ' + str(bytes[0]) + ' ' + str(bytes[1]) + ' ' + str(bytes[2]))
        leds.append(247)
        self._send_midi(tuple(leds))

    def set_absolute_mode(self, val=1):
        self._absolute_mode = (val != 0)
        if self._absolute_mode is True:
            self._send_midi(
                tuple([240, 0, 1, 97, 4, 17, 0, 0, 0, 0, 0, 0, 0, 0, 247]))
        else:
            self._send_midi(
                tuple([
                    240, 0, 1, 97, 4, 17, 127, 127, 127, 127, 127, 127, 127,
                    127, 247
                ]))

    def set_local_ring_control(self, val=1):
        self._local_ring_control = (val != 0)
        if (self._local_ring_control is True):
            #self._send_midi(tuple([240, 0, 1, 97, 4, 32, 0, 247]))
            self._send_midi(tuple([240, 0, 1, 97, 4, 8, 72, 247]))
        else:
            #self._send_midi(tuple([240, 0, 1, 97, 4, 32, 1, 247]))
            self._send_midi(tuple([240, 0, 1, 97, 4, 8, 64, 247]))

    def device_follows_track(self, val):
        self._device_selection_follows_track_selection = (val == 1)
        return self

    """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 += ' '
        assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
        return ret

    def notification_to_bridge(self, name, value, sender):
        if (isinstance(sender, CodecEncoderElement)):
            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 not self._host.is_enabled():
            if self._touched is 0:
                self._monobridge._send('touch', 'on')
                self.schedule_message(2, self.check_touch)
            self._touched += 1

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

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

    """overrides"""

    def allow_updates(self, allow_updates):
        for component in self.components:
            component.set_allow_update(int(allow_updates != 0))

    def set_device_component(self, device_component):
        if self._device_component != None:
            self._device_component._lock_callback = None
        assert (device_component != None)
        assert isinstance(device_component, DeviceComponent)
        self._device_component = device_component
        self._device_component._lock_callback = self._toggle_lock  #old:  self._device_component.set_lock_callback(self._toggle_lock)
        if self._device_select_buttons != None:
            for button in self._device_select_buttons:
                button.send_value(
                    self._device_select_buttons.index(button) ==
                    self._device.index(self._device_component))
        self._update_device_selection()
        return None

    def _update_selected_device(self):
        if self._device_selection_follows_track_selection is True:
            self._update_device_selection()
        return None

    def _update_linked_device_selection(self, device):
        #self.log_message('codec received ' + str(device.name))
        if self._device_component != None and device != None:
            if not self._device_component.is_locked():
                self._device_component.set_device(device)

    def _get_num_tracks(self):
        return self.num_tracks

    def _update_device_selection(self):
        #self.log_message('_update_device_selection')
        if self._device_component != None:
            if not self._device_component.is_locked():
                track = self.song().view.selected_track
                device_to_select = track.view.selected_device
                if ((device_to_select == None) and (len(track.devices) > 0)):
                    device_to_select = track.devices[0]
                if (device_to_select != None):
                    self.song().view.select_device(device_to_select)
                self._device_component.set_device(device_to_select)

    def _channelstrip_mute_value(self, channelstrip):
        def _mute_value(value):
            if not self._shift_pressed:
                self.log_message('shift not pressed')
                ChannelStripComponent._mute_value(channelstrip, value)

        return _mute_value

    def _channelstrip_solo_value(self, channelstrip):
        def _solo_value(value):
            if not self._shift_pressed:
                ChannelStripComponent._solo_value(channelstrip, value)

        return _solo_value

    def _mixer_next_track_value(self, mixer):
        def _next_track_value(value):
            if not self._shift_pressed:
                MixerComponent._next_track_value(mixer, value)

        return _next_track_value

    def _mixer_prev_track_value(self, mixer):
        def _prev_track_value(value):
            if not self._shift_pressed:
                MixerComponent._prev_track_value(mixer, value)

        return _prev_track_value
Exemple #36
0
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self.set_suppress_rebuild_requests(True)
        self._suppress_send_midi = True
        self._suppress_session_highlight = True
        is_momentary = True
        self._suggested_input_port = 'Launchpad'
        self._suggested_output_port = 'Launchpad'
        self._control_is_with_automap = False
        self._user_byte_write_button = ButtonElement(is_momentary,
                                                     MIDI_CC_TYPE, 0, 16)
        self._user_byte_write_button.name = 'User_Byte_Button'
        self._user_byte_write_button.send_value(1)
        self._user_byte_write_button.add_value_listener(self._user_byte_value)
        self._wrote_user_byte = False
        self._challenge = Live.Application.get_random_int(
            0, 400000000) & 2139062143
        matrix = ButtonMatrixElement()
        matrix.name = 'Button_Matrix'
        for row in range(8):
            button_row = []
            for column in range(8):
                button = ConfigurableButtonElement(is_momentary,
                                                   MIDI_NOTE_TYPE, 0,
                                                   row * 16 + column)
                button.name = str(column) + '_Clip_' + str(row) + '_Button'
                button_row.append(button)

            matrix.add_row(tuple(button_row))

        self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0)
        self._config_button.add_value_listener(self._config_value)
        top_buttons = [
            ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0,
                                      104 + index) for index in range(8)
        ]
        side_buttons = [
            ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                      SIDE_NOTES[index]) for index in range(8)
        ]
        top_buttons[0].name = 'Bank_Select_Up_Button'
        top_buttons[1].name = 'Bank_Select_Down_Button'
        top_buttons[2].name = 'Bank_Select_Left_Button'
        top_buttons[3].name = 'Bank_Select_Right_Button'
        top_buttons[4].name = 'Session_Button'
        top_buttons[5].name = 'User1_Button'
        top_buttons[6].name = 'User2_Button'
        top_buttons[7].name = 'Mixer_Button'
        side_buttons[0].name = 'Vol_Button'
        side_buttons[1].name = 'Pan_Button'
        side_buttons[2].name = 'SndA_Button'
        side_buttons[3].name = 'SndB_Button'
        side_buttons[4].name = 'Stop_Button'
        side_buttons[5].name = 'Trk_On_Button'
        side_buttons[6].name = 'Solo_Button'
        side_buttons[7].name = 'Arm_Button'
        self._selector = MainSelectorComponent(matrix, tuple(top_buttons),
                                               tuple(side_buttons),
                                               self._config_button, self)
        self._selector.name = 'Main_Modes'
        self._do_combine()
        for control in self.controls:
            if isinstance(control, ConfigurableButtonElement):
                control.add_value_listener(self._button_value)

        self._suppress_session_highlight = False
        self.set_suppress_rebuild_requests(False)

        self.log_message("LaunchPad85 Loaded !")
Exemple #37
0
class APC20(APC):
    """ Script for Akai's APC20 Controller """

    def __init__(self, *a, **k):
        super(APC20, self).__init__(*a, **k)
        self._skin = make_biled_skin()
        with self.component_guard():
            self._create_controls()
            self._create_session()
            self._create_mixer()
            self._create_transport()
            self._create_background()
            self._create_global_control()
            self._session.set_mixer(self._mixer)
            self.set_highlighting_session_component(self._session)
            for component in self.components:
                component.set_enabled(False)

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

    def _create_controls(self):
        make_color_button = partial(make_button, skin=self._skin)
        self._shift_button = make_button(0, 81, name='Shift_Button')
        self._matrix = ButtonMatrixElement(name='Button_Matrix')
        self._scene_launch_buttons = [ make_color_button(0, index + 82, name='Scene_%d_Launch_Button' % index) for index in xrange(SESSION_HEIGHT) ]
        self._track_stop_buttons = [ make_color_button(index, 52, name='Track_%d_Stop_Button' % index) for index in xrange(SESSION_WIDTH) ]
        for scene_index in xrange(SESSION_HEIGHT):
            row = [ make_color_button(track_index, scene_index + 53, name='%d_Clip_%d_Button' % (track_index, scene_index)) for track_index in xrange(SESSION_WIDTH) ]
            self._matrix.add_row(row)

        self._selected_scene_launch_button = make_pedal_button(64, name='Selected_Scene_Launch_Button')
        self._scene_launch_buttons = ButtonMatrixElement(name='Scene_Launch_Buttons', rows=[self._scene_launch_buttons])
        self._solo_buttons = [ make_button(track_index, 49, name='%d_Solo_Button' % track_index) for track_index in xrange(MIXER_SIZE) ]
        self._mute_buttons = [ make_button(track_index, 50, name='%d_Mute_Button' % track_index) for track_index in xrange(MIXER_SIZE) ]
        self._master_volume_control = make_slider(0, 14, name='Master_Volume_Control')
        self._prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, MapMode.relative_two_compliment, name='Prehear_Volume_Control')
        self._master_select_button = make_button(0, 80, name='Master_Select_Button')
        self._select_buttons = [ make_button(track_index, 51, name='%d_Select_Button' % track_index) for track_index in xrange(8) ]
        self._arm_buttons = [ make_button(track_index, 48, name='%d_Arm_Button' % track_index) for track_index in xrange(8) ]
        self._sliders = [ make_slider(track_index, 7, name='%d_Volume_Control' % track_index) for track_index in xrange(8) ]
        self._note_matrix = ButtonMatrixElement(name='Note_Button_Matrix')
        self._note_buttons = [ [ make_button(9, note + i, name='Note_%d_Button' % (note + i)) for i in xrange(4) ] for note in xrange(36, 75, 4) ]
        for row in self._note_buttons:
            for button in row:
                button.send_depends_on_forwarding = False

            self._note_matrix.add_row(row)

    def _create_session(self):
        self._session = SessionComponent(SESSION_WIDTH, SESSION_HEIGHT, name='Session_Control', auto_name=True, enable_skinning=True)
        self._session.set_clip_launch_buttons(self._matrix)
        self._session.set_stop_track_clip_buttons(tuple(self._track_stop_buttons))
        self._session.set_scene_launch_buttons(self._scene_launch_buttons)
        for scene_index in xrange(SESSION_HEIGHT):
            scene = self._session.scene(scene_index)
            for track_index in xrange(SESSION_WIDTH):
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = '%d_Clip_Slot_%d' % (track_index, scene_index)

        self._session.selected_scene().set_launch_button(self._selected_scene_launch_button)
        self._session_zoom = ShiftableZoomingComponent(self._session, tuple(self._track_stop_buttons), name='Session_Overview', enable_skinning=True)
        self._session_zoom.set_button_matrix(self._matrix)
        self._session_zoom.set_zoom_button(self._shift_button)
        self._session_zoom.set_scene_bank_buttons(self._scene_launch_buttons)

    def _create_mixer(self):
        self._mixer = MixerComponent(MIXER_SIZE, name='Mixer')
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        buttons = izip(self._solo_buttons, self._mute_buttons)
        for track_index, (solo_button, mute_button) in enumerate(buttons):
            strip = self._mixer.channel_strip(track_index)
            strip.name = 'Channel_Strip_%d' % track_index
            strip.set_solo_button(solo_button)
            strip.set_mute_button(mute_button)
            strip.set_shift_button(self._shift_button)
            strip.set_invert_mute_feedback(True)

        self._mixer.set_prehear_volume_control(self._prehear_control)
        self._mixer.master_strip().set_volume_control(self._master_volume_control)

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

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

    def _create_global_control(self):
        self._slider_modes = SliderModesComponent(self._mixer, tuple(self._sliders), name='Slider_Modes')
        self._shift_modes = ShiftableSelectorComponent(tuple(self._select_buttons), self._master_select_button, tuple(self._arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, self._transport, self._slider_modes, self._send_introduction_message, self._note_matrix, self._background, name='Shift_Modes')
        self._shift_modes.set_mode_toggle(self._shift_button)

    def _product_model_id_byte(self):
        return 123
class APC20(APC):
    """ Script for Akai's APC20 Controller """
    def __init__(self, c_instance):
        self._shift_modes = None
        APC.__init__(self, c_instance)

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

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

    def _setup_session_control(self):
        is_momentary = True
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81)
        self._session = APCSessionComponent(8, 5)
        self._session.name = 'Session_Control'
        self._matrix = ButtonMatrixElement()
        self._matrix.name = 'Button_Matrix'
        scene_launch_buttons = [
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, index + 82)
            for index in range(5)
        ]
        track_stop_buttons = [
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52)
            for index in range(8)
        ]
        for index in range(len(scene_launch_buttons)):
            scene_launch_buttons[index].name = 'Scene_' + str(
                index) + '_Launch_Button'

        for index in range(len(track_stop_buttons)):
            track_stop_buttons[index].name = 'Track_' + str(
                index) + '_Stop_Button'

        self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
        self._session.set_stop_track_clip_value(2)
        for scene_index in range(5):
            scene = self._session.scene(scene_index)
            scene.name = 'Scene_' + str(scene_index)
            button_row = []
            scene.set_launch_button(scene_launch_buttons[scene_index])
            scene.set_triggered_value(2)
            for track_index in range(8):
                button = ButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                       track_index, scene_index + 53)
                button.name = str(track_index) + '_Clip_' + str(
                    scene_index) + '_Button'
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                    scene_index)
                clip_slot.set_triggered_to_play_value(2)
                clip_slot.set_triggered_to_record_value(4)
                clip_slot.set_stopped_value(5)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(3)
                clip_slot.set_launch_button(button)

            self._matrix.add_row(tuple(button_row))

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

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        49)
            mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        50)
            solo_button.name = str(track) + '_Solo_Button'
            mute_button.name = str(track) + '_Mute_Button'
            strip.set_solo_button(solo_button)
            strip.set_mute_button(mute_button)
            strip.set_shift_button(self._shift_button)
            strip.set_invert_mute_feedback(True)

        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        prehear_control = EncoderElement(
            MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
        master_volume_control.name = 'Master_Volume_Control'
        prehear_control.name = 'Prehear_Volume_Control'
        self._mixer.set_prehear_volume_control(prehear_control)
        self._mixer.master_strip().set_volume_control(master_volume_control)

    def _setup_custom_components(self):
        is_momentary = True
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                             80)
        master_select_button.name = 'Master_Select_Button'
        select_buttons = []
        arm_buttons = []
        sliders = []
        for track in range(8):
            select_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51))
            arm_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48))
            sliders.append(SliderElement(MIDI_CC_TYPE, track, 7))
            select_buttons[-1].name = str(track) + '_Select_Button'
            arm_buttons[-1].name = str(track) + '_Arm_Button'
            sliders[-1].name = str(track) + '_Volume_Control'

        transport = TransportComponent()
        transport.name = 'Transport'
        slider_modes = SliderModesComponent(self._mixer, tuple(sliders))
        slider_modes.name = 'Slider_Modes'
        self._shift_modes = ShiftableSelectorComponent(
            tuple(select_buttons), master_select_button, tuple(arm_buttons),
            self._matrix, self._session, self._session_zoom, self._mixer,
            transport, slider_modes, self._send_introduction_message)
        self._shift_modes.name = 'Shift_Modes'
        self._shift_modes.set_mode_toggle(self._shift_button)

    def _product_model_id_byte(self):
        return 123
    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
            )
Exemple #40
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)
Exemple #41
0
class BlockMod(MonOhm):
	__module__ = __name__
	__doc__ = " Monomodular controller script for Livid Block "


	def __init__(self, *a, **k):
		self._shift_button = None
		self._shift_pressed = 0
		self._shift_pressed_timer = 0
		self._shift_thresh = SHIFT_THRESH
		super(BlockMod, self).__init__(*a, **k)
		self._host_name = 'BlockMod'
		self._color_type = 'Monochrome'
		self._link_mixer = LINK_MIXER
		self._rgb = 1
		self._ohm = 127
		self._ohm_type = 'static'
		self._pad_translations = PAD_TRANSLATION
		self._mem = [4, 8, 12, 16]
		self._host._navbox_selected = 8
	

	"""script initialization methods"""
	def _setup_monobridge(self):
		self._monobridge = MonoBridgeElement(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(2):
			self._fader[index] = MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, SLIDER_CC[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self)
		#for index in range(8):
		#	self._button[index] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_' + str(index), self)
		for index in range(8):
			self._dial[index] = MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, KNOB_CC[index], Live.MidiMap.MapMode.absolute, 'Dial_' + str(index), index + 8, self)
		for index in range(4):
			self._menu[index] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, FUNCTION_NOTES[index], 'Menu_' + str(index), self)	
		self._livid = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self)
		self._shift_l = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Shift_Button_Left', self)
		self._shift_r = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Shift_Button_Right', 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] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, (column * 8) + row, 'Grid_' + 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'
	

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

	def _setup_crossfader(self):
		pass
	

	def _setup_modes(self):
		self._monomod_mode = MonomodModeComponent(self, self.monomod_mode_update)
		self._monomod_mode.name = 'Monomod_Mode'
		self.set_shift_button(self._livid)
		self._shift_mode = BlockModShiftModeComponent(self, self.shift_update) 
		self._shift_mode.name = 'Shift_Mode'
		self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r)
		self._l_function_mode = FunctionModeComponent(self, self.l_function_update)
		self._l_function_mode.name = 'Left_Function_Mode'
		self._r_function_mode = FunctionModeComponent(self, self.r_function_update)
		self._r_function_mode.name = 'Right_Function_Mode'
		self._m_function_mode = FunctionModeComponent(self, self.m_function_update)
		self._m_function_mode.name = 'Main_Function_Mode'
		self._function_modes = [self._l_function_mode, self._r_function_mode, self._m_function_mode]
	


	"""livid double press mechanism"""
	def set_shift_button(self, button):
		assert ((button == None) or (isinstance(button, MonoButtonElement)))
		if self._shift_button != None:
			self._shift_button.remove_value_listener(self._shift_value)
		self._shift_button = button
		if self._shift_button != None:
			self._shift_button.add_value_listener(self._shift_value)
	

	def _shift_value(self, value):
		self._shift_pressed = int(value != 0)
		if self._shift_pressed > 0:
			if (self._shift_pressed_timer + self._shift_thresh) > self._timer:
				if(self._host._active_client != None):
					if(self._host.is_enabled() != True):
						self._monomod_mode.set_mode(1)
					else:
						self._monomod_mode.set_mode(0)
			else:
				self._shift_pressed_timer = self._timer % 256
			if(self._cntrlr != None):
				self._cntrlr._monohm_shift(2)
		else:
			if(self._cntrlr != None):
				self._cntrlr._monohm_shift(0)
	

	"""shift/zoom methods"""
	def deassign_matrix(self):
		self._session_zoom.set_button_matrix(None)
		self._session_zoom2.set_button_matrix(None)
		self._session.set_stop_track_clip_buttons(None)
		self._session2.set_stop_track_clip_buttons(None)
		self._session_zoom_main.set_button_matrix(None)
		self._session_main.set_stop_track_clip_buttons(None)
		for column in range(4):
			self._mixer2.channel_strip(column).set_select_button(None)
			self._mixer2.return_strip(column).set_mute_button(None)
			self._mixer2.return_strip(column).set_solo_button(None)
			self._mixer2.return_strip(column).set_arm_button(None)
			self._mixer2.return_strip(column).set_crossfade_toggle(None)
			self._mixer2.return_strip(column).set_select_button(None)			#shouldn't this be somewhere else?
			self._mixer2.channel_strip(column).set_crossfade_toggle(None)
			self._mixer2.channel_strip(column).set_mute_button(None)
			self._mixer2.channel_strip(column).set_solo_button(None)
			self._mixer2.channel_strip(column).set_arm_button(None)
			for row in range(5):
				self._scene[row].clip_slot(column).set_launch_button(None)
				self._scene2[row].clip_slot(column).set_launch_button(None)
		for index in range(5):
			self._scene[index].set_launch_button(None)
			self._scene2[index].set_launch_button(None)
			self._scene_main[index].set_launch_button(None)
		self._session_zoom.set_nav_buttons(None, None, None, None)
		self._session_zoom2.set_nav_buttons(None, None, None, None)
		self._session_zoom_main.set_nav_buttons(None, None, None, None)
		self._session.set_track_bank_buttons(None, None)
		self._session.set_scene_bank_buttons(None, None)
		self._session2.set_track_bank_buttons(None, None)
		self._session2.set_scene_bank_buttons(None, None)
		self._session_main.set_track_bank_buttons(None, None)
		self._session_main.set_scene_bank_buttons(None, None)
		for column in range(8):
			self._mixer.channel_strip(column).set_select_button(None)
			self._mixer.channel_strip(column).set_crossfade_toggle(None)
			self._mixer.channel_strip(column).set_mute_button(None)
			self._mixer.channel_strip(column).set_solo_button(None)
			self._mixer.channel_strip(column).set_arm_button(None)
			for row in range(5):
				self._scene_main[row].clip_slot(column).set_launch_button(None)
			for row in range(8):
				self._grid[column][row].set_channel(0)
				self._grid[column][row].release_parameter()
				self._grid[column][row].use_default_message()
				self._grid[column][row].set_enabled(True)
				self._grid[column][row].set_on_off_values(127, 0)
				self._grid[column][row].send_value(0, True)
		self._send_reset.set_buttons(tuple(None for index in range(4)))
	

	def zoom_off(self):
		for column in range(4):
			self._grid[column][5].set_on_value(MUTE[self._rgb])
			self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
			self._grid[column][6].set_on_value(ARM[self._rgb])
			self._mixer.channel_strip(column).set_arm_button(self._grid[column][6])
			for row in range(5):
				self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])
			if(self._r_function_mode._mode_index in range(0,3)):
				self._grid[column + 4][5].set_on_value(MUTE[self._rgb])
				self._mixer2.channel_strip(column).set_mute_button(self._grid[column + 4][5])
				self._grid[column + 4][6].set_on_value(ARM[self._rgb])
				self._mixer2.channel_strip(column).set_arm_button(self._grid[column + 4][6])
				for row in range(5):
					self._scene2[row].clip_slot(column).set_launch_button(self._grid[column + 4][row])
			elif(self._r_function_mode._mode_index is 3):
				self._grid[column + 4][5].set_on_value(MUTE[self._rgb])
				self._mixer2.return_strip(column).set_mute_button(self._grid[column + 4][5])
				for row in range(5):
					self._grid[column + 4][row].send_value(USER1_COLOR[self._rgb], True)
					self._grid[column + 4][row].set_channel(RIGHT_USER1_CHANNEL)
					self._grid[column + 4][row].set_identifier(RIGHT_USER1_MAP[column][row])
					self._grid[column + 4][row].set_enabled(False)	 #this has to happen for translate to work
				#self._session_zoom2.set_ignore_buttons(True)
		if(self._r_function_mode._mode_index is 0):
			for index in range(4):
				self._grid[index + 4][7].send_value(SEND_RESET[self._rgb], True)
			self._send_reset.set_buttons(tuple(self._grid[index + 4][7] for index in range(4)))
	

	def zoom_off_m(self):
		self.deassign_dials()
		for column in range(8):
			self._grid[column][5].set_on_value(MUTE[self._rgb])
			self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
			self._grid[column][6].set_on_value(ARM[self._rgb])
			self._mixer.channel_strip(column).set_arm_button(self._grid[column][6])
			for row in range(5):
				self._scene_main[row].clip_slot(column).set_launch_button(self._grid[column][row])
		#self._session_zoom.set_button_matrix(self._matrix)
	

	def zoom_left(self):
		track_stop_buttons = []
		track_stop_buttons2 = []
		for index in range(4):
			self._grid[index][6].set_off_value(TRACK_STOP[self._rgb])
			track_stop_buttons.append(self._grid[index][6])
			self._grid[index + 4][6].set_off_value(TRACK_STOP[self._rgb])
			track_stop_buttons2.append(self._grid[index + 4][6])
		for index in range(5):
			self._grid[7][index].set_off_value(SCENE_LAUNCH[self._rgb])
			self._scene[index].set_launch_button(self._grid[7][index])
		self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		self._session2.set_stop_track_clip_buttons(tuple(track_stop_buttons2))
		self._session_zoom.set_button_matrix(self._matrix)
		self._grid[0][5].set_on_value(RECORD[self._rgb])
		self._transport.set_record_button(self._grid[0][5])
		self._grid[1][5].set_on_value(OVERDUB[self._rgb])
		self._transport.set_overdub_button(self._grid[1][5])
		self._grid[2][5].set_on_value(LOOP[self._rgb])
		self._transport.set_loop_button(self._grid[2][5])
		self._grid[3][5].set_on_value(STOP_ALL[self._rgb])	
		self._session.set_stop_all_clips_button(self._grid[3][5])
		for index in range(4):
			self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True)
		self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4)))
		for index in range(4):
			self._grid[index + 4][7].set_off_value(DEVICE_SELECT[self._rgb])
		self._device_selector.assign_buttons(tuple(self._grid[index + 4][7] for index in range(4)), 4)
	

	def zoom_right(self):
		track_stop_buttons = []
		track_stop_buttons2 = []
		for index in range(4):
			self._grid[index][6].set_off_value(TRACK_STOP[self._rgb])
			track_stop_buttons.append(self._grid[index][6])
		for index in range(5):
			self._grid[7][index].set_off_value(SCENE_LAUNCH[self._rgb])
			self._scene2[index].set_launch_button(self._grid[7][index])
		self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		if(self._r_function_mode._mode_index < 3):
			for index in range(4):
				self._grid[index + 4][6].set_off_value(TRACK_STOP[self._rgb])
				track_stop_buttons2.append(self._grid[index + 4][6])
			self._session2.set_stop_track_clip_buttons(tuple(track_stop_buttons2))
		self._session_zoom2.set_button_matrix(self._matrix)
		self._grid[0][5].set_on_value(RECORD[self._rgb])
		self._transport.set_record_button(self._grid[0][5])
		self._grid[1][5].set_on_value(OVERDUB[self._rgb])
		self._transport.set_overdub_button(self._grid[1][5])
		self._grid[2][5].set_on_value(LOOP[self._rgb])
		self._transport.set_loop_button(self._grid[2][5])
		self._grid[3][5].set_on_value(STOP_ALL[self._rgb])
		self._session.set_stop_all_clips_button(self._grid[3][5])
		for index in range(4):
			self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True)
		self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4)))
		for index in range(4):
			self._grid[index][7].set_off_value(DEVICE_SELECT[self._rgb])
		self._device_selector.assign_buttons(tuple(self._grid[index][7] for index in range(4)), 0)
	

	def zoom_main(self):
		track_stop_buttons = []
		for index in range(8):
			self._grid[index][6].set_on_value(TRACK_STOP[self._rgb])
			track_stop_buttons.append(self._grid[index][6])
		for index in range(5):
			self._grid[7][index].set_on_value(SCENE_LAUNCH[self._rgb])
			self._scene_main[index].set_launch_button(self._grid[7][index])
		self._session_main.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		self._session_zoom_main.set_button_matrix(self._matrix)
		self._grid[0][5].set_on_value(RECORD[self._rgb])
		self._transport.set_record_button(self._grid[0][5])
		self._grid[1][5].set_on_value(OVERDUB[self._rgb])
		self._transport.set_overdub_button(self._grid[1][5])
		self._grid[2][5].set_on_value(LOOP[self._rgb])
		self._transport.set_loop_button(self._grid[2][5])
		self._grid[3][5].set_on_value(STOP_ALL[self._rgb])	
		self._session.set_stop_all_clips_button(self._grid[3][5])
		for index in range(4):
			self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True)
		self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4)))
		for index in range(4):
			self._grid[index + 4][7].set_off_value(DEVICE_SELECT[self._rgb])
		self._device_selector.assign_buttons(tuple(self._grid[index + 4][7] for index in range(4)), 4)
	


	"""function mode callbacks"""
	def l_function_update(self):
		mode = self._l_function_mode._mode_index
		#if(self._l_function_mode.is_enabled() is False):
		#	self._l_function_mode.set_mode_buttons(None)
		if(self._l_function_mode.is_enabled() is True):
			if(len(self._l_function_mode._modes_buttons) is 0):
				for index in range(4):
					self._mixer.channel_strip(index).set_select_button(None)
				buttons = []
				for index in range(4):
					buttons.append(self._grid[index][7]) 
				self._l_function_mode.set_mode_buttons(tuple(buttons))
			if(self._shift_mode._mode_index is 2):
				for index in range(4):
					if(mode != index):
						self._grid[index][7].turn_off()
					else:
						self._grid[index][7].turn_on()
		if(mode is 0):
			self.assign_device_dials()
			self.show_message('Mixer Split:Dials Device Mode')
		elif(mode is 1):
			self.assign_send_dials()
			self.show_message('Mixer Split:Dials Send Mode')
		elif(mode is 2):
			self.assign_split_volume_dials()
			self.show_message('Mixer Split:Dials Volume Mode')
		elif(mode is 3):
			self.assign_user_dials()
			self.show_message('Mixer Split:Dials User Map Mode')
	

	def r_function_update(self):
		mode = self._r_function_mode._mode_index
		#if(self._r_function_mode.is_enabled() is False):
		#	self._r_function_mode.set_mode_buttons(None)
			#self._session2.set_show_highlight(False)
			#self._session._highlighting_callback(self._session._track_offset, self._session._scene_offset, 4, 5, 1)
		if(self._r_function_mode.is_enabled() is True):
			if(len(self._r_function_mode._modes_buttons) is 0):
				for index in range(4):
					self._mixer2.channel_strip(index).set_select_button(None)
				buttons = []
				for index in range(4):
					buttons.append(self._grid[index + 4][7]) 
				self._r_function_mode.set_mode_buttons(tuple(buttons))
			if(self._shift_mode._mode_index is 3):
				for index in range(4):
					if(mode != index):
						self._grid[index + 4][7].turn_off()
					else:
						self._grid[index + 4][7].turn_on()
		self._session2.set_offsets(int(self._mem[mode]), self._session2._scene_offset)
		self.show_message('Mixer Split: Track Offset' + str(RIGHT_MODE_OFFSETS[mode]))
	

	def m_function_update(self):
		mode = self._m_function_mode._mode_index
		#if(self._m_function_mode.is_enabled() is False):
		#	self._m_function_mode.set_mode_buttons(None)
			#self._session.set_show_highlight(False)
			#self._session2.set_show_highlight(False)
			#self._session_main._highlighting_callback(self._session_main._track_offset, self._session_main._scene_offset, 8, 5, 1)
		if(self._m_function_mode.is_enabled() is True):
			if(len(self._m_function_mode._modes_buttons) is 0):
				for index in range(8):
					self._mixer.channel_strip(index).set_select_button(None)
				buttons = []
				for index in range(4):
					buttons.append(self._grid[index][7]) 
				self._m_function_mode.set_mode_buttons(tuple(buttons))
			if(self._shift_mode._mode_index is 4):
				for index in range(4):
					if(mode != index):
						self._grid[index][7].turn_off()
					else:
						self._grid[index][7].turn_on()
		if(mode is 0):
			self.assign_device_dials()
			self.show_message('Mixer Linked:Dials Device Mode')
		elif(mode is 1):
			self.assign_send_dials()
			self.show_message('Mixer Linked:Dials Send Mode')
		elif(mode is 2):
			self.assign_volume_dials()
			self.show_message('Mixer Linked:Dials Volume Mode')
		elif(mode is 3):
			self.assign_user_dials()
			self.show_message('Mixer Linked:Dials User Map Mode')
	

	def shift_update(self):
		self._clutch_device_selection = True
		#self.allow_updates(False)
		#if(not self._in_build_midi_map):
		#	self.set_suppress_rebuild_requests(True)
		self.deassign_channel_select_buttons()
		self.deassign_matrix()
		self.deassign_menu()
		if(self._monomod_mode._mode_index is 0):		#if monomod is not on
			if(self._shift_mode._mode_index is 0):							#if no shift is pressed
				self._shift_mode._mode_toggle1.turn_off()
				self._shift_mode._mode_toggle2.turn_off()
				if(self.split_mixer() is False):
					self.set_split_mixer(True)
				for zoom in self._zooms:
					zoom._on_zoom_value(0)
				self.zoom_off()
				self._device_selector.set_enabled(False)
				for mode in self._function_modes:
					mode.set_enabled(False)
				self.assign_channel_select_buttons()
				#self._recalculate_selected_channel()
				#self.assign_transport_to_menu()
				self.assign_session_nav_to_menu()
				self.l_function_update()
				self.r_function_update()
				self.assign_crossfader()
				self.set_highlighting_session_component(self._session)
				self._session._do_show_highlight()	
				#self._session.set_show_highlight(True)
			elif(self._shift_mode._mode_index is 1):						#if no shift is pressed, but mixer is linked
				self._shift_mode._mode_toggle1.turn_on()
				self._shift_mode._mode_toggle2.turn_on()
				if(self.split_mixer() is True):
					self.set_split_mixer(False)
				for zoom in self._zooms:
					zoom._on_zoom_value(0)
				self.zoom_off_m()
				self._device_selector.set_enabled(False)
				for mode in self._function_modes:
					mode.set_enabled(False)
				self.assign_main_channel_select_buttons()
				self.assign_session_main_nav_to_menu()
				self.m_function_update()
				self.assign_crossfader()
				self.set_highlighting_session_component(self._session_main)
				self._session_main._do_show_highlight()
			elif(self._shift_mode._mode_index > 1):						#if a shift is pressed
				self.assign_device_nav_to_menu()
				self.deassign_channel_select_buttons()
				if(self._shift_mode._mode_index is 2):					#if shift left
					self._shift_mode._mode_toggle1.turn_on()
					self.zoom_left()
					self._session_zoom._on_zoom_value(1)
					self._session.set_enabled(True) #this is a workaround so that the stop buttons still function
					self._l_function_mode.set_enabled(True)
					self.set_highlighting_session_component(self._session)
					self._session._do_show_highlight()
				elif(self._shift_mode._mode_index is 3):				#if shift right
					self._shift_mode._mode_toggle2.turn_on()
					self.zoom_right()
					self._session_zoom2._on_zoom_value(1)
					self._session2.set_enabled(True)  #this is a workaround so that the stop buttons still function
					self._r_function_mode.set_enabled(True)
					self.assign_master_fader()
					if(self._r_function_mode._mode_index < 4):
						self.set_highlighting_session_component(self._session2)
						self._session2._do_show_highlight()
				elif(self._shift_mode._mode_index is 4):				#if either shift pressed while mixer is linked
					self._shift_mode._mode_toggle1.turn_on()
					self._shift_mode._mode_toggle2.turn_on()
					self.zoom_main()
					self._session_zoom_main._on_zoom_value(1)
					self._session_main.set_enabled(True) #this is a workaround so that the stop buttons still function
					self._m_function_mode.set_enabled(True)
					self.assign_master_fader()
					self.set_highlighting_session_component(self._session_main)
					self._session_main._do_show_highlight()
				self._device_selector.set_enabled(True)
		self.allow_updates(True)
		#self.set_suppress_rebuild_requests(False)
		self._clutch_device_selection = False
		if(self._shift_mode._mode_index < 2):
			self._monobridge._send('touch', 'off')
		else:
			self._monobridge._send('touch', 'on')
	

	def monomod_mode_update(self):
		if (self._monomod_mode._mode_index == 0) or (self._host._active_client == None):
			self._host.set_enabled(False)
			self._host._set_button_matrix(None)
			self._host._set_nav_buttons(None)
			self._host._set_lock_button(None)
			self._host._set_alt_button(None)
			self._host._set_shift_button(None)
			self._livid.turn_off()
			self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r)
			self._shift_mode.update()
			#self._session._reassign_scenes()
			
		elif(self._monomod_mode._mode_index == 1):
			self._livid.turn_on()
			self.deassign_matrix()
			self.deassign_menu()
			self._monomod.reset()
			self._host._set_button_matrix(self._monomod)
			self._host._set_nav_buttons(self._menu[0:4])
			self._host._set_lock_button(self._shift_l)
			self._host._set_alt_button(self._shift_r)
			self._host._set_shift_button(self._livid)
			self._shift_mode.set_mode_toggle(None, None)
			self._host.set_enabled(True)
			self._shift_mode.update()
			#self.show_message('Monomod grid enabled')
	

	"""left control management methods"""
	def deassign_dials(self):
		for index in range(8):
			self._dial[index].use_default_message()
			self._dial[index].release_parameter()
			self._dial[index].set_enabled(True)
		if(self._device._parameter_controls != None):
			for control in self._device._parameter_controls:
				control.release_parameter()
			self._device._parameter_controls = None
		self._mixer.selected_strip().set_send_controls(None)
		self._mixer.selected_strip().set_volume_control(None)
		for track in range(4):
			self._mixer.channel_strip(track).set_volume_control(None)
			self._mixer.channel_strip(track+4).set_volume_control(None)
			self._mixer2.channel_strip(track).set_volume_control(None)
			self._mixer2.return_strip(track).set_volume_control(None)
	

	def assign_device_dials(self):
		self._ohm_type = OHM_TYPE[0]
		self._ohm = OHM_VALUE[0]
		self.deassign_dials()
		self._device.set_enabled(True)
		device_param_controls = []
		for index in range(8):
			device_param_controls.append(self._dial[index])
		self._device.set_parameter_controls(tuple(device_param_controls))
		self._mixer.selected_strip().set_volume_control(self._fader[0])
	

	def assign_send_dials(self):
		self._ohm_type = OHM_TYPE[1]
		self._ohm = OHM_VALUE[1]
		self.deassign_dials()
		dials = []
		for index in range(4):
			dials.append(self._dial[index])
		for index in range(4):
			if(self._mixer2.return_strip(index)):
				self._mixer2.return_strip(index).set_volume_control(self._dial[index + 4])
		self._mixer.selected_strip().set_send_controls(tuple(dials))
		self._mixer.selected_strip().set_volume_control(self._fader[0])
	

	def assign_volume_dials(self):
		self._ohm_type = OHM_TYPE[2]
		self._ohm = OHM_VALUE[2]
		self.deassign_dials()
		for track in range(8):
			self._mixer.channel_strip(track).set_volume_control(self._dial[track])
		self._mixer.selected_strip().set_volume_control(self._fader[0])
	

	def assign_split_volume_dials(self):
		self._ohm_type = OHM_TYPE[2]
		self._ohm = OHM_VALUE[2]
		self.deassign_dials()
		for track in range(4):
			self._mixer.channel_strip(track).set_volume_control(self._dial[track])
			self._mixer2.channel_strip(track).set_volume_control(self._dial[track+4])
		self._mixer.selected_strip().set_volume_control(self._fader[0])
	

	def assign_user_dials(self):
		self._ohm_type = OHM_TYPE[3]
		self._ohm = OHM_VALUE[3]
		self.deassign_dials()
		for index in range(8):
			self._dial[index].set_channel(L_USER_DIAL_CHAN)
			self._dial[index].set_identifier(L_USER_DIAL_MAP[index])
			self._dial[index].set_enabled(False)
		self._mixer.selected_strip().set_volume_control(self._fader[0])
	


	"""menu button management methods"""
	def deassign_menu(self):
		self._device.set_lock_button(None)
		self._device.set_on_off_button(None)
		self._device_navigator.set_device_nav_buttons(None, None)	
		self._device.set_bank_nav_buttons(None, None)
		self._transport.set_play_button(None)	
		self._transport.set_record_button(None) 
		self._transport.set_stop_button(None)
		self._transport.set_loop_button(None)	
		self._transport.set_overdub_button(None)	
		self._session.set_stop_all_clips_button(None)
		self._transport.set_play_button(None)	
		self._transport.set_stop_button(None)
		self._session_main.set_track_bank_buttons(None, None)
		self._session_main.set_scene_bank_buttons(None, None)
	

	def assign_device_nav_to_menu(self):
		self._device_navigator.set_device_nav_buttons(self._menu[2], self._menu[3]) 
		self._device.set_bank_nav_buttons(self._menu[0], self._menu[1])
	

	def assign_transport_to_menu(self):
		self._transport.set_play_button(self._menu[0])	
		self._transport.set_record_button(self._menu[2])
		self._transport.set_stop_button(self._menu[1])
		session.set_stop_all_clips_button(self._menu[3])
	

	def assign_session_nav_to_menu(self):
		self._session.set_track_bank_buttons(self._menu[3], self._menu[2])
		self._session.set_scene_bank_buttons(self._menu[1], self._menu[0])
	

	def assign_monomod_shift_to_menu(self):
		self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[2]) 
		self._device.set_bank_nav_buttons(self._menu[1], self._menu[0])
	

	def assign_session_bank_to_menu(self):
		self._session.set_track_bank_buttons(self._menu[3], self._menu[2])
		self._session.set_scene_bank_buttons(self._menu[1], self._menu[0])
	

	def assign_session2_bank_to_menu(self):
		self._session2.set_track_bank_buttons(self._menu[3], self._menu[2])
		self._session2.set_scene_bank_buttons(self._menu[1], self._menu[0])
	

	def assign_session_main_nav_to_menu(self):
		self._session_main.set_track_bank_buttons(self._menu[3], self._menu[2])
		self._session_main.set_scene_bank_buttons(self._menu[1], self._menu[0])
	


	"""channel selection management methods"""
	def deassign_channel_select_buttons(self):
		for index in range(8):
			if(self._mixer.channel_strip(index)):
				self._mixer.channel_strip(index).set_select_button(None)
			self._grid[index][7].release_parameter()
		for index in range(4):
			self._mixer2.channel_strip(index).set_select_button(None)
			self._mixer2.return_strip(index).set_select_button(None)
			self._mixer2.master_strip().set_select_button(None)
			self._grid[index + 4][7].release_parameter()
	

	def assign_channel_select_buttons(self):
		for index in range(4):
			#if(self._mixer.channel_strip(index)):
			self._grid[index][7].set_on_off_values(127, 0)
			self._mixer.channel_strip(index).set_select_button(self._grid[index][7])
		if(self._r_function_mode._mode_index < 3):
			for index in range(4):
				self._grid[index][7].set_on_off_values(127, 0)
				self._mixer2.channel_strip(index).set_select_button(self._grid[index + 4][7])	
		else:
			for index in range(4):
				self._grid[index][7].set_on_off_values(1, 0)
				self._mixer2.return_strip(index).set_select_button(self._grid[index + 4][7])
	

	def assign_return_select_buttons(self):
		for index in range(4):
			self._grid[index + 4][7].set_off_value(0) 
			if(self._mixer.channel_strip(index)):
				self._grid[index + 4][7].set_on_value(1)
				self._mixer.channel_strip(index).set_select_button(self._grid[index + 4][7])
	

	def assign_l_channel_select_buttons(self):
		self._mixer.set_select_buttons(None, None)
		self._session.set_select_buttons(None, None)
		for index in range(4):
			self._grid[index][7].set_off_value(0)
			if(self._mixer.channel_strip(index)):
				self._mixer.channel_strip(index).set_select_button(self._grid[index][7])
	

	def assign_r_channel_select_buttons(self):
		self._mixer2.set_select_buttons(None, None)
		self._session2.set_select_buttons(None, None)
		for index in range(4):
			self._grid[index + 4][7].set_off_value(0)
			if(self._mixer2.channel_strip(index)):
				self._mixer2.channel_strip(index).set_select_button(self._grid[index + 4][7])
	

	def assign_main_channel_select_buttons(self):
		for index in range(8):
			self._grid[index][7].set_off_value(0)
			if(self._mixer.channel_strip(index)):
				self._grid[index][7].set_on_value(127)
				self._mixer.channel_strip(index).set_select_button(self._grid[index][7])
	

	def assign_master_fader(self):
		self._mixer.set_crossfader_control(None)
		self._mixer.master_strip().set_volume_control(self._fader[1])
	

	def assign_crossfader(self):
		self._mixer.master_strip().set_volume_control(None)
		self._mixer.set_crossfader_control(self._fader[1])
	


	"""called on timer"""
	def update_display(self):
		super(BlockMod, self).update_display()
		if(self._timer == 0):
			self._shift_pressed_timer = -12
	

	def strobe(self):
		if(self._ohm_type != 'static'):
			if(self._ohm_type is 'pulse'):
				self._ohm = int(math.fabs(((self._timer * 8) % 64) -32) +32)
			if(self._ohm_type is 'up'):
				self._ohm = int(((self._timer * 4) % 64) + 16)
			if(self._ohm_type is 'down'):
				self._ohm = int(math.fabs(int(((self._timer * 4) % 64) - 64)) + 16)
		self._send_midi(tuple([176, 63, int(self._ohm)]))
		self._send_midi(tuple([176, 31, int(self._ohm)]))	
	

	def handle_sysex(self, midi_bytes):
		pass
	

	def _on_session_offset_changes(self):
		if self._r_function_mode._mode_index in range(0,4):
			self._mem[int(self._r_function_mode._mode_index)] = self._session2.track_offset()
	



#	a
Exemple #42
0
class MidiFighterTwister(ControlSurface):
    __module__ = __name__
    __doc__ = "MidiFighterTwister class"

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

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

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

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

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

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

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

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

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

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

    def bank_buttons_dummy(self):
        pass

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

    def dispatch_current_song_time_listener(self):
        self.sequencer_light_follows_beat()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

# Clip page setion

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # Update light of active pad
        #self._send_midi((self.light_midi_channel, light_encoder_cc, 63))
        try:
            self.current_clip = self.song().view.highlighted_clip_slot.clip
            self.current_clip.is_midi_clip
            self._sequencer_update_notes_to_light()
        except AttributeError:
            pass
Exemple #43
0
	def _setup_session_control(self):
		is_momentary = True		  
		right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 43)
		left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 42)
		up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 44)
		down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 45)
		right_button.name = 'Bank_Select_Right_Button'
		left_button.name = 'Bank_Select_Left_Button'
		up_button.name = 'Bank_Select_Up_Button'
		down_button.name = 'Bank_Select_Down_Button'
		global session
		session = SessionComponent(4, 4)
		session.name = 'Session_Control'
		session.set_track_bank_buttons(right_button, left_button)
		session.set_scene_bank_buttons(down_button, up_button)
		self._session = session
		matrix = ButtonMatrixElement()
		matrix.name = 'Button_Matrix'
		scene_launch_notes = [33,34,35,36]
		scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, scene_launch_notes[index]) for index in range(4) ]
		#track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(4) ]
		for index in range(len(scene_launch_buttons)):
			scene_launch_buttons[index].name = 'Scene_'+ str(index) + '_Launch_Button'
		#for index in range(len(track_stop_buttons)):
		#	 track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button'
		#stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81)
		#stop_all_button.name = 'Stop_All_Clips_Button'
		#self._session.set_stop_all_clips_button(stop_all_button)
		#self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		#self._session.set_stop_clip_value(2)
		button_notes = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32]
		for scene_index in range(4):
			scene = session.scene(scene_index)
			scene.name = 'Scene_' + str(scene_index)
			button_row = []
			scene.set_launch_button(scene_launch_buttons[scene_index])
			#scene.set_triggered_value(2)
			for track_index in range(4):
				button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, (track_index * 4) + scene_index + 1)
				button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button'
				button_row.append(button)
				clip_slot = scene.clip_slot(track_index)
				clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index)
				#clip_slot.set_triggered_to_play_value(2)
				#clip_slot.set_triggered_to_record_value(4)
				clip_slot.set_stopped_value(0)
				clip_slot.set_started_value(64)
				#clip_slot.set_recording_value(3)
				clip_slot.set_launch_button(button)
			matrix.add_row(tuple(button_row))
		#self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67))
		session.selected_scene().name = 'Selected_Scene'
		#session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
		#session_zoom = SessionZoomingComponent(session)
		#session_zoom.name = 'Session_Overview'
		#session_zoom.set_button_matrix(matrix)
		#session_zoom.set_zoom_button(self._shift_button)
		#session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button)
		#session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
		#session_zoom.set_stopped_value(0)
		#session_zoom.set_selected_value(127)
		self.set_highlighting_session_component(session)
		session.set_mixer(mixer)
		return None #return session
Exemple #44
0
class AumPC40(APC):
    __doc__ = " Script for Akai's APC40 Controller "

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

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

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

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

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

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

    def _product_model_id_byte(self):
        return 115

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

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

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

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

    """m4l bridge"""

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

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

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

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

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

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

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

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

    def flash(self):
        if (self.flash_status > 0):
            for row in range(8):
                for column in range(8):
                    button = self._monomod.get_button(column, row)
                    if (button._flash_state > 0):
                        button.flash(self._timer)
    def _setup_session_control(self):
        self.session = CustomSessionComponent(self.box_width, self.box_height, self) # subclass from _Framework
        is_momentary = True # what exactly does this do in the _Framework?
        if up_button_note_number >= 0 and down_button_note_number >= 0: # opt in enable UP/DOWN nav
            up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, up_button_note_number) 
            up_button.name = 'Bank_Select_Up_Button' # sure, why not
            down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, down_button_note_number)
            down_button.name = 'Bank_Select_Down_Button' #sure, why not
            self.session.set_scene_bank_buttons(down_button, up_button)
        if right_button_note_number >= 0 and left_button_note_number >= 0: # opt in enable LEFT/RIGHT nav
            right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, right_button_note_number)
            right_button.name = 'Bank_Select_Right_Button' #sure, why not
            left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, left_button_note_number)
            left_button.name = 'Bank_Select_Left_Button' #sure, why not
            self.session.set_track_bank_buttons(right_button, left_button)
        self.session.name = 'Session_Control' #sure, why not
        matrix = ButtonMatrixElement() # @todo subclass this via established new patterns
        matrix.name = 'Button_Matrix' #sure, why not
        # I loop a little different. The goal is readbility, flexibility, and the web app...incase you did not notice yet
        if len(scene_launch_notes) > 0 and len(scene_launch_notes) == self.box_height: # logic check have launch notes and scene = box height
            for index in range(self.box_height): 
                self.session.scene(index).set_launch_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, scene_launch_notes[index])) 
        else :
            self.log_message("..::|| Scene launch not in use or error on case of use. Modern.DJ ||::..")
        if len(stop_track_buttons) >0 and len(stop_track_buttons) == self.box_width: #logic check have track stop assignments and 
            track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, stop_track_buttons[index]) for index in range(len(stop_track_buttons))]
            for index in range(len(track_stop_buttons)):
                track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button' # sure, why not
            self.session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
        else :
            self.log_message("..::|| Stop notes not in use or error found Modern.DJ ||::..")
        # Check for stop all clips option
        if stop_all_clips >=0 : 
            self.session.set_stop_all_clips_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, stop_all_clips))
        # creating the matrix of buttons from the launch_button_list (tuple)
        launch_button_list_len = len(launch_button_list) # var used multiple times. This is a performance modification
        if (self.box_height*self.box_width) ==  launch_button_list_len : # check box size against number of button vars sent
            launch_ctr = launch_button_list_len -1 # decrement for zero offset in list/tuple
            launch_button_list.reverse() #reverse list from human readable for decrement use (performance tweak)
            ## check for use of RGB
            if use_velocity_for_RGB != 1: # if not enabled use these defaults
                self.log_message("..::|| RGB not in effect assigning defaults ||::..")
                self.clip_loaded_stopped = 1
                self.clip_currently_playing = 127
                self.clip_triggered_to_play = 64
            else: # yes RGB in effect...assign per the parameters script
                self.clip_loaded_stopped = clip_loaded_stopped
                self.clip_currently_playing = clip_currently_playing
                self.clip_triggered_to_play = clip_triggered_to_play

            for scene_index in range(self.box_height): # loop on the notes matrix
                scene = self.session.scene(scene_index) # part of the martix built, think rows
                scene.name = 'Scene_' + str(scene_index) # sure, why not
                button_row = [] # create recepticle
                # loop across the tracks
                for track_index in range(self.box_width): 
                    button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, launch_button_list[launch_ctr]) # button instance for _Framework
                    launch_ctr = launch_ctr -1# decrement is faster than increment
                    button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button' # sure, why not
                    button_row.append(button) # add to our growing list
                    clip_slot = scene.clip_slot(track_index) # clips slot and buttons are not the same thing, this aligns these ideas in the red box
                    clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index) # sure, why not
                    # assign the button and and status in th refrech update
                    clip_slot.set_stopped_value(self.clip_loaded_stopped ) # this number is sent back to the machine allowing diff colors for stopped
                    clip_slot.set_started_value(self.clip_currently_playing) # this number is sent back to the machine allowing diff colors for started/is-playing
                    clip_slot.set_triggered_to_play_value(self.clip_triggered_to_play) # this number is sent back to the machine allowing diff colors for cued, will play next                   
                    clip_slot.set_launch_button(button) # part of the slit+button = go time paradigm
                matrix.add_row(tuple(button_row)) # close out the matrix build. @todo - possible subclass here?
        else : # log message
            self.log_message("..::|| Number of notes defined does not match box height and width Modern.DJ ||::..")
        ''' live 9 only
        self.set_highlighting_session_component(self.session) # new for live9 -- this is for the box. via aumhaa/bitnomad
        '''
        return None
Exemple #46
0
 def _setup_session_control(self):
     is_momentary = True
     self._shift_button = FlashingButtonElement(is_momentary,
                                                MIDI_NOTE_TYPE, 0, 98, self)
     right_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                          96, self)
     self._right_button = right_button
     left_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                         97, self)
     self._left_button = left_button
     up_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94,
                                       self)
     self._up_button = up_button
     down_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                         95, self)
     self._down_button = down_button
     right_button.name = 'Bank_Select_Right_Button'
     left_button.name = 'Bank_Select_Left_Button'
     up_button.name = 'Bank_Select_Up_Button'
     down_button.name = 'Bank_Select_Down_Button'
     self._session = PedaledSessionComponent(8, 5)
     self._session.name = 'Session_Control'
     self._session.set_track_bank_buttons(right_button, left_button)
     self._session.set_scene_bank_buttons(down_button, up_button)
     matrix = ButtonMatrixElement()
     self._matrix = matrix  # added a
     matrix.name = 'Button_Matrix'
     scene_launch_buttons = [
         ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82))
         for index in range(5)
     ]
     track_stop_buttons = [
         FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52,
                               self) for index in range(8)
     ]
     self._track_stop_buttons = track_stop_buttons  # added a
     for index in range(len(scene_launch_buttons)):
         scene_launch_buttons[index].name = 'Scene_' + str(
             index) + '_Launch_Button'
     for index in range(len(track_stop_buttons)):
         track_stop_buttons[index].name = 'Track_' + str(
             index) + '_Stop_Button'
     stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81)
     stop_all_button.name = 'Stop_All_Clips_Button'
     self._session.set_stop_all_clips_button(stop_all_button)
     self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
     self._session.set_stop_track_clip_value(2)
     for scene_index in range(5):
         scene = self._session.scene(scene_index)
         scene.name = 'Scene_' + str(scene_index)
         button_row = []
         scene.set_launch_button(scene_launch_buttons[scene_index])
         scene.set_triggered_value(2)
         for track_index in range(8):
             button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                            track_index, (scene_index + 53),
                                            self)
             button.name = str(track_index) + '_Clip_' + str(
                 scene_index) + '_Button'
             button_row.append(button)
             clip_slot = scene.clip_slot(track_index)
             clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                 scene_index)
             clip_slot.set_triggered_to_play_value(2)
             clip_slot.set_triggered_to_record_value(4)
             clip_slot.set_stopped_value(5)
             clip_slot.set_started_value(1)
             clip_slot.set_recording_value(3)
             clip_slot.set_launch_button(button)
         matrix.add_row(tuple(button_row))
     self._session.set_slot_launch_button(
         ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67))
     self._session.selected_scene().name = 'Selected_Scene'
     self._session.selected_scene().set_launch_button(
         ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
     self._session_zoom = SessionZoomingComponent(self._session)
     self._session_zoom.name = 'Session_Overview'
     self._session_zoom.set_button_matrix(matrix)
     self._session_zoom.set_zoom_button(self._shift_button)
     self._session_zoom.set_nav_buttons(up_button, down_button, left_button,
                                        right_button)
     self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
     self._session_zoom.set_stopped_value(3)
     self._session_zoom.set_selected_value(5)
     return None
Exemple #47
0
	def __init__(self, c_instance):
		live = Live.Application.get_application()
		self._live_major_version = live.get_major_version()
		self._live_minor_version = live.get_minor_version()
		self._live_bugfix_version = live.get_bugfix_version()
		self._mk2 = Settings.DEVICE == 'Launchpad mk2'
		if self._mk2:
			self._skin = Skin('Launchpad mk2')
			self._side_notes = (89, 79, 69, 59, 49, 39, 29, 19)
			self._drum_notes = (20, 30, 31, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126)
		else:
			self._skin = Skin('Launchpad')
			self._side_notes = (8, 24, 40, 56, 72, 88, 104, 120)
			self._drum_notes = (41, 42, 43, 44, 45, 46, 47, 57, 58, 59, 60, 61, 62, 63, 73, 74, 75, 76, 77, 78, 79, 89, 90, 91, 92, 93, 94, 95, 105, 106, 107)
			
			
		ControlSurface.__init__(self, c_instance)
	
	
		with self.component_guard():
			self._suppress_send_midi = True
			self._suppress_session_highlight = True

			is_momentary = True
			if self._mk2:
				self._suggested_input_port = 'Launchpad'
				self._suggested_output_port = 'Launchpad'
			else:
				self._suggested_input_port = 'Launchpad MK2'
				self._suggested_output_port = 'Launchpad MK2'
				
			self._control_is_with_automap = False
			self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16)
			self._user_byte_write_button.name = 'User_Byte_Button'
			self._user_byte_write_button.send_value(1)
			self._user_byte_write_button.add_value_listener(self._user_byte_value)
			self._wrote_user_byte = False
			self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143
			matrix = ButtonMatrixElement()
			matrix.name = 'Button_Matrix'
			for row in range(8):
				button_row = []
				for column in range(8):
					if self._mk2:
						# for mk2 buttons are assigned "top to bottom"
 						midi_note = (81 - (10 * row)) + column
					else:
						midi_note = row * 16 + column
					button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, midi_note, self._skin.off)
					button.name = str(column) + '_Clip_' + str(row) + '_Button'
					button_row.append(button)

				matrix.add_row(tuple(button_row))

			self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False)
			self._config_button.add_value_listener(self._config_value)
			top_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, self._skin.off) for index in range(8)]
			side_buttons = [ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, self._side_notes[index], self._skin.off) for index in range(8)]
			top_buttons[0].name = 'Bank_Select_Up_Button'
			top_buttons[1].name = 'Bank_Select_Down_Button'
			top_buttons[2].name = 'Bank_Select_Left_Button'
			top_buttons[3].name = 'Bank_Select_Right_Button'
			top_buttons[4].name = 'Session_Button'
			top_buttons[5].name = 'User1_Button'
			top_buttons[6].name = 'User2_Button'
			top_buttons[7].name = 'Mixer_Button'
			side_buttons[0].name = 'Vol_Button'
			side_buttons[1].name = 'Pan_Button'
			side_buttons[2].name = 'SndA_Button'
			side_buttons[3].name = 'SndB_Button'
			side_buttons[4].name = 'Stop_Button'
			side_buttons[5].name = 'Trk_On_Button'
			side_buttons[6].name = 'Solo_Button'
			side_buttons[7].name = 'Arm_Button'
			self._osd = M4LInterface()
			self._osd.name = "OSD"
			self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self._osd, self, self._skin)
			self._selector.name = 'Main_Modes'
			self._do_combine()
			for control in self.controls:
				if isinstance(control, ConfigurableButtonElement):
					control.add_value_listener(self._button_value)

			self.set_highlighting_session_component(self._selector.session_component())
			self._suppress_session_highlight = False

			self.log_message("LaunchPad95 Loaded !")
Exemple #48
0
class OhmModesHH(ControlSurface):
	__module__ = __name__
	__doc__ = " OhmModes controller script, custom script for Herbie Hancock by amounra "


	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		with self.component_guard():
			self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= OhmModesHH2 log opened =--------------") # Writes message into Live's main log file. This is a ControlSurface method.
			#self.set_suppress_rebuild_requests(True) # Turn off rebuild MIDI map until after we're done setting up
			self.revision = 'HH'
			self.flash_status = 1
			self._backlight = 127
			self._backlight_type = 'static'
			self._ohm = 127
			self._ohm_type = 'static'
			self._pad_translations = PAD_TRANSLATION
			self._rgb = 1
			self._keys_octave = 5
			self._keys_scale = 0
			self._tempo_buttons = None
			self._scene_indexes = [[[0,0],  [8, 0], [16, 0], [24, 0], [32, 0],  [40, 0]], 
									[[0,0],  [8, 0], [16, 0], [24, 0], [32, 0],  [40, 0]], 
									[[0,0],  [8, 0], [16, 0], [24, 0], [32, 0],  [40, 0]], 
									[[0,0],  [8, 0], [16, 0], [24, 0], [32, 0],  [40, 0]], 
									[[0,0],  [8, 0], [16, 0], [24, 0], [32, 0],  [40, 0]]]
			self._scene_bank = 0
			self._bank_is_on = False
			self._setup_monobridge()
			self._setup_controls()
			self._setup_transport_control() # Run the transport setup part of the script
			self._setup_mixer_control() # Setup the mixer object
			self._setup_session_control()  # Setup the session object 
			self._setup_device_control() # Setup the device object
			self._setup_crossfader()
			self._setup_looper()
			#self._setup_scene_selector()
			#self._setup_modes() 
			self._assign_page_constants()
			self.assign_page_0()
			self._setup_hilight_knobs()
			self._last_device = None
			self._timer = 0
			#self.set_suppress_rebuild_requests(False) #Turn rebuild back on, now that we're done setting up
			self.song().view.add_selected_track_listener(self._update_selected_device)
			self._on_selected_scene_changed()
			self.show_message('OhmModes Control Surface Loaded')
			self._send_midi(tuple(switchxfader))
			#self.schedule_message(10, self.query_ohm, None)
			#self.song().view.selected_scene = self.song().scenes[0]
			self._assign_session_colors()
		
	def query_ohm(self):
		#self.log_message('querying Ohm')
		self._send_midi(tuple(check_model))

	

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



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

	def get_device_bank(self):
		return self._device._bank_index
	

	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] = EncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_FADERS[index], Live.MidiMap.MapMode.absolute)
			self._fader[index].name = 'Fader_' + str(index), self
		for index in range(8):
			self._button[index] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_' + str(index), self)
		for index in range(16):
			self._dial[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_DIALS[index], Live.MidiMap.MapMode.absolute)
			self._dial[index].name = 'Dial_' + str(index)
		for index in range(6):
			self._menu[index] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_MENU[index], 'Menu_' + str(index), self)	
		self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute)
		self._crossfader.name = "Crossfader"
		self._livid = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self)
		self._shift_l = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Page_Button_Left', self)
		self._shift_r = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Page_Button_Right', self)
		self._matrix = ButtonMatrixElement()
		self._matrix.name = 'Matrix'
		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] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, (column * 8) + row, 'Grid_' + str(column) + '_' + str(row), self)
		for row in range(6):
			button_row = []
			for column in range(7):
				button_row.append(self._grid[column][row])
			self._matrix.add_row(tuple(button_row)) 
	
		
	def _setup_modes(self):
		self._shift_mode = ShiftModeComponent(self) 
		self._shift_mode.name = 'Shift_Mode'
		#self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r)
		#self._select_mode = ModeSelectorComponent(self)
		#self._select_mode.name = 'Select_Mode'
		#self._select_mode.set_mode_toggle(self._menu[5])
		#self._select_mode.update = self.select_mode_update(self._select_mode)
		#self._menu[5].add_value_listener(self._select_mode)
		#self._scale_mode = ScaleModeComponent(self)
		#self._scale_mode.name = "Scale_Mode"
		#self._octave_mode = OctaveModeComponent(self)
		#self._octave_mode.name = "Octave_Mode"
	

			
		
	

	def select_mode_update(self, mode_selector):
		def update():
			if mode_selector._mode_index>0:
				pass
		return update
		
	

	def _setup_looper(self):
		self._looper = [None for index in range(2)]
		for index in range(2):
			self._looper[index] = LooperListenerComponent(self, index + 1)
			self._looper[index].assign_buttons(self._button[index*4], self._button[(index*4)+1], self._button[(index*4)+2], self._button[(index*4)+3])
	

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

	def _setup_mixer_control(self):
		is_momentary = True
		self._num_tracks = (7) #A mixer is one-dimensional; 
		global mixer
		mixer = SpecialMixerComponent(7, 0, True, False)
		mixer.name = 'Mixer'
		self._mixer = mixer
		mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
		for index in range(7):
			mixer.channel_strip(index).set_volume_control(self._fader[index])
		for index in range(7):
			mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index)
			mixer.track_eq(index).name = 'Mixer_EQ_' + str(index)
			mixer.channel_strip(index)._invert_mute_feedback = True
		self.song().view.selected_track = 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


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

		
	def _assign_session_colors(self):
		num_tracks = 7
		num_scenes = 7 
		self._session.set_stop_clip_value(STOP_CLIP_COLOR[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_TRIGD_TO_PLAY_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_triggered_to_record_value(CLIP_TRIGD_TO_RECORD_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_stopped_value(CLIP_STOPPED_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_started_value(CLIP_STARTED_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_recording_value(CLIP_RECORDING_COLOR[self._rgb])		
		self._session_zoom.set_stopped_value(ZOOM_STOPPED_COLOR[self._rgb])
		self._session_zoom.set_playing_value(ZOOM_PLAYING_COLOR[self._rgb])
		self._session_zoom.set_selected_value(ZOOM_SELECTED_COLOR[self._rgb])
		

	def _setup_device_control(self):
		self._device = DeviceComponent()
		self._device.name = 'Device_Component'
		self.set_device_component(self._device)
		self._device_navigator = DetailViewControllerComponent()
		self._device_navigator.name = 'Device_Navigator'
		self._device_selection_follows_track_selection = FOLLOW
		
	def device_follows_track(self, val):
		self._device_selection_follows_track_selection = (val == 1)
		return self
		
	def _setup_crossfader(self):
		self._mixer.set_crossfader_control(self._crossfader)
	

	def _setup_scene_selector(self):
		for index in range(5):
			self._menu[index].add_value_listener(self._select_new_scene, True)
	

	def set_bank(self, val):
		self._scene_bank = int(val)
		self._monobridge._send('bank', self._scene_bank)
		self._display_bank()
	

	def _select_mode(self, value):
		self.log_message('select mode update' + str(value))
		self._bank_is_on = value!=0
		if self._bank_is_on is True:
			self._display_bank()
		else:
			self._on_selected_scene_changed()
	

	def _select_new_scene(self, value, sender):
		if self._bank_is_on is False:
			if value > 0:
				new_scene = int(self._scene_indexes[self._scene_bank][self._menu.index(sender)][0])
				new_track = int(self._scene_indexes[self._scene_bank][self._menu.index(sender)][1])
				self.log_message('select new scene ' + str(new_scene) + ' and track ' + str(new_track))
				all_scenes = self.song().scenes
				all_tracks = self.song().tracks
				if (new_scene < len(all_scenes)) and (new_track < len(all_tracks)):
					self.song().view.selected_scene = all_scenes[(new_scene)]
					self.song().view.selected_track = all_tracks[(new_track)]
					self._session.set_offsets(self._scene_indexes[self._scene_bank][self._menu.index(sender)][1], self._scene_indexes[self._scene_bank][self._menu.index(sender)][0])
		else:
			if value > 0:
				self._scene_bank = int(self._menu.index(sender))
				self._monobridge._send('bank', self._scene_bank)
				self._display_bank()
	

	def _display_bank(self):
		if(self._bank_is_on):
			for index in range(5):
				if index == self._scene_bank:
					self._menu[index].send_value(11)
				else:
					self._menu[index].send_value(0)
	



	def _on_selected_scene_changed(self):
		ControlSurface._on_selected_scene_changed(self)
		#self.log_message('scene offset: ' + str(self._session._scene_offset))
		for index in range(6):
			if self._session._scene_offset == self._scene_indexes[self._scene_bank][index][0]:  ## and self._session._scene_offset < self._scene_indexes[index + 1]:
				self._menu[index].turn_on()
			else:
				self._menu[index].turn_off()
		#if self._session._scene_offset >= self._scene_indexes[5]:
		#	self._menu[5].turn_on
		#else:
		#	self._menu[5].turn_off
			
	
	def _setup_hilight_knobs(self):
		self._dial[15].add_value_listener(self._knob_set_scene, True)
		self._dial[14].add_value_listener(self._knob_set_track, True)
	

	def _knob_set_scene(self, value, sender):
		all_scenes = self.song().scenes
		num_scenes = len(all_scenes)
		new_scene = float(value/127.0) * float(num_scenes - 1)
		self.song().view.selected_scene = all_scenes[int(new_scene)]
		self._session.set_offsets(self._session._track_offset, int(new_scene))
	

	def _knob_set_track(self, value, sender):
		#self.log_message(str(value))
		all_tracks = self.song().visible_tracks  #self.song().tracks
		num_tracks = len(self.song().visible_tracks)
		new_track = float(value/127.0) * float(num_tracks - 1)
		#self.log_message(str(int(new_track)))
		#self.log_message(str(value) + str(float(value/127.0)))
		self.song().view.selected_track = all_tracks[int(new_track)]
		self._session.set_offsets(int(new_track), self._session._scene_offset)
	

	def disconnect(self):
		"""clean things up on disconnect"""
		for index in range(5):
			if self._menu[index].value_has_listener(self._select_new_scene):
				self._menu[index].remove_value_listener(self._select_new_scene)
		if self._menu[5].value_has_listener(self._select_mode):
			self._menu[5].remove_value_listener(self._select_mode)
		if self._dial[15].value_has_listener(self._knob_set_scene):
			self._dial[15].remove_value_listener(self._knob_set_scene)
		if self._dial[15].value_has_listener(self._knob_set_scene):		
			self._dial[15].remove_value_listener(self._knob_set_scene)
		self.song().view.remove_selected_track_listener(self._update_selected_device)
		ControlSurface.disconnect(self)
		self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= OhmModes log closed =--------------") #Create entry in log file
		return None

	def _get_num_tracks(self):
		return self.num_tracks

	def flash(self):
		#if(self.flash_status > 0):
		for index in range(6):
			if(self._menu[index]._flash_state>0):
				self._menu[index].flash(self._timer)
		for row in range(8):
			if(self._button[row]._flash_state > 0):
				self._button[row].flash(self._timer)
			for column in range(8):
				button = self._grid[column][row]
				if(button._flash_state > 0):
					button.flash(self._timer)


	def strobe(self):
		if(self._backlight_type != 'static'):
			if(self._backlight_type is 'pulse'):
				self._backlight = int(math.fabs(((self._timer * 16) % 64) -32) +32)
			if(self._backlight_type is 'up'):
				self._backlight = int(((self._timer * 8) % 64) + 16)
			if(self._backlight_type is 'down'):
				self._backlight = int(math.fabs(int(((self._timer * 8) % 64) - 64)) + 16)
		self._send_midi(tuple([176, 27, int(self._backlight)]))
		if(self._ohm_type != 'static'):
			if(self._ohm_type is 'pulse'):
				self._ohm = int(math.fabs(((self._timer * 16) % 64) -32) +32)
			if(self._ohm_type is 'up'):
				self._ohm = int(((self._timer * 8) % 64) + 16)
			if(self._ohm_type is 'down'):
				self._ohm = int(math.fabs(int(((self._timer * 8) % 64) - 64)) + 16)
		self._send_midi(tuple([176, 63, int(self._ohm)]))
		self._send_midi(tuple([176, 31, int(self._ohm)]))	

	def deassign_matrix(self):
		#self._scale_mode.set_mode_buttons(None)
		#self._scale_mode.set_enabled(False)
		#self._octave_mode.set_mode_buttons(None)
		#self._octave_mode.set_enabled(False)
		#self._session_zoom.set_button_matrix(None)
		#if self._dial[15].has_value_listener(self._knob_set_scene):
		#	self._dial[15].remove_value_listener(self._knob_set_scene)
		#if self._dial[14].has_value_listener(self._knob_set_track):
		#	self._dial[14].remove_value_listener(self._knob_set_track)
		self._session_zoom.set_enabled(False)
		self._session_zoom.set_nav_buttons(None, None, None, None)
		self._session.set_track_bank_buttons(None, None)
		self._session.set_scene_bank_buttons(None, None)
		for column in range(7):
			self._mixer.channel_strip(column).set_crossfade_toggle(None)
			self._mixer.channel_strip(column).set_mute_button(None)
			self._mixer.channel_strip(column).set_solo_button(None)
			self._mixer.channel_strip(column).set_arm_button(None)
			self._mixer.channel_strip(column).set_send_controls(None)
			self._mixer.channel_strip(column).set_pan_control(None)
			self._mixer.track_eq(column).set_enabled(False)
			for row in range(7):
				self._scene[row].clip_slot(column).set_launch_button(None)
		for column in range(8):
			#self._button[column]._on_value = SELECT_COLOR[self._rgb]
			for row in range(8):
				self._grid[column][row].set_channel(0)
				self._grid[column][row].release_parameter()
				self._grid[column][row].use_default_message()
				self._grid[column][row].set_enabled(True)
				self._grid[column][row].send_value(0, True)
				self._grid[column][row]._on_value = 127
				self._grid[column][row]._off_value = 0
		#for index in range(8):
		#	self._button[index].set_channel(0)
		#	self._button[index].use_default_message()
		#	self._button[index].set_enabled(True)
		#	self._button[index].reset()
		#for index in range(6):
		#	self._menu[index]._on_value = 127
		#	self._menu[index]._off_value = 0
		#	self._menu[index].reset()
		#for index in range(16):
		#	self._dial[index].use_default_message()
		#	self._dial[index].release_parameter()
			#self._dial[index].set_enabled(True)
		if(self._device._parameter_controls != None):
			for control in self._device._parameter_controls:
				control.release_parameter()
			self._device._parameter_controls = None
		self._device_navigator.set_enabled(False)
		self._mixer.update()
		self._matrix.reset()

		"""HH Specific"""
		#self._mixer.master_strip().set_select_button(None)
		#for column in range(7):
		#	self._mixer.channel_strip(column).set_select_button(None)
		self._session_zoom.set_zoom_button(None)
		self._transport.set_play_button(None)
		self._transport.set_stop_button(None)
		self._device_navigator.set_device_nav_buttons(None, None)
		
		#for index in range(2):
		#	self._looper[index].find_looper()
		
	def _assign_page_constants(self):
		#self._session_zoom.set_zoom_button(self._button[7]) #commented out pn 070111
		#self._session_zoom.set_zoom_button(self._grid[7][7]) #added pn 070111
		#self._session_zoom.set_button_matrix(self._matrix)
		#self._session_zoom.set_enabled(True)
		#for column in range(7):
			#self._mixer.channel_strip(column).set_select_button(self._button[column])
		#	self._mixer.channel_strip(column).set_volume_control(self._fader[column])
		#self._mixer.master_strip().set_volume_control(self._fader[7])
		#for column in range(8):
		#	self._button[column]._on_value = SELECT_COLOR[self._rgb]
		#self._mixer.master_strip().set_select_button(self._button[7]) #added pn 070111
		#self._mixer.set_prehear_volume_control(self._dial[15])
		#self._transport.set_play_button(self._menu[0])
		#self._menu[0].send_value(PLAY_COLOR[self._rgb], True)	
		#self._menu[0]._on_value = PLAY_COLOR[self._rgb]
		#self._transport.set_stop_button(self._menu[1])
		#self._menu[1]._off_value = STOP_COLOR[self._rgb]
		#self._menu[1]._on_value = STOP_COLOR[self._rgb]
		#self._menu[1].send_value(STOP_COLOR[self._rgb], True)	
		self._livid._on_value = TAP_COLOR[self._rgb]
		self._transport.set_tap_tempo_button(self._livid)
		#self._livid.send_value(TAP_COLOR, True)
		#self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[4])
		for index in range(2):
			self._menu[index + 4]._on_value = SESSION_NAV[self._rgb]
			self._menu[index * 3]._on_value = SESSION_NAV[self._rgb]
		self._session.set_track_bank_buttons(self._menu[5], self._menu[4])
		self._session.set_scene_bank_buttons(self._menu[3], self._menu[0])


	def assign_page_0(self):
		self._backlight_type = 'static'
		#self._session_zoom.set_button_matrix(self._matrix)
		self._session_zoom.set_enabled(True)
		for column in range(7):
			#self._grid[column][5]._on_value = MUTE_COLOR[self._rgb]
			#self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
			#self._grid[column][6]._on_value = SOLO_COLOR[self._rgb]
			#self._mixer.channel_strip(column).set_solo_button(self._grid[column][6])
			#self._grid[column][7]._on_value = ARM_COLOR[self._rgb]
			#self._mixer.channel_strip(column).set_arm_button(self._grid[column][7])
			#self._mixer.channel_strip(column).set_pan_control(self._dial[column + 8])
			for row in range(7):
				self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])
		#for column in range(4):
		#	self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column], self._dial[column + 4]]))
		track_stop_buttons = []
		for index in range(7):
			self._grid[7][index]._off_value = SCENE_LAUNCH_COLOR[self._rgb]
			self._scene[index].set_launch_button(self._grid[7][index])
			self._grid[index][7]._on_value = TRACK_STOP[self._rgb]
			self._grid[index][7]._off_value = TRACK_STOP[self._rgb]
			track_stop_buttons.append(self._grid[index][7])
		self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		self._session.set_stop_all_clips_button(self._grid[7][7])
		#for index in range(4):
		#	self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb]
		#self._session.set_track_bank_buttons(self._menu[4], self._menu[3])
		#self._session.set_scene_bank_buttons(self._menu[5], self._menu[2])
		#for index in range(6):
		#	self._menu[index]._on_value = HHMENU[index][1]
		#	self._menu[index]._off_value = HHMENU[index][0]
		for index in range(8):
			self._button[index].set_channel(2)
			self._button[index].set_identifier(index)
			#self._button[index].reset()
			self._button[index].set_enabled(False)
		self.request_rebuild_midi_map()
		for index in range(7):
			self._grid[index][7].turn_on()
		for index in range(2):
			self._looper[index]._state_change()
			self._button[1 + (index * 4)].send_value(3)
			self._button[2 + (index * 4)].send_value(6)
			self._button[3 + (index * 4)].send_value(1)

	def assign_page_1(self):
		self._backlight_type = 'pulse'
		self._session_zoom.set_enabled(False)
		for column in range(4):
			for row in range(4):
				self._grid[column][row].set_channel(PAGE1_DRUM_CHANNEL)
				self._grid[column][row].set_identifier(PAGE1_DRUM_MAP[column][row])
				self._grid[column][row].send_value(DRUM_COLOR[self._rgb], True)
				self._grid[column][row].set_enabled(False)
				self._grid[column + 4][row].set_channel(PAGE1_BASS_CHANNEL)
				self._grid[column + 4][row].set_identifier(PAGE1_BASS_MAP[column][row])
				self._grid[column + 4][row].send_value(BASS_COLOR[self._rgb], True)
				self._grid[column + 4][row].set_enabled(False)
		scale_mode_buttons = []
		for column in range(8):
			for row in range(3):
				self._grid[column][row + 4].set_enabled(False)
				self._grid[column][row + 4].set_channel(PAGE1_KEYS_CHANNEL)
				self._grid[column][row + 4].set_identifier(int(PAGE1_KEYS_MAP[column][row]) + int(PAGE1_MODES_MAP[self._scale_mode._mode_index][column]) + int(self._octave_mode._mode_index * 12))
				self._grid[column][row + 4].send_value(KEYS_COLOR[self._rgb], True)
			for row in range(1):
				scale_mode_buttons.append(self._grid[column][7])
		self._scale_mode.set_mode_buttons(tuple(scale_mode_buttons))
		self._scale_mode.set_enabled(True)
		#self._octave_mode.set_mode_buttons(tuple([self._menu[5], self._menu[2]]))
		#self._octave_mode.set_enabled(True)
		for column in range(7):
			self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column + 8]]))
			#self._button[column].set_on_off_values(REC_ARM, 0)
			#self._mixer.channel_strip(column).set_arm_button(self._button[column])
		self._device.set_enabled(True)
		device_param_controls = []
		for index in range(8):
			device_param_controls.append(self._dial[index])
		self._device.set_parameter_controls(tuple(device_param_controls))
		#for index in range(4):
		#	self._menu[2 + index]._on_value = (DEVICE_NAV_COLOR[self._rgb])
		#self._device_navigator.set_enabled(True)

		"""HH Specific from Constants"""
		#self._mixer.master_strip().set_select_button(self._button[7])
		#for column in range(7):
		#	self._button[column].set_on_off_values(REC_ARM, 0)
		#self._session_zoom.set_zoom_button(self._grid[7][7])
		#self._transport.set_play_button(self._menu[0])
		#self._menu[0].send_value(PLAY_COLOR[self._rgb], True)	
		#self._menu[0]._on_value = PLAY_COLOR[self._rgb]
		#self._transport.set_stop_button(self._menu[1])
		#self._menu[1]._off_value = STOP_COLOR[self._rgb]
		#self._menu[1]._on_value = STOP_COLOR[self._rgb]
		#self._menu[1].send_value(STOP_COLOR[self._rgb], True)
		#self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[4])
		for index in range(8):
			self._button[index].set_channel(2)
			self._button[index].set_identifier(index)
			#self._button[index].reset()
			self._button[index].set_enabled(False)
		self.request_rebuild_midi_map()
		#for index in range(8):
		#	self._grid[index][7].send(self.
		for index in range(2):
			self._looper[index]._state_change()
			self._button[1 + (index * 4)].send_value(3)
			self._button[2 + (index * 4)].send_value(6)
			self._button[3 + (index * 4)].send_value(1)
	
	def assign_page_2(self):
		self._backlight_type = 'up'
		#self._session_zoom.set_button_matrix(self._matrix)
		self._session_zoom.set_enabled(False)
		for column in range(7):
			self._grid[column][5]._on_value = MUTE_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
			self._grid[column][6]._on_value = CROSSFADE_ASSIGN_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_crossfade_toggle(self._grid[column][6])
			self._grid[column][7].set_channel(2)
			self._grid[column][7].set_identifier(column)
			self._grid[column][7].reset()
			self._grid[column][7].set_enabled(False)
			self._grid[column][7].send_value(4, True)
			for row in range(5):
				self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])
		for row in range(5):
			self._grid[7][row]._off_value = SCENE_LAUNCH_COLOR[self._rgb]
			self._scene[row].set_launch_button(self._grid[7][row])
		for column in range(4):
			self._mixer.track_eq(column).set_gain_controls(tuple([self._dial[column + 8], self._dial[column + 4], self._dial[column]]))
			self._mixer.track_eq(column).set_enabled(True)	
		for column in range(3):
			self._mixer.channel_strip(column+4).set_pan_control(self._dial[column + 12])
		#for index in range(4):
		#	self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb]
		#self._session.set_track_bank_buttons(self._menu[4], self._menu[3])
		#self._session.set_scene_bank_buttons(self._menu[5], self._menu[2])
		self._set_tempo_buttons([self._grid[7][5], self._grid[7][6]])
		
		"""HH Specific from Constants"""
		#self._mixer.master_strip().set_select_button(self._button[7])
		#for column in range(7):
		#	self._mixer.channel_strip(column).set_select_button(self._button[column])
		#for index in range(8):
		#	self._button[index].set_on_off_values(SELECT_COLOR[self._rgb], 0)
		self._session_zoom.set_zoom_button(self._grid[7][7])
		#self._transport.set_play_button(self._menu[0])
		#self._menu[0].send_value(PLAY_COLOR[self._rgb], True)	
		#self._menu[0]._on_value = PLAY_COLOR[self._rgb]
		#self._transport.set_stop_button(self._menu[1])
		#self._menu[1]._off_value = STOP_COLOR[self._rgb]
		#self._menu[1]._on_value = STOP_COLOR[self._rgb]
		#self._menu[1].send_value(STOP_COLOR[self._rgb], True)
		#self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[4])
		for index in range(8):
			self._button[index].set_channel(2)
			self._button[index].set_identifier(index)
			#self._button[index].reset()
			self._button[index].set_enabled(False)
		self.request_rebuild_midi_map()
		for index in range(2):
			self._looper[index]._state_change()
			self._button[1 + (index * 4)].send_value(3)
			self._button[2 + (index * 4)].send_value(6)
			self._button[3 + (index * 4)].send_value(1)
		
	
	def _update_selected_device(self):
		if self._device_selection_follows_track_selection is True:
			track = self.song().view.selected_track
			device_to_select = track.view.selected_device
			if device_to_select == None and len(track.devices) > 0:
				device_to_select = track.devices[0]
			if device_to_select != None:
				self.song().view.select_device(device_to_select)
			#self._device.set_device(device_to_select)
			self.set_appointed_device(device_to_select)
			#self._device_selector.set_enabled(True)
			self.request_rebuild_midi_map()
		return None
	
	def handle_sysex(self, midi_bytes):
		#self.log_message(str('>>sysexIN') + str(midi_bytes))
		if len(midi_bytes) > 10:
			#self.log_message(str('>>sysex>10') + str(midi_bytes[:11]))
			if midi_bytes[:11] == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 7]):
				self.log_message(str('>>>color detected'))
				self._rgb = 1
			elif midi_bytes[:11] == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 2]):
				self.log_message(str('>>>mono detected'))
				self._rgb = 0
		self._assign_session_colors()
		#self._shift_mode.update()
		self.deassign_matrix()
		self._assign_page_constants()
		self.assign_page_0()
		#self._setup_hilight_knobs()
		for index in range(8):
			self._grid[7][index].send_value(SCENE_LAUNCH_COLOR[self._rgb])
		for index in range(7):
			self._grid[index][7].turn_on()

# 	def handle_sysex(self, midi_bytes):
# 		#assert(isinstance (midi_bytes, tuple))
# 		##self.log_message(str('sysex') + str(midi_bytes))
# 		if midi_bytes == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 7, 0, 15, 10, 0, 0, 247]):
# 			self.log_message(str('color detected'))
# 			self._rgb = 1
# 		elif midi_bytes == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 2, 0, 0, 1, 1, 0, 247]):
# 			self.log_message(str('mono detected'))
# 			self._rgb = 0
# 		self._assign_session_colors()

	def receive_midi(self, midi_bytes):
		""" Live -> Script
		MIDI messages are only received through this function, when explicitly 
		forwarded in 'build_midi_map'.
	"""
		assert (midi_bytes != None)
		assert isinstance(midi_bytes, tuple)
		##self.log_message('got message' + str(midi_bytes))
		#self.set_suppress_rebuild_requests(True)
		with self.component_guard():
			if (len(midi_bytes) is 3):
				msg_type = (midi_bytes[0] & 240)
				forwarding_key = [midi_bytes[0]]
				if (msg_type is not MIDI_PB_TYPE):
					forwarding_key.append(midi_bytes[1])
				if (tuple(forwarding_key) in self._forwarding_registry.keys()):
					recipient = self._forwarding_registry[tuple(forwarding_key)]
					if (recipient != None):
						recipient.receive_value(midi_bytes[2])
				else:
					self.log_message(('Got unknown message: ' + str(midi_bytes)))
			else:
				self.handle_sysex(midi_bytes)
		#self.set_suppress_rebuild_requests(False)		 

	def _set_tempo_buttons(self, buttons):
		if self._tempo_buttons != None:
			self._tempo_buttons[0].remove_value_listener(self._tempo_value)
			self._tempo_buttons[1].remove_value_listener(self._tempo_value)
		self._tempo_buttons = buttons
		if buttons != None:
			for button in buttons:
				assert isinstance(button, FlashingButtonElement)
			self._tempo_buttons[0].set_on_off_values(4, 0)
			self._tempo_buttons[0].add_value_listener(self._tempo_value, True)
			self._tempo_buttons[1].set_on_off_values(4, 0)
			self._tempo_buttons[1].add_value_listener(self._tempo_value, True)
			self._tempo_buttons[0].turn_on()
			self._tempo_buttons[1].turn_on()

	def _tempo_value(self, value, sender):
		if (value > 0) and (self._tempo_buttons.index(sender) == 0):
			self.song().tempo = round(min((self.song().tempo + 1), 999))
		elif (value > 0) and (self._tempo_buttons.index(sender) == 1):
			self.song().tempo = round(max((self.song().tempo - 1), 20))
			
		

	def set_scene_index_value(self, bank_index, scene, track):
		bank = int(bank_index)/5
		index = int(bank_index)%5
		self.log_message('set_scene_index_value' + str(bank) + str(index) + str(scene) + str(track))
		#self.log_message( str(type(index)) + str(type(scene)) + str(type(track)))
		self._scene_indexes[bank][index][0] = scene
		self._scene_indexes[bank][index][1] = track
		#self._on_selected_scene_changed()
	

	def connect_script_instances(self, instanciated_scripts):
		#link = False
		#offsets = [0, 0]
		#new_channel = CHAN
		for s in instanciated_scripts:
			if isinstance(s, APC) or s is self:
				#link = True
				if not s._session._is_linked():
					s._session._link()
					#self.log_message('found other linked instance')
					#offsets[0] += (int(self._link_offset[0]) * 8)
					#offsets[1] += (int(self._link_offset[1]) * 4)
					#new_channel += 1
		#if link and not self._session._is_linked():
			#self._session.set_offsets(offsets[0], offsets[1])
			#self._session._link()
		#self._set_code_channels(new_channel)
	
	
#
#
Exemple #49
0
class code(ControlSurface):
	__module__ = __name__
	__doc__ = " Code controller script "
	
	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		with self.component_guard():
			self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= Code opened =--------------") # Writes message into Live's main log file. This is a ControlSurface method.		  
			self._send_midi(factoryreset)
			self._send_midi(btn_channels)
			self._send_midi(enc_channels)
			#self.set_suppress_rebuild_requests(True) # Turn off rebuild MIDI map until after we're done setting up
			self._setup_controls()
			self._setup_device_controls()
			self._setup_mixer_control() # Setup the mixer object
			self._setup_transport_control()
			self._setup_session_control()  # Setup the session object - do this last
			self._setup_modes()
			#self.set_suppress_rebuild_requests(False) # Turn rebuild back on, once we're done setting up
			##self.assign_page_2()

	def handle_sysex(self, midi_bytes):
		self._send_midi(tuple([240, 00, 01, 97, 04, 15, 01, 247]))
		#response = [long(0),long(0)]
		#self.log_message(str(response))
	
	def _setup_controls(self):
		is_momentary = True
		self._dial = [None for index in range(DIALCOUNT)]
		self._trackbtns = [None for index in range(8)]
		self._modebtns = [None for index in range(5)]
		for index in range(DIALCOUNT):
			self._dial[index] = EncoderElement(MIDI_CC_TYPE, CH, matrix_nums[index], Live.MidiMap.MapMode.absolute)
			self._dial[index].name = 'Dial_' + str(index)
			self._dial[index].set_feedback_delay(-1)
		for index in range(8):
			self._trackbtns[index] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index])
			self._trackbtns[index].name =  'Button_' + str(index)
		for index in range(5):
			self._modebtns[index] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, mode_select_notes[index])
			self._modebtns[index].name = 'ModeButton_' + str(index)
		self._matrix = ButtonMatrixElement()
		self._matrix.name = 'Matrix'
		self._grid = [None for index in range(COLS)]
		for column in range(COLS):
			self._grid[column] = [None for index in range(COLS)]
			for row in range(ROWS):
				nn = 1+(column * ROWS) + row
				self._grid[column][row] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, nn) #comment out if you don't want clip launch
				self._grid[column][row].name = 'Grid_' + str(column) + '_' + str(row)
		for row in range(ROWS):
			button_row = []
			for column in range(COLS):
				button_row.append(self._grid[column][row])
			self._matrix.add_row(tuple(button_row)) 
	  
	""" not sure about this bit, but somehow I'll need to set up the modes here...!"""
	def _setup_modes(self):
		self._shift_mode = ShiftModeComponent(self, tuple(button for button in self._modebtns))
		self._shift_mode.name = 'Mix_Mode' #mode 1
		#self._shift_mode.set_mode_buttons(self._modebtns)
		
	def _setup_transport_control(self):
		self._transport = TransportComponent() 
		self._transport.name = 'Transport'

	def _setup_mixer_control(self):
		is_momentary = True
		self._num_tracks = (COLS)
		global mixer
		mixer = MixerComponent(COLS, 0, True, True)
		mixer.name = 'Mixer'
		self._mixer = mixer
		mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
		for index in range(COLS):
			#use the bottom row of encoders for volume, so add 24 to offset the index
			mixer.channel_strip(index).set_volume_control(self._dial[index+24])
		for index in range(COLS):
			mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index)
			mixer.track_eq(index).name = 'Mixer_EQ_' + str(index)
			mixer.track_filter(index).name = 'Mixer_Filter_' + str(index)  #added by a
			mixer.channel_strip(index)._invert_mute_feedback = True
			#mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index]))
		self.song().view.selected_track = 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

	""" Technically, we aren't using the session control, but I'm going to set it up in case inter-script communication needs it"""
	def _setup_session_control(self):
		is_momentary = True
		num_tracks = COLS
		num_scenes = ROWS
		global session
		session = SessionComponent(num_tracks, num_scenes)
		session.name = "Session"
		session.set_offsets(0, 0)
		self._session = session
		self._session.set_stop_track_clip_value(0)
		self._scene = [None for index in range(ROWS)]
		for row in range(num_scenes):
			self._scene[row] = session.scene(row)
			self._scene[row].name = 'Scene_' + str(row)
			for column in range(num_tracks):
				clip_slot = self._scene[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_' + str(row)
				clip_slot.set_triggered_to_play_value(64)
				clip_slot.set_triggered_to_record_value(64)
				clip_slot.set_stopped_value(0)
				clip_slot.set_started_value(64)
				clip_slot.set_recording_value(64)
				#clip_slot.set_launch_button(self._grid[column][row]) #comment out if you don't want clip launch
		session.set_mixer(mixer)
		self._session_zoom = SessionZoomingComponent(session)
		self._session_zoom.name = 'Session_Overview'
		self._session_zoom.set_stopped_value(0)
		self._session_zoom.set_playing_value(64)
		self._session_zoom.set_selected_value(64)
		if STANDALONE is True:
			self.set_highlighting_session_component(self._session)
			self._session.set_track_bank_buttons(self._grid[5][3], self._grid[4][3])   #comment out when using with Griid
			self._session.set_scene_bank_buttons(self._grid[7][3], self._grid[6][3])	# comment out when using with Griid
		
		
	"""this is where we take care of setting up the the multiple devices per page, we will need 4"""
	def _setup_device_controls(self):
		self._device = [None for index in range(4)]
		for index in range(ROWS):
			self._device[index] = DeviceComponent()
			self._device[index].name = 'Device_Component_' + str(index)
			#self.set_device_component(self._device)  #this doesn't work anymore, because we have multiple devices for the controller....we'll have to get fancy here, but that's for later
			#self._device_navigator = DetailViewControllerComponent()  #its unclear if we'll need this....how is device navigation (i.e. banking for device parameter banks) going to be handled by the script? 
			#self._device_navigator.name = 'Device_Navigator'
			device_param_controls = []
			for control in range(COLS):
				"""this setups up 8 device parameters per row"""
				#dial_index = control + (index*COLS)
				"""alternatively, this setus up device controls in 4 4x2 groups"""
				dial_index = device_encoders[control + (index*COLS)]
				device_param_controls.append(self._dial[dial_index])

				
			
			self._device[index].set_parameter_controls(tuple(device_param_controls))

	"""this is where we deassign every control that will be changing function when we switch modes...best to just deassign them all, and reassign them on update"""
	def deassign_matrix(self):
		for index in range(DIALCOUNT):			#this should totally work!!! I'm over appealing to Python's sadistic mannerisms right now....
			self._dial[index].send_value(0, True)	##this is kind of a hack, and should be unnecessary; the bool at the end tells the send_value method to force the value out to the controller
		for index in range(COLS):
			self._mixer.track_eq(index).set_enabled(False)	##set_gain_controls(tuple([None for index in range(3)]))
			self._mixer.channel_strip(index).set_volume_control(None)
			self._mixer.track_filter(index).set_enabled(False)	##set_filter_controls(tuple([None, None]))
			self._mixer.channel_strip(index).set_pan_control(None)
			self._mixer.channel_strip(index).set_select_button(None)
			self._mixer.channel_strip(index).set_send_controls(tuple([None for index in range(4)]))
		for device in range(4):
			self._device[device].set_bank_nav_buttons(None, None)
			self._device[device].set_enabled(False)	 ##set_parameter_controls(tuple([None for index in range(8)]))
		for track in range(8):
			self._mixer.channel_strip(track).set_select_button(None)
			for scene in range(4):
				self._scene[scene].clip_slot(track).set_launch_button(None)
		#self.request_rebuild_midi_map()  # I think this is causing problems updating the leds when in build?

	"""EQ Hi/Mid/Low and volume"""
	def assign_page_0(self):
		"""for each column"""
		is_momentary = True
		for index in range(COLS):
			self._mixer.track_eq(index).set_gain_controls((self._dial[index+16],self._dial[index+8],self._dial[index]))
			self._mixer.track_eq(index).set_enabled(True)
			self._mixer.channel_strip(index).set_volume_control(self._dial[index+24])#use the bottom row of encoders for volume, so add 24 to offset the index
			self._mixer.channel_strip(index).set_select_button(self._trackbtns[index])
			self.assign_cliplaunch()
			self._mixer.update()
			
	"""sends 1-4"""
	def assign_page_1(self):
		is_momentary = True
		for index in range(COLS):
			send_controllers = [self._dial[index],self._dial[index+8],self._dial[index+16],self._dial[index+24]]
			self._mixer.channel_strip(index).set_send_controls(tuple(send_controllers))
			self._mixer.channel_strip(index).set_select_button(self._trackbtns[index])
			self._mixer.update()

	"""devices 1-8"""
	def assign_pages_2_3(self):			##these need to be here anyway, whether or not there is a device present to control
		for index in range(4):
			self._device[index].set_enabled(True)
			#device_param_controls = []			###no need to reassign it, since we are turning it off and on
			#for control in range(COLS):		###in fact, I think we can assign all this stuff in the header except for things directly connected to the mixer module
			#	device_param_controls.append(self._dial[control + (index*COLS)])
			#self._device[index].set_parameter_controls(tuple(device_param_controls))
		self._reassign_devices(self._shift_mode._mode_index)
	
	""" filter res,filter q, pan, volume"""
	def assign_page_4(self):
		is_momentary = True
		for index in range(COLS):
			self._mixer.track_filter(index).set_filter_controls(self._dial[index], self._dial[index + 8]) #set_filter_controls(self, freq, reso)
			self._mixer.track_filter(index).set_enabled(True) 
			#self._mixer.track_eq(index).set_gain_controls((self._dial[index],self._dial[index+8],self._dial[index+16]))
			self._mixer.channel_strip(index).set_pan_control(self._dial[index+16])
			self._mixer.channel_strip(index).set_volume_control(self._dial[index+24])
			self._mixer.channel_strip(index).set_select_button(self._trackbtns[index])
			self._mixer.update()
	

	def assign_cliplaunch(self):
		if STANDALONE is True:
			for column in range(COLS):
				for row in range(ROWS-1):
					self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])

	def _reassign_devices(self, mode_index):
		if self._shift_mode._mode_index in range(2, 4): ##both of these lines would be better handled by a property 
			offset = (mode_index - 2) * 4				## set up in an override module of the device_component....bleh
			track = self.song().view.selected_track
			for index in range(4):
				if index + offset < len(track.devices):
					#self.log_message('assigning device')
					self._device[index].set_device(track.devices[index + offset])
				else:
					#self.log_message('assigning device to None')
					self._device[index].set_device(None)
				self._device[index].set_bank_nav_buttons(self._trackbtns[(index * 2)], self._trackbtns[(index * 2) + 1])
				self._device[index].update()

	def disconnect(self):
		"""clean things up on disconnect"""
		self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= Code log closed =--------------") #Create entry in log file
		ControlSurface.disconnect(self)
		return None		
class BCRXL(ControlSurface, IsotonikCommon):
    def __init__(self, c_instance):
        self._dynamic = True
        self._LOG_BCL = False
        self._preset = 0
        self._use_32 = False
        self._enable_function = False
        self._track_navigation = False
        self._swap_arm = False
        self._direct_bank = False
        self._relative = False
        self._bit_14 = False
        self._fold_enabled = True
        self._can_fold = False
        self._show_returns = 0
        self._max_returns = -1
        self._returns_toggled = False
        self._has_pans = False
        self._track_bank_size = 1
        self._show_master = 0
        self._show_selected = 0
        self._button_row_1 = 'select'
        self._button_row_2 = 'mute'
        self._button_row_3 = 'solo'
        self._button_reselect_track = 'fold'
        self._channel_strip = False
        self._toggle_1 = False
        self._toggle_2 = False
        self._toggle_3 = False
        self._toggle_4 = False
        self._has_strip_device_enable = True
        self._USB = True
        self._has_transport = False
        self._showing_selected = False
        self._x_offset = 0
        self._y_offset = 0
        self._track_left = 113
        self._track_right = 114
        self._device_toggle = 109
        self._track_fold = 110
        self._refresh = 111
        self._device_lock = 110
        self._bank_up = 111
        self._bank_down = 112
        self._toggle_returns = False
        self._user_custom = False
        IsotonikCommon.__init__(self, parent=self, c_instance=c_instance)
        self._init(path.dirname(path.realpath(__file__)), 'BCR_XL', 24)
        super(BCRXL, self).__init__(c_instance)
        with self.component_guard():
            self._startup()

    def disconnect(self):
        if self._dynamic:
            pass
        self._shutdown()
        super(BCRXL, self).disconnect()

    def _sigabort_create(self):
        if self._show_returns == 3 or self._show_returns == 4:
            self._fold_enabled = False
            self._toggle_returns = True
        if not self._enable_function:
            self._direct_bank = False
            self._has_transport = False
        if self._channel_strip:
            self._fold_enabled = False
        self._user_custom = self._enable_function and not self._direct_bank and not self._has_transport
        self._bcr_controls = BCL(self, self._preset, self._relative,
                                 self._bit_14)
        self._device_selection_follows_track_selection = True
        self._default_skin = make_default_skin()
        with inject(skin=const(self._default_skin)).everywhere():
            self._create_controls()
        self._set_offsets_task = self._tasks.add(
            Task.sequence(Task.wait(0), Task.run(self._set_session_offsets)))
        self._set_offsets_task.kill()
        if self._show_selected:
            self._show_selected_task = self._tasks.add(
                Task.sequence(Task.wait(1),
                              Task.run(self._show_selected_track)))
        return False

    def _enable_components(self):
        with self.component_guard():
            for component in self.components:
                self.log('Enable: ' + component.name)
                component.set_enabled(True)

    def set_session_offsets(self, x, y):
        self.log('bcrxl: set_session_offsets: ' + str(x) + ',' + str(y))
        self._scene = y
        self._x_offset = x
        self._y_offset = y
        self._set_offsets_task.restart()

    def _set_session_offsets(self):
        self._set_offsets_task.kill()
        self.log('_set_session_offsets')
        self._session.set_offsets(self._x_offset, self._y_offset)

    def _show_controlled_tracks_message(self, session):
        track_offset = session.track_offset()
        self.log('_show_controlled_tracks_message: ' + str(track_offset) +
                 ', ' + str(self._scene))
        self._set_session_highlight(track_offset, self._scene, 8, 1, False)

    def _set_session_highlight(self, track_offset, scene_offset, width, height,
                               include_return_tracks):
        self.log('_set_session_highlight: ' + str(track_offset) + ', ' +
                 str(scene_offset) + ', ' + str(width) + ', ' + str(height) +
                 ', ' + str(include_return_tracks))
        super(BCRXL,
              self)._set_session_highlight(track_offset, scene_offset, width,
                                           height, include_return_tracks)

    def _on_selected_scene_changed(self):
        if self._box_follows_scene:
            self._scene = list(self.song().scenes).index(
                self.song().view.selected_scene)
            self._show_controlled_tracks_message(
                self._on_session_offset_changed.subject)
            self.log('_on_selected_scene_changed: index: ' + str(self._scene))
        super(BCRXL, self)._on_selected_scene_changed()

    def _show_selected_track(self):
        self.log('_show_selected_track: ' + str(self._showing_selected) +
                 ', index: ' + str(self._mixer._selected_track_index))
        self._showing_selected = not self._showing_selected
        volume_cc = 0 if self._bit_14 else 1
        if self._mixer._selected_track_index != -1:
            curr_val = self._mixer._channel_strips[
                self._mixer.
                _selected_track_index]._track.mixer_device.volume.value
            self._do_send_midi(
                (176 + MIXER_MODE,
                 volume_cc + self._mixer._selected_track_index,
                 int(math.floor(curr_val *
                                127.0)) if self._showing_selected else 0))
        self._show_selected_task = self._tasks.add(
            Task.sequence(Task.delay(2), Task.run(self._show_selected_track)))

    def on_identified(self):
        self.log('on_identified')
        self._identified = True
        if hasattr(self, 'default_session'):
            self.default_session.set_show_highlight(True)
            self._set_session_highlight(0, 0, 8, 1, False)
        super(BCRXL, self).on_identified()

    def _create_controls(self):
        self.log(
            '_create_controls: dynamic: ' + str(self._dynamic) +
            ', function: ' + str(self._enable_function), True)
        if not self._dynamic:
            self._track_left = 105
            self._track_right = 106
            self._device_toggle = 107
        elif not self._enable_function:
            self._device_toggle = 105
            self._track_fold = 106
            self._device_lock = 106
            self._bank_up = 107
            self._bank_down = 108
        self.log('left: ' + str(self._track_left) + ', right: ' +
                 str(self._track_right) + ', toggle: ' +
                 str(self._device_toggle) + ', user_custom: ' +
                 str(self._user_custom))
        if self._dynamic:
            if self._user_custom:
                self._bcr_controls.connect(self._toggle_1, self._toggle_2,
                                           self._toggle_3, self._toggle_4)
            else:
                self._bcr_controls.connect()
        self._modes = ModesComponent()
        self._create_our_controls()
        self._create_mixer()
        self._create_session()
        self._create_device()
        self._create_transport()

    def log(self, msg, force=False):
        if self._LOG or force:
            if isinstance(msg, str):
                logger.info(msg)
            else:
                logger.error('**++** Invalid log msg: ' + str(type(msg)) +
                             ': ' + IsotonikCommon.repr3(msg))

    def _create_our_controls(self):
        self.log('_create_our_controls')

        def make_button(identifier,
                        name,
                        midi_type=MIDI_CC_TYPE,
                        skin=self._default_skin):
            control = ButtonElement(False,
                                    midi_type,
                                    MIXER_MODE,
                                    identifier,
                                    name=name,
                                    skin=skin)
            return control

        def make_button_list(identifiers, name, midi_type=MIDI_NOTE_TYPE):
            return [
                make_button(identifier, name % (i + 1), midi_type,
                            self._default_skin)
                for i, identifier in enumerate(identifiers)
            ]

        def make_encoder(identifier, name, bit_14=True):
            if self._bit_14:
                self.log('make_encoder: ' + name + ', CC: ' + str(identifier) +
                         ', 14_bit: ' + str(bit_14))
                control = EncoderElement(
                    MIDI_CC_TYPE,
                    MIXER_MODE,
                    identifier,
                    Live.MidiMap.MapMode.absolute_14_bit
                    if bit_14 else Live.MidiMap.MapMode.absolute,
                    name=name)
            else:
                control = EncoderElement(
                    MIDI_CC_TYPE,
                    MIXER_MODE,
                    identifier,
                    Live.MidiMap.MapMode.absolute if not self._relative else
                    Live.MidiMap.MapMode.relative_two_compliment,
                    name=name)
            return control

        self._top_buttons = ButtonMatrixElement(rows=[
            make_button_list(chain(xrange(65, 73)), 'BCR_Top_Buttons_%d',
                             MIDI_CC_TYPE)
        ])
        self._bottom_buttons = ButtonMatrixElement(rows=[
            make_button_list(chain(xrange(73, 81)), 'BCR_Bottom_Buttons_%d',
                             MIDI_CC_TYPE)
        ])
        self._strip_enable_buttons = ButtonMatrixElement(rows=[
            make_button_list(chain(xrange(73, 81)), 'BCR_Bottom_Buttons_%d',
                             MIDI_CC_TYPE)
        ])
        if self._direct_bank or self._has_transport:
            self._direct_bank_buttons = ButtonMatrixElement(rows=[
                make_button_list(chain(xrange(105, 109)),
                                 'BCR_User_Buttons_%d', MIDI_CC_TYPE)
            ])
        self._left_button = make_button(self._track_left, 'Track_Left',
                                        MIDI_CC_TYPE)
        self._right_button = make_button(self._track_right, 'Track_Right',
                                         MIDI_CC_TYPE)
        self._device_engage_button = make_button(self._device_toggle,
                                                 'XXL_Pan_Device_Mode')
        self._track_fold_button = make_button(self._track_fold, 'Track_Fold',
                                              MIDI_CC_TYPE)
        if self._fold_enabled or self._toggle_returns or self._channel_strip:
            self._on_track_fold.subject = self._track_fold_button
            self._track_fold_button.enabled = False
        self._bank_up_button = make_button(self._bank_up, 'Device_Bank_Up',
                                           MIDI_CC_TYPE)
        self._bank_down_button = make_button(self._bank_down,
                                             'Device_Bank_Down', MIDI_CC_TYPE)
        if self._bit_14:
            volume_cc = 0
            sends_cc = 8
            pans_cc = 81
            select_cc = 89
        else:
            volume_cc = 1
            sends_cc = 81
            pans_cc = 9
            select_cc = 33
        self._volume_encoders = ButtonMatrixElement(rows=[[
            make_encoder(volume_cc + i, 'Volume_%d' % (i + 1))
            for i in xrange(8)
        ]])
        if self._has_pans:
            self._pan_encoders = ButtonMatrixElement(rows=[[
                make_encoder(pans_cc + i, 'Pan_%d' % (i + 1), bit_14=False)
                for i in xrange(8)
            ]])
        self._send_encoders = ButtonMatrixElement(
            rows=[[
                make_encoder(sends_cc + i, 'Send_0_%d' % (i + 1))
                for i in xrange(8)
            ],
                  [
                      make_encoder(sends_cc + 8 + i, 'Send_1_%d' % (i + 1))
                      for i in xrange(8)
                  ],
                  [
                      make_encoder(sends_cc + 16 + i, 'Send_2_%d' % (i + 1))
                      for i in xrange(8)
                  ]])
        self._push_buttons = ButtonMatrixElement(rows=[
            make_button_list(chain(xrange(select_cc, select_cc + 8)),
                             'BCR_Track_Select_%d', MIDI_CC_TYPE)
        ])

    def _do_send_midi(self, midi_bytes):
        is_sysex = midi_bytes[0] == 240
        if self._LOG_MIDI and not is_sysex:
            self.log('_do_send_midi: ' + str(midi_bytes))
        if self._LOG_SYSEX and is_sysex:
            self.log('_do_send_midi: ' + str(midi_bytes))
        super(BCRXL, self)._do_send_midi(midi_bytes)

    def receive_midi(self, midi_bytes):
        is_sysex = midi_bytes[0] == 240
        send_off = False
        midi_id = 176 + MIXER_MODE
        adjusted = False
        if self._LOG_MIDI and not is_sysex:
            self.log('receive_midi: ' + str(midi_bytes) + ', id: ' +
                     str(midi_id))
        if self._LOG_SYSEX and is_sysex:
            self.log('receive_midi: ' + str(midi_bytes))
        if midi_bytes[0] == midi_id:
            if midi_bytes[2] == 0:
                if self._has_transport:
                    if midi_bytes[1] in (107, 108):
                        midi_bytes = (midi_id, midi_bytes[1], 127)
                        adjusted = True
                    elif midi_bytes[1] == 106:
                        midi_bytes = (midi_id, midi_bytes[1], 127)
                        self._do_send_midi(midi_bytes)
                        adjusted = True
                if not self._device_mode:
                    if midi_bytes[1] in pad_identifiers:
                        midi_bytes = (midi_id, midi_bytes[1], 127)
                        adjusted = True
                if midi_bytes[1] in [self._track_left, self._track_right]:
                    midi_bytes = (midi_id, midi_bytes[1], 127)
                    adjusted = True
        if self._LOG_MIDI and adjusted:
            self.log('receive_midi(adjusted): ' + str(midi_bytes) +
                     ', send_off: ' + str(send_off))
        if send_off:
            midi_bytes_new = (midi_id, midi_bytes[1], 0)
            if self._LOG_MIDI:
                self.log('send_off:receive_midi: ' + str(midi_bytes_new), True)
            super(BCRXL, self).receive_midi(midi_bytes_new)
        super(BCRXL, self).receive_midi(midi_bytes)

    def _create_user(self):
        def make_control_button(identifier, name, channel=0, is_pad=False):
            button = ButtonElement(True,
                                   MIDI_NOTE_TYPE if is_pad else MIDI_CC_TYPE,
                                   channel, identifier)
            button.name = name
            button.set_on_off_values(127, 0)
            return button

        def make_control_encoder(identifier, name, channel=0):
            encoder = EncoderElement(
                MIDI_CC_TYPE, channel, identifier,
                Live.MidiMap.MapMode.absolute if not self._relative else
                Live.MidiMap.MapMode.relative_two_compliment)
            encoder.reset = nop
            encoder.set_feedback_delay(-1)
            encoder.name = name
            return encoder

        def make_all_encoders(name_prefix='',
                              make_encoder=make_control_encoder):
            return ([
                make_encoder(13 + index, name_prefix + '_' + str(index) + '_0')
                for index in xrange(8)
            ], [
                make_encoder(80 + index, name_prefix + '_' + str(index) + '_1')
                for index in xrange(8)
            ], [
                make_encoder(88 + index, name_prefix + '_' + str(index) + '_2')
                for index in xrange(8)
            ], [
                make_encoder(96 + index, name_prefix + '_' + str(index) + '_3')
                for index in xrange(8)
            ])

        make_button = partial(make_control_button, channel=USER_MODE)
        make_encoder = partial(make_control_encoder, channel=USER_MODE)
        encoders_row_1, encoders_row_2, encoders_row_3, encoders_row_4 = make_all_encoders(
            'User_Encoder', make_encoder)
        buttons_0 = [
            make_button(pad_identifiers[i],
                        'User_Button_Matrix_' + str(i) + '_0',
                        is_pad=True) for i in xrange(8)
        ]
        buttons_1 = [
            make_button(pad_identifiers[i + 8],
                        'User_Button_Matrix_' + str(i) + '_1',
                        is_pad=True) for i in xrange(8)
        ]
        self._matrix = ButtonMatrixElement()
        self._matrix.name = 'User_Button_Matrix'
        self._matrix.add_row(tuple(buttons_0))
        self._matrix.add_row(tuple(buttons_1))
        self.request_rebuild_midi_map()

    def on_selected_track_changed(self):
        self._selected_track = self.song().view.selected_track
        if hasattr(self, '_mixer'):
            if self._show_selected and self._mixer._last_selected_track_index != -1:
                volume_cc = 0 if self._bit_14 else 1
                curr_val = self._mixer._channel_strips[
                    self._mixer.
                    _last_selected_track_index]._track.mixer_device.volume.value
                self.log(
                    'reset value for track: ' +
                    str(self._mixer._last_selected_track_index) + ' to ' +
                    str(curr_val), True)
                self._do_send_midi(
                    (176 + MIXER_MODE,
                     volume_cc + self._mixer._last_selected_track_index,
                     int(math.floor(curr_val * 127.0))))
        if self._fold_enabled:
            can_fold = False
            if self._selected_track != None:
                can_fold = self._selected_track.is_foldable
            self._can_fold = can_fold
            self.log('on_selected_track_changed: can_fold: ' + str(can_fold))
            self._track_fold_button.enabled = can_fold
            self._track_fold_button.send_value(127 if can_fold else 0)
        if hasattr(self, '_device'):
            self._device.on_selected_track_changed()

    @subject_slot('value')
    def _on_track_fold(self, value):
        self.log('_on_track_fold: ' + str(value) + ', fold_enabled: ' +
                 str(self._fold_enabled) + ', can_fold: ' +
                 str(self._can_fold) + ', toggle_returns: ' +
                 str(self._toggle_returns) + ', channel_strip: ' +
                 str(self._channel_strip))
        if self._channel_strip and self._modes.selected_mode != 'device':
            self.log('process channel_strip')
            if value:
                self.device_mode.layer = None
                self._on_device_engage(127, True)
                self._device.enable_channel_strip(True, True)
                self._on_strip_up.subject = self._bank_down_button
                self._on_strip_down.subject = self._bank_up_button
                if self._has_strip_device_enable:
                    self._on_strip_enable.replace_subjects(
                        self._strip_enable_buttons)
                self._update_strip_bank_buttons()
                self._update_strip_enable_buttons()
            else:
                self.device_mode.layer = Layer(
                    device_mode_button=self._device_engage_button)
                self._device.enable_channel_strip(False, True)
                self._on_device_engage(0, True)
                self._on_strip_up.subject = None
                self._on_strip_down.subject = None
                if self._has_strip_device_enable:
                    self._on_strip_enable.replace_subjects([])
        elif self._fold_enabled:
            self.log('process fold')
            self._track_fold_button.send_value(127 if self._can_fold else 0)
            if self._selected_track:
                self.log('can_fold: ' + str(self._selected_track.is_foldable))
                if self._selected_track.is_foldable:
                    self.log('currently folded: ' +
                             str(self._selected_track.fold_state))
                    self._selected_track.fold_state = not self._selected_track.fold_state
        elif self._toggle_returns:
            self.log('process toggle returns')
            self._returns_toggled = value == 127
            self.log('returns_toggled: ' + str(self._returns_toggled))
            self._mixer._reassign_tracks(1 if self._returns_toggled else 0)

    @subject_slot('value')
    def _on_strip_up(self, value):
        self.log('_on_strip_up', True)
        self._device._do_strip_up()
        self._update_strip_bank_buttons()

    @subject_slot('value')
    def _on_strip_down(self, value):
        self.log('_on_strip_down', True)
        self._device._do_strip_down()
        self._update_strip_bank_buttons()

    @subject_slot_group('value')
    def _on_strip_enable(self, value, button):
        index = list(self._strip_enable_buttons).index(button)
        self.log('_on_strip_enable: ' + str(index) + ', ' + str(value), True)
        self._device._do_strip_enable(index)

    def _update_strip_bank_buttons(self):
        self._bank_up_button.send_value(
            127 if self._device._channel_strip_bank != 0 else 0)
        self._bank_down_button.send_value(
            127 if self._device._channel_strip_bank != 2 else 0)

    def _update_strip_enable_buttons(self):
        for i in range(0, len(self._device._iso_rack_enable)):
            if self._strip_enable_buttons[i] is not None:
                on = self._device._iso_rack_enable[
                    i] and self._device._iso_rack_enable[i].value
                self._strip_enable_buttons[i].send_value(127 if on else 0)

    @subject_slot('value')
    def _on_skip_racks(self, value):
        if value == 127:
            self._device.toggle_enable_or_select()

    def _release_parameters(self, controls):
        if controls != None:
            for control in controls:
                if control != None:
                    control.release_parameter()

    def _create_transport(self):
        self.log('_create_transport: ' + str(self._has_transport), True)
        if not self._has_transport:
            return
        self._transport = TransportComponent()
        self._transport.set_stop_button(self._direct_bank_buttons[0])
        self._transport.set_play_button(self._direct_bank_buttons[1])
        self._transport.set_record_button(self._direct_bank_buttons[2])
        self._transport.set_overdub_button(self._direct_bank_buttons[3])

    def _create_session(self):
        self.log('_create_session', True)
        self._session = SessionComponent(self,
                                         name='BCR2K_Session',
                                         num_tracks=NUM_TRACKS,
                                         track_bank_size=self._track_bank_size,
                                         is_enabled=True,
                                         auto_name=True)
        self._session.layer = Layer(track_bank_left_button=self._left_button,
                                    track_bank_right_button=self._right_button)
        self._session.set_mixer(self._mixer)
        self._session._setup_controls()
        self._on_session_offset_changed.subject = self._session
        self._session.set_show_highlight(True)
        self._set_session_highlight(0, 0, 8, 1, False)

    @subject_slot('offset')
    def _on_session_offset_changed(self):
        self.log('_on_session_offset_changed')
        session = self._on_session_offset_changed.subject
        self._show_controlled_tracks_message(session)
        if hasattr(self._device, '_assign_channel_strip'
                   ) and self._device._assign_channel_strip:
            self._device._on_session_offset_changed()

    def _create_mixer(self):
        self.log('_create_mixer', True)
        mixer = MixerComponent(self,
                               NUM_TRACKS,
                               3,
                               show_returns=self._show_returns,
                               max_returns=self._max_returns,
                               show_master=self._show_master,
                               delayed_update=True,
                               is_enabled=True,
                               auto_name=True)
        layer = Layer(volume_controls=self._volume_encoders,
                      send_controls=self._send_encoders,
                      next_sends_button=self._bank_down_button,
                      prev_sends_button=self._bank_up_button)
        valid_opts = self._get_button_options()
        layer += Layer(**valid_opts)
        mixer.layer = layer
        self._mixer = mixer
        self._bcr_controls.setup_mixer_controls()
        self._modes.add_mode('mixer', [AddLayerMode(self._mixer, layer)])
        self._modes.selected_mode = 'mixer'

    def _get_button_options(self, channel_strip=False):
        opts = {}
        use_bottom_row_for_channel_strip = self._has_strip_device_enable
        if not use_bottom_row_for_channel_strip:
            channel_strip = False
        if self._has_pans:
            opts['pan_controls'] = self._pan_encoders
        opts[
            'track_select_buttons'] = self._push_buttons if self._button_row_1 == 'select' else (
                self._top_buttons if self._button_row_2 == 'select' else
                (self._bottom_buttons if self._button_row_3 == 'select'
                 and not channel_strip else None))
        opts[
            'mute_buttons'] = self._push_buttons if self._button_row_1 == 'mute' else (
                self._top_buttons if self._button_row_2 == 'mute' else
                (self._bottom_buttons if self._button_row_3 == 'mute'
                 and not channel_strip else None))
        opts[
            'solo_buttons'] = self._push_buttons if self._button_row_1 == 'solo' else (
                self._top_buttons if self._button_row_2 == 'solo' else
                (self._bottom_buttons if self._button_row_3 == 'solo'
                 and not channel_strip else None))
        opts[
            'arm_buttons'] = self._push_buttons if self._button_row_1 == 'arm' else (
                self._top_buttons if self._button_row_2 == 'arm' else
                (self._bottom_buttons if self._button_row_3 == 'arm'
                 and not channel_strip else None))
        valid_opts = {}
        for k, v in opts.iteritems():
            if v is not None:
                valid_opts[k] = v

        return valid_opts

    def _on_device_engage(self, value, channel_strip=False):
        self.log('_on_device_engage: ' + str(value) + ', channel_strip: ' +
                 str(channel_strip))
        if value == 127:
            if not channel_strip:
                self._session.set_mixer(None)
                self._session.layer = None
            self.set_device_component(self._device)
            self._device_mode = True
            self._bcr_controls._mode = 1
            self._modes.selected_mode = 'device_strip' if channel_strip else 'device'
            if self._use_32:
                self._mixer.set_volume_controls(None)
        else:
            self._device_mode = False
            self._bcr_controls._mode = 0
            self._bcr_controls.setup_mixer_controls(-1, -1, True, -1)
            if not channel_strip:
                self._session.set_mixer(self._mixer)
                self._session.layer = Layer(
                    track_bank_left_button=self._left_button,
                    track_bank_right_button=self._right_button)
            if self._fold_enabled or self._toggle_returns:
                if self._fold_enabled:
                    self._can_fold = self._selected_track != None and self._selected_track.is_foldable
                self._on_track_fold.subject = self._track_fold_button
            self._modes.selected_mode = 'mixer'
            if self._use_32:
                self._mixer.set_volume_controls(self._volume_encoders)

    def _create_device(self):
        self.log('_create_device', True)

        def make_button(identifier,
                        name,
                        midi_type=MIDI_CC_TYPE,
                        skin=self._default_skin):
            return ButtonElement(True,
                                 midi_type,
                                 MIXER_MODE,
                                 identifier,
                                 name=name,
                                 skin=skin)

        def make_encoder(identifier, name, bit_14=True):
            if self._bit_14:
                self.log('make_encoder: ' + name + ', CC: ' + str(identifier) +
                         ', 14_bit: ' + str(bit_14))
                control = EncoderElement(
                    MIDI_CC_TYPE,
                    MIXER_MODE,
                    identifier,
                    Live.MidiMap.MapMode.absolute_14_bit
                    if bit_14 else Live.MidiMap.MapMode.absolute,
                    name=name)
            else:
                control = EncoderElement(
                    MIDI_CC_TYPE,
                    MIXER_MODE,
                    identifier,
                    Live.MidiMap.MapMode.absolute if not self._relative else
                    Live.MidiMap.MapMode.relative_two_compliment,
                    name=name)
            return control

        if self._bit_14:
            volume_cc = 0
            sends_cc = 8
        else:
            volume_cc = 1
            sends_cc = 81
        if self._use_32:
            self._device_encoders = ButtonMatrixElement(
                rows=[[
                    make_encoder(volume_cc + i, 'Volume_%d' % (i + 1))
                    for i in xrange(8)
                ],
                      [
                          make_encoder(sends_cc + i, 'BCR_Device_0_%d' %
                                       (i + 1)) for i in xrange(8)
                      ],
                      [
                          make_encoder(sends_cc + 8 + i, 'BCR_Device_1_%d' %
                                       (i + 1)) for i in xrange(8)
                      ],
                      [
                          make_encoder(sends_cc + 16 + i, 'BCR_Device_2_%d' %
                                       (i + 1)) for i in xrange(8)
                      ]])
            self._send_encoders = self._device_encoders.submatrix[:8, 1:4]
        else:
            self._device_encoders = self._send_encoders
        if self._channel_strip:
            self._device = DeviceComponent_Strip(
                self,
                name='XL_Device',
                is_enabled=True,
                direct_bank=self._direct_bank,
                num_params=32 if self._use_32 else 24,
                path=self._my_path,
                delayed_update=True)
        else:
            self._device = DeviceComponent(
                self,
                name='XL_Device',
                is_enabled=True,
                direct_bank=self._direct_bank,
                num_params=32 if self._use_32 else 24,
                path=self._my_path,
                delayed_update=True)
        self.set_preditor_device_component(self._device)
        if self._direct_bank:
            device_layer = Layer(parameter_controls=self._device_encoders,
                                 device_select=self._top_buttons,
                                 device_enable=self._bottom_buttons,
                                 device_lock_button=self._track_fold_button,
                                 bank_up_button=self._bank_down_button,
                                 bank_down_button=self._bank_up_button,
                                 direct_bank=self._direct_bank_buttons)
        else:
            device_layer = Layer(parameter_controls=self._device_encoders,
                                 device_select=self._top_buttons,
                                 device_enable=self._bottom_buttons,
                                 device_lock_button=self._track_fold_button,
                                 bank_up_button=self._bank_down_button,
                                 bank_down_button=self._bank_up_button)
        device_settings_layer = Layer()
        self.device_mode = DeviceModeComponent(script=self,
                                               component=self._device,
                                               device_settings_mode=[
                                                   AddLayerMode(
                                                       self._device,
                                                       device_settings_layer)
                                               ],
                                               is_enabled=True)
        self.device_mode.layer = Layer(
            device_mode_button=self._device_engage_button)
        if self._has_pans:
            mixer_layer = Layer(volume_controls=self._volume_encoders,
                                pan_controls=self._pan_encoders)
        else:
            mixer_layer = Layer(volume_controls=self._volume_encoders)
        self._modes.add_mode('device', [
            AddLayerMode(self._device, device_layer),
            AddLayerMode(self._mixer, mixer_layer)
        ])
        if self._channel_strip:
            if hasattr(self._device, 'enable_channel_strip'):
                strip_layer = Layer(parameter_controls=self._device_encoders)
                valid_opts = self._get_button_options(True)
                mixer_layer += Layer(**valid_opts)
                self._modes.add_mode('device_strip', [
                    AddLayerMode(self._device, strip_layer),
                    AddLayerMode(self._mixer, mixer_layer),
                    AddLayerMode(
                        self._session,
                        Layer(track_bank_left_button=self._left_button,
                              track_bank_right_button=self._right_button))
                ])
            else:
                self._channel_strip = False

    def update(self):
        self.log('update: device_mode: ' + str(self._device_mode))
        super(BCRXL, self).update()

    def refresh_state(self):
        self.log('refresh_state')
        super(BCRXL, self).refresh_state()

    def handle_sysex(self, midi_bytes):
        if self._LOG_SYSEX:
            self.log('handle_sysex: ' + str(midi_bytes))
        if midi_bytes[:4] == BCR_SYSEX[:4] and midi_bytes[5] == 21:
            if self._bcr_controls.receive_ack(midi_bytes):
                if self._device_mode:
                    self._device.map_controls()
                else:
                    self._mixer.map_controls()
            if midi_bytes[9:10] != (0, ):
                self.log('Received sysex error code: ' + str(midi_bytes), True)

    @subject_slot_group('value')
    def _on_select_pressed(self, value, button):
        pass

    def same_track_selected(self):
        self.log('BCRXL: same_track_selected')
        selected_track = self.song().view.selected_track
        if selected_track != None:
            if self._device_mode:
                self.song().view.selected_track = self.song().master_track
            elif self._button_reselect_track == 'mute':
                selected_track.mute = not selected_track.mute
            elif self._button_reselect_track == 'solo':
                selected_track.solo = not selected_track.solo
            elif self._button_reselect_track == 'arm':
                if selected_track.can_be_armed:
                    selected_track.arm = not selected_track.arm
            elif self._button_reselect_track == 'fold':
                if self._selected_track.is_foldable:
                    self._selected_track.fold_state = not self._selected_track.fold_state
        return False
class MaschineMk2(ControlSurface):
    __module__ = __name__
    __doc__ = 'Control Script for Maschine Mk2 and Maschine Mikro Mk2'

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance, False)
        with self.component_guard():
            self._suppress_send_midi = True
            self.togglecolor = (10, 30, 50, 70, 90)
            self.toggleindex = 0
            self._c_ref = c_instance
            self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143
            self._c_inst = c_instance
            is_momentary = True
            self._active = True
            self._modifier_down = False
            self._return_mode = 0
            self._returntopad = False
            self._mode = CLIP_MODE
            self.init_slot = 0
            self.init_done = False
            self._midi_pause_count = 0
            self.nav_index = 0
            self._base_note = 0
            self._octave = 0.55
            self._scale_select_mode = MODE_PRESS_NONE
            self.send_slider_index = 0
            self._pad_mode = PM_OFF
            self._note_display_mode = ND_KEYBOARD1
            self._set_suppress_rebuild_requests(True)
            self._scenematrix = SceneMatrix(self)
            self._master_knob = Mk2KnobControl(self)
            self._device = self._set_up_device_control()
            self.show_message(str(''))
            self.request_rebuild_midi_map()
            self._set_global_buttons()
            self._set_mode_buttons()
            self._setup_transport()
            self._set_modecontrol()
            self._set_up_session()
            self._set_up_mixer()
            self._set_up_timer()
            self._set_up_machine_knobs()
            self.current_scale_index = 0
            self.assign_transpose(SCALES[self.current_scale_index])
            self.set_highlighting_session_component(self._session)
            self._navigate_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 127)
            self._navigate_button.add_value_listener(self._do_focus_navigate)
            self.display_update_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 86)
            self.display_update_button.add_value_listener(self._a_display_update)
            self._set_suppress_rebuild_requests(False)
            self.song().view.add_detail_clip_listener(self.clip_handle)
            self.song().add_visible_tracks_listener(self.clip_handle)
            self.song().add_scenes_listener(self.clip_handle)
            self.application().view.add_view_focus_changed_listener(self.focus_changed)
            self.log_message('########## LIVE 9 MASCHINE MK2 V 1.02 #############')
            self._suppress_send_midi = False

    def _set_up_mixer(self):
        is_momentary = True
        self._mixer = MixerComponent(8)
        self.send_sliders = []
        for track in range(8):
            self.send_sliders.append(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, SEND_CC_OFF + track))

        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.set_arm_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, ARM_CC_OFF + track))
            strip.set_solo_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SOLO_CC_OFF + track))
            strip.set_mute_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, MUTE_CC_OFF + track))
            strip.set_volume_control(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, LEVEL_CC_OFF + track))
            strip.set_pan_control(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, PAN_CC_OFF + track))
            strip.set_select_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SELECT_CC_OFF + track))
            st = tuple([self.send_sliders[track]])
            strip.set_send_controls(st)

        self.send_slider_toggle_button = StateButton(False, MIDI_CC_TYPE, 0, 90)
        self.send_slider_toggle_button.add_value_listener(self._do_toggle_send)
        self._session.set_mixer(self._mixer)

    def _set_global_buttons(self):
        is_momentary = True
        self._undo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 85)
        self._undo_button.add_value_listener(self._do_undo)
        self._redo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 87)
        self._redo_button.add_value_listener(self._do_redo)
        self._armsolomode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 89)
        self._armsolomode_button.add_value_listener(self._do_armsolo_mode)
        self._fire_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 9)
        self._fire_button.add_value_listener(self._do_fire_button)
        self.track_left_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 120)
        self.track_right_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 121)
        self.track_left_button.add_value_listener(self._a_trk_left)
        self.track_right_button.add_value_listener(self._a_trk_right)
        self.test_button = StateButton(True, MIDI_CC_TYPE, 5, 60)
        self.note_repeat_button = StateButton(True, MIDI_CC_TYPE, 5, 61)
        self.test_button.add_value_listener(self.do_test)
        self.note_repeat_button.add_value_listener(self.do_note_repeat)
        self.reset_test_button = StateButton(True, MIDI_CC_TYPE, 5, 62)
        self.reset_test_button.add_value_listener(self.do_reset)

    def _set_mode_buttons(self):
        self.xfade_assign_button = StateButton(True, MIDI_CC_TYPE, 0, 116)
        self._pad_select_button = StateButton(False, MIDI_CC_TYPE, 0, 117)
        self._pad_solo_button = StateButton(False, MIDI_CC_TYPE, 0, 118)
        self._mute_button = StateButton(False, MIDI_CC_TYPE, 0, 119)
        self._pad_scale_up = GatedColorButton(True, MIDI_CC_TYPE, 83, 0)
        self._pad_scale_down = GatedColorButton(True, MIDI_CC_TYPE, 94, 16)
        self._pad_select_button.add_value_listener(self._do_pad_select_multi)
        self._mute_button.add_value_listener(self._do_mute_button)
        self._pad_solo_button.add_value_listener(self._do_pad_solo_multi)
        self.xfade_assign_button.add_value_listener(self._do_xfade_assign)
        self._pad_scale_up.add_value_listener(self._do_pad_note_up)
        self._pad_scale_down.add_value_listener(self._do_pad_note_down)

    def set_appointed_device(self, device):
        with self.component_guard():
            self._device_component.set_device(device)

    def _set_up_device_control(self):
        is_momentary = True
        device = MaschineDeviceComponent(self)
        device.set_device_changed_listener(self._handle_device_changed)
        device.set_device_parm_listener(self._hande_device_parm_changed)
        param_controls = []
        for index in range(8):
            param_controls.append(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_CC_OFF + index))

        device.set_parameter_controls(tuple(param_controls))
        device.set_on_off_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF))
        device.set_bank_nav_buttons(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 4), ButtonElement(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 5))
        self._device_nav_button_left = StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 6)
        self._device_nav_button_right = StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 7)
        self._device_nav_button_left.add_value_listener(self._nav_value_left)
        self._device_nav_button_right.add_value_listener(self._nav_value_right)
        device.name = 'Device_Component'
        self.set_device_component(device)
        return device

    def _setup_transport(self):
        is_momentary = True
        transport = TransportComponent()
        playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108)
        stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110)
        recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109)
        overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107)
        metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104)
        playButton.name = 'Play'
        stopButton.name = 'Stop'
        recordButton.name = 'Record'
        overdubButton.name = 'Overdub'
        metrononmeButton.name = 'Metronome'
        transport.set_play_button(playButton)
        transport.set_stop_button(stopButton)
        transport.set_record_button(recordButton)
        transport.set_overdub_button(overdubButton)
        transport.set_metronome_button(metrononmeButton)
        transport.set_nudge_buttons(StateButton(is_momentary, MIDI_CC_TYPE, 1, 51), StateButton(is_momentary, MIDI_CC_TYPE, 1, 50))
        punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52)
        punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53)
        punchinbutton.name = 'Punch In'
        punchoutbutton.name = 'Punch Out'
        transport.set_punch_buttons(punchinbutton, punchoutbutton)
        transport.set_loop_button(StateButton(is_momentary, MIDI_CC_TYPE, 1, 54))
        self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59)
        self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58)
        transport.set_seek_buttons(self.transp_ff_button, self.transp_rw_button)
        self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 100)
        self.xfadeKnob.connect_to(self.song().master_track.mixer_device.crossfader)
        self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88)
        self.tap_button.add_value_listener(self._do_tap_tempo)
        self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 55)
        self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56)
        self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57)
        self.cue_add_delete_button.add_value_listener(self._do_toggle_cue)
        self.cue_prev_button.add_value_listener(self._do_toggle_prev_cue)
        self.cue_next_button.add_value_listener(self._do_toggle_next_cue)

    def _set_up_machine_knobs(self):
        master_track = self.song().master_track
        self.master_volume = SliderElement(MIDI_CC_TYPE, 0, 40)
        self.prehear = SliderElement(MIDI_CC_TYPE, 0, 41)
        self.master_volume.connect_to(master_track.mixer_device.volume)
        self.prehear.connect_to(master_track.mixer_device.cue_volume)

    def _set_up_session(self):
        is_momentary = True
        self._session = MaschineSessionComponent()
        self._session.add_offset_listener(self.notify_track_scroll)
        nhue = COLOR_HUE_NAV
        self.nav_buttons = (GatedColorButton(True, MIDI_CC_TYPE, 92, nhue),
         GatedColorButton(True, MIDI_CC_TYPE, 81, nhue),
         GatedColorButton(True, MIDI_CC_TYPE, 93, nhue),
         GatedColorButton(True, MIDI_CC_TYPE, 91, nhue))
        self._session.set_scene_bank_buttons(self.nav_buttons[0], self.nav_buttons[1])
        self._session.set_track_bank_buttons(self.nav_buttons[2], self.nav_buttons[3])
        self._session.set_stop_all_clips_button(StateButton(is_momentary, MIDI_CC_TYPE, 0, 111))
        track_stop_buttons = [ StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, index + STOP_CC_OFF) for index in range(4) ]
        self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
        self._init_matrix()
        self._set_up_buttons()
        self._session._link()
        self._session.set_advance(STEP4)

    def _set_up_buttons(self):
        self._bmatrix = ButtonMatrixElement()
        for scene_index in range(4):
            button_row = []
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                button = self._matrix[scene_index][track_index]
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(button)
                clip_slot.set_triggered_to_play_value(1)
                clip_slot.set_triggered_to_record_value(1)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(1)
                clip_slot.set_stopped_value(1)

            self._bmatrix.add_row(tuple(button_row))

    def _init_matrix(self):
        is_momentary = True
        self._button_sequence = []
        self._matrix = []
        for scene_index in range(4):
            button_row = []
            for track_index in range(4):
                button = VarButtonElement(is_momentary, 0, scene_index, track_index, self)
                partner = TwinButton(is_momentary, 1, button)
                partner.add_value_listener(self.ox, True)
                button_row.append(button)

            self._matrix.append(tuple(button_row))

        for scene_index in [3,
         2,
         1,
         0]:
            for track_index in range(4):
                self._button_sequence.append(self._matrix[scene_index][track_index])

        self._session.set_matrix(self._matrix)

    def set_pad_translations(self, pad_translations):
        ControlSurface.set_pad_translations(pad_translations)

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

    def ox(self, value, button):
        if not isinstance(button, TwinButton):
            raise AssertionError
            self._mode == PAD_MODE and button.fire(value)

    def _update_hardware(self):
        self._session.update()
        self._set_suppress_rebuild_requests(True)
        self._set_mode()
        self._master_knob.update()
        if self._scenematrix.soloexclusive:
            self._armsolomode_button.send_value(1, True)
        else:
            self._armsolomode_button.send_value(0, True)
        self._master_knob.start_up()
        self._pad_scale_up.activate()
        self._pad_scale_down.activate()
        self.current_scale_to_display()
        self.send_to_display(KEY_COLOR_MODES_STRINGS[self._note_display_mode], 1)
        for scene_index in range(4):
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                button = self._matrix[scene_index][track_index]
                button.refresh()

        self._set_suppress_rebuild_requests(False)

    def get_color(self, value, track_index, scene_index):
        if not self._active:
            return
        if self._mode == SCENE_MODE or self._mode == CONTROL_MODE or self._pad_mode == PM_ON:
            element = self._scenematrix.get_element(scene_index, track_index)
            return element.get_color(value)
        elif self._mode == CLIP_MODE:
            scene = self._session.scene(scene_index)
            clip_slot = scene.clip_slot(track_index)._clip_slot
            cindex = 0
            if value == 0:
                cindex = 1
            if clip_slot != None:
                if clip_slot.has_clip:
                    if clip_slot.clip.is_recording or clip_slot.clip.will_record_on_start:
                        return PColor.CLIP_RECORD[cindex]
                    if clip_slot.clip.is_playing:
                        return PColor.CLIP_PLAY[cindex]
                    elif clip_slot.clip.is_triggered:
                        return PColor.CLIP_PLAY[cindex]
                    else:
                        return PColor.CLIP_STOPPED[cindex]
                elif clip_slot.will_record_on_start:
                    return PColor.CLIP_RECORD[cindex]
                elif clip_slot.is_playing:
                    return PColor.CLIP_GROUP_PLAY[cindex]
                elif clip_slot.controls_other_clips:
                    return PColor.CLIP_GROUP_CONTROL[cindex]
                elif clip_slot.is_triggered:
                    return PColor.CLIP_GROUP_TRIGGER[cindex]
        elif self._mode == PAD_MODE:
            button = self._matrix[scene_index][track_index]
            return self.get_color_by_note_mode(button.get_identifier(), value > 0)

    def step_key_color_mode(self):
        self._note_display_mode = (self._note_display_mode + 1) % len(KEY_COLOR_MODES_STRINGS)
        self.show_message('Pad Mode Key Color = ' + KEY_COLOR_MODES_STRINGS[self._note_display_mode])
        self.send_to_display('Colors: ' + KEY_COLOR_MODES_STRINGS[self._note_display_mode], 1)
        if self._mode == PAD_MODE:
            for note_index in range(16):
                button = self._button_sequence[note_index]
                button.send_color_direct(self.get_color_by_note_mode(button.get_identifier(), False))

    def get_color_by_note_mode(self, midi_note, on):
        if self._note_display_mode == ND_BASE_OTHER:
            interval = (midi_note + 12 - self._base_note) % 12
            if on:
                return INTERVAL_COLOR_MAP[interval][0]
            else:
                return INTERVAL_COLOR_MAP[interval][1]
        elif on:
            return KEY_COLOR_MAP[midi_note % 12][0]
        else:
            return KEY_COLOR_MAP[midi_note % 12][1]

    def _send_midi(self, midi_bytes, **keys):
        self._c_ref.send_midi(midi_bytes)
        if self._midi_pause_count == 2:
            time.sleep(0.002)
            self._midi_pause_count = 0
        else:
            self._midi_pause_count = self._midi_pause_count + 1
        return True

    def clip_handle(self):
        if self._mode == SCENE_MODE or self._mode == CONTROL_MODE or self._modifier_down:
            self._scenematrix.update()

    def _a_display_update(self, value):
        if not self.display_update_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            (value != 0 or not self.display_update_button.is_momentary()) and self._update_hardware()
            self.show_message('Maschine Display Updated')

    def _set_up_timer(self):
        self.blink_state = 1

    def update_display(self):
        with self.component_guard():
            with self._is_sending_scheduled_messages():
                self._task_group.update(0.1)
            if self._mode == CLIP_MODE and not self._modifier_down:
                if self.blink_state == 0:
                    self._session.notify(1, 0)
                elif self.blink_state == 1:
                    self._session.notify(1, 1)
                elif self.blink_state == 3:
                    self._session.notify(2, 0)
                elif self.blink_state == 4:
                    self._session.notify(2, 1)
            elif self._mode == PAD_MODE:
                pass
            elif self.blink_state == 0:
                self._scenematrix.notify_scene_mode(1)
            elif self.blink_state == 2:
                self._scenematrix.notify_scene_mode(0)
            self.blink_state = (self.blink_state + 1) % 4
            self.init_slot += 1

    def _invoke_track_edit(self, mode):
        self._deassign_matrix()
        self._scenematrix.assign()
        self._scenematrix.set_mode(mode)
        self._pad_mode = PM_ON
        self.request_rebuild_midi_map()
        self._scenematrix.update()

    def _set_modecontrol(self):
        is_momentary = True
        self.scene_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 112)
        self.clip_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 113)
        self.pad_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 114)
        self.control_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 115)
        self.xfade_assign_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 116)
        self.scene_mode_button.add_value_listener(self._a_mode_scene)
        self.clip_mode_button.add_value_listener(self._a_mode_clip)
        self.pad_mode_button.add_value_listener(self._a_mode_pad)
        self.control_mode_button.add_value_listener(self._a_mode_control)

    def _set_mode(self, mode = None):
        if mode == None:
            mode = self._mode
        if mode == SCENE_MODE:
            self.clip_mode_button.send_value(OFF_VALUE, True)
            self.pad_mode_button.send_value(OFF_VALUE, True)
            self.control_mode_button.send_value(OFF_VALUE, True)
            self.scene_mode_button.send_value(ON_VALUE, True)
        elif mode == CLIP_MODE:
            self.scene_mode_button.send_value(OFF_VALUE, True)
            self.pad_mode_button.send_value(OFF_VALUE, True)
            self.control_mode_button.send_value(OFF_VALUE, True)
            self.clip_mode_button.send_value(ON_VALUE, True)
        elif mode == PAD_MODE:
            self.scene_mode_button.send_value(OFF_VALUE, True)
            self.clip_mode_button.send_value(OFF_VALUE, True)
            self.control_mode_button.send_value(OFF_VALUE, True)
            self.pad_mode_button.send_value(ON_VALUE, True)
        elif mode == CONTROL_MODE:
            self.scene_mode_button.send_value(OFF_VALUE, True)
            self.clip_mode_button.send_value(OFF_VALUE, True)
            self.pad_mode_button.send_value(OFF_VALUE, True)
            self.control_mode_button.send_value(ON_VALUE, True)

    def _reset_matrix(self):
        for scene_index in range(4):
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                button = self._matrix[scene_index][track_index]
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(button)

    def update_button_matrix(self):
        self._session.update()
        for scene_index in range(4):
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                button = self._matrix[scene_index][track_index]
                clip_slot = scene.clip_slot(track_index)
                if clip_slot._clip_slot != None and clip_slot._clip_slot.clip != None:
                    button.send_value(1, True)
                else:
                    button.send_value(0, True)

    def _deassign_matrix(self):
        for scene_index in range(4):
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(None)

    def _from_pad_mode(self, matrix_mode):
        self._mode = SCENE_MODE
        self._register_buttons()
        self._scenematrix.assign()
        self._scenematrix.set_mode(matrix_mode)
        self._set_suppress_rebuild_requests(True)
        self.request_rebuild_midi_map()
        self._scenematrix.update()
        self._set_suppress_rebuild_requests(False)

    def _enter_pad_mode(self):
        self._set_mode(PAD_MODE)
        if self._mode == CLIP_MODE:
            self._deassign_matrix()
        elif self._mode == SCENE_MODE:
            self._scenematrix.deassign()
        elif self._mode == CONTROL_MODE:
            self._scenematrix.deassign()
            self._master_knob.exit_matrix_mode()
        self._mode = PAD_MODE
        self._set_suppress_rebuild_requests(True)
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                button.send_value(0, True)
                button.set_to_notemode(True)
                self._forwarding_registry[MIDI_NOTE_ON_STATUS, button.get_identifier()] = button
                self._forwarding_registry[MIDI_NOTE_OFF_STATUS, button.get_identifier()] = button

        self._set_suppress_rebuild_requests(False)

    def _register_buttons(self, update = False):
        self._set_suppress_rebuild_requests(True)
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                button.set_to_notemode(False)
                if update:
                    button.send_value(127, True)
                fwkey = [MIDI_NOTE_ON_STATUS]
                fwkey.append(button.get_identifier())
                self._forwarding_registry[tuple(fwkey)] = button
                self._forwarding_registry[MIDI_NOTE_OFF_STATUS, button.get_identifier()] = button

        self._set_suppress_rebuild_requests(False)

    def _back_to_clip_mode(self):
        self._pad_mode = PM_OFF
        self._scenematrix.set_mode(SCENE_MODE_NORMAL)
        self._scenematrix.deassign()
        self._set_up_clip_matrix()

    def _set_up_clip_matrix(self):
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                button.set_to_notemode(False)

        self._set_suppress_rebuild_requests(True)
        self.request_rebuild_midi_map()
        self._reset_matrix()
        self.update_button_matrix()
        self._set_suppress_rebuild_requests(False)

    def _enter_scene_mode(self):
        self._set_mode(SCENE_MODE)
        if self._mode == CLIP_MODE:
            self._deassign_matrix()
        elif self._mode == CONTROL_MODE:
            self._master_knob.exit_matrix_mode()
        elif self._mode == PAD_MODE:
            self._register_buttons()
        self._mode = SCENE_MODE
        self._scenematrix.assign()
        self._scenematrix.set_mode(SCENE_MODE_NORMAL)
        self._return_mode = SCENE_MODE_NORMAL
        self.request_rebuild_midi_map()

    def _enter_clip_mode(self):
        self._set_suppress_rebuild_requests(True)
        self._set_mode(CLIP_MODE)
        if self._mode == SCENE_MODE:
            self._scenematrix.deassign()
        elif self._mode == CONTROL_MODE:
            self._master_knob.exit_matrix_mode()
        self._mode = CLIP_MODE
        self._set_up_clip_matrix()
        self.request_rebuild_midi_map()
        self._set_suppress_rebuild_requests(False)

    def _enter_control_mode(self):
        self._set_mode(CONTROL_MODE)
        if self._mode == CLIP_MODE:
            self._deassign_matrix()
        elif self._mode == PAD_MODE:
            self._mode = CONTROL_MODE
            self._register_buttons()
        self._mode = CONTROL_MODE
        self._set_suppress_rebuild_requests(True)
        self._scenematrix.set_mode(SCENE_MODE_CONTROL)
        self._return_mode = SCENE_MODE_CONTROL
        self._scenematrix.assign()
        self._master_knob.switch_to_matrix_mode()
        self._set_suppress_rebuild_requests(False)
        self.request_rebuild_midi_map()
        self._scenematrix.update()

    def _a_mode_scene(self, value):
        if not self.scene_mode_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.show_message('SCENE MODE')
            self._enter_scene_mode()

    def _a_mode_clip(self, value):
        if not self.clip_mode_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.show_message('CLIP MODE')
            self._enter_clip_mode()

    def _a_mode_pad(self, value):
        if not self.pad_mode_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.show_message('PAD MODE')
            self._enter_pad_mode()

    def _a_mode_control(self, value):
        if not self.control_mode_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.show_message('CONTROL MODE')
            self._enter_control_mode()

    def _do_pad_select_multi(self, value):
        if not value in range(128):
            raise AssertionError
            self._modifier_down = value != 0
            if self._mode == PAD_MODE or self._returntopad:
                value != 0 and self._from_pad_mode(SCENE_MODE_SELECT)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == CLIP_MODE:
            if value != 0:
                self._invoke_track_edit(SCENE_MODE_SELECT)
            else:
                self._back_to_clip_mode()
        elif self._mode != PAD_MODE:
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_SELECT)

    def _do_mute_button(self, value):
        if not self._mute_button != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                self._modifier_down = value != 0
                (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_MUTE)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE:
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
                self._pad_mode = PM_OFF
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_MUTE)
                self._pad_mode = PM_ON
        elif self._mode == CLIP_MODE:
            if value > 0:
                self._invoke_track_edit(SCENE_MODE_MUTE)
            else:
                self._back_to_clip_mode()
                self._pad_mode = PM_OFF

    def _do_pad_solo_multi(self, value):
        if not value in range(128):
            raise AssertionError
            self._modifier_down = value != 0
            if self._mode == PAD_MODE or self._returntopad:
                value != 0 and self._from_pad_mode(SCENE_MODE_SOLO)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == CLIP_MODE:
            if value != 0:
                self._invoke_track_edit(SCENE_MODE_SOLO)
            else:
                self._back_to_clip_mode()
        elif self._mode != PAD_MODE:
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_SOLO)

    def _do_xfade_assign(self, value):
        if not self.xfade_assign_button != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_XFADE)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == CLIP_MODE:
            if value != 0:
                self._invoke_track_edit(SCENE_MODE_XFADE)
            else:
                self._back_to_clip_mode()
        elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE:
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_XFADE)

    def _do_pad_note_up(self, value):
        if not self._pad_scale_up != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                self._pad_scale_up.send_value(value, True)
                self._modifier_down = value != 0
                (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_ARM)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == CLIP_MODE:
            self.show_message('Arm tracks with pads')
            if value != 0:
                self._invoke_track_edit(SCENE_MODE_ARM)
            else:
                self._back_to_clip_mode()
        elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE:
            self.show_message('Arm tracks with pads')
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_ARM)

    def _do_pad_note_down(self, value):
        if not self._pad_scale_down != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                self._pad_scale_down.send_value(value, True)
                self._modifier_down = value != 0
                (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_STOP)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == CLIP_MODE:
            self.show_message('Stop tracks with pads')
            if value != 0:
                self._invoke_track_edit(SCENE_MODE_STOP)
            else:
                self._back_to_clip_mode()
        elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE:
            self.show_message('Stop tracks with pads')
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_STOP)

    def modify_track_offset(self, delta):
        self._scenematrix.mod_track_offset(delta)

    def modify_scene_offset(self, delta):
        self._scenematrix.mod_scene_offset(delta)

    def move_view_horizontal(self, delta):
        if delta == 1:
            self._session.bank_right()
        else:
            self._session.bank_left()
        if self._mode == CONTROL_MODE:
            self._scenematrix.update()

    def inc_octave(self, inc):
        scale = SCALES[self.current_scale_index]
        octave = scale.to_octave(self._octave)
        newoctave = octave + inc
        if newoctave < 0:
            newoctave = 0
        elif newoctave > scale.octave_range:
            newoctave = scale.octave_range
        self._octave = scale.to_relative(newoctave, self._octave)
        scale = SCALES[self.current_scale_index]
        self.show_message(' OCTAVE ' + BASE_NOTE[self._base_note] + str(newoctave - 2) + ' to ' + scale.name)
        self.current_scale_to_display()

    def inc_base_note(self, inc):
        newbase = self._base_note + inc
        if newbase < 0:
            self._base_note = 0
        elif newbase > 11:
            self._base_note = 11
        else:
            self._base_note = newbase
        scale = SCALES[self.current_scale_index]
        self.show_message(' Base Note ' + BASE_NOTE[self._base_note] + ' to ' + scale.name)
        self.current_scale_to_display()

    def current_scale_to_display(self):
        scale = SCALES[self.current_scale_index]
        text = scale.name + ' ' + BASE_NOTE[self._base_note] + str(scale.to_octave(self._octave))
        self.send_to_display(text)

    def inc_scale(self, inc):
        nr_of_scales = len(SCALES)
        newindex = self.current_scale_index + inc
        if newindex < 0:
            newindex = 0
        elif newindex >= nr_of_scales:
            newindex = nr_of_scales - 1
        else:
            self.current_scale_index += inc
        newscale = SCALES[self.current_scale_index]
        self.show_message(' PAD Scale ' + newscale.name + ' ' + BASE_NOTE[self._base_note] + str(newscale.to_octave(self._octave) - 2))
        self.current_scale_to_display()

    def update_transpose(self):
        self.assign_transpose(SCALES[self.current_scale_index])
        self._set_suppress_rebuild_requests(True)
        self.request_rebuild_midi_map()
        self._set_suppress_rebuild_requests(False)

    def set_scale(self, scale):
        raise isinstance(scale, PadScale) or AssertionError
        scale_len = len(scale.notevalues)
        octave = scale.to_octave(self._octave)

    def assign_transpose(self, scale):
        raise isinstance(scale, PadScale) or AssertionError
        scale_len = len(scale.notevalues)
        octave = scale.to_octave(self._octave)
        last_note_val = None
        for note_index in range(16):
            button = self._button_sequence[note_index]
            scale_index = note_index % scale_len
            octave_offset = note_index / scale_len
            note_value = scale.notevalues[scale_index] + self._base_note + octave * 12 + octave_offset * 12
            if note_value < 128:
                last_note_val = note_value
            elif last_note_val != None:
                note_value = last_note_val
            button.set_send_note(note_value)
            if self._mode == PAD_MODE:
                button.send_color_direct(self.get_color_by_note_mode(note_value, False))

    def do_reset(self, value):
        if value == 0:
            return
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                data_byte1 = button._original_identifier
                button.send_midi((MIDI_CC_STATUS + 2, data_byte1, 0))

    def do_test(self, value):
        color = self.togglecolor[self.toggleindex]
        self.toggleindex = (self.toggleindex + 1) % len(self.togglecolor)
        if value == 0:
            return
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                self.schedule_message(1, self.dosend, (color,
                 127,
                 127,
                 row,
                 column))

    def dosend(self, parm = None):
        button = self._matrix[parm[3]][parm[4]]
        data_byte1 = button._original_identifier
        button.send_midi((MIDI_CC_STATUS + 0, data_byte1, parm[0]))
        button.send_midi((MIDI_CC_STATUS + 1, data_byte1, parm[1]))
        button.send_midi((MIDI_CC_STATUS + 2, data_byte1, parm[2]))

    def do_note_repeat(self, value):
        nrvalue = 0
        if value != 0:
            nrvalue = 1
        self._c_ref.set_note_repeat_state(nrvalue)

    def _do_toggle_send(self, value):
        nr_of_tracks = len(self.song().return_tracks)
        if value == 0 or nr_of_tracks < 1:
            return
        prev = self.send_slider_index
        self.send_slider_index += 1
        if self.send_slider_index >= nr_of_tracks:
            self.send_slider_index = 0
        self.show_message(' Set Send ' + str(SENDS[self.send_slider_index]))
        if prev != self.send_slider_index:
            for track in range(8):
                strip = self._mixer.channel_strip(track)
                slider_list = []
                for index in range(self.send_slider_index + 1):
                    if index < self.send_slider_index - 1:
                        slider_list.append(None)
                    else:
                        slider_list.append(self.send_sliders[track])
                    strip.set_send_controls(tuple(slider_list))

    def _do_armsolo_mode(self, value):
        if not self._armsolomode_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self._scenematrix.set_armsolo_exclusive(self._armsolomode_button)

    def _do_fire_button(self, value):
        if not self._fire_button != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                clip_slot = (value != 0 or not self._mute_button.is_momentary()) and self.song().view.highlighted_clip_slot
                clip_slot and clip_slot.fire()

    def _do_undo(self, value):
        if not self._undo_button != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                (value != 0 or not self._undo_button.is_momentary()) and self.song().can_undo == 1 and self.song().undo()
                self.show_message(str('UNDO'))

    def _do_redo(self, value):
        if not self._redo_button != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                (value != 0 or not self._redo_button.is_momentary()) and self.song().can_redo == 1 and self.song().redo()
                self.show_message(str('REDO'))

    def _a_trk_left(self, value):
        if not value in range(128):
            raise AssertionError
            if value != 0:
                direction = self.application().view.is_view_visible('Session') and Live.Application.Application.View.NavDirection.left
                self.application().view.scroll_view(direction, 'Session', True)

    def _a_trk_right(self, value):
        if not value in range(128):
            raise AssertionError
            if value != 0:
                direction = self.application().view.is_view_visible('Session') and Live.Application.Application.View.NavDirection.right
                self.application().view.scroll_view(direction, 'Session', True)

    def _nav_value_left(self, value):
        if not self._device_nav_button_left != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                modifier_pressed = True
                value > 0 and (not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain')) and self.application().view.show_view('Detail')
                self.application().view.show_view('Detail/DeviceChain')
            else:
                direction = Live.Application.Application.View.NavDirection.left
                self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)

    def _nav_value_right(self, value):
        if not self._device_nav_button_right != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                modifier_pressed = value > 0 and True
                (not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain')) and self.application().view.show_view('Detail')
                self.application().view.show_view('Detail/DeviceChain')
            else:
                direction = Live.Application.Application.View.NavDirection.right
                self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)

    def _do_tap_tempo(self, value):
        if not value in range(128):
            raise AssertionError
            value > 0 and self.song().tap_tempo()

    def _do_toggle_cue(self, value):
        if not value in range(128):
            raise AssertionError
            value > 0 and self.song().set_or_delete_cue()

    def _do_toggle_prev_cue(self, value):
        if not value in range(128):
            raise AssertionError
            value > 0 and self.song().jump_to_prev_cue()

    def _do_toggle_next_cue(self, value):
        if not value in range(128):
            raise AssertionError
            value > 0 and self.song().jump_to_next_cue()

    def focus_changed(self):
        pass

    def _handle_device_changed(self, device):
        pass

    def _hande_device_parm_changed(self):
        pass

    def _do_focus_navigate(self, value):
        if not self._navigate_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            self.nav_index = value != 0 and (self.nav_index + 1) % len(VIEWS_ALL)
            self.application().view.focus_view(VIEWS_ALL[self.nav_index])
            self.show_message('Focus on : ' + str(VIEWS_ALL[self.nav_index]))

    def scroll_focus(self, delta):
        if delta == 1:
            self.nav_index = (self.nav_index + 1) % len(VIEWS_ALL)
        elif self.nav_index == 0:
            self.nav_index = len(VIEWS_ALL) - 1
        else:
            self.nav_index -= 1
        self.show_message('Focus on : ' + str(VIEWS_ALL[self.nav_index]))
        self.application().view.focus_view(VIEWS_ALL[self.nav_index])

    def scroll_device(self, delta):
        if not (delta == 1 or delta == -1):
            raise AssertionError
            direction = delta == 1 and Live.Application.Application.View.NavDirection.right
        else:
            direction = Live.Application.Application.View.NavDirection.left
        self.application().view.scroll_view(direction, 'Detail/DeviceChain', True)

    def scroll_scene(self, delta):
        if not self.track_left_button != None:
            raise AssertionError
            raise delta == 1 or delta == -1 or AssertionError
            direction = delta == 1 and Live.Application.Application.View.NavDirection.down
        else:
            direction = Live.Application.Application.View.NavDirection.up
        self.application().view.scroll_view(direction, 'Session', True)

    def index_in_strip(self, track):
        for ind in range(len(self._mixer._channel_strips)):
            strack = self._mixer._channel_strips[ind]._track
            if strack == track:
                return ind

        return -1

    def notify_track_scroll(self):
        self._scenematrix.update_control_selection()
        if self._mode == CONTROL_MODE:
            self._scenematrix.eval_matrix()
            self._scenematrix.fire_values()

    def send_to_display(self, text, grid = 0):
        if USE_DISPLAY == False:
            return
        if len(text) > 28:
            text = text[:27]
        msgsysex = [240,
         0,
         0,
         102,
         23,
         18,
         min(grid, 3) * 28]
        filled = text.ljust(28)
        for c in filled:
            msgsysex.append(ord(c))

        msgsysex.append(247)
        self._send_midi(tuple(msgsysex))

    def send_color(self, button, hue, sat, bright):
        raise isinstance(button, ButtonElement) or AssertionError
        raise hue in range(128) or AssertionError
        raise sat in range(128) or AssertionError
        raise bright in range(128) or AssertionError
        data_byte1 = button._original_identifier
        button.send_midi((MIDI_CC_STATUS + 2, data_byte1, bright))
        button.send_midi((MIDI_CC_STATUS + 1, data_byte1, sat))
        button.send_midi((MIDI_CC_STATUS + 0, data_byte1, hue))

    def turn_off_matrix(self):
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                self.send_color(button, 2, 0, 0)
                button.set_to_notemode(False)

    def remove_listener(self, control, callback):
        if control != None and control.value_has_listener(callback):
            control.remove_value_listener(callback)
        control.disconnect()

    def disconnect(self):
        self.turn_off_matrix()
        self.scene_mode_button.send_value(0, True)
        self.clip_mode_button.send_value(0, True)
        self.pad_mode_button.send_value(0, True)
        self.control_mode_button.send_value(0, True)
        time.sleep(0.2)
        self._active = False
        self._suppress_send_midi = True
        self.remove_listener(self.scene_mode_button, self._a_mode_scene)
        self.remove_listener(self.clip_mode_button, self._a_mode_clip)
        self.remove_listener(self.pad_mode_button, self._a_mode_pad)
        self.remove_listener(self.control_mode_button, self._a_mode_control)
        self.remove_listener(self._undo_button, self._do_undo)
        self.remove_listener(self._redo_button, self._do_redo)
        self.remove_listener(self._armsolomode_button, self._do_armsolo_mode)
        self.remove_listener(self.xfade_assign_button, self._do_xfade_assign)
        self.remove_listener(self._fire_button, self._do_fire_button)
        self._session.remove_offset_listener(self.notify_track_scroll)
        self._mixer.disconnect()
        ControlSurface.disconnect(self)
Exemple #52
0
 def _setup_session_control(self):
     is_momentary = True
     right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 43)
     left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 42)
     up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 44)
     down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 45)
     right_button.name = 'Bank_Select_Right_Button'
     left_button.name = 'Bank_Select_Left_Button'
     up_button.name = 'Bank_Select_Up_Button'
     down_button.name = 'Bank_Select_Down_Button'
     global session
     session = SessionComponent(4, 4)
     session.name = 'Session_Control'
     session.set_track_bank_buttons(right_button, left_button)
     session.set_scene_bank_buttons(down_button, up_button)
     self._session = session
     matrix = ButtonMatrixElement()
     matrix.name = 'Button_Matrix'
     scene_launch_notes = [33, 34, 35, 36]
     scene_launch_buttons = [
         ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN,
                       scene_launch_notes[index]) for index in range(4)
     ]
     #track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(4) ]
     for index in range(len(scene_launch_buttons)):
         scene_launch_buttons[index].name = 'Scene_' + str(
             index) + '_Launch_Button'
     #for index in range(len(track_stop_buttons)):
     #	 track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button'
     #stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81)
     #stop_all_button.name = 'Stop_All_Clips_Button'
     #self._session.set_stop_all_clips_button(stop_all_button)
     #self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
     #self._session.set_stop_clip_value(2)
     button_notes = [
         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
         20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
     ]
     for scene_index in range(4):
         scene = session.scene(scene_index)
         scene.name = 'Scene_' + str(scene_index)
         button_row = []
         scene.set_launch_button(scene_launch_buttons[scene_index])
         #scene.set_triggered_value(2)
         for track_index in range(4):
             button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN,
                                    (track_index * 4) + scene_index + 1)
             button.name = str(track_index) + '_Clip_' + str(
                 scene_index) + '_Button'
             button_row.append(button)
             clip_slot = scene.clip_slot(track_index)
             clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                 scene_index)
             #clip_slot.set_triggered_to_play_value(2)
             #clip_slot.set_triggered_to_record_value(4)
             clip_slot.set_stopped_value(0)
             clip_slot.set_started_value(64)
             #clip_slot.set_recording_value(3)
             clip_slot.set_launch_button(button)
         matrix.add_row(tuple(button_row))
     #self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67))
     session.selected_scene().name = 'Selected_Scene'
     #session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
     #session_zoom = SessionZoomingComponent(session)
     #session_zoom.name = 'Session_Overview'
     #session_zoom.set_button_matrix(matrix)
     #session_zoom.set_zoom_button(self._shift_button)
     #session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button)
     #session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
     #session_zoom.set_stopped_value(0)
     #session_zoom.set_selected_value(127)
     self.set_highlighting_session_component(session)
     session.set_mixer(mixer)
     return None  #return session
Exemple #53
0
class Codec(ControlSurface):
	__module__ = __name__
	__doc__ = " MonoCode controller script "


	def __init__(self, c_instance, *a, **k):
		super(Codec, self).__init__(c_instance, *a, **k)
		self._monomod_version = 'b995'
		self._version_check = 'b995'
		self._host_name = 'Codec'
		self._color_type = 'Monochrome'
		self._link_mixer = LINK_MIXER
		self._hosts = []
		self._linked_script = None
		self._local_ring_control = True
		self._last_device = None
		self._device_list = [None, None, None, None]
		self._device_select_buttons = None
		self._last_device_component = None
		self._timer = 0
		self._touched = 0
		self._locked = False
		self.flash_status = 1
		self._shift_button = None
		self._shift_pressed = 0
		self._shift_pressed_timer = 0
		self._shift_thresh = SHIFT_THRESH
		self._use_device_selector = USE_DEVICE_SELECTOR
		self._device_selection_follows_track_selection=FOLLOW
		with self.component_guard():
			#self.local_ring_control(True)
			#self.set_absolute_mode(True)
			self._setup_controls()
			self._setup_monobridge()
			self._setup_device_controls()
			self._setup_special_device_control() 
			self._device.append(self._special_device)			#necessary for device browsing to work with special device
			self._setup_device_chooser()
			self._setup_mixer_controls()
			self._setup_monomod()
			self._setup_modes() 
			self._setup_device_selector()
			self._setup_send_reset()
			self._setup_default_buttons()
			self.set_local_ring_control(1)
			self.song().view.add_selected_track_listener(self._update_selected_device)
			self._initialize_code()
			#self._shift_mode.set_mode(0)
			#self._monomod_mode.set_mode(0)
		self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Codec ' + str(self._monomod_version) + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>')
		self.show_message('Codec Control Surface Loaded')
		self.request_rebuild_midi_map()
	


	"""script initialization methods"""
	def _initialize_code(self):
		self._send_midi(factoryreset)
		self._send_midi(btn_channels)
		self._send_midi(enc_channels)	
	

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

	def _setup_controls(self):
		is_momentary = True
		self._livid = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self)
		
		self._dial = [None for index in range(8)]
		for column in range(8):
			self._dial[column] = [None for index in range(4)]
			for row in range(4):
				self._dial[column][row] = CodecEncoderElement(MIDI_CC_TYPE, CHANNEL, CODE_DIALS[row][column], Live.MidiMap.MapMode.absolute, 'Dial_' + str(column) + '_' +	str(row), (column + (row*8)), self)	#CODE_DIALS[row][column]
				
		self._button = [None for index in range(8)]
		for column in range(8):
			self._button[column] = [None for index in range(4)]
			for row in range(4):
				self._button[column][row] = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_BUTTONS[row][column], 'Button_' + str(column) + '_' + str(row), self) 
		

		self._column_button = [None for index in range(8)]
		for index in range(8):
			self._column_button[index] = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_COLUMN_BUTTONS[index], 'Column_Button_' + str(index), self)		
			
		self._row_button = [None for index in range(4)]
		for index in range(4):
			self._row_button[index] = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_ROW_BUTTONS[index], 'Row_Button_' + str(index), self)		

		self._dial_matrix = EncoderMatrixElement(self)
		self._dial_matrix.name = 'Encoder_Matrix'
		for row in range(4):
			dial_row = tuple([self._dial[column][row] for column in range(8)])
			self._dial_matrix.add_row(dial_row)

		self._button_matrix = ButtonMatrixElement()
		self._button_matrix.name = 'Button_Matrix'
		for row in range(4):
			button_row = [self._button[column][row] for column in range(8)]
			button_row.append(self._row_button[row])
			self._button_matrix.add_row(tuple(button_row))
		self._button_matrix.add_row(tuple(self._column_button + [self._livid]))
	

	def _setup_modes(self):
		self._monomod_mode = MonomodModeComponent(self._mod_mode_update, self)
		self._monomod_mode.name = 'Monomod_Mode'
		self.set_shift_button(self._livid)
		self._shift_mode = ShiftModeComponent(self._shift_update, self) 
		self._shift_mode.name = 'Shift_Mode'
		self._shift_mode.set_mode_buttons(tuple([self._row_button[0], self._row_button[1], self._row_button[2], self._row_button[3]]))
	

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

	def _setup_monomod(self):
		self._host = CodecMonomodComponent(self)
		self._host.name = 'Monomod_Host'
		self._host._set_dial_matrix(self._dial_matrix, self._button_matrix)
		self.hosts = [self._host]
		encs = []
		for row in range(4):
			for col in range(8):
				encs.append(self._dial[col][row])
		self._host._set_parameter_controls(encs)
	

	def _setup_mixer_controls(self):
		is_momentary = True
		self._num_tracks = (8)
		self._session = SessionComponent(self._num_tracks, 0)
		self._session.name = 'Session'
		self._mixer = MixerComponent(self._num_tracks, 0, False, False)
		self._mixer.name = 'Mixer'
		self._mixer._next_track_value = self._mixer_next_track_value(self._mixer)
		self._mixer._prev_track_value = self._mixer_prev_track_value(self._mixer)
		self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
		#for index in range(8):
			#use the bottom row of encoders for volume, so add 24 to offset the index
		#	self._mixer.channel_strip(index).set_volume_control(self._dial[index+24])
		for index in range(8):
			self._mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index)
			self._mixer.channel_strip(index)._invert_mute_feedback = True
			self._mixer.channel_strip(index)._mute_value = self._channelstrip_mute_value(self._mixer.channel_strip(index))
			self._mixer.channel_strip(index)._solo_value = self._channelstrip_solo_value(self._mixer.channel_strip(index))
			#mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index]))
		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._session.set_mixer(self._mixer)
	

	def _setup_device_controls(self):
		self._device = [None for index in range(4)]
		for index in range(4):
			self._device[index] = CodecDeviceComponent(self)
			self._device[index].name = 'CodecDevice_Component_' + str(index)
			device_param_controls = []
			for control in range(8):
				device_param_controls.append(self._dial[control][index])
			self._device[index].set_on_off_button(self._button[1][index])
			self._device[index].set_lock_button(self._button[2][index])
			self._device[index].set_bank_nav_buttons(self._button[4][index], self._button[5][index])
			self._device[index].set_nav_buttons(self._button[6][index], self._button[7][index])
			self._device[index].set_parameter_controls(tuple(device_param_controls))
		self.set_device_component(self._device[0])
		self._last_device_component = self._device[0]
	

	def _setup_special_device_control(self):
		self._special_device = SpecialCodecDeviceComponent(self)
		self._special_device.name = 'SpecialCodecDeviceComponent'
		self._special_device.set_on_off_button(self._button[1][0])
		self._special_device.set_lock_button(self._button[2][0])
		self._special_device.set_bank_nav_buttons(self._button[4][0], self._button[5][0])
		self._special_device.set_nav_buttons(self._button[6][0], self._button[7][0])
		device_param_controls = []
		for row in range(4):
			for column in range(8):
				device_param_controls.append(self._dial[column][row])
		self._special_device.set_parameter_controls(tuple(device_param_controls))
	

	def _setup_device_chooser(self):
		self._selected_device = self._device[0]
		self._last_selected_device = self._device[0]
		self._device_select_buttons = [self._button[0][index] for index in range(4)]
		for button in self._device_select_buttons:
			button.add_value_listener(self._device_select_value, True)
	

	def _setup_device_selector(self):
		self._device_selector = CodecDeviceSelectorComponent(self, 'c', self._device + [self._special_device])
		self._device_selector.name = 'Device_Selector'
		self._device_selector.set_mode_buttons(self._column_button)
		#self._device_selector.set_mode_toggle(self._livid)
	

	def _setup_send_reset(self):
		self._send_reset = CodecResetSendsComponent(self)
		self._send_reset.set_buttons(self._button)
	

	def _setup_default_buttons(self):
		self._value_default = ParameterDefaultComponent(self)
		buttons = []
		dials = []
		for column in self._button:
			for button in column:
				buttons.append(button)
		for column in self._dial:
			for dial in column:
				dials.append(dial)
		self._value_default.set_buttons(buttons)
		self._value_default.set_dials(dials)
	


	"""multiple device support"""
	def _device_select_value(self, value, sender):
		#self.log_message('device_select_value ' + str(value) + ' ' + str(self._device_select_buttons.index(sender)))
		if not self._shift_pressed:
			if sender.is_momentary or value > 0:
				if self._shift_mode._mode_index == 2:
					self.set_device_component(self._device[self._device_select_buttons.index(sender)])
					self._last_device_component = self._device_component
					if self._device_component != None and isinstance(self._device_component._device, Live.Device.Device):
						if self._device_component.find_track(self._device_component._device) == self.song().view.selected_track:
							self._device_component.display_device()
	


	"""livid double press mechanism"""
	def set_shift_button(self, button):
		assert ((button == None) or (isinstance(button, MonoButtonElement)))
		if self._shift_button != None:
			self._shift_button.remove_value_listener(self._shift_value)
		self._shift_button = button
		if self._shift_button != None:
			self._shift_button.add_value_listener(self._shift_value)
	

	def _shift_value(self, value):
		self._shift_pressed = int(value != 0)
		if self._shift_pressed > 0:
			self._send_midi(SLOWENCODER)
			if (self._shift_pressed_timer + self._shift_thresh) > self._timer:
				#if(self._host.is_enabled() != True)
				self.log_message('mod mode: ' + str(abs(self._monomod_mode._mode_index - 1)))
				self._monomod_mode.set_mode(max(0, min(1, abs(self._monomod_mode._mode_index - 1))))
				#else:
				#	self._monomod_mode.set_mode(0)
			self._shift_pressed_timer = self._timer % 256
		else:
			self._send_midi(NORMALENCODER)
	

	def _mod_mode_update(self):
		if(self._monomod_mode._mode_index == 0):
			self._host._set_shift_button(None)
			self._host.set_enabled(False)
			self._dial_matrix.reset()
			self._shift_mode.set_enabled(True)
			self._shift_update()
			self.request_rebuild_midi_map()
			self._livid.turn_off()
		elif(self._monomod_mode._mode_index == 1):
			self._shift_mode.set_enabled(False)
			self._deassign_all()
			self._dial_matrix.reset()
			self._button_matrix.reset()			
			self._livid.turn_on()
			if not self._host._active_client == None:
				self._host.set_enabled(True)
				self._host._set_shift_button(self._livid)
			else:
				self._assign_alternate_mappings(1)
			self.request_rebuild_midi_map()
	


	"""Mode Functions"""
	def _shift_update(self):
		if(self._shift_mode.is_enabled()):
			with self.component_guard():
				self.allow_updates(False)
				#if(not self._in_build_midi_map):
				#	self.set_suppress_rebuild_requests(True)
				self._deassign_all()
				if(self._shift_mode._mode_index is 0):
					self._assign_volume()
				elif(self._shift_mode._mode_index is 1):
					self._assign_sends()
				elif(self._shift_mode._mode_index is 2):
					self._assign_devices()
				elif(self._shift_mode._mode_index is 3):
					self._assign_special_device()
				for index in range(self._shift_mode.number_of_modes()):
					if index == self._shift_mode._mode_index:
						self._shift_mode._modes_buttons[index].turn_on()
					else:
						self._shift_mode._modes_buttons[index].turn_off()
				self.allow_updates(True)
				#self.set_suppress_rebuild_requests(False)
				self.request_rebuild_midi_map()
	

	def _deassign_all(self):
		self._assign_alternate_mappings(0)
		self._device_selector.set_enabled(False)
		for index in range(8):
			self._mixer.channel_strip(index).set_volume_control(None)
			self._mixer.channel_strip(index).set_pan_control(None)
			self._mixer.channel_strip(index).set_send_controls(tuple([None, None, None, None]))
		for index in range(4):
			self._device[index].set_enabled(False)
			self._device[index]._parameter_controls = None
			#self._device_navigator[index].set_enabled(False)
		self._special_device.set_enabled(False)
		self._special_device._parameter_controls = None
		self._device_selector.set_enabled(False)
		self._deassign_buttons()
		for control in self.controls:
			control.reset()
		self.request_rebuild_midi_map()
	

	def _deassign_buttons(self):
		for index in range(8):
			self._mixer.channel_strip(index).set_select_button(None)
			self._mixer.channel_strip(index).set_solo_button(None)
			self._mixer.channel_strip(index).set_mute_button(None)
		self._mixer.set_select_buttons(None, None)
		self._send_reset.set_enabled(False)
	

	def _assign_volume(self):
		for index in range(8):
			self._mixer.channel_strip(index).set_volume_control(self._dial[index][3])
			self._mixer.channel_strip(index).set_pan_control(self._dial[index][2])
			self._mixer.channel_strip(index).set_send_controls(tuple([self._dial[index][0], self._dial[index][1]]))
			self._mixer.channel_strip(index).set_select_button(self._column_button[index])
			self._mixer.channel_strip(index).set_solo_button(self._button[index][2])
			self._mixer.channel_strip(index).set_mute_button(self._button[index][3])
		self._mixer.set_select_buttons(self._button[7][0], self._button[6][0])
	

	def _assign_sends(self):
		for index in range(8):
			self._mixer.channel_strip(index).set_send_controls(tuple([self._dial[index][0], self._dial[index][1], self._dial[index][2], self._dial[index][3]]))
			self._mixer.channel_strip(index).set_select_button(self._column_button[index])
			self._send_reset.set_enabled(True)
	

	def _assign_devices(self):
		self.set_device_component(self._last_device_component)
		self._device_select_value(1, self._device_select_buttons[self._device.index(self._device_component)])
		for index in range(4):
			device_param_controls = []
			for control in range(8):
				device_param_controls.append(self._dial[control][index])
			self._device[index].set_parameter_controls(tuple(device_param_controls))
			self._device[index].set_enabled(True)
		self._device_selector.set_enabled(self._use_device_selector)
		if not self._use_device_selector:
			for index in range(8):
				self._mixer.channel_strip(index).set_select_button(self._column_button[index])				
	

	def _assign_special_device(self):
		self.set_device_component(self._special_device)
		device_param_controls = []
		for row in range(4):
			for column in range(8):
				device_param_controls.append(self._dial[column][row])
		self._special_device.set_parameter_controls(tuple(device_param_controls))
		self._special_device.set_enabled(True)
		self._device_selector.set_enabled(self._use_device_selector)
		if not self._use_device_selector:
			for index in range(8):
				self._mixer.channel_strip(index).set_select_button(self._column_button[index])	
	

	def _assign_alternate_mappings(self, chan):
		for column in self._dial:
			for control in column:
				control.set_channel(chan)
				control.set_enabled(chan is 0)
		for column in self._button:
			for control in column:
				control.set_channel(chan)
				control.set_enabled(chan is 0)
		for control in self._column_button:
			control.set_channel(chan)
			control.set_enabled(chan is 0)
		for control in self._row_button:
			control.set_channel(chan)
			control.set_enabled(chan is 0)
	


	"""general functionality"""
	def disconnect(self):
		"""clean things up on disconnect"""
		if not self._shift_button is None:
			if self._shift_button.value_has_listener(self._shift_value):
				self._shift_button.remove_value_listener(self._shift_value)
		for button in self._device_select_buttons:
			if button.value_has_listener(self._device_select_value):
				button.remove_value_listener(self._device_select_value)
		if self._session._is_linked():
			self._session._unlink()
		self.song().view.remove_selected_track_listener(self._update_selected_device)
		"""for cs in self._control_surfaces():
			for host in self._hosts:
				self.log_message('installed: ' + str(cs) + ' vs. ' + str(host))
				if str(type(cs)) == str(type(host)):
					self.log_message('disconnecting: ' + str(type(cs)))
					cs.disconnect(cs)"""
		#self._host._set_parameter_controls(None)
		self._hosts = []
		if self._linked_script != None:
			self._linked_script._update_linked_device_selection = None
		self._linked_script = None
		#self._disconnect_notifier.set_mode(0)
		self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Codec log closed >>>>>>>>>>>>>>>>>>>>>>>>>')
		ControlSurface.disconnect(self)
		return None
		
	

	def connect_script_instances(self, instanciated_scripts):
		found = False
		for s in instanciated_scripts:
			if '_codec_version' in dir(s):
				if s._codec_version == self._version_check:
					if s._host_name == ('MonOhm'):
						self.log_message('found codec version ' + str(s._codec_version) + ' in script ' + str(s._host_name))
						found = True
						self._linked_script = s
						self._linked_script._update_linked_device_selection = self._update_linked_device_selection
						if not self._session._is_linked() and self._link_mixer is True:
							self._session.set_offsets(LINK_OFFSET[0], LINK_OFFSET[1])
							self._session._link()
				else:
					self.log_message('version mismatch: Monomod version ' + str(self._version_check) + ' vs. Host version ' + str(s._codec_version))
					

		if found == False:
			for s in instanciated_scripts:
				if '_codec_version' in dir(s):
					if s._codec_version == self._version_check:
						if s._host_name == 'BlockMod':
							self.log_message('found codec version ' + str(s._codec_version) + ' in script ' + str(s._host_name))
							self._linked_script = s
							self._linked_script._update_linked_device_selection = self._update_linked_device_selection
						if not self._session._is_linked() and self._link_mixer is True:
							self._session.set_offsets(LINK_OFFSET[0], LINK_OFFSET[1])
							self._session._link()
					else:
						self.log_message('version mismatch: Monomod version ' + str(self._version_check) + ' vs. Host version ' + str(s._codec_version))
		#self.log_message('hosts: ' + str(self._hosts))"""
	

	def update_display(self):
		ControlSurface.update_display(self)		#since we are overriding this from the inherited method, we need to call the original routine as well
		self._timer = (self._timer + 1) % 256
		if(self._timer == 0):
			self._shift_pressed_timer = -12
		if(self._local_ring_control is False):
			self.send_ring_leds()
		self.flash()
	

	def handle_sysex(self, midi_bytes):
		#self._send_midi(tuple([240, 00, 01, 97, 04, 15, 01, 247]))
		#response = [long(0),long(0)]
		#self.log_message(response)
		pass
	

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

	def send_ring_leds(self):
		leds = [240, 0, 1, 97, 4, 31]
		for column in range(8):
			for row in range(4):
				wheel = self._dial[column][row]
				bytes = wheel._get_ring()
				leds.append(bytes[0])
				leds.append(int(bytes[1]) + int(bytes[2]))
				#if(row == 1 and column == 0):
				#	self.log_message(str(leds) + ' ' + str(bytes[0]) + ' ' + str(bytes[1]) + ' ' + str(bytes[2]))
		leds.append(247)
		self._send_midi(tuple(leds))
	

	def set_absolute_mode(self, val = 1):
		self._absolute_mode = (val!=0)
		if self._absolute_mode is True:
			self._send_midi(tuple([240, 0, 1, 97, 4, 17, 0, 0, 0, 0, 0, 0, 0, 0, 247]))
		else:
			self._send_midi(tuple([240, 0, 1, 97, 4, 17, 127, 127, 127, 127, 127, 127, 127, 127, 247]))
	

	def set_local_ring_control(self, val = 1):
		self._local_ring_control = (val!=0)
		if(self._local_ring_control is True):
			#self._send_midi(tuple([240, 0, 1, 97, 4, 32, 0, 247]))
			self._send_midi(tuple([240, 0, 1, 97, 4, 8, 72, 247]))
		else:
			#self._send_midi(tuple([240, 0, 1, 97, 4, 32, 1, 247]))
			self._send_midi(tuple([240, 0, 1, 97, 4, 8, 64, 247]))
	

	def device_follows_track(self, val):
		self._device_selection_follows_track_selection = (val == 1)
		return self
	


	"""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 += ' '
		assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
		return ret
	

	def notification_to_bridge(self, name, value, sender):
		if(isinstance(sender, CodecEncoderElement)):
			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 not self._host.is_enabled():
			if self._touched is 0:
				self._monobridge._send('touch', 'on')
				self.schedule_message(2, self.check_touch)
			self._touched +=1
	

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

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


	"""overrides"""
	def allow_updates(self, allow_updates):
		for component in self.components:
			component.set_allow_update(int(allow_updates!=0))
	

	def set_device_component(self, device_component):
		if self._device_component != None:
			self._device_component._lock_callback = None
		assert (device_component != None)
		assert isinstance(device_component, DeviceComponent)
		self._device_component = device_component
		self._device_component._lock_callback = self._toggle_lock	#old:  self._device_component.set_lock_callback(self._toggle_lock)
		if self._device_select_buttons != None:
			for button in self._device_select_buttons:
				button.send_value(self._device_select_buttons.index(button) == self._device.index(self._device_component))
		self._update_device_selection()
		return None
	

	def _update_selected_device(self):
		if self._device_selection_follows_track_selection is True:
			self._update_device_selection()
		return None 
	

	def _update_linked_device_selection(self, device):
		#self.log_message('codec received ' + str(device.name))
		if self._device_component != None and device != None:
			if not self._device_component.is_locked():
				self._device_component.set_device(device)
	

	def _get_num_tracks(self):
		return self.num_tracks
	

	def _update_device_selection(self):
		#self.log_message('_update_device_selection')
		if self._device_component != None:
			if not self._device_component.is_locked():
				track = self.song().view.selected_track
				device_to_select = track.view.selected_device
				if ((device_to_select == None) and (len(track.devices) > 0)):
					device_to_select = track.devices[0]
				if (device_to_select != None):
					self.song().view.select_device(device_to_select)
				self._device_component.set_device(device_to_select)
 	

	def _channelstrip_mute_value(self, channelstrip):
		def _mute_value(value):
			if not self._shift_pressed:
				self.log_message('shift not pressed')
				ChannelStripComponent._mute_value(channelstrip, value)
		return _mute_value
		
	

	def _channelstrip_solo_value(self, channelstrip):
		def _solo_value(value):
			if not self._shift_pressed:
				ChannelStripComponent._solo_value(channelstrip, value)
		return _solo_value
		
	

	def _mixer_next_track_value(self, mixer):
		def _next_track_value(value):
			if not self._shift_pressed:
				MixerComponent._next_track_value(mixer, value)
		return _next_track_value
		
	

	def _mixer_prev_track_value(self, mixer):
		def _prev_track_value(value):
			if not self._shift_pressed:
				MixerComponent._prev_track_value(mixer, value)
		return _prev_track_value
Exemple #54
0
class code(ControlSurface):
	__module__ = __name__
	__doc__ = " Code controller script "
	
	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		with self.component_guard():
			self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= Code opened =--------------") # Writes message into Live's main log file. This is a ControlSurface method.		  
			self._send_midi(factoryreset)
			self._send_midi(btn_channels)
			self._send_midi(enc_channels)
			#self.set_suppress_rebuild_requests(True) # Turn off rebuild MIDI map until after we're done setting up
			self._setup_controls()
			self._setup_device_controls()
			self._setup_mixer_control() # Setup the mixer object
			self._setup_transport_control()
			self._setup_session_control()  # Setup the session object - do this last
			self._setup_modes()
			self._setup_m4l_interface()
			#self.set_suppress_rebuild_requests(False) # Turn rebuild back on, once we're done setting up
			##self.assign_page_2()

	def handle_sysex(self, midi_bytes):
		self._send_midi(tuple([240, 00, 01, 97, 04, 15, 01, 247]))
		#response = [long(0),long(0)]
		#self.log_message(str(response))
	

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

	def _setup_controls(self):
		is_momentary = True
		self._dial = [None for index in range(DIALCOUNT)]
		self._trackbtns = [None for index in range(8)]
		self._modebtns = [None for index in range(5)]
		for index in range(DIALCOUNT):
			self._dial[index] = EncoderElement(MIDI_CC_TYPE, CH, matrix_nums[index], Live.MidiMap.MapMode.absolute)
			self._dial[index].name = 'Dial_' + str(index)
			self._dial[index].set_feedback_delay(-1)
		for index in range(8):
			self._trackbtns[index] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index])
			self._trackbtns[index].name =  'Button_' + str(index)
		for index in range(5):
			self._modebtns[index] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, mode_select_notes[index])
			self._modebtns[index].name = 'ModeButton_' + str(index)
		self._matrix = ButtonMatrixElement()
		self._matrix.name = 'Matrix'
		self._grid = [None for index in range(COLS)]
		for column in range(COLS):
			self._grid[column] = [None for index in range(COLS)]
			for row in range(ROWS):
				nn = 1+(column * ROWS) + row
				self._grid[column][row] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, nn) #comment out if you don't want clip launch
				self._grid[column][row].name = 'Grid_' + str(column) + '_' + str(row)
		for row in range(ROWS):
			button_row = []
			for column in range(COLS):
				button_row.append(self._grid[column][row])
			self._matrix.add_row(tuple(button_row)) 
	  
	""" not sure about this bit, but somehow I'll need to set up the modes here...!"""
	def _setup_modes(self):
		self._shift_mode = ShiftModeComponent(self, tuple(button for button in self._modebtns))
		self._shift_mode.name = 'Mix_Mode' #mode 1
		#self._shift_mode.set_mode_buttons(self._modebtns)
		
	def _setup_transport_control(self):
		self._transport = TransportComponent() 
		self._transport.name = 'Transport'

	def _setup_mixer_control(self):
		is_momentary = True
		self._num_tracks = (COLS)
		global mixer
		mixer = MixerComponent(COLS, 0, True, True)
		mixer.name = 'Mixer'
		self._mixer = mixer
		mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
		for index in range(COLS):
			#use the bottom row of encoders for volume, so add 24 to offset the index
			mixer.channel_strip(index).set_volume_control(self._dial[index+24])
		for index in range(COLS):
			mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index)
			mixer.track_eq(index).name = 'Mixer_EQ_' + str(index)
			mixer.track_filter(index).name = 'Mixer_Filter_' + str(index)  #added by a
			mixer.channel_strip(index)._invert_mute_feedback = True
			#mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index]))
		self.song().view.selected_track = 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

	""" Technically, we aren't using the session control, but I'm going to set it up in case inter-script communication needs it"""
	def _setup_session_control(self):
		is_momentary = True
		num_tracks = COLS
		num_scenes = ROWS
		global session
		session = SessionComponent(num_tracks, num_scenes)
		session.name = "Session"
		session.set_offsets(0, 0)
		self._session = session
		self._session.set_stop_clip_value(0)
		self._scene = [None for index in range(ROWS)]
		for row in range(num_scenes):
			self._scene[row] = session.scene(row)
			self._scene[row].name = 'Scene_' + str(row)
			for column in range(num_tracks):
				clip_slot = self._scene[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_' + str(row)
				clip_slot.set_triggered_to_play_value(64)
				clip_slot.set_triggered_to_record_value(64)
				clip_slot.set_stopped_value(0)
				clip_slot.set_started_value(64)
				clip_slot.set_recording_value(64)
				#clip_slot.set_launch_button(self._grid[column][row]) #comment out if you don't want clip launch
		session.set_mixer(mixer)
		self._session_zoom = SessionZoomingComponent(session)
		self._session_zoom.name = 'Session_Overview'
		self._session_zoom.set_stopped_value(0)
		self._session_zoom.set_playing_value(64)
		self._session_zoom.set_selected_value(64)
		if STANDALONE is True:
			self.set_highlighting_session_component(self._session)
			self._session.set_track_bank_buttons(self._grid[5][3], self._grid[4][3])   #comment out when using with Griid
			self._session.set_scene_bank_buttons(self._grid[7][3], self._grid[6][3])	# comment out when using with Griid
		
		
	"""this is where we take care of setting up the the multiple devices per page, we will need 4"""
	def _setup_device_controls(self):
		self._device = [None for index in range(4)]
		for index in range(ROWS):
			self._device[index] = DeviceComponent()
			self._device[index].name = 'Device_Component_' + str(index)
			#self.set_device_component(self._device)  #this doesn't work anymore, because we have multiple devices for the controller....we'll have to get fancy here, but that's for later
			#self._device_navigator = DetailViewControllerComponent()  #its unclear if we'll need this....how is device navigation (i.e. banking for device parameter banks) going to be handled by the script? 
			#self._device_navigator.name = 'Device_Navigator'
			device_param_controls = []
			for control in range(COLS):
				"""this setups up 8 device parameters per row"""
				#dial_index = control + (index*COLS)
				"""alternatively, this setus up device controls in 4 4x2 groups"""
				dial_index = device_encoders[control + (index*COLS)]
				device_param_controls.append(self._dial[dial_index])

				
			
			self._device[index].set_parameter_controls(tuple(device_param_controls))

	"""this is where we deassign every control that will be changing function when we switch modes...best to just deassign them all, and reassign them on update"""
	def deassign_matrix(self):
		for index in range(DIALCOUNT):			#this should totally work!!! I'm over appealing to Python's sadistic mannerisms right now....
			self._dial[index].send_value(0, True)	##this is kind of a hack, and should be unnecessary; the bool at the end tells the send_value method to force the value out to the controller
		for index in range(COLS):
			self._mixer.track_eq(index).set_enabled(False)	##set_gain_controls(tuple([None for index in range(3)]))
			self._mixer.channel_strip(index).set_volume_control(None)
			self._mixer.track_filter(index).set_enabled(False)	##set_filter_controls(tuple([None, None]))
			self._mixer.channel_strip(index).set_pan_control(None)
			self._mixer.channel_strip(index).set_select_button(None)
			self._mixer.channel_strip(index).set_send_controls(tuple([None for index in range(4)]))
		for device in range(4):
			self._device[device].set_bank_nav_buttons(None, None)
			self._device[device].set_enabled(False)	 ##set_parameter_controls(tuple([None for index in range(8)]))
		for track in range(8):
			self._mixer.channel_strip(track).set_select_button(None)
			for scene in range(4):
				self._scene[scene].clip_slot(track).set_launch_button(None)
		#self.request_rebuild_midi_map()  # I think this is causing problems updating the leds when in build?

	"""EQ Hi/Mid/Low and volume"""
	def assign_page_0(self):
		"""for each column"""
		is_momentary = True
		for index in range(COLS):
			self._mixer.track_eq(index).set_gain_controls((self._dial[index+16],self._dial[index+8],self._dial[index]))
			self._mixer.track_eq(index).set_enabled(True)
			self._mixer.channel_strip(index).set_volume_control(self._dial[index+24])#use the bottom row of encoders for volume, so add 24 to offset the index
			self._mixer.channel_strip(index).set_select_button(self._trackbtns[index])
			self.assign_cliplaunch()
			self._mixer.update()
			
	"""sends 1-4"""
	def assign_page_1(self):
		is_momentary = True
		for index in range(COLS):
			send_controllers = [self._dial[index],self._dial[index+8],self._dial[index+16],self._dial[index+24]]
			self._mixer.channel_strip(index).set_send_controls(tuple(send_controllers))
			self._mixer.channel_strip(index).set_select_button(self._trackbtns[index])
			self._mixer.update()

	"""devices 1-8"""
	def assign_pages_2_3(self):			##these need to be here anyway, whether or not there is a device present to control
		for index in range(4):
			self._device[index].set_enabled(True)
			#device_param_controls = []			###no need to reassign it, since we are turning it off and on
			#for control in range(COLS):		###in fact, I think we can assign all this stuff in the header except for things directly connected to the mixer module
			#	device_param_controls.append(self._dial[control + (index*COLS)])
			#self._device[index].set_parameter_controls(tuple(device_param_controls))
		self._reassign_devices(self._shift_mode._mode_index)
	
	""" filter res,filter q, pan, volume"""
	def assign_page_4(self):
		is_momentary = True
		for index in range(COLS):
			self._mixer.track_filter(index).set_filter_controls(self._dial[index], self._dial[index + 8]) #set_filter_controls(self, freq, reso)
			self._mixer.track_filter(index).set_enabled(True) 
			#self._mixer.track_eq(index).set_gain_controls((self._dial[index],self._dial[index+8],self._dial[index+16]))
			self._mixer.channel_strip(index).set_pan_control(self._dial[index+16])
			self._mixer.channel_strip(index).set_volume_control(self._dial[index+24])
			self._mixer.channel_strip(index).set_select_button(self._trackbtns[index])
			self._mixer.update()
	

	def assign_cliplaunch(self):
		if STANDALONE is True:
			for column in range(COLS):
				for row in range(ROWS-1):
					self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])

	def _reassign_devices(self, mode_index):
		if self._shift_mode._mode_index in range(2, 4): ##both of these lines would be better handled by a property 
			offset = (mode_index - 2) * 4				## set up in an override module of the device_component....bleh
			track = self.song().view.selected_track
			for index in range(4):
				if index + offset < len(track.devices):
					#self.log_message('assigning device')
					self._device[index].set_device(track.devices[index + offset])
				else:
					#self.log_message('assigning device to None')
					self._device[index].set_device(None)
				self._device[index].set_bank_nav_buttons(self._trackbtns[(index * 2)], self._trackbtns[(index * 2) + 1])
				self._device[index].update()

	def disconnect(self):
		"""clean things up on disconnect"""
		self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= Code log closed =--------------") #Create entry in log file
		ControlSurface.disconnect(self)
		return None		
Exemple #55
0
	def init(self):
		#skip init if already done.
		if self._init_done:
			return
		self._init_done = True
		
		# second part of the __init__ after model has been identified using its challenge response
		if self._mk2_rgb:
			from SkinMK2 import make_skin
			self._skin = make_skin()
			self._side_notes = (89, 79, 69, 59, 49, 39, 29, 19)
			#self._drum_notes = (20, 30, 31, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126)
			self._drum_notes = (20, 30, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126)
		else:
			from SkinMK1 import make_skin
			self._skin = make_skin()
			self._side_notes = (8, 24, 40, 56, 72, 88, 104, 120)
			self._drum_notes = (41, 42, 43, 44, 45, 46, 47, 57, 58, 59, 60, 61, 62, 63, 73, 74, 75, 76, 77, 78, 79, 89, 90, 91, 92, 93, 94, 95, 105, 106, 107)
		
		with self.component_guard():
			is_momentary = True
			self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False)
			self._config_button.add_value_listener(self._config_value)
			self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16)
			self._user_byte_write_button.name = 'User_Byte_Button'
			self._user_byte_write_button.send_value(1)
			self._user_byte_write_button.add_value_listener(self._user_byte_value)
			matrix = ButtonMatrixElement()
			matrix.name = 'Button_Matrix'
			for row in range(8):
				button_row = []
				for column in range(8):
					if self._mk2_rgb:
						# for mk2 buttons are assigned "top to bottom"
						midi_note = (81 - (10 * row)) + column
					else:
						midi_note = row * 16 + column
					button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, midi_note, skin = self._skin, control_surface = self)
					button.name = str(column) + '_Clip_' + str(row) + '_Button'
					button_row.append(button)
				matrix.add_row(tuple(button_row))

			top_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, skin = self._skin) for index in range(8)]
			side_buttons = [ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, self._side_notes[index], skin = self._skin) for index in range(8)]
			top_buttons[0].name = 'Bank_Select_Up_Button'
			top_buttons[1].name = 'Bank_Select_Down_Button'
			top_buttons[2].name = 'Bank_Select_Left_Button'
			top_buttons[3].name = 'Bank_Select_Right_Button'
			top_buttons[4].name = 'Session_Button'
			top_buttons[5].name = 'User1_Button'
			top_buttons[6].name = 'User2_Button'
			top_buttons[7].name = 'Mixer_Button'
			side_buttons[0].name = 'Vol_Button'
			side_buttons[1].name = 'Pan_Button'
			side_buttons[2].name = 'SndA_Button'
			side_buttons[3].name = 'SndB_Button'
			side_buttons[4].name = 'Stop_Button'
			side_buttons[5].name = 'Trk_On_Button'
			side_buttons[6].name = 'Solo_Button'
			side_buttons[7].name = 'Arm_Button'
			self._osd = M4LInterface()
			self._osd.name = "OSD"
			self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self._osd, self)
			self._selector.name = 'Main_Modes'
			self._do_combine()
			for control in self.controls:
				if isinstance(control, ConfigurableButtonElement):
					control.add_value_listener(self._button_value)

			self.set_highlighting_session_component(self._selector.session_component())
			self._suppress_session_highlight = False
			# due to our 2 stage init, we need to rebuild midi map 
			self.request_rebuild_midi_map()
			# and request update 
			self._selector.update()
			if self._mk2_rgb:
				self.log_message("LaunchPad95 (mk2) Loaded !")
			else:
				self.log_message("LaunchPad95 Loaded !")
Exemple #56
0
class Lemur256(ControlSurface):
    __module__ = __name__
    __doc__ = " Lemur Monomodular 256cell 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.
        super(Lemur256, self).__init__(*a, **k)
        self._host_name = "Lemur256"
        self._color_type = 'AumPad'
        self.connected = 0
        self._suggested_input_port = 'None'
        self._suggested_output_port = 'None'
        self._monomod_version = 'b995'
        self.hosts = []
        self._bright = True
        self._rgb = 0
        self._timer = 0
        self.flash_status = 1
        self._osc_registry = {}
        with self.component_guard():
            self._setup_monobridge()
            self._setup_controls()
            self._setup_monomod()
            self._setup_touchosc()
            self._assign_host2()
        self.reset()
        self.refresh_state()
        self.show_message(str(self._host_name) + ' Control Surface Loaded')
        self.log_message("<<<<<<<<<<<<<<<<<<<<  " + str(self._host_name) +
                         " " + str(self._monomod_version) +
                         " log opened   >>>>>>>>>>>>>>>>>>>>")

    def _setup_controls(self):
        is_momentary = True
        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),
                    '/Grid/set ' + str(column) + ' ' + str(row), None, 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._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),
                '/Shift/set ' + str(index), None, self)
        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),
                '/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))

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

    """script initialization methods"""

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

    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
        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))

    """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(Lemur256, 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):
        self.log_message("<<<<<<<<<<<<<<<<<<<<  " + str(self._host_name) +
                         " log closed   >>>>>>>>>>>>>>>>>>>>")
        super(ControlSurface, 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):
        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)
Exemple #57
0
	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		with self.component_guard():
			#self.set_suppress_rebuild_requests(True)
			self._suppress_send_midi = True
			self._suppress_session_highlight = True
			is_momentary = True
			self._suggested_input_port = "Launchpad"
			self._suggested_output_port = "Launchpad"
			self._control_is_with_automap = False
			self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) 
			self._user_byte_write_button.name = "User_Byte_Button"
			self._user_byte_write_button.send_value(1)
			self._user_byte_write_button.add_value_listener(self._user_byte_value)
			self._wrote_user_byte = False
			self._challenge = (Live.Application.get_random_int(0, 400000000) & 2139062143)
			matrix = ButtonMatrixElement()
			matrix.name = "Button_Matrix"
			
			""" TRACKFINDER TEST 
			track_index = 0
			for track in self.song().tracks:
				if track_index < 8:
					button_row = []			
					if track.is_foldable:
						for column in range(8):	
							log("right one: " + str(track_index))		
							button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((track_index * 16) + column)) #@UndefinedVariable
							button.name = (((str(column) + "_Clip_") + str(track_index)) + "_Button")
							button_row.append(button)
						track_index = track_index + 1
					else:
						for column in range(8):
							log("wrong one: " + str(track_index))
							button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99, True) #@UndefinedVariable
							button.name = (str(column) + "_Clip_Button-DUMMY")
							button_row.append(button)
					matrix.add_row(tuple(button_row))
			log("done")"""
			
			""" ORIGINAL CODE """
			for row in range(8):
				button_row = []
				for column in range(8):
					button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((row * 16) + column)) 
					button.name = (((str(column) + "_Clip_") + str(row)) + "_Button")
					button_row.append(button)
				matrix.add_row(tuple(button_row))
				
			self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False)
			self._config_button.add_value_listener(self._config_value)
			top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, (104 + index)) for index in range(8) ] 
			side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index]) for index in range(8) ] 
			top_buttons[0].name = "Bank_Select_Up_Button"
			top_buttons[1].name = "Bank_Select_Down_Button"
			top_buttons[2].name = "Bank_Select_Left_Button"
			top_buttons[3].name = "Bank_Select_Right_Button"
			top_buttons[4].name = "Session_Button"
			top_buttons[5].name = "User1_Button"
			top_buttons[6].name = "User2_Button"
			top_buttons[7].name = "Mixer_Button"
			side_buttons[0].name = "Vol_Button"
			side_buttons[1].name = "Pan_Button"
			side_buttons[2].name = "SndA_Button"
			side_buttons[3].name = "SndB_Button"
			side_buttons[4].name = "Stop_Button"
			side_buttons[5].name = "Trk_On_Button"
			side_buttons[6].name = "Solo_Button"
			side_buttons[7].name = "Arm_Button"
			self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button)
			self._selector.name = "Main_Modes"
			for control in self.controls:
				if isinstance(control, ConfigurableButtonElement):
					control.add_value_listener(self._button_value)
			self.set_highlighting_session_component(self._selector.session_component())
			self._suppress_session_highlight = False
class Maschine(ControlSurface):
    __module__ = __name__
    __doc__ = 'Basic Control Script for All Maschine Modell Mikro, Mikro Mk2, Mk1, Mk2, Studio'

    def __init__(self, c_instance):
        super(Maschine, self).__init__(c_instance)
        with self.component_guard():
            register_sender(self)
            self._diplay_cache = ['',
             '',
             '',
             '']
            self._suppress_send_midi = True
            is_momentary = True
            self._c_ref = c_instance
            self.display_task = DisplayTask()
            self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143
            self._active = False
            self._midi_pause_count = 0
            self.blink_state = 0
            self.send_slider_index = 0
            self.nav_index = 0
            self.arm_selected_track = False
            self.undo_state = 0
            self.redo_state = 0
            self._set_suppress_rebuild_requests(True)
            self._modeselect = ModeSelector(self.is_monochrome())
            self._device = self._set_up_device_control()
            self._set_up_session(self._modeselect)
            self._set_up_mixer()
            self._setup_transport()
            self._set_global_buttons()
            self._editsection = EditSection()
            self._editsection.connect_session(self._session)
            self._editsection.set_mode_selector(self._modeselect)
            self._session.set_mode(self._modeselect._clip_mode)
            self._audio_clip_editor = AudioClipEditComponent()
            self._note_repeater = NoteRepeatComponent(c_instance.note_repeat)
            self._midi_edit = MidiEditSection()
            self._init_settings()
            self._init_maschine()
            self.set_highlighting_session_component(self._session)
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._on_selected_track_changed()
            self.set_up_function_buttons()
            self.show_message(str(''))
            self.request_rebuild_midi_map()
            self._set_suppress_rebuild_requests(False)
            self._active = True
            self._display_device_param = False
            self.set_feedback_channels(FEEDBACK_CHANNELS)
            self._final_init()
            self._suppress_send_midi = False
            self.apply_preferences()
            self.init_text_display()
            self._on_appointed_device_changed.subject = self.song()

    def _init_maschine(self):
        pass

    def _final_init(self):
        pass

    def create_pad_button(self, scene_index, track_index, color_source):
        pass

    def create_gated_button(self, identifier, hue):
        pass

    def apply_preferences(self):
        pref_dict = self._pref_dict
        if 'step_advance' in pref_dict:
            self._session.set_step_advance(pref_dict['step_advance'])
        if 'solo_exclusive' in pref_dict:
            self._modeselect.set_solo_exclusive(pref_dict['solo_exclusive'])
        else:
            self._modeselect.set_solo_exclusive(True)
        if 'arm_exclusive' in pref_dict:
            self._modeselect.set_arm_exclusive(pref_dict['arm_exclusive'])
        else:
            self._modeselect.set_arm_exclusive(True)
        if 'quantize_val' in pref_dict:
            self._editsection.quantize = pref_dict['quantize_val']
        else:
            self._editsection.quantize = 5
        if 'initial_cliplen' in pref_dict:
            self._editsection.initial_clip_len = pref_dict['initial_cliplen']
        else:
            self._editsection.initial_clip_len = 4.0
        if 'auto_arm_sel_track' in pref_dict:
            self.arm_selected_track = pref_dict['auto_arm_sel_track']
        else:
            self.arm_selected_track = False
        if 'note_color_mode' in pref_dict:
            self._modeselect._pad_mode._note_display_mode = pref_dict['note_color_mode']
        else:
            self._modeselect._pad_mode._note_display_mode = ND_KEYBOARD1
        self._pref_dict['note_color_mode'] = self._modeselect._pad_mode._note_display_mode
        self.set_sel_arm_button.send_value(self.arm_selected_track and 127 or 0, True)
        self._note_repeater.recall_values(self._pref_dict)

    def store_preferences(self):
        self._pref_dict['step_advance'] = self._session.get_step_advance()
        self._pref_dict['solo_exclusive'] = self._modeselect.is_solo_exclusive()
        self._pref_dict['arm_exclusive'] = self._modeselect.is_arm_exclusive()
        self._pref_dict['quantize_val'] = self._editsection.quantize
        self._pref_dict['initial_cliplen'] = self._editsection.initial_clip_len
        self._pref_dict['auto_arm_sel_track'] = self.arm_selected_track
        self._pref_dict['note_color_mode'] = self._modeselect._pad_mode._note_display_mode
        self._note_repeater.store_values(self._pref_dict)

    def _init_settings(self):
        from pickle import loads, dumps
        from encodings import ascii
        nop(ascii)
        preferences = self._c_instance.preferences(self.preferences_name())
        self._pref_dict = {}
        try:
            self._pref_dict = loads(str(preferences))
        except Exception:
            pass

        pref_dict = self._pref_dict
        preferences.set_serializer(lambda : dumps(pref_dict))

    def preferences_name(self):
        return 'Maschine'

    def _pre_serialize(self):
        from pickle import dumps
        from encodings import ascii
        nop(ascii)
        preferences = self._c_instance.preferences('Maschine')
        self.store_preferences()
        dump = dumps(self._pref_dict)
        preferences.set_serializer(lambda : dump)

    def toggle_nav_mode(self):
        self._session.switch_step_advance()
        self.show_message(' View Navigation in steps of ' + str(self._session.get_step_advance()))

    def _set_up_session(self, mode_selector):
        is_momentary = True
        self._session = MaschineSessionComponent()
        self._session.set_color_manager(mode_selector.get_color_manager())
        self.nav_buttons = (self.create_gated_button(92, COLOR_HUE_NAV),
         self.create_gated_button(81, COLOR_HUE_NAV),
         self.create_gated_button(93, COLOR_HUE_NAV),
         self.create_gated_button(91, COLOR_HUE_NAV))
        self._session.set_scene_bank_buttons(self.nav_buttons[0], self.nav_buttons[1])
        self._session.set_track_bank_buttons(self.nav_buttons[2], self.nav_buttons[3])
        track_stop_buttons = [ StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, index + STOP_CC_OFF) for index in range(4) ]
        self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
        self._matrix = []
        self._bmatrix = ButtonMatrixElement()
        for scene_index in range(4):
            button_row = []
            for track_index in range(4):
                button = self.create_pad_button(scene_index, track_index, mode_selector)
                button_row.append(button)

            self._matrix.append(tuple(button_row))
            self._bmatrix.add_row(tuple(button_row))

        self._session.set_matrix(self._matrix)
        for button, (track_index, scene_index) in self._bmatrix.iterbuttons():
            if button:
                scene = self._session.scene(scene_index)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(button)
                clip_slot.set_triggered_to_play_value(1)
                clip_slot.set_triggered_to_record_value(1)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(1)
                clip_slot.set_stopped_value(1)

        self._session._link()

    def _set_up_mixer(self):
        is_momentary = True
        self._mixer = MaschineMixerComponent(8)
        self.send_sliders = []
        for track in range(8):
            self.send_sliders.append(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, SEND_CC_OFF + track))

        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.set_arm_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, ARM_CC_OFF + track))
            strip.set_solo_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SOLO_CC_OFF + track))
            strip.set_mute_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, MUTE_CC_OFF + track))
            strip.set_volume_control(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, LEVEL_CC_OFF + track))
            strip.set_pan_control(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, PAN_CC_OFF + track))
            strip.set_select_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SELECT_CC_OFF + track))
            st = tuple([self.send_sliders[track]])
            strip.set_send_controls(st)

        self.send_slider_toggle_button = StateButton(False, MIDI_CC_TYPE, 0, 90)
        self._do_toggle_send.subject = self.send_slider_toggle_button
        self._session.set_mixer(self._mixer)

    def _set_global_buttons(self):
        is_momentary = True
        self._undo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 85)
        self._do_undo.subject = self._undo_button
        self._redo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 87)
        self._do_redo.subject = self._redo_button
        self._stop_all_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 111)
        self._do_stop_all.subject = self._stop_all_button
        self._toggle_detail_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 121)
        self._action_toogle_detail_view.subject = self._toggle_detail_button
        self._fire_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 9)
        self._do_fire_button.subject = self._fire_button
        self._g_clear_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 106)
        self._hold_clear_action.subject = self._g_clear_button
        self._g_duplicate_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 107)
        self._hold_duplicate_action.subject = self._g_duplicate_button
        self.track_left_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 120)
        self.track_right_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 121)
        self.set_sel_arm_button = StateButton(is_momentary, MIDI_CC_TYPE, 2, 56)
        self._reenable_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 120)
        self._do_auto_reenable.subject = self._reenable_button
        self._on_change_reenabled.subject = self.song()
        self._on_change_reenabled()
        self._a_trk_left.subject = self.track_left_button
        self._a_trk_right.subject = self.track_right_button
        self._a_sel_arm.subject = self.set_sel_arm_button

    def _set_up_device_control(self):
        is_momentary = True
        device = MaschineDeviceComponent()
        param_controls = []
        for index in range(8):
            param_controls.append(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_CC_OFF + index))

        device.set_parameter_controls(tuple(param_controls))
        self.device_control = param_controls
        device.set_on_off_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF))
        device.set_bank_nav_buttons(StateButton(is_momentary, MIDI_CC_TYPE, 3, 104), ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 105))
        self._device_nav_button_left = StateButton(is_momentary, MIDI_CC_TYPE, 3, 106)
        self._device_nav_button_right = StateButton(is_momentary, MIDI_CC_TYPE, 3, 107)
        self._navigate_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 127)
        self._nav_value_left.subject = self._device_nav_button_left
        self._nav_value_right.subject = self._device_nav_button_right
        self._do_focus_navigate.subject = self._navigate_button
        self.set_device_component(device)
        return device

    def _setup_transport(self):
        is_momentary = True
        transport = TransportComponent()
        studiotransport = MaschineTransport()
        playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108)
        stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110)
        recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109)
        overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107)
        metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104)
        eventRecButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 98)
        playButton.name = 'Play'
        stopButton.name = 'Stop'
        recordButton.name = 'Record'
        overdubButton.name = 'Overdub'
        metrononmeButton.name = 'Metronome'
        transport.set_play_button(playButton)
        transport.set_stop_button(stopButton)
        transport.set_record_button(recordButton)
        transport.set_overdub_button(overdubButton)
        transport.set_metronome_button(metrononmeButton)
        studiotransport.set_session_auto_button(eventRecButton)
        studiotransport.set_arrangement_overdub_button(StateButton(is_momentary, MIDI_CC_TYPE, 0, 106))
        studiotransport.set_back_arrange_button(StateButton(is_momentary, MIDI_CC_TYPE, 0, 105))
        transport.set_nudge_buttons(StateButton(is_momentary, MIDI_CC_TYPE, 1, 51), StateButton(is_momentary, MIDI_CC_TYPE, 1, 50))
        punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52)
        punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53)
        punchinbutton.name = 'Punch In'
        punchoutbutton.name = 'Punch Out'
        transport.set_punch_buttons(punchinbutton, punchoutbutton)
        transport.set_loop_button(StateButton(is_momentary, MIDI_CC_TYPE, 1, 54))
        self.song_follow_button = ButtonElement(True, MIDI_CC_TYPE, 2, 98)
        self._do_song_follow.subject = self.song_follow_button
        self._song_follow_changed.subject = self.song().view
        self._song_follow_changed()
        self.prehear_knob = SliderElement(MIDI_CC_TYPE, 0, 41)
        self.prehear_knob.connect_to(self.song().master_track.mixer_device.cue_volume)
        self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59)
        self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58)
        transport.set_seek_buttons(self.transp_ff_button, self.transp_rw_button)
        self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 105)
        self.xfadeKnob.connect_to(self.song().master_track.mixer_device.crossfader)
        self.master_knob = SliderElement(MIDI_CC_TYPE, 0, 99)
        self.master_knob.connect_to(self.song().master_track.mixer_device.volume)
        self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88)
        self._do_tap_tempo.subject = self.tap_button
        self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 55)
        self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56)
        self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57)
        self._do_toggle_cue.subject = self.cue_add_delete_button
        self._do_toggle_prev_cue.subject = self.cue_prev_button
        self._do_toggle_next_cue.subject = self.cue_next_button

    def set_up_function_buttons(self):
        is_momentary = True
        self.keycolor_mod_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 73)
        self._do_key_color.subject = self.keycolor_mod_button
        self._update_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 86)
        self._do_update_display.subject = self._update_button

    @subject_slot('appointed_device')
    def _on_appointed_device_changed(self):
        self._modeselect._device_changed()

    def _update_hardware(self):
        self._session.update()
        self._modeselect.refresh()
        self.update_undo_redo(True)

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

    def _send_midi(self, midi_bytes, **keys):
        self._c_ref.send_midi(midi_bytes)
        return True

    def init_text_display(self):
        if USE_DISPLAY:
            self._modeselect._pad_mode.update_text_display()

    def _on_selected_track_changed(self):
        super(Maschine, self)._on_selected_track_changed()
        self.set_controlled_track(self.song().view.selected_track)
        self._on_devices_changed.subject = self.song().view.selected_track

    @subject_slot('devices')
    def _on_devices_changed(self):
        pass

    def update(self):
        self.set_feedback_channels(FEEDBACK_CHANNELS)
        super(Maschine, self).update()

    def is_monochrome(self):
        return False

    def _deassign_matrix(self):
        for scene_index in range(4):
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(None)

    def update_display(self):
        with self.component_guard():
            with self._is_sending_scheduled_messages():
                self._task_group.update(0.1)
            self._modeselect.notify(self.blink_state)
            self.blink_state = (self.blink_state + 1) % 4
            self.display_task.tick()
            self.update_undo_redo(False)

    def update_undo_redo(self, force = False):
        if force:
            self.undo_state = self.song().can_undo
            self.redo_state = self.song().can_redo
        if self.song().can_undo != self.undo_state:
            self.undo_state = self.song().can_undo
            self._undo_button.send_value(self.undo_state == 1 and 127 or 0)
        if self.song().can_redo != self.redo_state:
            self.redo_state = self.song().can_redo
            self._redo_button.send_value(self.redo_state == 1 and 127 or 0)

    def adjust_loop_start(self, delta):
        loopval = self.song().loop_start
        self.song().loop_start = min(self.song().song_length, max(0, loopval + delta))

    def adjust_loop_length(self, delta):
        loopval = self.song().loop_length
        self.song().loop_length = min(self.song().song_length, max(abs(delta), loopval + delta))

    def _do_armsolo_mode(self, value):
        pass

    @subject_slot('value')
    def _do_fire_button(self, value):
        raise self._fire_button != None or AssertionError
        raise value in range(128) or AssertionError
        if value != 0:
            if self.isShiftDown():
                self.song().tap_tempo()
            else:
                clip_slot = self.song().view.highlighted_clip_slot
                if clip_slot:
                    clip_slot.fire()

    @subject_slot('value')
    def _do_undo(self, value):
        if value != 0:
            if self.use_layered_buttons() and self.isShiftDown():
                if self.song().can_redo == 1:
                    self.song().redo()
                    self.show_message(str('REDO'))
            elif self.song().can_undo == 1:
                self.song().undo()
                self.show_message(str('UNDO'))

    @subject_slot('value')
    def _do_redo(self, value):
        if value != 0:
            if self.song().can_redo == 1:
                self.song().redo()
                self.show_message(str('REDO'))

    @subject_slot('value')
    def _do_stop_all(self, value):
        if value != 0:
            if self.use_layered_buttons() and self.isShiftDown():
                self.song().stop_all_clips(0)
            else:
                self.song().stop_all_clips(1)

    def isShiftDown(self):
        return self._editsection.isShiftdown()

    def modifiers(self):
        return self._editsection.modifiers()

    def use_layered_buttons(self):
        return False

    def _handle_base_note(self, diff):
        self._modeselect._pad_mode.inc_base_note(diff)

    def _handle_octave(self, diff):
        self._modeselect._pad_mode.inc_octave(diff)
        octave_val = self._modeselect._pad_mode

    def _handle_scale(self, diff):
        self._modeselect._pad_mode.inc_scale(diff)

    @subject_slot('value')
    def _do_update_display(self, value):
        if value != 0:
            self.refresh_state()

    @subject_slot('value')
    def _do_key_color(self, value):
        if not value in range(128):
            raise AssertionError
            value != 0 and self._modeselect._pad_mode.step_key_color_mode()

    @subject_slot('value')
    def _do_tap_tempo(self, value):
        if not value in range(128):
            raise AssertionError
            value != 0 and self.song().tap_tempo()

    @subject_slot('value')
    def _do_toggle_cue(self, value):
        if not value in range(128):
            raise AssertionError
            value != 0 and self.song().set_or_delete_cue()

    @subject_slot('value')
    def _do_toggle_prev_cue(self, value):
        if not value in range(128):
            raise AssertionError
            value != 0 and self.song().jump_to_prev_cue()

    @subject_slot('value')
    def _do_toggle_next_cue(self, value):
        if not value in range(128):
            raise AssertionError
            value != 0 and self.song().jump_to_next_cue()

    @subject_slot('value')
    def _do_toggle_send(self, value):
        if not value in range(128):
            raise AssertionError
            if self.isShiftDown():
                value != 0 and self.refresh_state()
                self.show_message('Refresh Display')
        else:
            nr_of_tracks = len(self.song().return_tracks)
            if value == 0 or nr_of_tracks < 1:
                return
            prev = self.send_slider_index
            self.send_slider_index += 1
            if self.send_slider_index >= nr_of_tracks:
                self.send_slider_index = 0
            self.show_message(' Set Send ' + str(SENDS[self.send_slider_index]))
            self.timed_message(2, ' Set Send ' + str(SENDS[self.send_slider_index]))
            if prev != self.send_slider_index:
                for track in range(8):
                    strip = self._mixer.channel_strip(track)
                    slider_list = []
                    for index in range(self.send_slider_index + 1):
                        if index < self.send_slider_index - 1:
                            slider_list.append(None)
                        else:
                            slider_list.append(self.send_sliders[track])
                        strip.set_send_controls(tuple(slider_list))

    @subject_slot('value')
    def _a_trk_left(self, value):
        if not value in range(128):
            raise AssertionError
            if value != 0:
                if self.application().view.is_view_visible('Session'):
                    direction = Live.Application.Application.View.NavDirection.left
                    self.application().view.scroll_view(direction, 'Session', True)
                    track = self.song().view.selected_track
                    self.timed_message(2, 'T:' + track.name, False)
                    self.arm_selected_track and track.can_be_armed and arm_exclusive(self.song(), track)

    @subject_slot('value')
    def _a_trk_right(self, value):
        if not value in range(128):
            raise AssertionError
            if value != 0:
                if self.application().view.is_view_visible('Session'):
                    direction = Live.Application.Application.View.NavDirection.right
                    self.application().view.scroll_view(direction, 'Session', True)
                    track = self.song().view.selected_track
                    self.timed_message(2, 'T:' + track.name, False)
                    self.arm_selected_track and track.can_be_armed and arm_exclusive(self.song(), track)

    @subject_slot('value')
    def _a_sel_arm(self, value):
        if value != 0:
            if self.arm_selected_track:
                self.arm_selected_track = False
                self.set_sel_arm_button.send_value(0, True)
            else:
                self.arm_selected_track = True
                self.set_sel_arm_button.send_value(127, True)

    @subject_slot('value')
    def _nav_value_left(self, value):
        if not self._device_nav_button_left != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                modifier_pressed = True
                value != 0 and (not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain')) and self.application().view.show_view('Detail')
                self.application().view.show_view('Detail/DeviceChain')
            else:
                direction = Live.Application.Application.View.NavDirection.left
                self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)

    @subject_slot('value')
    def _nav_value_right(self, value):
        if not self._device_nav_button_right != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                modifier_pressed = value != 0 and True
                (not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain')) and self.application().view.show_view('Detail')
                self.application().view.show_view('Detail/DeviceChain')
            else:
                direction = Live.Application.Application.View.NavDirection.right
                self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)

    @subject_slot('value')
    def _do_focus_navigate(self, value):
        if not self._navigate_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            self.nav_index = value != 0 and (self.nav_index + 1) % len(VIEWS_ALL)
            self.application().view.focus_view(VIEWS_ALL[self.nav_index])
            self.show_message('Focus on : ' + str(VIEWS_ALL[self.nav_index]))

    def focus_clip_detail(self):
        self.application().view.focus_view('Detail/Clip')

    @subject_slot('follow_song')
    def _song_follow_changed(self):
        view = self.song().view
        if view.follow_song:
            self.song_follow_button.send_value(1, True)
        else:
            self.song_follow_button.send_value(0, True)

    @subject_slot('value')
    def _do_song_follow(self, value):
        if value != 0:
            view = self.song().view
            if view.follow_song:
                view.follow_song = False
                self.song_follow_button.send_value(0, True)
            else:
                view.follow_song = True
                self.song_follow_button.send_value(1, True)

    @subject_slot('value')
    def _hold_duplicate_action(self, value):
        if value != 0:
            pass

    @subject_slot('value')
    def _hold_clear_action(self, value):
        if value != 0:
            self._mixer.enter_clear_mode()
            self._device_component.enter_clear_mode()
        else:
            self._mixer.exit_clear_mode()
            self._device_component.exit_clear_mode()

    @subject_slot('value')
    def _action_toogle_main_view(self, value):
        if value != 0:
            appv = self.application().view
            if appv.is_view_visible('Arranger'):
                appv.show_view('Session')
            else:
                appv.show_view('Arranger')

    @subject_slot('value')
    def _action_toogle_detail_view(self, value):
        if value != 0:
            appv = self.application().view
            if self.isShiftDown():
                if appv.is_view_visible('Arranger'):
                    appv.show_view('Session')
                else:
                    appv.show_view('Arranger')
            elif appv.is_view_visible('Detail/Clip'):
                appv.show_view('Detail/DeviceChain')
            else:
                appv.show_view('Detail/Clip')

    @subject_slot('re_enable_automation_enabled')
    def _on_change_reenabled(self):
        if self.song().re_enable_automation_enabled:
            self._reenable_button.turn_on()
        else:
            self._reenable_button.turn_off()

    @subject_slot('value')
    def _do_auto_reenable(self, value):
        if value != 0:
            self.song().re_enable_automation()

    def to_color_edit_mode(self, active):
        pass

    def clear_display_all(self):
        self.send_to_display('', 0)
        self.send_to_display('', 1)
        self.send_to_display('', 2)
        self.send_to_display('', 3)

    def clear_display(self, grid):
        self.send_to_display('', grid)

    def timed_message(self, grid, text, hold = False):
        if USE_DISPLAY == False:
            self.show_message(text)
        else:
            self.display_task.set_func(self.clear_display, grid)
            self.send_to_display(text, grid)
            if hold:
                self.display_task.hold()
            self.display_task.start()

    def timed_message_release(self):
        self.display_task.release()

    def update_bank_display(self):
        if USE_DISPLAY:
            name, bank = self._device._current_bank_details()
            if self._display_device_param:
                prms = len(bank)
                d1 = ''
                for i in range(4):
                    parm = bank[i]
                    if parm:
                        name = parm.name
                        d1 += name[:6] + (i < 3 and '|' or '')
                    else:
                        d1 += '      ' + (i < 3 and '|' or '')

                self.send_to_display(d1, 2)
                d1 = ''
                for i in range(4):
                    parm = bank[i + 4]
                    if parm:
                        name = parm.name
                        d1 += name[:6] + (i < 3 and '|' or '')
                    else:
                        d1 += '      ' + (i < 3 and '|' or '')

                self.send_to_display(d1, 4)
            else:
                self.timed_message(2, 'Bank: ' + name)

    def display_parameters(self, paramlist):
        if USE_DISPLAY == False:
            return

    def send_to_display(self, text, grid = 0):
        if USE_DISPLAY == False:
            return
        if self._diplay_cache[grid] == text:
            return
        self._diplay_cache[grid] = text
        if len(text) > 28:
            text = text[:27]
        msgsysex = [240,
         0,
         0,
         102,
         23,
         18,
         min(grid, 3) * 28]
        filled = text.ljust(28)
        for c in filled:
            msgsysex.append(ord(c))

        msgsysex.append(247)
        self._send_midi(tuple(msgsysex))

    def cleanup(self):
        pass

    def disconnect(self):
        self._pre_serialize()
        self.clear_display_all()
        for button, (track_index, scene_index) in self._bmatrix.iterbuttons():
            if button:
                button.send_color_direct(PColor.OFF[0])

        time.sleep(0.2)
        self._active = False
        self._suppress_send_midi = True
        super(Maschine, self).disconnect()