def _setup_background(self):
     self._background = BackgroundComponent()
     self._background.layer = Layer(priority=1,
                                    pads=self._pad_matrix,
                                    buttons=self._button_matrix,
                                    keys=self._key_matrix,
                                    dials=self._dial_matrix,
                                    sliders=self._slider_matrix)
     self._background.set_enabled(False)
Example #2
0
 def _setup_background(self):
     self._background = BackgroundComponent()
     self._background.layer = Layer(
         priority=3,
         matrix=self._matrix.submatrix[:, :],
         side_buttons=self._side_button_matrix,
         top_buttons=self._top_button_matrix.submatrix[:, :],
         bottom_button=self._bottom_button)
     self._background.set_enabled(False)
class Morph(ControlSurface):


	_model_name = 'Morph'

	def __init__(self, c_instance, *a, **k):
		self.log_message = logger.info
		super(Morph, self).__init__(c_instance, *a, **k)
		self._skin = Skin(MorphColors)
		with self.component_guard():
			self._setup_controls()
			self._setup_background()
			#self._setup_button_background()
			self._setup_drum_group()
			self._setup_keys_group()
			self._setup_piano_group()
			self._setup_autoarm()
			self._setup_device()
			self._setup_session()
			self._setup_session2()
			self._setup_mixer()
			self._setup_transport()
			self._setup_viewcontrol()
			self._setup_recorder()
			self._setup_translations()
			self._setup_modes()
		self._on_device_changed.subject = self._device_provider
		self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Morph log opened >>>>>>>>>>>>>>>>>>>>>>>>>')
		self.show_message('Morph Control Surface Loaded')
		self.schedule_message(2, self._init_surface)
		#debug('device:', self._device._get_device())



	def _init_surface(self):
		self._main_modes.selected_mode = 'Main'


	def _setup_controls(self):
		is_momentary = True
		optimized = False
		resource = ExclusiveResource #PrioritizedResource
		self._pad = [[ButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MORPH_PADS[row][column], name = 'Pad_' + str(column) + '_' + str(row), skin = self._skin, resource_type = resource) for column in range(4)] for row in range(4)]
		for row in self._pad:
			for pad in row:
				pad.enabled = False
		self._button = [ButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MORPH_BUTTONS[index], name = 'Button_' + str(index), skin = self._skin, resource_type = resource) for index in range(8)]
		for button in self._button:
			button.set_enabled = False
		self._key = [MorphButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = KEY_CHANNEL, identifier = MORPH_KEYS[index], name = 'Key_' + str(index), skin = self._skin, resource_type = resource) for index in range(13)]
		self._dials = [MorphEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = MORPH_DIALS[index], map_mode = Live.MidiMap.MapMode.absolute, name = 'Dial_' + str(index), resource_type = resource) for index in range(8)]
		self._slider = [MorphEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = MORPH_SLIDERS[index], map_mode = Live.MidiMap.MapMode.absolute, name = 'Slider_' + str(index), resource_type = resource) for index in range(2)]
		self._send_pressure = [MorphEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = MORPH_SEND_PRESSURE[index], map_mode = Live.MidiMap.MapMode.absolute, name = 'SendPressure_' + str(index), resource_type = resource) for index in range(2)]

		self._pad_matrix = ButtonMatrixElement(name = 'PadMatrix', rows = self._pad)
		self._dial_matrix = ButtonMatrixElement(name = 'DialMatrix', rows = [self._dials])
		self._button_matrix = ButtonMatrixElement(name = 'ButtonMatrix', rows = [self._button])
		self._key_matrix = ButtonMatrixElement(name = 'KeyMatrix', rows = [self._key])
		self._key_shift_matrix = ButtonMatrixElement(name = 'KeyShiftMatrix', rows = [self._key[2:11]])
		self._slider_matrix = ButtonMatrixElement(name = 'SliderMatrix', rows = [self._slider])
		self._send_pressure_matrix = ButtonMatrixElement(name = 'SendAMatrix', rows = [self._send_pressure])
		#self._shift_send_pressure_matrix = ButtonMatrixElement(name = 'ShiftSendMatrix', rows = [ [None, None, self._send_pressure[0], self._send_pressure[1]] ])

		self._piano_button = [MorphButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = PIANO_BUTTONS[index], name = 'PianoButton_' + str(index), skin = self._skin, resource_type = resource) for index in range(4)]
		for button in self._piano_button:
			button.enabled = False
		self._piano_key = [MorphButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = PIANO_CHANNEL, identifier = PIANO_KEYS[index], name = 'PianoKey_' + str(index), skin = self._skin, resource_type = resource) for index in range(25)]

		self._piano_matrix = ButtonMatrixElement(name = 'PianoMatrix', rows = [self._piano_key])
		self._piano_session_matrix = ButtonMatrixElement(name = 'PianoSessionMatrix', rows = [self._piano_key[0:4], self._piano_key[4:8], self._piano_key[8:12], self._piano_key[12:16]])


	def _setup_background(self):
		self._background = BackgroundComponent()
		self._background.layer = Layer(priority = 1, pads = self._pad_matrix, buttons = self._button_matrix, keys = self._key_matrix, dials = self._dial_matrix, sliders = self._slider_matrix)
		self._background.set_enabled(False)



	def _setup_drum_group(self):
		self._drum_group = MorphDrumGroup(set_pad_translations = self.set_pad_translations, translation_channel = DRUM_TRANSLATION_CHANNEL)
		self._drum_group.main_layer = AddLayerMode(self._drum_group, Layer(priority = 2, matrix = self._pad_matrix))
		self._drum_group.nav_layer = AddLayerMode(self._drum_group, Layer(priority = 2, scroll_up_button = self._key[1], scroll_down_button = self._key[0]))
		self._drum_group.set_enabled(False)


	def _setup_keys_group(self):
		self._keys_group = MorphKeysGroup()
		self._keys_group.main_layer = AddLayerMode(self._keys_group, Layer(priority = 2, matrix = self._key_matrix))
		self._keys_group.shift_layer = AddLayerMode(self._keys_group, Layer(priority = 2, matrix = self._key_shift_matrix, scroll_up_button = self._key[12], scroll_down_button = self._key[11]))
		self._keys_group.set_enabled(False)


	def _setup_piano_group(self):
		self._piano_group = MorphKeysGroup()
		self._piano_group._hi_limit = 8
		self._piano_group.main_layer = AddLayerMode(self._piano_group, Layer(priority = 2, matrix = self._piano_matrix, scroll_up_button = self._piano_button[1], scroll_down_button = self._piano_button[0]))
		#self._piano_group.shift_layer = AddLayerMode(self._piano_group, Layer(matrix = self._piano_shift_matrix, scroll_up_button = self._pian0[12], scroll_down_button = self._key[11]))
		self._piano_group.set_enabled(False)


	def _setup_autoarm(self):
		self._auto_arm = AutoArmComponent(name='Auto_Arm')
		self._auto_arm.can_auto_arm_track = self._can_auto_arm_track
		self._auto_arm._update_notification = lambda: None


	def _setup_transport(self):
		self._transport = TransportComponent(name = 'Transport')
		self._transport.layer = Layer(priority = 2, play_button = self._button[4], stop_button = self._button[5], overdub_button = self._button[6])
		self._transport.set_enabled(False)


	def _setup_translations(self):
		self._translations = TranslationComponent(name='Translations',
													channel=USER_CHANNEL,
													controls = self._dials + self._slider)
		self._translations.set_enabled(False)


	def _setup_device(self):
		self._device = MorphDeviceComponent(device_provider = self._device_provider, device_bank_registry = self._device_bank_registry)
		self._device.layer = Layer(priority = 2, parameter_controls = self._dial_matrix)
		self._device.set_enabled(False)


	def _setup_session(self):
		self._session_ring = SessionRingComponent(name = 'Session_Ring', num_tracks = 4, num_scenes = 4)

		self._session = SessionComponent(name = 'Session', session_ring = self._session_ring, auto_name = True)
		self._session.layer = Layer(priority = 2, clip_launch_buttons = self._pad_matrix,) # stop_all_clips_button = self._button[5])
		self._session.set_enabled(False)

		self._session_navigation = SessionNavigationComponent(name = 'Session_Navigation', session_ring = self._session_ring)
		self._session_navigation.layer = Layer(priority = 2, left_button = self._button[0], right_button = self._button[1])
		self._session_navigation.set_enabled(False)


	def _setup_session2(self):
		self._session2 = SessionComponent(name = 'Session2', session_ring = self._session_ring, auto_name = True)
		self._session2.layer = Layer(priority = 2, clip_launch_buttons = self._piano_session_matrix)
		self._session2.set_enabled(False)

		#self._session_navigation2 = SessionNavigationComponent(name = 'Session_Navigation2', session_ring = self._session_ring)
		#self._session_navigation2.layer = Layer(priority = 2, left_button = self._button[0], right_button = self._button[1])
		#self._session_navigation2.set_enabled(False)


	def _setup_mixer(self):
		self._mixer = MorphMixerComponent(tracks_provider = self._session_ring, track_assigner = SimpleTrackAssigner(), auto_name = True, invert_mute_feedback = False)
		self._mixer._selected_strip.main_layer = AddLayerMode(self._mixer._selected_strip, Layer(priority = 2, send_controls = self._send_pressure_matrix))
		self._mixer._selected_strip.shift_layer = AddLayerMode(self._mixer._selected_strip, Layer(priority = 2, stop_button = self._button[5]))
		#self._mixer._selected_strip.shift_layer = AddLayerMode(self._mixer, Layer(send_controls = self._shift_send_pressure_matrix.submatrix[:,]))


	def _setup_viewcontrol(self):
		self._viewcontrol = ViewControlComponent()
		self._viewcontrol.layer = Layer(priority = 2, prev_track_button = self._button[0], next_track_button = self._button[1])
		self._viewcontrol.set_enabled(False)


	def _setup_recorder(self):
		self._recorder = SessionRecordingComponent(view_controller = ViewControlComponent())
		self._recorder.layer = Layer(priority = 2, record_button = self._button[6])
		self._recorder.set_enabled(False)


	def _assign_crossfader(self):
		self._slider[1].connect_to(self.song.master_track.mixer_device.crossfader)
		debug('_assign_crossfader:', self._slider[1]._parameter_to_map_to)


	def _deassign_crossfader(self):
		self._slider[1].release_parameter()
		debug('_assign_crossfader:', self._slider[1]._parameter_to_map_to)


	def _setup_modes(self):
		self._main_modes = ModesComponent(name = 'MainModes')
		self._main_modes.add_mode('disabled', self._background)
		self._main_modes.add_mode('Main', [self._piano_group, self._piano_group.main_layer, self._mixer, self._mixer._selected_strip.main_layer, self._viewcontrol, self._drum_group, self._drum_group.main_layer, self._keys_group, self._keys_group.main_layer, self._device, self._transport, self._assign_crossfader, self._report_mode])
		self._main_modes.add_mode('Shift', [self._mixer, self._mixer._selected_strip.shift_layer, self._session, self._session2, self._session_navigation,  self._drum_group, self._drum_group.nav_layer, self._keys_group, self._keys_group.shift_layer, self._deassign_crossfader, self._recorder, self._translations, self._report_mode], behaviour = MomentaryBehaviour())
		self._main_modes.layer = Layer(Shift_button = self._button[7])
		self._main_modes.set_enabled(True)
		self._report_mode.subject = self._main_modes
		self._main_modes.selected_mode = 'disabled'





	@listens('selected_mode')
	def _report_mode(self, *a, **k):
		debug('Mode:', self._main_modes.selected_mode)



	def _can_auto_arm_track(self, track):
		routing = track.current_input_routing
		return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith('Sensel') or routing.startswith('Morph')



	@listens('device')
	def _on_device_changed(self):
		debug('_on_device_changed:', self._device_provider.device)
		self._drum_group.set_drum_group_device(self._device_provider.device)



	def disconnect(self):
		self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Morph log closed >>>>>>>>>>>>>>>>>>>>>>>>>')
		super(Morph, self).disconnect()


	def handle_sysex(self, midi_bytes):
		#debug('sysex: ', str(midi_bytes))
		#debug('matching:', midi_bytes[1:5], 'to', tuple([0, 1, 97]  + [self._sysex_id]))
		if len(midi_bytes)==9 and midi_bytes[1:5] == tuple([0, 1, 97]  + [self._sysex_id]):
			if not self._connected:
				#debug('connecting from sysex...')
				self._connected = True
				self._initialize_hardware()
				self._initialize_script()
Example #4
0
class Minim(LividControlSurface):

    _sysex_id = 18
    _model_name = 'Minim'

    def __init__(self, c_instance, *a, **k):
        super(Minim, self).__init__(c_instance, *a, **k)
        self._shift_latching = LatchingShiftedBehaviour if SHIFT_LATCHING else ShiftedBehaviour
        self._skin = Skin(MinimColors)
        with self.component_guard():
            self._define_sysex()
            self._setup_monobridge()
            self._setup_controls()
            self._setup_background()
            self._setup_autoarm()
            self._setup_viewcontrol()
            self._setup_session()
            self._setup_mixer()
            self._setup_transport()
            self._setup_recorder()
            self._setup_instrument()
            self._setup_modes()
            self._setup_m4l_interface()
        self.log_message(
            '<<<<<<<<<<<<<<<<<<<<<<<<< Minim log opened >>>>>>>>>>>>>>>>>>>>>>>>>'
        )
        self.show_message('Minim Control Surface Loaded')
        self._background.set_enabled(True)

    def _check_connection(self):
        if not self._connected:
            debug(self._model_name, '_check_connection')
            self._livid_settings.new_query_surface()
            #self._connection_routine.restart()
            self.schedule_message(5, self._check_connection)

    def _initialize_hardware(self):
        debug('sending local control off')
        self.local_control_off.enter_mode()

    def _initialize_script(self):
        self._on_device_changed.subject = self._device_provider
        self._main_modes.set_enabled(True)
        self._main_modes.selected_mode = 'session'
        self._session_ring._update_highlight()
        self.refresh_state()

    def _setup_controls(self):
        is_momentary = True
        optimized = False
        resource = PrioritizedResource
        self._fader = MonoEncoderElement(msg_type=MIDI_CC_TYPE,
                                         channel=CHANNEL,
                                         identifier=MINIM_SLIDER,
                                         name='Fader',
                                         script=self,
                                         mapping_feedback_delay=-1,
                                         optimized_send_midi=optimized,
                                         resource_type=resource)
        self._pad = [[
            MonoButtonElement(is_momentary=is_momentary,
                              msg_type=MIDI_NOTE_TYPE,
                              channel=CHANNEL,
                              identifier=MINIM_PADS[row][column],
                              name='Pad_' + str(column) + '_' + str(row),
                              script=self,
                              skin=self._skin,
                              color_map=COLOR_MAP,
                              optimized_send_midi=optimized,
                              resource_type=resource) for column in range(4)
        ] for row in range(2)]
        self._button = [[
            MonoButtonElement(is_momentary=is_momentary,
                              msg_type=MIDI_NOTE_TYPE,
                              channel=CHANNEL,
                              identifier=MINIM_BUTTONS[row][column],
                              name='Button_' + str(column) + '_' + str(row),
                              script=self,
                              skin=self._skin,
                              color_map=COLOR_MAP,
                              optimized_send_midi=optimized,
                              resource_type=resource) for column in range(4)
        ] for row in range(2)]
        self._side_button = [
            MonoButtonElement(is_momentary=is_momentary,
                              msg_type=MIDI_NOTE_TYPE,
                              channel=CHANNEL,
                              identifier=MINIM_SIDE_BUTTONS[index],
                              name='Side_Button_' + str(index),
                              script=self,
                              skin=self._skin,
                              color_map=COLOR_MAP,
                              optimized_send_midi=optimized,
                              resource_type=resource) for index in range(5)
        ]
        self._top_button = [
            MonoButtonElement(is_momentary=is_momentary,
                              msg_type=MIDI_NOTE_TYPE,
                              channel=CHANNEL,
                              identifier=MINIM_TOP_BUTTONS[index],
                              name='Top_Button_' + str(index),
                              script=self,
                              skin=self._skin,
                              color_map=COLOR_MAP,
                              optimized_send_midi=optimized,
                              resource_type=resource) for index in range(2)
        ]
        self._bottom_button = MonoButtonElement(is_momentary=is_momentary,
                                                msg_type=MIDI_NOTE_TYPE,
                                                channel=CHANNEL,
                                                identifier=MINIM_BOTTOM_BUTTON,
                                                name='Bottom_Button',
                                                script=self,
                                                skin=self._skin,
                                                color_map=COLOR_MAP,
                                                optimized_send_midi=optimized,
                                                resource_type=resource)

        self._matrix = ButtonMatrixElement(name='Pad_Matrix',
                                           rows=[
                                               self._button[:][0],
                                               self._pad[:][0],
                                               self._pad[:][1],
                                               self._button[:][1]
                                           ])
        self._side_button_matrix = ButtonMatrixElement(
            name='Side_Button_Matrix', rows=[self._side_button])
        self._top_button_matrix = ButtonMatrixElement(name='Button_Matrix',
                                                      rows=[self._top_button])

    def _setup_background(self):
        self._background = BackgroundComponent()
        self._background.layer = Layer(
            priority=3,
            matrix=self._matrix.submatrix[:, :],
            side_buttons=self._side_button_matrix,
            top_buttons=self._top_button_matrix.submatrix[:, :],
            bottom_button=self._bottom_button)
        self._background.set_enabled(False)

    def _define_sysex(self):
        self._livid_settings = LividSettings(model=18, control_surface=self)
        self.local_control_off = SendLividSysexMode(
            livid_settings=self._livid_settings,
            call='set_local_control',
            message=[42, 42])

    def _setup_autoarm(self):
        self._auto_arm = AutoArmComponent(name='Auto_Arm')
        self._auto_arm.can_auto_arm_track = self._can_auto_arm_track
        self._auto_arm._update_notification = lambda: None

    def _setup_viewcontrol(self):
        self._viewcontrol = ViewControlComponent()
        self._viewcontrol.layer = Layer(priority=4,
                                        prev_track_button=self._top_button[0],
                                        next_track_button=self._top_button[1])
        self._viewcontrol.set_enabled(False)

    def _setup_transport(self):
        self._transport = TransportComponent(name='Transport')
        self._transport.layer = Layer(
            priority=4, play_button=self._side_button[0]
        )  #, overdub_button = self._side_button[1])
        self._transport.set_enabled(False)

    def _setup_mixer(self):
        self._mixer = MonoMixerComponent(
            name='Mixer',
            tracks_provider=self._session_ring,
            track_assigner=SimpleTrackAssigner(),
            invert_mute_feedback=True,
            auto_name=True,
            enable_skinning=True,
            channel_strip_component_type=MonoChannelStripComponent)
        self._mixer._selected_strip.layer = Layer(priority=4,
                                                  volume_control=self._fader)
        self._mixer.solo_mute_record_stop_layer = AddLayerMode(
            self._mixer,
            Layer(
                priority=4,
                mute_buttons=self._matrix.submatrix[:, 0],
                solo_buttons=self._matrix.submatrix[:, 1],
                arm_buttons=self._matrix.submatrix[:, 2],
            ))
        self._mixer.select_layer = AddLayerMode(
            self._mixer,
            Layer(priority=4,
                  arming_track_select_buttons=self._matrix.submatrix[:, 3]))
        self._mixer.mute_layer = AddLayerMode(
            self._mixer,
            Layer(priority=4, mute_buttons=self._matrix.submatrix[:, 3]))

    def _setup_session(self):
        self._session_ring = SessionRingComponent(name='Session_Ring',
                                                  num_tracks=4,
                                                  num_scenes=4)

        self._session = SessionComponent(name='Session',
                                         session_ring=self._session_ring,
                                         auto_name=True)
        self._session.cliplaunch_layer = AddLayerMode(
            self._session,
            Layer(priority=4,
                  clip_launch_buttons=self._matrix.submatrix[:, :]))
        self._session.stop_layer = AddLayerMode(
            self._session,
            Layer(priority=4,
                  stop_track_clip_buttons=self._matrix.submatrix[:, 3]))

        self._session_navigation = SessionNavigationComponent(
            name='Session_Navigation', session_ring=self._session_ring)
        self._session_navigation._horizontal_layer = AddLayerMode(
            self._session_navigation,
            Layer(priority=4,
                  left_button=self._top_button[0],
                  right_button=self._top_button[1]))
        self._session_navigation._vertical_layer = AddLayerMode(
            self._session_navigation,
            Layer(priority=4,
                  up_button=self._top_button[0],
                  down_button=self._top_button[1]))
        self._session_navigation.set_enabled(False)

    def _setup_recorder(self):
        self._recorder = SessionRecordingComponent(
            view_controller=self._viewcontrol)
        self._recorder.layer = Layer(priority=4,
                                     new_button=self._side_button[2],
                                     record_button=self._side_button[1])
        self._recorder.set_enabled(False)

    def _setup_instrument(self):
        self._grid_resolution = GridResolution()

        self._c_instance.playhead.enabled = True
        self._playhead_element = PlayheadElement(self._c_instance.playhead)

        self._drum_group_finder = PercussionInstrumentFinder(
            device_parent=self.song.view.selected_track)

        self._instrument = MinimMonoInstrumentComponent(
            name='InstrumentComponent',
            script=self,
            skin=self._skin,
            drum_group_finder=self._drum_group_finder,
            grid_resolution=self._grid_resolution,
            settings=DEFAULT_INSTRUMENT_SETTINGS,
            device_provider=self._device_provider,
            parent_task_group=self._task_group)
        self._instrument._drumpad._drumgroup._button_coordinates_to_pad_index = lambda first_note, coordinates: coordinates[
            1] + (abs(coordinates[0] - 1) * 4) + first_note
        self._instrument._drumpad._drumgroup.create_translation_entry = lambda button: (
            button.coordinate[1], button.coordinate[
                0] + 2, button.identifier, button.channel)

        self._instrument.layer = Layer(priority=6,
                                       shift_button=self._side_button[3])

        self._instrument.keypad_options_layer = AddLayerMode(
            self._instrument,
            Layer(
                priority=6,
                scale_up_button=self._button[0][3],
                scale_down_button=self._button[0][2],
                offset_up_button=self._button[0][1],
                offset_down_button=self._button[0][0],
            ))
        #vertical_offset_up_button = self._top_button[1],
        #vertical_offset_down_button = self._top_button[0]))
        self._instrument.drumpad_options_layer = AddLayerMode(
            self._instrument,
            Layer(
                priority=6,
                scale_up_button=self._button[0][3],
                scale_down_button=self._button[0][2],
                drum_offset_up_button=self._button[0][1],
                drum_offset_down_button=self._button[0][0],
            ))

        self._instrument._keypad.main_layer = LayerMode(
            self._instrument._keypad,
            Layer(priority=6, keypad_matrix=self._matrix.submatrix[:, 1:3]))
        self._instrument._keypad.select_layer = LayerMode(
            self._instrument._keypad,
            Layer(priority=6,
                  keypad_select_matrix=self._matrix.submatrix[:, 1:3]))

        self._instrument._drumpad.main_layer = LayerMode(
            self._instrument._drumpad,
            Layer(priority=6, drumpad_matrix=self._matrix.submatrix[:, 1:3]))
        self._instrument._drumpad.select_layer = LayerMode(
            self._instrument._drumpad,
            Layer(priority=6,
                  drumpad_select_matrix=self._matrix.submatrix[:, 1:3]))

        self._instrument._main_modes = ModesComponent(name='InstrumentModes')
        self._instrument._main_modes.add_mode('disabled', [])
        self._instrument._main_modes.add_mode('drumpad', [
            self._instrument._drumpad, self._instrument._drumpad.main_layer,
            self._instrument.drumpad_options_layer
        ])
        self._instrument._main_modes.add_mode('drumpad_shifted', [
            self._instrument._drumpad, self._instrument._drumpad.select_layer,
            self._instrument.drumpad_options_layer
        ])
        self._instrument._main_modes.add_mode('keypad', [
            self._instrument._keypad, self._instrument._keypad.main_layer,
            self._instrument.keypad_options_layer
        ])
        self._instrument._main_modes.add_mode('keypad_shifted', [
            self._instrument._keypad, self._instrument._keypad.select_layer,
            self._instrument.keypad_options_layer
        ])
        #self._instrument.register_component(self._instrument._main_modes)

        self._instrument.set_enabled(False)
        #self._instrument.audioloop_layer = LayerMode(self._instrument, Layer(priority = 6, loop_selector_matrix = self._base_grid))

    def _setup_modes(self):
        self._main_modes = ModesComponent(name='MainModes')
        self._main_modes.add_mode('disabled', [])
        self._main_modes.add_mode(
            'session_shifted', [
                self._recorder, self._mixer,
                self._mixer.solo_mute_record_stop_layer, self._session,
                self._session.stop_layer, self._session_navigation,
                self._session_navigation._vertical_layer, self._transport
            ],
            groups=['shifted'],
            behaviour=self._shift_latching(color='Mode.Session'))
        self._main_modes.add_mode(
            'session', [
                self._recorder, self._mixer, self._session,
                self._session.cliplaunch_layer, self._session_navigation,
                self._session_navigation._horizontal_layer, self._transport
            ],
            behaviour=self._shift_latching(color='Mode.Session'))
        self._main_modes.add_mode(
            'instrument_shifted', [
                self._recorder, self._mixer, self._mixer.mute_layer,
                self._viewcontrol, self._instrument, self._transport
            ],
            groups=['shifted'],
            behaviour=self._shift_latching(color='Mode.Instrument'))
        self._main_modes.add_mode(
            'instrument', [
                self._recorder, self._mixer, self._mixer.select_layer,
                self._viewcontrol, self._instrument, self._transport
            ],
            behaviour=self._shift_latching(color='Mode.Instrument'))

        self._main_modes.layer = Layer(priority=6,
                                       session_button=self._side_button[4],
                                       instrument_button=self._side_button[3])
        self._main_modes.set_enabled(False)
        self._main_modes.selected_mode = 'disabled'

    def _can_auto_arm_track(self, track):
        routing = track.current_input_routing
        return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith(
            'Livid Minim Input')

    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

    @listens('device')
    def _on_device_changed(self):
        pass

    def disconnect(self):
        self.log_message(
            '<<<<<<<<<<<<<<<<<<<<<<<<< Minim log closed >>>>>>>>>>>>>>>>>>>>>>>>>'
        )
        super(Minim, self).disconnect()

    def handle_sysex(self, midi_bytes):
        #debug('sysex: ', str(midi_bytes))
        #debug('matching:', midi_bytes[1:5], 'to', tuple([0, 1, 97]  + [self._sysex_id]))
        if len(midi_bytes) == 9 and midi_bytes[1:5] == tuple([0, 1, 97] +
                                                             [self._sysex_id]):
            if not self._connected:
                #debug('connecting from sysex...')
                self._connected = True
                self._initialize_hardware()
                self._initialize_script()
class Minim(LividControlSurface):


	_sysex_id = 18
	_model_name = 'Minim'

	def __init__(self, c_instance, *a, **k):
		super(Minim, self).__init__(c_instance, *a, **k)
		self._shift_latching = LatchingShiftedBehaviour if SHIFT_LATCHING else ShiftedBehaviour
		self._skin = Skin(MinimColors)
		with self.component_guard():
			self._define_sysex()
			self._setup_monobridge()
			self._setup_controls()
			self._setup_background()
			self._setup_autoarm()
			self._setup_viewcontrol()
			self._setup_session()
			self._setup_mixer()
			self._setup_transport()
			self._setup_recorder()
			self._setup_instrument()
			self._setup_modes() 
			self._setup_m4l_interface()
		self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Minim log opened >>>>>>>>>>>>>>>>>>>>>>>>>')
		self.show_message('Minim Control Surface Loaded')
		self._background.set_enabled(True)
	

	def _check_connection(self):
		if not self._connected:
			debug(self._model_name, '_check_connection')
			self._livid_settings.new_query_surface()
			#self._connection_routine.restart()
			self.schedule_message(5, self._check_connection)
	

	def _initialize_hardware(self):
		debug('sending local control off')
		self.local_control_off.enter_mode()
	

	def _initialize_script(self):
		self._on_device_changed.subject = self._device_provider
		self._main_modes.set_enabled(True)
		self._main_modes.selected_mode = 'session'
		self._session_ring._update_highlight()
		self.refresh_state()
	

	def _setup_controls(self):
		is_momentary = True
		optimized = False
		resource = PrioritizedResource
		self._fader = MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = MINIM_SLIDER, name = 'Fader', script = self, mapping_feedback_delay = -1, optimized_send_midi = optimized, resource_type = resource)
		self._pad = [[MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MINIM_PADS[row][column], name = 'Pad_' + str(column) + '_' + str(row), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource) for column in range(4)] for row in range(2)]
		self._button = [[MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MINIM_BUTTONS[row][column], name = 'Button_' + str(column) + '_' + str(row), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource) for column in range(4)] for row in range(2)]
		self._side_button = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MINIM_SIDE_BUTTONS[index], name = 'Side_Button_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource) for index in range(5)]		
		self._top_button = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MINIM_TOP_BUTTONS[index], name = 'Top_Button_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource) for index in range(2)]	
		self._bottom_button = MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MINIM_BOTTOM_BUTTON, name = 'Bottom_Button', script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource)	


		self._matrix = ButtonMatrixElement(name = 'Pad_Matrix', rows = [self._button[:][0], self._pad[:][0], self._pad[:][1],self._button[:][1]])
		self._side_button_matrix = ButtonMatrixElement(name = 'Side_Button_Matrix', rows = [self._side_button])
		self._top_button_matrix = ButtonMatrixElement(name = 'Button_Matrix', rows = [self._top_button])
	

	def _setup_background(self):
		self._background = BackgroundComponent()
		self._background.layer = Layer(priority = 3, matrix = self._matrix.submatrix[:,:], side_buttons = self._side_button_matrix, top_buttons = self._top_button_matrix.submatrix[:,:], bottom_button = self._bottom_button)
		self._background.set_enabled(False)
	

	def _define_sysex(self):
		self._livid_settings = LividSettings(model = 18, control_surface = self)
		self.local_control_off = SendLividSysexMode(livid_settings = self._livid_settings, call = 'set_local_control', message = [42, 42])
	

	def _setup_autoarm(self):
		self._auto_arm = AutoArmComponent(name='Auto_Arm')
		self._auto_arm.can_auto_arm_track = self._can_auto_arm_track
		self._auto_arm._update_notification = lambda: None
	

	def _setup_viewcontrol(self):
		self._viewcontrol = ViewControlComponent()
		self._viewcontrol.layer = Layer(priority = 4, prev_track_button = self._top_button[0], next_track_button = self._top_button[1])
		self._viewcontrol.set_enabled(False)
	

	def _setup_transport(self):
		self._transport = TransportComponent(name = 'Transport') 
		self._transport.layer = Layer(priority = 4, play_button = self._side_button[0]) #, overdub_button = self._side_button[1])
		self._transport.set_enabled(False)
	

	def _setup_mixer(self):
		self._mixer = MonoMixerComponent(name = 'Mixer',tracks_provider = self._session_ring, track_assigner = simple_track_assigner, invert_mute_feedback = True, auto_name = True, enable_skinning = True)
		self._mixer._selected_strip.layer = Layer(priority = 4, volume_control = self._fader)
		self._mixer.solo_mute_record_stop_layer = AddLayerMode(self._mixer, Layer(priority = 4, 
																					mute_buttons = self._matrix.submatrix[:, 0], 
																					solo_buttons = self._matrix.submatrix[:, 1],
																					arm_buttons = self._matrix.submatrix[:, 2],
																					))
		self._mixer.select_layer = AddLayerMode(self._mixer, Layer(priority = 4, arming_track_select_buttons = self._matrix.submatrix[:, 3]))
		self._mixer.mute_layer = AddLayerMode(self._mixer, Layer(priority = 4, mute_buttons = self._matrix.submatrix[:, 3]))
	

	def _setup_session(self):
		self._session_ring = SessionRingComponent(name = 'Session_Ring', num_tracks = 4, num_scenes = 4)

		self._session = SessionComponent(name = 'Session', session_ring = self._session_ring, auto_name = True)
		self._session.cliplaunch_layer = AddLayerMode(self._session, Layer(priority = 4, clip_launch_buttons = self._matrix.submatrix[:,:]))
		self._session.stop_layer = AddLayerMode(self._session, Layer(priority = 4, stop_track_clip_buttons = self._matrix.submatrix[:,3]))

		self._session_navigation = SessionNavigationComponent(name = 'Session_Navigation', session_ring = self._session_ring)
		self._session_navigation._horizontal_layer = AddLayerMode(self._session_navigation, Layer(priority = 4, left_button = self._top_button[0], right_button = self._top_button[1]))
		self._session_navigation._vertical_layer = AddLayerMode(self._session_navigation, Layer(priority = 4, up_button = self._top_button[0], down_button = self._top_button[1]))
		self._session_navigation.set_enabled(False)
	

	def _setup_recorder(self):
		self._recorder = SessionRecordingComponent(view_controller = self._viewcontrol)
		self._recorder.layer = Layer(priority = 4, new_button = self._side_button[2], record_button = self._side_button[1])
		self._recorder.set_enabled(False)
	

	def _setup_instrument(self):
		self._grid_resolution = GridResolution()

		self._c_instance.playhead.enabled = True
		self._playhead_element = PlayheadElement(self._c_instance.playhead)

		self._drum_group_finder = PercussionInstrumentFinder(device_parent=self.song.view.selected_track)

		self._instrument = MinimMonoInstrumentComponent(name = 'InstrumentComponent', script = self, skin = self._skin, drum_group_finder = self._drum_group_finder, grid_resolution = self._grid_resolution, settings = DEFAULT_INSTRUMENT_SETTINGS, device_provider = self._device_provider, parent_task_group = self._task_group)
		self._instrument._drumpad._drumgroup._button_coordinates_to_pad_index = lambda first_note, coordinates: coordinates[1] + (abs(coordinates[0]-1)*4) + first_note
		self._instrument._drumpad._drumgroup.create_translation_entry = lambda button: (button.coordinate[1], button.coordinate[0]+2, button.identifier, button.channel)

		self._instrument.layer = Layer(priority = 6, shift_button = self._side_button[3])

		self._instrument.keypad_options_layer = AddLayerMode(self._instrument, Layer(priority = 6, 
									scale_up_button = self._button[0][3], 
									scale_down_button = self._button[0][2],
									offset_up_button = self._button[0][1], 
									offset_down_button = self._button[0][0],))
									#vertical_offset_up_button = self._top_button[1],
									#vertical_offset_down_button = self._top_button[0]))
		self._instrument.drumpad_options_layer = AddLayerMode(self._instrument, Layer(priority = 6, 
									scale_up_button = self._button[0][3],
									scale_down_button = self._button[0][2],
									drum_offset_up_button = self._button[0][1], 
									drum_offset_down_button = self._button[0][0],))

		self._instrument._keypad.main_layer = LayerMode(self._instrument._keypad, Layer(priority = 6, keypad_matrix = self._matrix.submatrix[:,1:3]))
		self._instrument._keypad.select_layer = LayerMode(self._instrument._keypad, Layer(priority = 6, keypad_select_matrix = self._matrix.submatrix[:, 1:3]))

		self._instrument._drumpad.main_layer = LayerMode(self._instrument._drumpad, Layer(priority = 6, drumpad_matrix = self._matrix.submatrix[:,1:3]))
		self._instrument._drumpad.select_layer = LayerMode(self._instrument._drumpad, Layer(priority = 6, drumpad_select_matrix = self._matrix.submatrix[:,1:3]))

		self._instrument._main_modes = ModesComponent(name = 'InstrumentModes')
		self._instrument._main_modes.add_mode('disabled', [])
		self._instrument._main_modes.add_mode('drumpad', [self._instrument._drumpad, self._instrument._drumpad.main_layer, self._instrument.drumpad_options_layer])
		self._instrument._main_modes.add_mode('drumpad_shifted', [self._instrument._drumpad, self._instrument._drumpad.select_layer, self._instrument.drumpad_options_layer])
		self._instrument._main_modes.add_mode('keypad', [self._instrument._keypad, self._instrument._keypad.main_layer, self._instrument.keypad_options_layer])
		self._instrument._main_modes.add_mode('keypad_shifted', [self._instrument._keypad, self._instrument._keypad.select_layer, self._instrument.keypad_options_layer])
		self._instrument.register_component(self._instrument._main_modes)

		self._instrument.set_enabled(False)
		#self._instrument.audioloop_layer = LayerMode(self._instrument, Layer(priority = 6, loop_selector_matrix = self._base_grid))
	

	def _setup_modes(self):
		self._main_modes = ModesComponent(name = 'MainModes')
		self._main_modes.add_mode('disabled', [])
		self._main_modes.add_mode('session_shifted', [self._recorder, self._mixer, self._mixer.solo_mute_record_stop_layer, self._session, self._session.stop_layer, self._session_navigation, self._session_navigation._vertical_layer, self._transport], groups = ['shifted'], behaviour = self._shift_latching(color = 'Mode.Session'))
		self._main_modes.add_mode('session', [self._recorder, self._mixer, self._session, self._session.cliplaunch_layer, self._session_navigation, self._session_navigation._horizontal_layer, self._transport], behaviour = self._shift_latching(color = 'Mode.Session'))
		self._main_modes.add_mode('instrument_shifted', [self._recorder, self._mixer, self._mixer.mute_layer, self._viewcontrol, self._instrument, self._transport], groups = ['shifted'], behaviour = self._shift_latching(color = 'Mode.Instrument'))
		self._main_modes.add_mode('instrument', [self._recorder, self._mixer, self._mixer.select_layer, self._viewcontrol, self._instrument, self._transport], behaviour = self._shift_latching(color = 'Mode.Instrument'))

		self._main_modes.layer = Layer(priority = 6, session_button = self._side_button[4], instrument_button = self._side_button[3])
		self._main_modes.set_enabled(False)
		self._main_modes.selected_mode = 'disabled'
	

	def _can_auto_arm_track(self, track):
		routing = track.current_input_routing
		return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith('Livid Minim Input')
	

	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
	

	@listens('device')
	def _on_device_changed(self):
		pass
	

	def disconnect(self):
		self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Minim log closed >>>>>>>>>>>>>>>>>>>>>>>>>')
		super(Minim, self).disconnect()
	

	def handle_sysex(self, midi_bytes):
		#debug('sysex: ', str(midi_bytes))
		#debug('matching:', midi_bytes[1:5], 'to', tuple([0, 1, 97]  + [self._sysex_id]))
		if len(midi_bytes)==9 and midi_bytes[1:5] == tuple([0, 1, 97]  + [self._sysex_id]):
			if not self._connected:
				#debug('connecting from sysex...')
				self._connected = True
				self._initialize_hardware()
				self._initialize_script()
	def _setup_background(self):
		self._background = BackgroundComponent()
		self._background.layer = Layer(priority = 3, matrix = self._matrix.submatrix[:,:], side_buttons = self._side_button_matrix, top_buttons = self._top_button_matrix.submatrix[:,:], bottom_button = self._bottom_button)
		self._background.set_enabled(False)
class Morph(ControlSurface):

    _model_name = 'Morph'
    bank_definitions = BANK_DEFINITIONS

    def __init__(self, c_instance, *a, **k):
        self.log_message = logger.info
        super(Morph, self).__init__(c_instance, *a, **k)
        self._skin = Skin(MorphColors)
        with self.component_guard():
            self._setup_controls()
            self._setup_background()
            #self._setup_button_background()
            self._setup_percussion_instrument_finder()
            self._setup_drum_group()
            self._setup_drum_group2()
            self._setup_keys_group()
            self._setup_piano_group()
            self._setup_autoarm()
            self._setup_device()
            self._setup_session()
            self._setup_session2()
            self._setup_session3()
            self._setup_mixer()
            self._setup_transport()
            self._setup_viewcontrol()
            self._setup_recorder()
            self._setup_translations()
            self._setup_modes()
        self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Morph ' + VERSION +
                         ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>')
        self.show_message('Morph ' + VERSION +
                          ' Control Surface Loaded, Autoarm is: ' +
                          ('ON' if AUTOARM else 'OFF'))
        self.schedule_message(2, self._init_surface)
        #debug('device:', self._device._get_device())

    def _init_surface(self):
        #self._main_modes.selected_mode = 'Main'
        self._on_device_changed.subject = self._device_provider
        self._on_selected_track_changed.subject = self.song.view
        self._on_selected_track_changed()
        self._send_midi(CHECK_MAPS)
        self._send_midi(MAGNET_VALUES_CALL)

    def port_settings_changed(self):
        super(Morph, self).port_settings_changed()
        self._init_surface()

    def _setup_controls(self):
        is_momentary = True
        optimized = False
        resource = ExclusiveResource  #PrioritizedResource
        self._pad_raw = [None for index in range(16)]
        self._pad = [[None, None, None, None] for index in range(4)]
        # for index in range(4):
        # 	self._pad[index] = [None, None, None, None]
        for chan in range(16):
            # debug('making ...', chan)
            self._pad_raw[chan] = [[
                ButtonElement(is_momentary=is_momentary,
                              msg_type=MIDI_NOTE_TYPE,
                              channel=chan,
                              identifier=MORPH_PADS[row][column],
                              name='Pad_' + str(column) + '_' + str(row) +
                              '_' + str(chan),
                              skin=self._skin,
                              resource_type=resource) for column in range(4)
            ] for row in range(4)]
            for row in self._pad_raw[chan]:
                for pad in row:
                    pad.enabled = False

        for proxy in range(16):
            buttons = []
            # debug('making pad ...', chan, proxy%4, math.floor(proxy/4))
            for chan in range(16):
                button = self._pad_raw[chan][int(proxy % 4)][int(
                    math.floor(proxy / 4))]
                buttons.append(button)
            self._pad[int(proxy % 4)][int(
                math.floor(proxy / 4))] = SpecialMultiElement(
                    buttons[0], buttons[1], buttons[2], buttons[3], buttons[4],
                    buttons[5], buttons[6], buttons[7], buttons[8], buttons[9],
                    buttons[10], buttons[11], buttons[12], buttons[13],
                    buttons[14], buttons[15])
            self._pad[int(proxy % 4)][int(math.floor(
                proxy / 4))]._name = 'PadCombo_' + str(proxy)
            # self.log_message('self._pad '+str(self._pad[int(proxy%4)][int(math.floor(proxy/4))]._name))
            # self.log_message('hasattr:'+ str(hasattr(self._pad[int(proxy%4)][int(math.floor(proxy/4))], '_name')))

        self._button = [
            ButtonElement(is_momentary=is_momentary,
                          msg_type=MIDI_NOTE_TYPE,
                          channel=CHANNEL,
                          identifier=MORPH_BUTTONS[index],
                          name='Button_' + str(index),
                          skin=self._skin,
                          resource_type=resource) for index in range(8)
        ]
        for button in self._button:
            button.set_enabled = True

        self._key_raw = [None for index in range(16)]
        self._key = [None for index in range(25)]
        for chan in range(16):

            self._key_raw[chan] = [
                MorphButtonElement(is_momentary=is_momentary,
                                   msg_type=MIDI_NOTE_TYPE,
                                   channel=chan,
                                   identifier=MORPH_KEYS[index],
                                   name='Key_' + str(index) + '_' + str(chan),
                                   skin=self._skin,
                                   resource_type=resource)
                for index in range(25)
            ]
            for key in self._key_raw[chan]:
                key.enabled = False

        for proxy in range(25):
            keys = []
            for chan in range(16):
                key = self._key_raw[chan][proxy]
                keys.append(key)
            self._key[proxy] = SpecialMultiElement(keys[0], keys[1], keys[2],
                                                   keys[3], keys[4], keys[5],
                                                   keys[6], keys[7], keys[8],
                                                   keys[9], keys[10], keys[11],
                                                   keys[12], keys[13],
                                                   keys[14], keys[15])
            self._key[proxy]._name = 'KeyCombo_' + str(proxy)

        self._dials = [
            MorphEncoderElement(msg_type=MIDI_CC_TYPE,
                                channel=CHANNEL,
                                identifier=MORPH_DIALS[index],
                                map_mode=Live.MidiMap.MapMode.absolute,
                                name='Dial_' + str(index),
                                resource_type=resource) for index in range(8)
        ]
        self._slider = [
            MorphEncoderElement(msg_type=MIDI_CC_TYPE,
                                channel=CHANNEL,
                                identifier=MORPH_SLIDERS[index],
                                map_mode=Live.MidiMap.MapMode.absolute,
                                name='Slider_' + str(index),
                                resource_type=resource) for index in range(2)
        ]
        self._send_pressure = [
            MorphEncoderElement(msg_type=MIDI_CC_TYPE,
                                channel=CHANNEL,
                                identifier=MORPH_SEND_PRESSURE[index],
                                map_mode=Live.MidiMap.MapMode.absolute,
                                name='SendPressure_' + str(index),
                                resource_type=resource) for index in range(2)
        ]
        self._thunder_slider = [
            MorphEncoderElement(msg_type=MIDI_CC_TYPE,
                                channel=CHANNEL,
                                identifier=MORPH_THUNDER_SLIDERS[index],
                                map_mode=Live.MidiMap.MapMode.absolute,
                                name='Slider_' + str(index),
                                resource_type=resource) for index in range(6)
        ]

        self._pad_matrix = ButtonMatrixElement(name='PadMatrix',
                                               rows=self._pad)
        self._dial_matrix = ButtonMatrixElement(name='DialMatrix',
                                                rows=[self._dials])
        self._button_matrix = ButtonMatrixElement(name='ButtonMatrix',
                                                  rows=[self._button])
        self._key_matrix = ButtonMatrixElement(name='KeyMatrix',
                                               rows=[self._key[:14]])
        self._key_shift_matrix = ButtonMatrixElement(name='KeyShiftMatrix',
                                                     rows=[self._key[2:11]])
        self._slider_matrix = ButtonMatrixElement(name='SliderMatrix',
                                                  rows=[self._slider])
        self._send_pressure_matrix = ButtonMatrixElement(
            name='SendAMatrix', rows=[self._send_pressure])
        self._thunder_slider_matrix = ButtonMatrixElement(
            name='ThunderSliderMatrix', rows=[self._thunder_slider])
        #self._shift_send_pressure_matrix = ButtonMatrixElement(name = 'ShiftSendMatrix', rows = [ [None, None, self._send_pressure[0], self._send_pressure[1]] ])

        self._piano_button = [
            MorphButtonElement(is_momentary=is_momentary,
                               msg_type=MIDI_NOTE_TYPE,
                               channel=CHANNEL,
                               identifier=PIANO_BUTTONS[index],
                               name='PianoButton_' + str(index),
                               skin=self._skin,
                               resource_type=resource) for index in range(4)
        ]
        for button in self._piano_button:
            button.enabled = False
        #self._piano_key = [MorphButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = PIANO_CHANNEL, identifier = PIANO_KEYS[index], name = 'PianoKey_' + str(index), skin = self._skin, resource_type = resource) for index in range(25)]

        self._piano_matrix = ButtonMatrixElement(name='PianoMatrix',
                                                 rows=[self._key])
        self._piano_session_matrix = ButtonMatrixElement(
            name='PianoSessionMatrix',
            rows=[
                self._key[0:4], self._key[4:8], self._key[8:12],
                self._key[12:16]
            ])
        #self._drum_session_matrix = ButtonMatrixElement(name = 'DrumSessionMatrix', rows = )

    def _setup_background(self):
        self._background = BackgroundComponent()
        self._background.layer = Layer(priority=1,
                                       pads=self._pad_matrix,
                                       buttons=self._button_matrix,
                                       keys=self._key_matrix,
                                       dials=self._dial_matrix,
                                       sliders=self._slider_matrix)
        self._background.set_enabled(False)

    def _setup_percussion_instrument_finder(self):
        self._percussion_instrument_finder = PercussionInstrumentFinder(
            device_parent=self.song.view.selected_track)

    def _setup_drum_group(self):
        # self._drum_group = MorphDrumGroup(set_pad_translations = self.set_pad_translations, translation_channel = PAD_TRANSLATION_CHANNEL)
        self._drum_group = MorphDrumGroup()
        self._drum_group.position = 9
        self._drum_group.main_layer = AddLayerMode(
            self._drum_group, Layer(priority=2, matrix=self._pad_matrix))
        self._drum_group.nav_layer = AddLayerMode(
            self._drum_group,
            Layer(priority=2,
                  scroll_up_button=self._key[1],
                  scroll_down_button=self._key[0]))
        self._drum_group.set_enabled(False)

    def _setup_drum_group2(self):
        # self._drum_group2 = MorphDrumGroup(set_pad_translations = self.set_pad_translations, translation_channel = DRUM_TRANSLATION_CHANNEL)
        self._drum_group2 = MorphDrumGroup()
        self._drum_group2.position = 9
        self._drum_group2.main_layer = AddLayerMode(
            self._drum_group2, Layer(priority=2, matrix=self._pad_matrix))
        self._drum_group2.nav_layer = AddLayerMode(
            self._drum_group2,
            Layer(priority=2,
                  scroll_up_button=self._key[1],
                  scroll_down_button=self._key[0]))
        self._drum_group2.set_enabled(False)

    def _setup_keys_group(self):
        # self._keys_group = MorphKeysGroup(translation_channel = KEY_TRANSLATION_CHANNEL)
        self._keys_group = MorphKeysGroup()
        self._keys_group.main_layer = AddLayerMode(
            self._keys_group, Layer(priority=2, matrix=self._key_matrix))
        self._keys_group.shift_layer = AddLayerMode(
            self._keys_group,
            Layer(priority=2,
                  matrix=self._key_shift_matrix,
                  scroll_up_button=self._key[12],
                  scroll_down_button=self._key[11]))
        self._keys_group.set_enabled(False)

    def _setup_piano_group(self):
        # self._piano_group = MorphKeysGroup(translation_channel = PIANO_TRANSLATION_CHANNEL)
        self._piano_group = MorphKeysGroup()
        self._piano_group._hi_limit = 8
        self._piano_group.main_layer = AddLayerMode(
            self._piano_group,
            Layer(priority=2,
                  matrix=self._piano_matrix,
                  scroll_up_button=self._piano_button[1],
                  scroll_down_button=self._piano_button[0]))
        #self._piano_group.shift_layer = AddLayerMode(self._piano_group, Layer(matrix = self._piano_shift_matrix, scroll_up_button = self._pian0[12], scroll_down_button = self._key[11]))
        self._piano_group.set_enabled(False)

    def _setup_autoarm(self):
        self._auto_arm = AutoArmComponent(name='Auto_Arm', is_enabled=AUTOARM)
        self._auto_arm.can_auto_arm_track = self._can_auto_arm_track
        self._auto_arm._update_notification = lambda: None

    def _setup_transport(self):
        self._transport = TransportComponent(name='Transport')
        self._transport.layer = Layer(priority=2,
                                      play_button=self._button[4],
                                      stop_button=self._button[5],
                                      overdub_button=self._button[6])
        self._transport.set_enabled(False)

    def _setup_translations(self):
        self._translations = TranslationComponent(name='Translations',
                                                  channel=USER_CHANNEL,
                                                  controls=self._dials +
                                                  self._slider)
        self._translations.set_enabled(False)

    def _setup_device(self):
        self._device = MorphDeviceComponent(
            device_decorator_factory=DeviceDecoratorFactory(),
            banking_info=BankingInfo(self.bank_definitions),
            device_provider=self._device_provider,
            device_bank_registry=DeviceBankRegistry())
        self._device_parameters = DeviceParameterComponent(self._device)
        self._device_parameters.layer = Layer(
            priority=2, parameter_controls=self._dial_matrix)
        self._device.set_enabled(False)
        self._device_parameters.set_enabled(False)

        self._device2 = MorphDeviceComponent(
            device_decorator_factory=DeviceDecoratorFactory(),
            banking_info=BankingInfo(self.bank_definitions),
            device_provider=self._device_provider,
            device_bank_registry=DeviceBankRegistry())
        self._device_parameters2 = DeviceParameterComponent(self._device2)
        self._device_parameters2.layer = Layer(
            priority=2, parameter_controls=self._thunder_slider_matrix)
        self._device2.set_enabled(False)
        self._device_parameters2.set_enabled(False)

    def _setup_session(self):
        self._session_ring = SessionRingComponent(name='Session_Ring',
                                                  num_tracks=4,
                                                  num_scenes=4)

        self._session = SessionComponent(name='Session',
                                         session_ring=self._session_ring,
                                         auto_name=True)
        self._session.layer = Layer(
            priority=2,
            clip_launch_buttons=self._pad_matrix,
        )  # stop_all_clips_button = self._button[5])
        self._session.set_enabled(False)

        self._session_navigation = SessionNavigationComponent(
            name='Session_Navigation', session_ring=self._session_ring)
        self._session_navigation.layer = Layer(priority=2,
                                               left_button=self._button[0],
                                               right_button=self._button[1])
        self._session_navigation.set_enabled(False)

    def _setup_session2(self):
        self._session2 = SessionComponent(name='Session2',
                                          session_ring=self._session_ring,
                                          auto_name=True)
        self._session2.layer = Layer(
            priority=2, clip_launch_buttons=self._piano_session_matrix)
        self._session2.set_enabled(False)

    def _setup_session3(self):
        self._session3 = SessionComponent(name='Session3',
                                          session_ring=self._session_ring,
                                          auto_name=True)
        self._session3.layer = Layer(priority=2,
                                     clip_launch_buttons=self._pad_matrix)
        self._session3.set_enabled(False)

    def _setup_mixer(self):
        self._mixer = MorphMixerComponent(
            tracks_provider=self._session_ring,
            track_assigner=SimpleTrackAssigner(),
            auto_name=True,
            invert_mute_feedback=False,
            channel_strip_component_type=MorphChannelStripComponent)
        self._mixer._selected_strip.main_layer = AddLayerMode(
            self._mixer._selected_strip,
            Layer(priority=2, send_controls=self._send_pressure_matrix))
        self._mixer._selected_strip.shift_layer = AddLayerMode(
            self._mixer._selected_strip,
            Layer(priority=2, stop_button=self._button[5]))
        #self._mixer._selected_strip.shift_layer = AddLayerMode(self._mixer, Layer(send_controls = self._shift_send_pressure_matrix.submatrix[:,]))

    def _setup_viewcontrol(self):
        self._viewcontrol = ViewControlComponent()
        self._viewcontrol.layer = Layer(priority=2,
                                        prev_track_button=self._button[0],
                                        next_track_button=self._button[1])
        self._viewcontrol.set_enabled(False)

    def _setup_recorder(self):
        self._recorder = SessionRecordingComponent(
            view_controller=ViewControlComponent())
        self._recorder.layer = Layer(priority=2, record_button=self._button[6])
        self._recorder.set_enabled(False)

    def _assign_crossfader(self):
        self._slider[1].connect_to(
            self.song.master_track.mixer_device.crossfader)
        # debug('_assign_crossfader:', self._slider[1]._parameter_to_map_to)

    def _deassign_crossfader(self):
        self._slider[1].release_parameter()
        # debug('_assign_crossfader:', self._slider[1]._parameter_to_map_to)

    def _setup_modes(self):
        self._production_modes = ModesComponent(name='ProductionModes')
        self._production_modes.add_mode('Main', [
            self._mixer, self._mixer._selected_strip.main_layer,
            self._viewcontrol, self._drum_group, self._drum_group.main_layer,
            self._keys_group, self._keys_group.main_layer, self._device,
            self._device_parameters, self._transport, self._assign_crossfader
        ])
        self._production_modes.add_mode('Shift', [
            self._mixer, self._mixer._selected_strip.shift_layer,
            self._session, self._session_navigation, self._drum_group,
            self._drum_group.nav_layer, self._keys_group,
            self._keys_group.shift_layer, self._deassign_crossfader,
            self._recorder, self._translations
        ],
                                        behaviour=MomentaryBehaviour())
        self._production_modes.layer = Layer(Shift_button=self._button[7])
        self._production_modes.selected_mode = 'Main'
        self._production_modes.set_enabled(False)

        self._piano_modes = ModesComponent(name='PianoModes')
        self._piano_modes.add_mode('Main', [
            self._piano_group, self._piano_group.main_layer, self._mixer,
            self._mixer._selected_strip.main_layer, self._viewcontrol,
            self._device, self._device_parameters, self._transport,
            self._assign_crossfader
        ])
        self._piano_modes.add_mode('Shift', [
            self._mixer, self._mixer._selected_strip.shift_layer,
            self._session2, self._session_navigation, self._recorder
        ],
                                   behaviour=MomentaryBehaviour())
        self._piano_modes.layer = Layer(Shift_button=self._button[7])
        self._piano_modes.selected_mode = 'Main'
        self._piano_modes.set_enabled(False)

        self._drumpad_modes = ModesComponent(name='DrumpadModes')
        self._drumpad_modes.add_mode('Main', [
            self._mixer, self._mixer._selected_strip.main_layer,
            self._viewcontrol, self._drum_group2, self._drum_group2.main_layer,
            self._transport, self._assign_crossfader
        ])
        self._drumpad_modes.add_mode('Shift', [
            self._mixer, self._mixer._selected_strip.shift_layer,
            self._session3, self._session_navigation, self._recorder
        ],
                                     behaviour=MomentaryBehaviour())
        self._drumpad_modes.layer = Layer(Shift_button=self._button[7])
        self._drumpad_modes.selected_mode = 'Main'
        self._drumpad_modes.set_enabled(False)

        self._thunder_modes = ModesComponent(name='ThunderModes')
        self._thunder_modes.add_mode('Main', [
            self._mixer, self._mixer._selected_strip.main_layer,
            self._viewcontrol, self._transport, self._assign_crossfader,
            self._device2, self._device_parameters2
        ])
        self._thunder_modes.add_mode('Shift', [
            self._mixer, self._mixer._selected_strip.shift_layer,
            self._recorder, self._device2, self._device_parameters2
        ],
                                     behaviour=MomentaryBehaviour())
        self._thunder_modes.layer = Layer(Shift_button=self._button[7])
        self._thunder_modes.selected_mode = 'Main'
        self._thunder_modes.set_enabled(False)

        self._innovator_modes = ModesComponent(name='InnovatorModes')
        self._innovator_modes.add_mode('Main', [
            self._mixer, self._mixer._selected_strip.main_layer,
            self._viewcontrol, self._device, self._device_parameters,
            self._transport, self._assign_crossfader
        ])
        self._innovator_modes.add_mode('Shift', [
            self._mixer, self._mixer._selected_strip.shift_layer,
            self._deassign_crossfader, self._recorder, self._translations
        ],
                                       behaviour=MomentaryBehaviour())
        self._innovator_modes.layer = Layer(Shift_button=self._button[7])
        self._innovator_modes.selected_mode = 'Main'
        self._innovator_modes.set_enabled(False)

        self._main_modes = ModesComponent(name='MainModes')
        self._main_modes.add_mode('disabled', self._background)
        self._main_modes.add_mode('ProductionMode', [self._production_modes])
        self._main_modes.add_mode('PianoMode', [self._piano_modes])
        self._main_modes.add_mode('DrumpadMode', [self._drumpad_modes])
        self._main_modes.add_mode('ThunderMode', [self._thunder_modes])
        self._main_modes.add_mode('InnovatorMode', [self._innovator_modes])

        self._report_mode.subject = self._main_modes
        self._main_modes.selected_mode = 'disabled'

    @listens('selected_mode')
    def _report_mode(self, *a, **k):
        debug('Modes:', self._main_modes.selected_mode,
              self._production_modes.selected_mode,
              self._piano_modes.selected_mode,
              self._drumpad_modes.selected_mode,
              self._thunder_modes.selected_mode)

    def _maintestfunc(self, *a, **k):
        debug('maintestfunc')

    def _can_auto_arm_track(self, track):
        if not AUTOARM:
            return False
        routing = track.current_input_routing
        return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith(
            'Sensel') or routing.startswith('Morph')

    @listens('device')
    def _on_device_changed(self):
        debug('_on_device_changed:', self._device_provider.device)
        self._on_selected_track_changed()
        # self._drum_group.set_drum_group_device(self._device_provider.device)
        # self._drum_group2.set_drum_group_device(self._device_provider.device)

    @listens('selected_track')
    def _on_selected_track_changed(self):
        debug('_on_selected_track_changed')
        track = self.song.view.selected_track
        self._percussion_instrument_finder.device_parent = track
        self._percussion_instrument_finder.update()
        self._drum_group.set_drum_group_device(
            self._percussion_instrument_finder.drum_group)
        self._drum_group2.set_drum_group_device(
            self._percussion_instrument_finder.drum_group)

    def disconnect(self):
        self.log_message(
            '<<<<<<<<<<<<<<<<<<<<<<<<< Morph log closed >>>>>>>>>>>>>>>>>>>>>>>>>'
        )
        super(Morph, self).disconnect()

    def process_midi_bytes(self, midi_bytes, midi_processor):
        super(Morph, self).process_midi_bytes(midi_bytes, midi_processor)
        if midi.is_sysex(midi_bytes):
            self.handle_sysex(midi_bytes)

    def handle_sysex(self, midi_bytes):
        debug('sysex: ', str(midi_bytes))
        #debug('matching:', midi_bytes[1:5], 'to', tuple([0, 1, 97]  + [self._sysex_id]))
        if len(midi_bytes) == 9 and midi_bytes[1:5] == tuple([0, 1, 97] +
                                                             [self._sysex_id]):
            if not self._connected:
                #debug('connecting from sysex...')
                self._connected = True
                self._initialize_hardware()
                self._initialize_script()
        if len(midi_bytes) == 11:
            if midi_bytes == PIANO_OVERLAY:
                debug('piano overlay...')
                self._main_modes.selected_mode = 'PianoMode'
            elif midi_bytes == PRODUCTION_OVERLAY:
                debug('production overlay...')
                self._main_modes.selected_mode = 'ProductionMode'
            elif midi_bytes == DRUM_OVERLAY:
                debug('drum overlay...')
                self._main_modes.selected_mode = 'DrumpadMode'
            elif midi_bytes == THUNDER_OVERLAY:
                debug('thunder overlay...')
                self._main_modes.selected_mode = 'ThunderMode'
            elif midi_bytes == INNOVATOR_OVERLAY:
                debug('innovator overlay...')
                self._main_modes.selected_mode = 'InnovatorMode'
            elif midi_bytes == NO_OVERLAY:
                debug('no overlay...')
                self._main_modes.selected_mode = 'InnovatorMode'
Example #8
0
	def _create_background(self):
		self._background = BackgroundComponent(name = 'Background')
		self._background.layer = Layer(priority = 5, matrix = self._matrix, side_buttons = self._side_matrix, top_buttons = self._top_matrix)
		self._background.set_enabled(True)
Example #9
0
class Launchpad(ControlSurface):
	u""" Script for Novation's Launchpad Controller """

	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		is_momentary = True
		self._suppress_send_midi = False
		with self.component_guard():
			self._skin = make_default_skin()
			#with inject(skin=const(self._skin)).everywhere():
			#	self._midimap = MidiMap()
			self._suggested_input_port = u'Launchpad'
			self._suggested_output_port = u'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 = u'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
			self._matrix = ButtonMatrixElement()
			self._matrix.name = u'Button_Matrix'
			#with inject(skin=const(self._skin)).everywhere():
			for row in range(8):
				button_row = []
				for column in range(8):
					button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, row * 16 + column, skin = self._skin)
					button.name = str(column) + u'_Clip_' + str(row) + u'_Button'
					button_row.append(button)

				self._matrix.add_row(tuple(button_row))
			self._top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, skin = self._skin) for index in range(8) ]
			self._side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index], skin = self._skin) for index in range(8) ]
			self._top_matrix = ButtonMatrixElement(name = u'Top_Button_Matrix', rows = [self._top_buttons])
			self._side_matrix = ButtonMatrixElement(name = u'Side_Button_Matrix', rows = [self._side_buttons])

			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._top_buttons[0].name = u'Bank_Select_Up_Button'
			self._top_buttons[1].name = u'Bank_Select_Down_Button'
			self._top_buttons[2].name = u'Bank_Select_Left_Button'
			self._top_buttons[3].name = u'Bank_Select_Right_Button'
			self._top_buttons[4].name = u'Session_Button'
			self._top_buttons[5].name = u'User1_Button'
			self._top_buttons[6].name = u'User2_Button'
			self._top_buttons[7].name = u'Mixer_Button'
			self._side_buttons[0].name = u'Vol_Button'
			self._side_buttons[1].name = u'Pan_Button'
			self._side_buttons[2].name = u'SndA_Button'
			self._side_buttons[3].name = u'SndB_Button'
			self._side_buttons[4].name = u'Stop_Button'
			self._side_buttons[5].name = u'Trk_On_Button'
			self._side_buttons[6].name = u'Solo_Button'
			self._side_buttons[7].name = u'Arm_Button'

			self._create_background()
			self._create_translations()
			self._create_session()
			self._create_mixer()
			self._create_modes()
	

	def _create_background(self):
		self._background = BackgroundComponent(name = 'Background')
		self._background.layer = Layer(priority = 5, matrix = self._matrix, side_buttons = self._side_matrix, top_buttons = self._top_matrix)
		self._background.set_enabled(True)
	

	def _create_translations(self):
		self._translations1 = TranslationComponent(name = 'User1Translation', translated_channel=2, should_enable=True, should_reset=True, is_enabled=False, layer=Layer(matrix = self._matrix, top_buttons = self._top_matrix.submatrix[:4,1], side_buttons = self._side_matrix))
		self._translations2 = TranslationComponent(name = 'User2Translation', translated_channel=3, should_enable=True, should_reset=True, is_enabled=False, layer=Layer(matrix = self._matrix, top_buttons = self._top_matrix.submatrix[:4,1], side_buttons = self._side_matrix))
	

	def _create_session(self):
		self._session_ring = SessionRingComponent(8,  8, name = u'Session_Ring')
		self._session = SpecialSessionComponent(session_ring = self._session_ring, name = u'Session', is_enabled = False, auto_name = True)
		self._session_navigation = SessionNavigationComponent(session_ring = self._session_ring, name = u'SessionNavigation', is_enabled = False)
		self._session_navigation._vertical_banking.scroll_up_button.color = 'Session.NavigationButtonOn'
		self._session_navigation._vertical_banking.scroll_up_button.disabled_color = 'Session.NavigationButtonOff'
		self._session_navigation._vertical_banking.scroll_down_button.color = 'Session.NavigationButtonOn'
		self._session_navigation._vertical_banking.scroll_down_button.disabled_color = 'Session.NavigationButtonOff'
		self._session_navigation._horizontal_banking.scroll_up_button.color = 'Session.NavigationButtonOn'
		self._session_navigation._horizontal_banking.scroll_up_button.disabled_color = 'Session.NavigationButtonOff'
		self._session_navigation._horizontal_banking.scroll_down_button.color = 'Session.NavigationButtonOn'
		self._session_navigation._horizontal_banking.scroll_down_button.disabled_color = 'Session.NavigationButtonOff'
		self._session_navigation._vertical_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn'
		self._session_navigation._vertical_paginator.scroll_up_button.disabled_color = 'Session.PageNavigationButtonOff'
		self._session_navigation._vertical_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn'
		self._session_navigation._vertical_paginator.scroll_down_button.disabled_color = 'Session.PageNavigationButtonOff'
		self._session_navigation._horizontal_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn'
		self._session_navigation._horizontal_paginator.scroll_up_button.disabled_color = 'Session.PageNavigationButtonOff'
		self._session_navigation._horizontal_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn'
		self._session_navigation._horizontal_paginator.scroll_down_button.disabled_color = 'Session.PageNavigationButtonOff'
		self._zooming = SessionOverviewComponent(session_ring = self._session_ring, enable_skinning = True, name = u'Session_Zooming', is_enabled = False)
		self._zooming.layer = Layer(button_matrix = self._matrix)

		self._session_navigation.nav_layer = AddLayerMode(self._session_navigation, Layer(up_button = self._top_buttons[0], down_button = self._top_buttons[1], left_button = self._top_buttons[2], right_button = self._top_buttons[3]))
		self._session_navigation.page_layer = AddLayerMode(self._session_navigation, Layer(page_up_button = self._top_buttons[0], page_down_button = self._top_buttons[1], page_left_button = self._top_buttons[2], page_right_button = self._top_buttons[3]))
		self._session.cliplaunch_layer = AddLayerMode(self._session, Layer(priority = 1, clip_launch_buttons = self._matrix, scene_launch_buttons = self._side_matrix))
		self._session.clipstop_layer = AddLayerMode(self._session, Layer(priority = 1, stop_all_clips_button = self._side_buttons[4], stop_track_clip_buttons = self._matrix.submatrix[:, 4:5]))

	def _create_mixer(self):
		self._mixer = SpecialMixerComponent(tracks_provider = self._session_ring, auto_name=True, is_enabled=True, invert_mute_feedback=True)
		self._mixer.name = u'Mixer'
		self._mixer.master_strip().name = u'Master_Channel_strip'
		self._mixer.selected_strip().name = u'Selected_Channel_strip'
		self._sliders = []
		self._slider_volume_modes = []
		self._slider_pan_modes = []
		self._slider_single_modes = []
		for column in range(8):
			self._mixer.channel_strip(column).name = u'Channel_Strip_' + str(column)
			self._sliders.append(PreciseButtonSliderElement(buttons = tuple([ self._matrix._orig_buttons[7-row][column]for row in range(8) ])))
			self._sliders[-1].name = u'Button_Slider_' + str(column)
		self._slider_matrix = ButtonMatrixElement(name = u'SliderMatrix', rows = [self._sliders])
		self._mixer.overview_layer = AddLayerMode(self._mixer, Layer(priority = 1, default_volume_buttons = self._matrix.submatrix[:, :1],
																					default_panning_buttons = self._matrix.submatrix[:, 1:2],
																					default_send1_buttons = self._matrix.submatrix[:, 2:3],
																					default_send2_buttons = self._matrix.submatrix[:, 3:4],
																					mute_buttons = self._matrix.submatrix[:, 5:6],
																					solo_buttons = self._matrix.submatrix[:, 6:7],
																					arm_buttons = self._matrix.submatrix[:, 7:8],
																					unarm_all_button = self._side_buttons[7],
																					unsolo_all_button = self._side_buttons[6],
																					unmute_all_button = self._side_buttons[5]))
		self._mixer.volume_layer = AddLayerMode(self._mixer, Layer(priority = 1, volume_controls = self._slider_matrix))
		self._mixer.pan_layer = AddLayerMode(self._mixer, Layer(priority = 1, pan_controls = self._slider_matrix))
		self._mixer.send1_layer = AddLayerMode(self._mixer, Layer(priority = 1, send_controls = self._slider_matrix))
		self._mixer.send2_layer = AddLayerMode(self._mixer, Layer(priority = 1, send_controls = self._slider_matrix))
	

	def _create_modes(self):
		self._session_modes = ModesComponent(name = u'SessionModes')
		self._session_modes.add_mode(u'Session', [self._session, self._session.cliplaunch_layer, self._session_navigation, self._session_navigation.nav_layer], cycle_mode_button_color = u'MainModes.SelectedOn')
		self._session_modes.add_mode(u'Zoom', [self._zooming, self._session_navigation, self._session_navigation.page_layer], cycle_mode_button_color = u'MainModes.SelectedPressed')
		self._session_modes.selected_mode = u'Session'
		self._session_modes.layer = Layer(priority = 1, cycle_mode_button = self._top_buttons[4])
		self._session_modes.set_enabled(False)

		self._mixer_modes = ModesComponent(name = u'MixerModes')
		self._mixer_modes.add_mode(u'Overview', [self._session_navigation, self._session_navigation.nav_layer, self._session, self._session.clipstop_layer, self._mixer, self._mixer.overview_layer])
		self._mixer_modes.add_mode(u'TrackVolume', [self._session_navigation, self._session_navigation.nav_layer, self._mixer, self._mixer.volume_layer, tuple([self.set_slider_volume_mode, self.set_slider_single_mode])])
		self._mixer_modes.add_mode(u'TrackPan', [self._session_navigation, self._session_navigation.nav_layer, self._mixer, self._mixer.pan_layer, tuple([self.set_slider_pan_mode, self.set_slider_single_mode])])
		self._mixer_modes.add_mode(u'TrackSend1', [self._session_navigation, self._session_navigation.nav_layer, self._mixer, self._mixer.send1_layer, SetAttributeMode(obj=self._mixer, attribute=u'send_index', value=0), tuple([self.set_slider_send_mode, self.set_slider_single_mode])])
		self._mixer_modes.add_mode(u'TrackSend2', [self._session_navigation, self._session_navigation.nav_layer, self._mixer, self._mixer.send2_layer, SetAttributeMode(obj=self._mixer, attribute=u'send_index', value=1), tuple([self.set_slider_send_mode, self.set_slider_single_mode])])
		for mode in self._mixer_modes._mode_list:
			if mode == 'Overview':
				self._mixer_modes.get_mode_button(mode).mode_selected_color = u'MainModes.SelectedOn'
				self._mixer_modes.get_mode_button(mode).mode_unselected_color = u'MainModes.SelectedOn'
			else:
				self._mixer_modes.get_mode_button(mode).mode_selected_color = u'SubModes.SelectedOn'
				self._mixer_modes.get_mode_button(mode).mode_unselected_color = u'SubModes.SelectedOff'
		self._mixer_modes.selected_mode = 'Overview'
		self._mixer_modes.layer = Layer(priority = 1, Overview_button = self._top_buttons[7], TrackVolume_button = self._side_buttons[0], TrackPan_button = self._side_buttons[1], TrackSend1_button = self._side_buttons[2], TrackSend2_button = self._side_buttons[3])
		self._mixer_modes.set_enabled(False)

		self._selector = ModesComponent(name = u'Selector')
		self._selector.add_mode(u'disabled', [self._background])
		self._selector.add_mode(u'Session', [self._session_modes])
		self._selector.add_mode(u'User1', [self._translations1])
		self._selector.add_mode(u'User2', [self._translations2])
		self._selector.add_mode(u'Mixer', [tuple([self.enable_sliders, self.disable_sliders]), self._mixer_modes])
		for mode in self._selector._mode_list:
			self._selector.get_mode_button(mode).mode_selected_color = u'MainModes.SelectedOn'
			self._selector.get_mode_button(mode).mode_unselected_color = u'MainModes.SelectedOff'
		self._selector.layer = Layer(priority = 1, Session_button = self._top_buttons[4], User1_button = self._top_buttons[5], User2_button = self._top_buttons[6], Mixer_button = self._top_buttons[7])
		self._selector.set_enabled(True)
		self._selector.selected_mode = u'disabled'

	def enable_sliders(self):
		for slider in self._sliders:
			slider._disabled = False
	

	def disable_sliders(self):
		for slider in self._sliders:
			slider._disabled = True
	

	def set_slider_single_mode(self):
		for slider in self._sliders:
			slider.set_mode(0)
	

	def set_slider_volume_mode(self):
		for slider in self._sliders:
			slider.set_mode(1)
	

	def set_slider_pan_mode(self):
		for slider in self._sliders:
			slider.set_mode(2)
	

	def set_slider_send_mode(self):
		for slider in self._sliders:
			slider.set_mode(1)
	

	def disconnect(self):
		self._suppress_send_midi = True
		for control in self.controls:
			if isinstance(control, ConfigurableButtonElement):
				control.remove_value_listener(self._button_value)

		self._selector = None
		self._user_byte_write_button.remove_value_listener(self._user_byte_value)
		self._config_button.remove_value_listener(self._config_value)
		super(Launchpad, self).disconnect()
		self._suppress_send_midi = False
		self._config_button.send_value(32)
		self._config_button.send_value(0)
		self._config_button = None
		self._user_byte_write_button.send_value(0)
		self._user_byte_write_button = None
	

	def refresh_state(self):
		super(Launchpad, self).refresh_state()
		self.schedule_message(5, self._update_hardware)
	

	def process_midi_bytes(self, midi_bytes, midi_processor):
		#def handle_sysex(self, midi_bytes):
		if len(midi_bytes) == 8:
			if midi_bytes[1:5] == (0, 32, 41, 6):
				response = long(midi_bytes[5])
				response += long(midi_bytes[6]) << 8
				if response == Live.Application.encrypt_challenge2(self._challenge):
					self._on_handshake_successful()
		else:
			super(Launchpad, self).process_midi_bytes(midi_bytes, midi_processor)
	

	def _on_handshake_successful(self):
		debug('Launchpad._on_handshake_successful')
		self._suppress_send_midi = False
		self.set_enabled(True)
		self._selector.selected_mode = 'Session'
		self._selector.set_enabled(True)
		debug(self._selector.selected_mode)
	
	"""
	def build_midi_map(self, midi_map_handle):
		ControlSurface.build_midi_map(self, midi_map_handle)
		#if self._selector.mode_index == 1:
		#	new_channel = self._selector.channel_for_current_mode()
		#	for note in DRUM_NOTES:
		#		self._translate_message(MIDI_NOTE_TYPE, note, 0, note, new_channel)
	"""
	"""
	def _send_midi(self, midi_bytes, optimized = None):
		sent_successfully = False
		if not self._suppress_send_midi:
			sent_successfully = ControlSurface._send_midi(self, midi_bytes, optimized=optimized)
		return sent_successfully
	"""

	def _update_hardware(self):
		self._suppress_send_midi = False
		self._wrote_user_byte = True
		self._user_byte_write_button.send_value(1)
		self._suppress_send_midi = True
		self.set_enabled(False)
		self._suppress_send_midi = False
		self._send_challenge()
	

	def _send_challenge(self):
		for index in range(4):
			challenge_byte = self._challenge >> 8 * index & 127
			self._send_midi((176, 17 + index, challenge_byte))
	

	def _user_byte_value(self, value):
		if not value in range(128):
			raise AssertionError
			enabled = self._wrote_user_byte or value == 1
			self._control_is_with_automap = not enabled
			self._suppress_send_midi = self._control_is_with_automap
			if not self._control_is_with_automap:
				for control in self.controls:
					if isinstance(control, ConfigurableButtonElement):
						control.set_force_next_value()

			#self._selector.set_mode(0)
			self._selector.selected_mode = u'Session'
			self.set_enabled(enabled)
			self._suppress_send_midi = False
		else:
			self._wrote_user_byte = False
	

	def _button_value(self, value):
		debug('_button_value', value, self._selector.selected_mode, self._selector.is_enabled())
		#self._top_buttons[0].send_value(127)
		#assert value in range(128)
	

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