Ejemplo n.º 1
0
Archivo: Cntrlr.py Proyecto: aumhaa/mod
class CntrlrMonoInstrumentComponent(MonoInstrumentComponent):


	def _setup_shift_mode(self):
		self._shifted = False
		self._shift_mode = ModesComponent()
		self._shift_mode.add_mode('shift', tuple([self._enable_shift, self._disable_shift]), behaviour = ColoredCancellableBehaviourWithRelease(color = 'MonoInstrument.ShiftOn', off_color = 'MonoInstrument.ShiftOff'))
 def _create_track_button_modes(self):
     track_button_modes = ModesComponent(name='Track Button Modes',
                                         is_enabled=False)
     select_button_matrix = self.wrap_matrix(self._select_buttons)
     track_button_modes.add_mode(
         'clip_stop',
         AddLayerMode(self._session,
                      Layer(stop_track_clip_buttons=select_button_matrix)))
     track_button_modes.add_mode(
         'solo',
         AddLayerMode(self._mixer,
                      layer=Layer(solo_buttons=select_button_matrix)))
     track_button_modes.add_mode(
         'arm',
         AddLayerMode(self._mixer,
                      layer=Layer(arm_buttons=select_button_matrix)))
     track_button_modes.add_mode(
         'mute',
         AddLayerMode(self._mixer,
                      layer=Layer(mute_buttons=select_button_matrix)))
     track_button_modes.add_mode(
         'select',
         AddLayerMode(
             self._mixer,
             layer=Layer(track_select_buttons=select_button_matrix)))
     track_button_modes.selected_mode = 'clip_stop'
     track_button_modes.layer = Layer(clip_stop_button=self._stop_button,
                                      solo_button=self._solo_button,
                                      arm_button=self._arm_button,
                                      mute_button=self._mute_button,
                                      select_button=self._select_button)
 def _create_step_button_modes(self):
     matrix_modes = ModesComponent(name='Step_Button_Modes')
     clip_mode = AddLayerMode(self._session, Layer(clip_launch_buttons=self._step_buttons, stop_track_clip_buttons=self._modified_step_buttons))
     scene_mode = AddLayerMode(self._session, Layer(scene_launch_buttons=self._step_buttons))
     matrix_modes.add_mode('clip', clip_mode)
     matrix_modes.add_mode('scene', scene_mode)
     matrix_modes.layer = Layer(clip_button=self._recall_button, scene_button=self._store_button)
     matrix_modes.selected_mode = 'clip'
     return matrix_modes
 def _create_track_button_modes(self):
     track_button_modes = ModesComponent(name='Track Button Modes', is_enabled=False)
     select_button_matrix = self.wrap_matrix(self._select_buttons)
     track_button_modes.add_mode('clip_stop', AddLayerMode(self._session, Layer(stop_track_clip_buttons=select_button_matrix)))
     track_button_modes.add_mode('solo', AddLayerMode(self._mixer, layer=Layer(solo_buttons=select_button_matrix)))
     track_button_modes.add_mode('arm', AddLayerMode(self._mixer, layer=Layer(arm_buttons=select_button_matrix)))
     track_button_modes.add_mode('mute', AddLayerMode(self._mixer, layer=Layer(mute_buttons=select_button_matrix)))
     track_button_modes.add_mode('select', AddLayerMode(self._mixer, layer=Layer(track_select_buttons=select_button_matrix)))
     track_button_modes.selected_mode = 'clip_stop'
     track_button_modes.layer = Layer(clip_stop_button=self._stop_button, solo_button=self._solo_button, arm_button=self._arm_button, mute_button=self._mute_button, select_button=self._select_button)
    def _create_mixer(self):
        mixer = MixerComponent(NUM_TRACKS, is_enabled=True, auto_name=True)
        mixer.layer = Layer(track_select_buttons=self._select_buttons, send_controls=self._send_encoders, next_sends_button=self._down_button, prev_sends_button=self._up_button, pan_controls=self._pan_device_encoders, volume_controls=self._volume_faders, send_lights=self._send_encoder_lights, pan_lights=self._pan_device_encoder_lights)
        mixer.on_send_index_changed = partial(self._show_controlled_sends_message, mixer)
        for channel_strip in map(mixer.channel_strip, xrange(NUM_TRACKS)):
            channel_strip.empty_color = 'Mixer.NoTrack'

        mixer_modes = ModesComponent()
        mixer_modes.add_mode('mute', [AddLayerMode(mixer, Layer(mute_buttons=self._state_buttons))])
        mixer_modes.add_mode('solo', [AddLayerMode(mixer, Layer(solo_buttons=self._state_buttons))])
        mixer_modes.add_mode('arm', [AddLayerMode(mixer, Layer(arm_buttons=self._state_buttons))])
        mixer_modes.layer = Layer(mute_button=self._mute_mode_button, solo_button=self._solo_mode_button, arm_button=self._arm_mode_button)
        mixer_modes.selected_mode = 'mute'
        return mixer
Ejemplo n.º 6
0
 def _create_encoder_modes(self):
     knob_modes = ModesComponent(name=u'Knob Modes', is_enabled=False)
     parameter_knobs_matrix = self.wrap_matrix(self._parameter_knobs)
     send_toggle_component = SendToggleComponent(
         self._mixer,
         name=u'Toggle Send',
         is_enabled=False,
         layer=Layer(toggle_button=self._send_button, priority=1))
     knob_modes.add_mode(
         u'volume',
         AddLayerMode(self._mixer,
                      Layer(volume_controls=parameter_knobs_matrix)))
     knob_modes.add_mode(
         u'pan',
         AddLayerMode(self._mixer,
                      Layer(pan_controls=parameter_knobs_matrix)))
     knob_modes.add_mode(u'send', [
         AddLayerMode(self._mixer,
                      Layer(send_controls=parameter_knobs_matrix)),
         send_toggle_component
     ])
     knob_modes.add_mode(
         u'device',
         AddLayerMode(self._device,
                      Layer(parameter_controls=parameter_knobs_matrix)))
     knob_modes.selected_mode = u'volume'
     knob_modes.layer = Layer(volume_button=self._volume_button,
                              pan_button=self._pan_button,
                              send_button=self._send_button,
                              device_button=self._device_button)
     return knob_modes
 def _create_encoder_modes(self):
     knob_modes = ModesComponent(name='Knob Modes', is_enabled=False)
     parameter_knobs_matrix = self.wrap_matrix(self._parameter_knobs)
     knob_modes.add_mode(
         'volume',
         AddLayerMode(self._mixer,
                      Layer(volume_controls=parameter_knobs_matrix)))
     knob_modes.add_mode(
         'pan',
         AddLayerMode(self._mixer,
                      Layer(pan_controls=parameter_knobs_matrix)))
     knob_modes.add_mode('send', [
         AddLayerMode(self._mixer,
                      Layer(send_controls=parameter_knobs_matrix)),
         DelayMode(LayerMode(
             SendToggleComponent(
                 self._mixer, name='Toggle Send', is_enabled=False),
             Layer(priority=MODE_PRIORITY,
                   toggle_button=self._send_button)),
                   delay=TIMER_DELAY)
     ])
     knob_modes.add_mode(
         'device',
         AddLayerMode(self._device,
                      Layer(parameter_controls=parameter_knobs_matrix)))
     knob_modes.selected_mode = 'volume'
     knob_modes.layer = Layer(volume_button=self._volume_button,
                              pan_button=self._pan_button,
                              send_button=self._send_button,
                              device_button=self._device_button)
     knob_modes.layer.priority = MODE_PRIORITY
 def _create_encoder_modes(self):
     knob_modes = ModesComponent(name='Knob Modes', is_enabled=False)
     parameter_knobs_matrix = self.wrap_matrix(self._parameter_knobs)
     knob_modes.add_mode('volume', AddLayerMode(self._mixer, Layer(volume_controls=parameter_knobs_matrix)))
     knob_modes.add_mode('pan', AddLayerMode(self._mixer, Layer(pan_controls=parameter_knobs_matrix)))
     knob_modes.add_mode('send', [AddLayerMode(self._mixer, Layer(send_controls=parameter_knobs_matrix)), DelayMode(LayerMode(SendToggleComponent(self._mixer, name='Toggle Send', is_enabled=False), Layer(priority=MODE_PRIORITY, toggle_button=self._send_button)), delay=TIMER_DELAY)])
     knob_modes.add_mode('device', AddLayerMode(self._device, Layer(parameter_controls=parameter_knobs_matrix)))
     knob_modes.selected_mode = 'volume'
     knob_modes.layer = Layer(volume_button=self._volume_button, pan_button=self._pan_button, send_button=self._send_button, device_button=self._device_button)
     knob_modes.layer.priority = MODE_PRIORITY
 def _create_encoder_modes(self):
     knob_modes = ModesComponent(name='Knob Modes', is_enabled=False)
     parameter_knobs_matrix = self.wrap_matrix(self._parameter_knobs)
     send_toggle_component = SendToggleComponent(self._mixer, name='Toggle Send', is_enabled=False, layer=Layer(toggle_button=self._send_button, priority=1))
     knob_modes.add_mode('volume', AddLayerMode(self._mixer, Layer(volume_controls=parameter_knobs_matrix)))
     knob_modes.add_mode('pan', AddLayerMode(self._mixer, Layer(pan_controls=parameter_knobs_matrix)))
     knob_modes.add_mode('send', [AddLayerMode(self._mixer, Layer(send_controls=parameter_knobs_matrix)), send_toggle_component])
     knob_modes.add_mode('device', AddLayerMode(self._device, Layer(parameter_controls=parameter_knobs_matrix)))
     knob_modes.selected_mode = 'volume'
     knob_modes.layer = Layer(volume_button=self._volume_button, pan_button=self._pan_button, send_button=self._send_button, device_button=self._device_button)
     return knob_modes
 def _create_track_button_modes(self):
     track_button_modes = ModesComponent(name="Track Button Modes", is_enabled=False)
     select_button_matrix = self.wrap_matrix(self._select_buttons)
     track_button_modes.add_mode(
         "clip_stop", AddLayerMode(self._session, Layer(stop_track_clip_buttons=select_button_matrix))
     )
     track_button_modes.add_mode("solo", AddLayerMode(self._mixer, layer=Layer(solo_buttons=select_button_matrix)))
     track_button_modes.add_mode("arm", AddLayerMode(self._mixer, layer=Layer(arm_buttons=select_button_matrix)))
     track_button_modes.add_mode("mute", AddLayerMode(self._mixer, layer=Layer(mute_buttons=select_button_matrix)))
     track_button_modes.add_mode(
         "select", AddLayerMode(self._mixer, layer=Layer(track_select_buttons=select_button_matrix))
     )
     track_button_modes.selected_mode = "clip_stop"
     track_button_modes.layer = Layer(
         clip_stop_button=self._stop_button,
         solo_button=self._solo_button,
         arm_button=self._arm_button,
         mute_button=self._mute_button,
         select_button=self._select_button,
     )
     return track_button_modes
Ejemplo n.º 11
0
    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)

            return None

        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)

            return

        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_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=u'Track_Control_Modes',
                                       is_enabled=False)
        encoder_modes.add_mode(u'pan', [set_pan_controls])
        encoder_modes.add_mode(u'send_a', [partial(set_send_controls, 0)])
        encoder_modes.add_mode(u'send_b', [partial(set_send_controls, 1)])
        encoder_modes.add_mode(u'send_c', [partial(set_send_controls, 2)])
        encoder_modes.selected_mode = u'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=u'Global_Translations')
class ChannelStripComponent(BaseChannelStripComponent):
    """ A custom channel strip with support for fx knobs and LED level meters """

    def __init__(self):
        for send_num in range(1,4):
            send_key = '_send%s_control' % send_num
            setattr(self, send_key, None)
            setattr(self, 'set%s' % send_key, set_send_control(self, send_num))

        for fx_num in range(1,4):
            fx_device_key = '_fx%s_device' % fx_num
            setattr(self, fx_device_key, None)
            for macro_num in range(1,5):
                fx_macro_key = '_fx%s_macro%s_control' % (fx_num, macro_num)
                setattr(self, fx_macro_key, None)
                setattr(self, 'set%s' % fx_macro_key, set_fx_control(self, fx_num, macro_num))

        self._vu_meter_control = None

        super(ChannelStripComponent, self).__init__()

    def disconnect(self):
        """ releasing references and removing listeners"""
        super(ChannelStripComponent, self).disconnect()
        for send_num in range(1,4):
            send_key = '_send%s_control' % send_num
            setattr(self, send_key, None)
        for fx_num in range(1,4):
            fx_device_key = '_fx%s_device' % fx_num
            setattr(self, fx_device_key, None)
            for macro_num in range(1,5):
                fx_macro_key = '_fx%s_macro%s_control' % (fx_num, macro_num)
                setattr(self, fx_macro_key, None)

    def set_modes(self, sends_layer, fx1_layer, fx2_layer, fx3_layer):
        if hasattr(self, '_modes'):
            self._modes.disconnect()
        self._modes = ModesComponent()
        self._modes.add_mode('sends', [LayerMode(self, sends_layer)])
        self._modes.add_mode('fx1', [LayerMode(self, fx1_layer)])
        self._modes.add_mode('fx2', [LayerMode(self, fx2_layer)])
        self._modes.add_mode('fx3', [LayerMode(self, fx3_layer)])
        self._modes._set_selected_mode('sends')

    def set_send_control(self, send_num, control):
        current = getattr(self, '_send%s_control' % send_num)
        if control != current:
            changed = True
            if current:
                current.release_parameter()
            setattr(self, '_send%s_control' % send_num, control)
            self.update()

    def set_fx_control(self, fx_num, macro_num, control):
        current = getattr(self, '_fx%s_macro%s_control' % (fx_num, macro_num))
        if control != current:
            changed = True
            if current:
                current.release_parameter()
            setattr(self, '_fx%s_macro%s_control' % (fx_num, macro_num), control)
            self.update()

    def set_vu_meter_control(self, control):
        try:
            current = self._vu_meter_control.slider
        except AttributeError:
            current = None

        if current != control:
            if control is None:
                self._vu_meter_control = None
            else:
                self._vu_meter_control = VUMeterComponent(self)
                if self._track:
                    self._vu_meter_control.set_vu_meter(self._track)
                    self._vu_meter_control.set_led_slider(control)
            self.update()

    def _connect_parameters(self):
        current_mode = self._get_current_mode_index()
        if self._pan_control != None:
            self._pan_control.connect_to(self._track.mixer_device.panning)
        if self._volume_control != None:
            self._volume_control.connect_to(self._track.mixer_device.volume)
        if self._send1_control != None:
            self._send1_control.connect_to(self._track.mixer_device.sends[0])
        if self._send2_control != None:
            self._send2_control.connect_to(self._track.mixer_device.sends[1])
        if self._send3_control != None:
            self._send3_control.connect_to(self._track.mixer_device.sends[2])
        self._set_fx_devices()
        for fx_num in range(1,4):
            for macro_num in range(1,5):
                control_key = '_fx%s_macro%s_control' % (fx_num, macro_num)
                fx_control = getattr(self, control_key)
                if fx_control:
                    fx_device = getattr(self, '_fx%s_device' % fx_num)
                    if fx_device:
                        fx_control.connect_to(fx_device['macro%s' % macro_num])

    def _all_controls(self):
        return [
            self._pan_control, 
            self._volume_control, 
            self._fx1_macro1_control, 
            self._fx1_macro2_control, 
            self._fx1_macro3_control, 
            self._fx1_macro4_control,
            self._fx2_macro1_control, 
            self._fx2_macro2_control, 
            self._fx2_macro3_control, 
            self._fx2_macro4_control,
            self._fx3_macro1_control, 
            self._fx3_macro2_control, 
            self._fx3_macro3_control, 
            self._fx3_macro4_control,
            self._send1_control, 
            self._send2_control, 
            self._send3_control, 
        ]

    def set_track(self, track):
        super(ChannelStripComponent, self).set_track(track)
        self._set_fx_devices()
        self.update()

    def _get_current_mode_index(self):
        if hasattr(self, '_modes') and self._modes.selected_mode:
            return self._modes._mode_list.index(self._modes.selected_mode)
    
    def _set_fx_devices(self):
        self._fx1_device = None
        self._fx2_device = None
        self._fx3_device = None
        if self._track != None:
            matched_devices = []
            for device in self._track.devices:
                if device.class_name in FX_DEVICES.keys():
                     matched_devices.append(device)

            if not matched_devices:
                return

            device = None

            # FX1 Device (required)
            device = matched_devices[0]
            device_dict = FX_DEVICES[device.class_name]
            self._fx1_device = {
                'device': device,
                'macro1': get_parameter_by_name(device, device_dict['macro1']),
                'macro2': get_parameter_by_name(device, device_dict['macro2']),
                'macro3': get_parameter_by_name(device, device_dict['macro3']),
                'macro4': get_parameter_by_name(device, device_dict['macro4']),
            }
            
            # FX2 Device (optional)
            try:
                device = matched_devices[1]
                device_dict = FX_DEVICES[device.class_name]
                self._fx2_device = {
                    'device': device,
                    'macro1': get_parameter_by_name(device, device_dict['macro1']),
                    'macro2': get_parameter_by_name(device, device_dict['macro2']),
                    'macro3': get_parameter_by_name(device, device_dict['macro3']),
                    'macro4': get_parameter_by_name(device, device_dict['macro4']),
                }
            except IndexError:
                pass

            # FX3 Device (optional)
            try:
                device = matched_devices[2]
                device_dict = FX_DEVICES[device.class_name]
                self._fx3_device = {
                    'device': device,
                    'macro1': get_parameter_by_name(device, device_dict['macro1']),
                    'macro2': get_parameter_by_name(device, device_dict['macro2']),
                    'macro3': get_parameter_by_name(device, device_dict['macro3']),
                    'macro4': get_parameter_by_name(device, device_dict['macro4']),
                }
            except IndexError:
                pass
Ejemplo n.º 14
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)
Ejemplo n.º 15
0
Archivo: Cntrlr.py Proyecto: aumhaa/mod
class Cntrlr(ControlSurface):
	__module__ = __name__
	__doc__ = " Monomodular controller script for Livid CNTRLR "


	def __init__(self, *a, **k):
		super(Cntrlr, self).__init__(*a, **k)
		self._version_check = 'b996'
		self._host_name = 'Cntrlr'
		self._color_type = 'OhmRGB'
		self._client = [None for index in range(4)]
		self._active_client = None
		self._rgb = 0
		self._timer = 0
		self._touched = 0
		self.flash_status = 1
		self._skin = Skin(CntrlrColors)
		self._device_selection_follows_track_selection = FOLLOW
		with self.component_guard():
			self._setup_monobridge()
			self._setup_controls()
			self._define_sysex()
			self._setup_transport_control()
			self._setup_autoarm()
			self._setup_session_recording_component()
			self._setup_mixer_control()
			self._setup_send_resets()
			self._setup_session_control()
			self._setup_device_control()
			self._setup_device_selector()
			self._setup_translations()
			self._setup_viewcontrol()
			self._setup_mod()
			self._setup_instrument()
			self._setup_modswitcher()
			self._setup_modes() 
			self._setup_m4l_interface()
			self._on_device_changed.subject = self.song()
			self.set_feedback_channels(range(14, 15))
		self._main_modes.selected_mode = 'MixMode'
		self.schedule_message(1, self._open_log)
	

	def _open_log(self):
		self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) + " " + str(self._version_check) + " 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):
		is_momentary = True 
		self._fader = [MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, CNTRLR_FADERS[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self) for index in range(8)]
		self._dial_left = [MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, CNTRLR_KNOBS_LEFT[index], Live.MidiMap.MapMode.absolute, 'Dial_Left_' + str(index), CNTRLR_KNOBS_LEFT[index], self) for index in range(12)]
		self._dial_right = [MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, CNTRLR_KNOBS_RIGHT[index], Live.MidiMap.MapMode.absolute, 'Dial_Right_' + str(index), CNTRLR_KNOBS_RIGHT[index], self) for index in range(12)]
		self._encoder = [CodecEncoderElement(MIDI_CC_TYPE, CHANNEL, CNTRLR_DIALS[index], Live.MidiMap.MapMode.absolute, 'Encoder_' + str(index), CNTRLR_DIALS[index], self) for index in range(12)] 
		self._encoder_button = [MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CNTRLR_DIAL_BUTTONS[index], name = 'Encoder_Button_' + str(index), script = self, skin = self._skin) for index in range(12)]	
		self._grid = [MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CNTRLR_GRID[index], name = 'Grid_' + str(index), script = self, skin = self._skin) for index in range(16)]
		self._button = [MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CNTRLR_BUTTONS[index], name = 'Button_' + str(index), script = self, skin = self._skin) for index in range(32)]
		self._knobs = self._dial_left + self._dial_right

		self._fader_matrix = ButtonMatrixElement(name = 'Fader_Matrix', rows = [self._fader])
		self._matrix = ButtonMatrixElement(name = 'Matrix', rows = [self._grid[index*4:(index*4)+4] for index in range(4)])
		self._knob_left_matrix = ButtonMatrixElement(name = 'Knob_Left_Matrix', rows = [self._dial_left[index*4:(index*4)+4] for index in range(3)])
		self._knob_right_matrix = ButtonMatrixElement(name = 'Knob_Right_Matrix', rows = [self._dial_right[index*4:(index*4)+4] for index in range(3)])
		self._dial_matrix = ButtonMatrixElement(name = 'Dial_Matrix', rows = [self._encoder[index*4:(index*4)+4] for index in range(3)])
		self._dial_button_matrix = ButtonMatrixElement(name = 'Dial_Button_Matrix', rows = [self._encoder_button[index*4:(index*4)+4] for index in range(1,3)])
		self._key_matrix = ButtonMatrixElement(name = 'Key_Matrix', rows = [self._button[0:16], self._button[16:32]])
		
		self._translated_controls = self._fader + self._knobs + self._encoder[4:] + self._grid + self._button
	

	def _define_sysex(self):
		self.encoder_navigation_on = SendSysexMode(script = self, sysex = (240, 0, 1, 97, 8, 17, 15, 0, 0, 0, 0, 0, 0, 0, 247))
		self.encoder_navigation_off = SendSysexMode(script = self, sysex = (240, 0, 1, 97, 8, 17, 0, 0, 0, 0, 0, 0, 0, 0, 247))
	

	def _setup_transport_control(self):
		self._transport = CntrlrTransportComponent() 
		self._transport.name = 'Transport'
		self._transport.layer = Layer(priority = 4,
									play_button = self._button[28],
									record_button = self._button[30],
									stop_button = self._button[29])
	

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

	def _setup_session_recording_component(self):
		self._clip_creator = ClipCreator()
		self._clip_creator.name = 'ClipCreator'
		self._recorder = CntrlrSessionRecordingComponent(self._clip_creator, ViewControlComponent()) # is_enabled = False)
		self._recorder.layer = Layer(priority = 4, new_button = self._button[28], record_button = self._button[29], automation_button = self._button[30])
		self._recorder.set_enabled(False)
	

	def _setup_mixer_control(self):
		is_momentary = True
		self._num_tracks = (4)
		self._mixer = MixerComponent(num_tracks = 4, num_returns = 2, name = 'Mixer', auto_name = True, invert_mute_feedback = True)
		self._mixer.set_track_offset(0)
		if self._mixer.channel_strip(0)._track:
			self.song().view.selected_track = self._mixer.channel_strip(0)._track
		self._mixer.main_faders_layer = AddLayerMode(self._mixer, Layer(priority = 4,
											volume_controls = self._fader_matrix.submatrix[:4, :],
											return_controls = self._fader_matrix.submatrix[4:6, :],
											prehear_volume_control = self._fader[6],))
		self._mixer.main_buttons_layer = AddLayerMode(self._mixer, Layer(priority = 4, 
											mute_buttons = self._key_matrix.submatrix[:4, 1:],
											arm_buttons = self._key_matrix.submatrix[4:8, :1],
											solo_buttons = self._key_matrix.submatrix[:4, :1],
											track_select_buttons = self._key_matrix.submatrix[4:8, 1:],))
		self._mixer.stop_layer = AddLayerMode(self._mixer, Layer(priority = 4,
											stop_clip_buttons = self._key_matrix.submatrix[8:12, 1:],))
		self._mixer.main_knobs_layer = AddLayerMode(self._mixer, Layer(priority = 4,
											send_controls = self._knob_left_matrix.submatrix[:, :2],
											pan_controls = self._knob_left_matrix.submatrix[:, 2:],
											eq_gain_controls = self._knob_right_matrix))
		self._mixer.master_fader_layer = AddLayerMode(self._mixer.master_strip(), Layer(priority = 4,
											volume_control = self._fader[7]))
		self._mixer.instrument_buttons_layer = AddLayerMode(self._mixer, Layer(priority = 4,
											mute_buttons = self._key_matrix.submatrix[:4, 1:],
											track_select_buttons = self._key_matrix.submatrix[4:8, 1:],))
		self._mixer.dial_nav_layer = AddLayerMode(self._mixer, Layer(priority = 4,
									track_select_dial = self._encoder[3]))
	

	def _setup_send_resets(self):
		self._send_reset = CntrlrResetSendsComponent(self)
		self._send_reset.name = 'Sends_Reset'
		self._send_reset.layer = Layer(buttons = self._key_matrix.submatrix[8:12, :1])
	

	def _setup_session_control(self):
		self._session = CntrlrSessionComponent(num_tracks = 4, num_scenes = 4, name = 'Session', enable_skinning = True, auto_name = True)
		self._session.set_mixer(self._mixer)
		self.set_highlighting_session_component(self._session)
		self._session.layer = Layer(priority = 4, clip_launch_buttons = self._matrix)
		self._session.nav_layer = AddLayerMode(self._session, Layer(priority = 4,
									scene_bank_down_button = self._button[14],
									scene_bank_up_button = self._button[15],
									track_bank_left_button = self._button[12],
									track_bank_right_button = self._button[13]))
		self._session.dial_nav_layer = AddLayerMode(self._session, Layer(priority = 4,
									scene_select_dial = self._encoder[2]))

		self._session_zoom = SessionZoomingComponent(session = self._session, name = 'Session_Overview', enable_skinning = True)  # is_enabled = False)	 #
		self._session_zoom.buttons_layer = AddLayerMode(self._session_zoom, Layer(priority = 4, button_matrix = self._matrix))

		self._session.set_offsets(0, 0)
	

	def _setup_device_control(self):
		self._device_selection_follows_track_selection = FOLLOW
		self._device = DeviceComponent()
		self._device.name = 'Device_Component'
		self._device._is_banking_enabled = self.device_is_banking_enabled(self._device)
		self.set_device_component(self._device)
		self._device.layer = Layer(priority = 4, parameter_controls = self._dial_matrix.submatrix[:, 1:3], 
											lock_button = self._encoder_button[5],
											on_off_button = self._encoder_button[4],
											bank_prev_button = self._encoder_button[6],
											bank_next_button = self._encoder_button[7])

		self._device_navigator = DeviceNavigator(self._device, self._mixer, self)
		self._device_navigator.name = 'Device_Navigator'
		self._device_navigator.layer = Layer(priority = 4, prev_button = self._encoder_button[8], 
											next_button = self._encoder_button[9], 
											prev_chain_button = self._encoder_button[10], 
											next_chain_button = self._encoder_button[11],)
	

	def _setup_device_selector(self):
		self._device_selector = DeviceSelectorComponent(self)  # is_enabled = False)
		self._device_selector.name = 'Device_Selector'
		self._device_selector.layer = Layer(matrix = self._matrix.submatrix[:, :3])
		self._device_selector.set_enabled(False)
	

	def _setup_translations(self):
		self._translations = TranslationComponent(self._translated_controls, user_channel_offset = 4, channel = 4)	# is_enabled = False)
		self._translations.name = 'TranslationComponent'
		self._translations.layer = Layer(priority = 10,)
		self._translations.selector_layer = AddLayerMode(self._translations, Layer(priority = 10, channel_selector_buttons = self._dial_button_matrix))
		self._translations.set_enabled(False)

		self._optional_translations = CompoundMode(TranslationComponent(controls = self._fader, user_channel_offset = 4, channel = 4, name = 'FaderTranslation', is_enabled = False, layer = Layer(priority = 10)) if FADER_BANKING else None, 
														TranslationComponent(controls = self._knobs, user_channel_offset = 4, channel = 4, name = 'DialTranslation', is_enabled = False, layer = Layer(priority = 10)) if DIAL_BANKING else None)
	

	def _setup_mod(self):
		self.monomodular = get_monomodular(self)
		self.monomodular.name = 'monomodular_switcher'
		self.modhandler = CntrlrModHandler(self) # is_enabled = False)
		self.modhandler.name = 'ModHandler' 
		self.modhandler.set_lock_button(self._encoder_button[1])
		self.modhandler.layer = Layer(priority = 8, cntrlr_encoder_grid = self._dial_matrix,
										cntrlr_encoder_button_grid = self._dial_button_matrix,
										cntrlr_grid = self._matrix,
										cntrlr_keys = self._key_matrix,)
										#parameter_controls = self._dial_matrix)
	

	def _setup_instrument(self):
		self._grid_resolution = self.register_disconnectable(GridResolution())
		self._c_instance.playhead.enabled = True
		self._playhead_element = PlayheadElement(self._c_instance.playhead)
		self._playhead_element.reset()

		self._instrument = CntrlrMonoInstrumentComponent(self, self._skin, grid_resolution = self._grid_resolution, name = 'InstrumentModes') # is_enabled = False)
		#self._instrument.layer = Layer(priority = 10, shift_mode_button = self._button[31])
		self._instrument.shift_button_layer = AddLayerMode(self._instrument, Layer(priority = 5, shift_mode_button = self._button[31]))
		self._instrument.audioloop_layer = LayerMode(self._instrument, Layer(priority = 4, loop_selector_matrix = self._key_matrix.submatrix[:, :1]))
		self._instrument.keypad_shift_layer = AddLayerMode(self._instrument, Layer(priority = 4, 
									scale_up_button = self._button[13], 
									scale_down_button = self._button[12],
									offset_up_button = self._button[11], 
									offset_down_button = self._button[10],
									vertical_offset_up_button = self._button[9],
									vertical_offset_down_button = self._button[8],
									split_button = self._button[14],
									sequencer_button = self._button[15]))
		self._instrument.drumpad_shift_layer = AddLayerMode(self._instrument, Layer(priority = 4, 
									scale_up_button = self._button[13],
									scale_down_button = self._button[12],
									drum_offset_up_button = self._button[11], 
									drum_offset_down_button = self._button[10],
									drumpad_mute_button = self._button[9],
									drumpad_solo_button = self._button[8],
									split_button = self._button[14],
									sequencer_button = self._button[15]))
		self._instrument._keypad.main_layer = LayerMode(self._instrument._keypad, Layer(priority = 4, keypad_matrix = self._matrix))
		self._instrument._keypad.sequencer_layer = LayerMode(self._instrument._keypad, Layer(priority = 4, playhead = self._playhead_element, keypad_matrix = self._matrix, sequencer_matrix = self._key_matrix.submatrix[:,:1]))
		self._instrument._keypad.split_layer = LayerMode(self._instrument._keypad, Layer(priority = 4, keypad_matrix = self._matrix, split_matrix = self._key_matrix.submatrix[:8,:1]))
		self._instrument._keypad.sequencer_shift_layer = LayerMode(self._instrument._keypad, Layer(priority = 4, keypad_matrix = self._matrix, loop_selector_matrix = self._key_matrix.submatrix[:8, :1], quantization_buttons = self._key_matrix.submatrix[:7, 1:], follow_button = self._button[23]))
		self._instrument._drumpad.main_layer = LayerMode(self._instrument._drumpad, Layer(priority = 4, drumpad_matrix = self._matrix))
		self._instrument._drumpad.sequencer_layer = LayerMode(self._instrument._drumpad, Layer(priority = 4, playhead = self._playhead_element, drumpad_matrix = self._matrix, sequencer_matrix = self._key_matrix.submatrix[:,:1]))
		self._instrument._drumpad.split_layer = LayerMode(self._instrument._drumpad, Layer(priority = 4, drumpad_matrix = self._matrix, split_matrix = self._key_matrix.submatrix[:8,:1]))
		self._instrument._drumpad.sequencer_shift_layer = LayerMode(self._instrument._drumpad, Layer(priority = 4, drumpad_matrix = self._matrix, loop_selector_matrix = self._key_matrix.submatrix[:8, :1], quantization_buttons = self._key_matrix.submatrix[:7, 1:], follow_button = self._button[23]))
		self._instrument.set_enabled(False)
	

	def _setup_modswitcher(self):
		self._modswitcher = ModesComponent(name = 'ModSwitcher')  # is_enabled = False)
		#self._modswitcher.add_mode('instrument', [self._optional_translations])
		self._modswitcher.add_mode('mod', [self.modhandler, self._optional_translations])
		self._modswitcher.add_mode('instrument', [self._instrument, self._instrument.shift_button_layer, self._optional_translations])
		self._modswitcher.set_enabled(False)
	

	def _setup_viewcontrol(self):
		self._view_control = ViewControlComponent(name='View_Control')# is_enabled = False)
		self._view_control.main_layer = AddLayerMode(self._view_control, Layer(prev_track_button=self._button[24], 
													next_track_button= self._button[25], 
													next_scene_button=self._button[27], 
													prev_scene_button = self._button[26]))
		#self._view_control.set_enabled(False)
		self._view_control.selector_layer = AddLayerMode(self._view_control, Layer(priority = 8, 
													prev_track_button = self._grid[12], 
													next_track_button = self._grid[13], 
													next_scene_button = self._grid[15], 
													prev_scene_button = self._grid[14]))
	

	def _setup_modes(self):
		main_buttons=CompoundMode(self._mixer.main_buttons_layer, self._mixer.stop_layer, self._transport, self._send_reset, self._session.nav_layer)
		main_buttons_instrument=CompoundMode(self._mixer.main_buttons_layer, self._recorder, self._view_control.main_layer)
		main_faders=CompoundMode(self._mixer.main_faders_layer, self._mixer.master_fader_layer)
		bottom_buttons=CompoundMode(self._mixer.instrument_buttons_layer, self._recorder, self._view_control.main_layer)

		self._instrument._main_modes = ModesComponent(name = 'InstrumentModes')
		self._instrument._main_modes.add_mode('disabled', [main_buttons_instrument, main_faders, self._mixer.main_knobs_layer, self._device, self._session, self._recorder, self._view_control.main_layer, self._send_reset, self._session.nav_layer,])
		self._instrument._main_modes.add_mode('drumpad', [self._instrument._drumpad.main_layer, main_buttons_instrument, self._send_reset, self._session.nav_layer])
		self._instrument._main_modes.add_mode('drumpad_split', [self._instrument._drumpad.split_layer, self._send_reset, self._session.nav_layer])
		self._instrument._main_modes.add_mode('drumpad_sequencer', [self._instrument._drumpad.sequencer_layer, bottom_buttons])
		self._instrument._main_modes.add_mode('drumpad_shifted', [self._instrument._drumpad.main_layer, self._instrument.drumpad_shift_layer, main_buttons_instrument, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('drumpad_split_shifted', [self._instrument._drumpad.split_layer, self._instrument.drumpad_shift_layer, bottom_buttons, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('drumpad_sequencer_shifted', [self._instrument._drumpad.sequencer_shift_layer, self._instrument.drumpad_shift_layer, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('keypad', [self._instrument._keypad.main_layer, main_buttons_instrument, self._send_reset, self._session.nav_layer])
		self._instrument._main_modes.add_mode('keypad_split', [self._instrument._keypad.split_layer, bottom_buttons, self._send_reset, self._session.nav_layer])
		self._instrument._main_modes.add_mode('keypad_sequencer', [self._instrument._keypad.sequencer_layer, bottom_buttons])
		self._instrument._main_modes.add_mode('keypad_shifted', [self._instrument._keypad.main_layer, self._instrument.keypad_shift_layer, main_buttons_instrument, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('keypad_split_shifted', [self._instrument._keypad.split_layer, self._instrument.keypad_shift_layer, bottom_buttons, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('keypad_sequencer_shifted', [self._instrument._keypad.sequencer_shift_layer, self._instrument.keypad_shift_layer, self._recorder, self._view_control.main_layer])
		self._instrument._main_modes.add_mode('audioloop', [self._instrument.audioloop_layer, self._session, bottom_buttons, self._recorder, self._view_control.main_layer])
		self._instrument.register_component(self._instrument._main_modes)
		self._instrument.set_enabled(False)

		self._session_modes = ModesComponent(name = 'SessionModes', is_enabled = False)
		self._session_modes.add_mode('Session', [self._session])
		self._session_modes.add_mode('SessionZoom', [self._session_zoom.buttons_layer], behaviour = BicoloredMomentaryBehaviour(color = 'Session.ZoomOn', off_color = 'Session.ZoomOff'))
		self._session_modes.layer = Layer(priority = 4, SessionZoom_button = self._button[31])
		self._session_modes.selected_mode = 'Session'

		self._main_modes = ModesComponent(name = 'MainModes')
		self._main_modes.add_mode('MixMode', [main_buttons, main_faders, self._mixer.main_knobs_layer, self._device, self._session_modes, self._session.nav_layer,])  # self._session.dial_nav_layer, self._mixer.dial_nav_layer, self.encoder_navigation_on])
		self._main_modes.add_mode('ModSwitcher', [main_faders, self._mixer.main_knobs_layer, self._modswitcher], behaviour = DefaultedBehaviour(default_mode = 'MixMode', color = 'ModeButtons.ModSwitcher', off_color = 'ModeButtons.ModSwitcherDisabled'))
		self._main_modes.add_mode('Translations', [main_faders, self._mixer.main_knobs_layer, self._translations, DelayMode(self._translations.selector_layer)], behaviour = DefaultedBehaviour(default_mode = 'MixMode', color = 'ModeButtons.Translations', off_color = 'ModeButtons.TranslationsDisabled'))
		self._main_modes.add_mode('DeviceSelector', [self._device_selector, main_buttons, main_faders, self._mixer.main_knobs_layer, self._device, self._device_navigator, self._view_control.selector_layer], behaviour = ColoredCancellableBehaviourWithRelease(color = 'ModeButtons.DeviceSelector', off_color = 'ModeButtons.DeviceSelectorDisabled'))
		self._main_modes.layer = Layer(priority = 4, ModSwitcher_button = self._encoder_button[0], Translations_button = self._encoder_button[3], DeviceSelector_button = self._encoder_button[2])
	

	def _setup_m4l_interface(self):
		self._m4l_interface = MonoM4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard, priority = 10)
		self._m4l_interface.name = "M4LInterface"
		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 _can_auto_arm_track(self, track):
		routing = track.current_input_routing
		return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith('Cntrlr Input')
	

	@subject_slot('appointed_device')
	def _on_device_changed(self):
		debug('appointed device changed, script')
		self.schedule_message(2, self._update_modswitcher)
	

	def _on_selected_track_changed(self):
		super(Cntrlr, self)._on_selected_track_changed()
		self.schedule_message(2, self._update_modswitcher)
	

	def _update_modswitcher(self):
		debug('update modswitcher', self.modhandler.active_mod())
		if self.modhandler.active_mod():
			self._modswitcher.selected_mode = 'mod'
		else:
			self._modswitcher.selected_mode = 'instrument'
	

	def reset_controlled_track(self, track = None, *a):
		if not track:
			track = self.song().view.selected_track
		self.set_controlled_track(track)
	

	def set_controlled_track(self, track = None, *a):
		if isinstance(track, Live.Track.Track):
			super(Cntrlr, self).set_controlled_track(track)
		else:
			self.release_controlled_track()
	

	"""called on timer"""
	def update_display(self):
		super(Cntrlr, self).update_display()		#since we are overriding this from the inherited method, we need to call the original routine as well
		self._timer = (self._timer + 1) % 256	#each 100/60ms, increase the self._timer property by one.  Start over at 0 when we hit 256
		self.modhandler.send_ring_leds()	#if local rings are turned off, then we need to send the new values if they've changed			
		self.flash()							#call the flash method below
	

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

	"""m4l lcd 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 += ' '
		ret = ret.replace(' ', '_')
		assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
		return ret
	

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

	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 handle_sysex(self, midi_bytes):
		pass
	

	def disconnect(self):
		self.log_message("<<<<<<<<<<<<<<<<<<<<<<<<< " + str(self._host_name) + " log closed >>>>>>>>>>>>>>>>>>>>>>>>>")
		super(Cntrlr, self).disconnect()
	

	def restart_monomodular(self):
		#debug('restart monomodular')
		self.modhandler.disconnect()
		with self.component_guard():
			self._setup_mod()
	

	def _get_num_tracks(self):
		return self.num_tracks
	

	"""a closure fix for banking when we deassign the bank buttons and still want to change bank indexes"""
	def device_is_banking_enabled(self, device):
		def _is_banking_enabled():
			return True
		return _is_banking_enabled
Ejemplo n.º 16
0
class Crate(ControlSurface):
	__module__ = __name__
	__doc__ = " Monomodular controller script for Crate "


	def __init__(self, *a, **k):
		super(Crate, self).__init__(*a, **k)
		self._host_name = 'Crate'
		self._version_check = '1.0'
		self._rgb = 0
		self._timer = 0
		self._touched = 0
		self.flash_status = 1
		with self.component_guard():
			self._setup_monobridge()
			self._setup_controls()
			self._setup_session()
			self._setup_next_buttons()
			self._setup_tempo()
			self._setup_modes()
			self._create_fallback_control_owner()
		self.schedule_message(1, self._open_log)
		self.schedule_message(3, self._initialize_surface)
	

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

	def _initialize_surface(self):
		debug('setting to main mode')
		#self._main_modes.selected_mod = 'Main'
		#self._session.set_enabled(True)
	

	def port_settings_changed(self):
		debug('port settings changed!')
		self._connected = False
		super(Crate, self).port_settings_changed()
	

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

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

	def _setup_controls(self):
		self._button = [CrateButtonElement(True, MIDI_NOTE_TYPE, 0, index, name = 'Button_' + str(index), script = self) for index in range(20)]
		self._track_button = [CrateButtonElement(True, MIDI_NOTE_TYPE, 0, index+50, name = 'Button_' + str(index+50), script = self) for index in range(6)]
		self._next_button = [CrateButtonElement(True, MIDI_NOTE_TYPE, 0, index+60, name = 'Button_' + str(index+60), script = self) for index in range(2)]
		self._crate_button = [CrateButtonElement(True, MIDI_NOTE_TYPE, 0, index+70, name = 'Button_' + str(index+70), script = self) for index in range(3)]
		#self._tempo_slider = EncoderElement(MIDI_CC_TYPE, 0, 0, Live.MidiMap.MapMode.absolute, name = 'Slider')

		self._matrix = ButtonMatrixElement(name = 'Matrix', rows = [[self._button[index]] for index in range(20)])

		self._left_matrix = ButtonMatrixElement(name = 'Left_Matrix', rows = [[self._button[index]] for index in range(10)])
		self._right_matrix = ButtonMatrixElement(name = 'Right_Matrix', rows = [[self._button[index+10]] for index in range(10)])

		self._track_select_matrix = ButtonMatrixElement(name = 'Track_Matrix', rows = [self._track_button])

	

	def _setup_session(self):
		self._left_session = CrateSessionComponent(script = self, name = 'Session_Component_A', num_tracks = 1, num_scenes = 20, autonaming = True, is_enabled = False, layer = Layer(priority = 1, clip_launch_buttons = self._matrix, track_nav_buttons = self._track_select_matrix))
		self._left_session.set_group_track('DECK A')
		self._left_session_zooming = SessionZoomingComponent(session = self._left_session)

		self._right_session = CrateSessionComponent(script = self, name = 'Session_Component_B', num_tracks = 1, num_scenes = 20, autonaming = True, is_enabled = False, layer = Layer(priority = 1, clip_launch_buttons = self._matrix, track_nav_buttons = self._track_select_matrix))
		self._right_session.set_group_track('DECK B')
		self._right_session_zooming = SessionZoomingComponent(session = self._right_session)

		self._left_set_session = CrateSetSessionComponent(script = self, name = 'Session_Component_SETA', num_tracks = 1, num_scenes = 10, autonaming = True, is_enabled = False, layer = Layer(priority = 1, clip_launch_buttons = self._left_matrix))
		self._left_set_session.set_group_track('SET A')
		self._left_set_session_zooming = SessionZoomingComponent(session = self._left_set_session)

		self._right_set_session = CrateSetSessionComponent(script = self, name = 'Session_Component_SETB', num_tracks = 1, num_scenes = 10, autonaming = True, is_enabled = False, layer = Layer(priority = 1, clip_launch_buttons = self._right_matrix))
		self._right_set_session.set_group_track('SET B')
		self._right_set_session_zooming = SessionZoomingComponent(session = self._right_set_session)
	

	def _setup_next_buttons(self):
		self._next_a_button = FireNextClipComponent()
		self._next_a_button.set_track('SET A')
		self._next_a_button.layer = Layer(button = self._next_button[0])

		self._next_b_button = FireNextClipComponent()
		self._next_b_button.set_track('SET B')
		self._next_b_button.layer = Layer(button = self._next_button[1])
	

	def _setup_tempo(self):
		self._on_tempo_changed.subject = self.song()
		self._on_tempo_changed()
	

	@subject_slot('value')
	def _on_tempo_slider_value(self, value):
		self.song().tempo = ((value/127.)*979.)+20.
	

	@subject_slot('tempo')
	def _on_tempo_changed(self, *a, **k):
		debug('on tempo changed:', self.song().tempo)
		new_tempo = self.song().tempo
		#self._on_tempo_slider_value.subject and self._on_tempo_slider_value.subject.send_value(((new_tempo-20)/979)*127)
		self.send_tempo('Tempo '+str(new_tempo))
	

	def _setup_modes(self):

		next_buttons = CompoundMode(self._next_a_button, self._next_a_button)
		self._main_modes = ModesComponent(name = 'MainModes')
		self._main_modes.add_mode('disabled', None)
		self._main_modes.add_mode('left_session', [self._left_session, next_buttons])
		self._main_modes.add_mode('right_session', [self._right_session, next_buttons])
		self._main_modes.add_mode('set_session', [self._left_set_session, self._right_set_session, next_buttons])
		self._main_modes.layer = Layer(priority = 6, left_session_button = self._crate_button[0], right_session_button = self._crate_button[1], set_session_button = self._crate_button[2])
		self._main_modes.selected_mode = 'set_session'
		self._main_modes.set_enabled(True)

		#self._next_a_button.set_enabled(True)
		#self._next_b_button.set_enabled(True)
	

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

	def update_display(self):
		super(Crate, 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)		
	

	@subject_slot('appointed_device')
	def _on_device_changed(self):
		debug('appointed device changed, script')
	

	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 += ' '
		ret = ret.replace(' ', '_')
		assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
		return ret
	

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

	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 handle_sysex(self, midi_bytes):
		pass
	

	def disconnect(self):
		self.log_message("<<<<<<<<<<<<<<<<<<<<<<<<< " + str(self._host_name) + " log closed >>>>>>>>>>>>>>>>>>>>>>>>>")
		super(Crate, self).disconnect()
	

	def handle_sysex(self, midi_bytes):
		#debug('sysex: ', str(midi_bytes))
		pass
	

	def clip_name(self, sender, name):
		offset = self._button.index(sender)
		shortname = encode_name_to_sysex(name)
		display_sysex = (240,
			 0,
			 0,
			 102,
			 1,
			 offset) + tuple(shortname) + (247,)
		self._do_send_midi(display_sysex)
	

	def track_name(self, offset, name):
		shortname = encode_name_to_sysex(name)
		display_sysex = (240,
			 0,
			 0,
			 102,
			 2,
			 offset) + tuple(shortname) + (247,)
		self._do_send_midi(display_sysex)
	

	def send_tempo(self, tempo):
		shortname = encode_name_to_sysex(tempo)
		display_sysex = (240,
			 0,
			 0,
			 102,
			 3,) + tuple(shortname) + (247,)
		self._do_send_midi(display_sysex)
	



#	a
Ejemplo n.º 17
0
class APSequencer(APC40_MkII):
  """ APC40Mk2 script with step sequencer mode """
  def __init__(self, *a, **k):
    self._double_press_context = DoublePressContext()
    APC40_MkII.__init__(self, *a, **k)
    with self.component_guard():
      self._create_sequencer()
      self._create_session_mode()
      self._init_auto_arm()
    self.set_pad_translations(PAD_TRANSLATIONS)
    self.set_feedback_channels(FEEDBACK_CHANNELS)
  
  def _create_controls(self):
    """ Add some additional stuff baby """
    super(APSequencer, self)._create_controls()
    self._grid_resolution = GridResolution()
    self._velocity_slider = ButtonSliderElement(tuple(self._scene_launch_buttons_raw[::-1])) 
    double_press_rows = recursive_map(DoublePressElement, self._matrix_rows_raw) 
    self._double_press_matrix = ButtonMatrixElement(name='Double_Press_Matrix', rows=double_press_rows)
    self._double_press_event_matrix = ButtonMatrixElement(name='Double_Press_Event_Matrix', rows=recursive_map(lambda x: x.double_press, double_press_rows))
    self._playhead = PlayheadElement(self._c_instance.playhead)

    # Make these prioritized resources, which share between Layers() equally
    # Rather than building a stack
    self._pan_button._resource_type = PrioritizedResource 
    self._user_button._resource_type = PrioritizedResource 
    

  def _create_sequencer(self):
    self._sequencer = StepSeqComponent(grid_resolution = self._grid_resolution)

  def _create_session_mode(self): 
    """ Switch between Session and StepSequencer modes """
    self._session_mode = ModesComponent(name='Session_Mode', is_enabled = False)
    self._session_mode.default_behaviour = ImmediateBehaviour()
    self._session_mode.add_mode('session', self._session_mode_layers())
    self._session_mode.add_mode('session_2', self._session_mode_layers())
    self._session_mode.add_mode('sequencer', (self._sequencer, self._sequencer_layer()))
    self._session_mode.layer = Layer(
        session_button = self._pan_button,
        session_2_button = self._sends_button, 
        sequencer_button = self._user_button)
    self._session_mode.selected_mode = "session"

  def _session_mode_layers(self):
    return [ self._session, self._session_zoom]

  def _sequencer_layer(self):
    return Layer(
        velocity_slider = self._velocity_slider,
        drum_matrix = self._session_matrix.submatrix[:4, 1:5],
        button_matrix = self._double_press_matrix.submatrix[4:8, 1:5],
        select_button = self._user_button,
        delete_button = self._stop_all_button,
        playhead = self._playhead,
        quantization_buttons = self._stop_buttons,
        shift_button = self._shift_button,
        loop_selector_matrix = self._double_press_matrix.submatrix[:8, :1],
        short_loop_selector_matrix = self._double_press_event_matrix.submatrix[:8, :1],
        drum_bank_up_button = self._up_button,
        drum_bank_down_button = self._down_button)

  def _session_layer(self):
    def when_bank_on(button):
      return self._bank_toggle.create_toggle_element(on_control=button)
    def when_bank_off(button):
      return self._bank_toggle.create_toggle_element(off_control=button)
    return Layer(
      track_bank_left_button = when_bank_off(self._left_button), 
      track_bank_right_button = when_bank_off(self._right_button), 
      scene_bank_up_button = when_bank_off(self._up_button), 
      scene_bank_down_button = when_bank_off(self._down_button), 
      page_left_button = when_bank_on(self._left_button), 
      page_right_button = when_bank_on(self._right_button), 
      page_up_button = when_bank_on(self._up_button), 
      page_down_button = when_bank_on(self._down_button), 
      stop_track_clip_buttons = self._stop_buttons,
      stop_all_clips_button = self._stop_all_button, 
      scene_launch_buttons = self._scene_launch_buttons, 
      clip_launch_buttons = self._session_matrix)

  def _session_zoom_layer(self):
    return Layer(button_matrix=self._shifted_matrix, 
      nav_left_button=self._with_shift(self._left_button), 
      nav_right_button=self._with_shift(self._right_button), 
      nav_up_button=self._with_shift(self._up_button), 
      nav_down_button=self._with_shift(self._down_button), 
      scene_bank_buttons=self._shifted_scene_buttons)

  def _init_auto_arm(self):
    self._auto_arm = AutoArmComponent(is_enabled = True)

  # EVENT HANDLING FUNCTIONS
  def reset_controlled_track(self):
    self.set_controlled_track(self.song().view.selected_track)
  
  def update(self):
    self.reset_controlled_track()
    super(APSequencer, self).update()

  def _on_selected_track_changed(self):
    self.reset_controlled_track()
    if self._auto_arm.needs_restore_auto_arm:
      self.schedule_message(1, self._auto_arm.restore_auto_arm)
    super(APSequencer, self)._on_selected_track_changed()

  @contextmanager
  def component_guard(self):
    """ Customized to inject additional things """
    with super(APSequencer, self).component_guard():
      with self.make_injector().everywhere():
        yield

  def make_injector(self):
    """ Adds some additional stuff to the injector, used in BaseMessenger """
    return inject(
      double_press_context = const(self._double_press_context),
      control_surface = const(self),
      log_message = const(self.log_message))
Ejemplo n.º 18
0
class LaunchControl(ControlSurface):

    def __init__(self, c_instance):
        super(LaunchControl, self).__init__(c_instance)
        with self.component_guard():
            self._device_selection_follows_track_selection = True
            self._init_mixer()
            self._init_session()
            self._init_device()
            self._init_modes()
            self._refresh_state_task = self._tasks.add(Task.sequence(Task.delay(3), Task.run(self._do_refresh_state)))
            self._refresh_state_task.kill()
        self.log_message('Launch Control script loaded')

    def disconnect(self):
        super(LaunchControl, self).disconnect()
        for channel in xrange(16):
            self._send_midi((CC_STATUS + channel, 0, 0))

    def refresh_state(self):
        self._refresh_state_task.restart()

    def _do_refresh_state(self):
        self._send_current_mode()
        self._update_hardware()
        self.schedule_message(3, super(LaunchControl, self).refresh_state)

    def _update_hardware(self):
        for channel in xrange(8, 11):
            self._send_midi(Sysex.make_automatic_flashing_message(channel))

    def _send_current_mode(self):
        try:
            self._send_midi(MODE_SYSEX_MAP[self._modes.selected_mode])
        except KeyError:
            pass

    def _init_mixer(self):
        make_button = partial(make_launch_control_button, channel=8)
        make_encoder = partial(make_launch_control_encoder, channel=8)
        bottom_encoders, top_encoders = make_all_encoders('Mixer', make_encoder)
        pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders]))
        sends_layer = Layer(sends_controls=ButtonMatrixElement(rows=[bottom_encoders, top_encoders]))
        modes_layer = Layer(pan_volume_button=make_button(114, 'Pan_Volume_Mode_Button'), sends_button=make_button(115, 'Sends_Mode_Button'))
        self._mixer = SpecialMixerComponent(8, modes_layer, pan_volume_layer, sends_layer)
        self._mixer.set_enabled(False)
        self._mixer.name = 'Mixer'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer_track_nav_layer = Layer(track_bank_left_button=make_button(116, 'Mixer_Track_Left_Button'), track_bank_right_button=make_button(117, 'Mixer_Track_Right_Button'))
        for index in xrange(8):
            strip = self._mixer.channel_strip(index)
            strip.name = 'Channel_Strip_' + str(index)
            strip.empty_color = Colors.LED_OFF
            strip.set_invert_mute_feedback(True)
            mute_button = make_button(pad_identifiers[index], 'Track_Mute_Button_' + str(index), is_pad=True)
            mute_button.set_on_off_values(Colors.AMBER_FULL, Colors.AMBER_THIRD)
            strip.set_mute_button(mute_button)

        self._on_selected_send_index.subject = self._mixer
        self._on_selected_mixer_mode.subject = self._mixer

    def _init_session(self):
        make_button = partial(make_launch_control_button, channel=9)
        make_encoder = partial(make_launch_control_encoder, channel=9)
        bottom_encoders, top_encoders = make_all_encoders('Session_Mixer', make_encoder)
        pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders]))
        self._session_mixer = SpecialMixerComponent(8, Layer(), pan_volume_layer, Layer())
        self._session_mixer.set_enabled(False)
        self._session_mixer.name = 'Session_Mixer'
        clip_launch_buttons = [ make_button(identifier, 'Clip_Launch_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ]
        self._session = SpecialSessionComponent(num_tracks=8, num_scenes=0, name='Session')
        self._session.set_enabled(False)
        self._session.set_mixer(self._session_mixer)
        self._session_layer = Layer(track_bank_left_button=make_button(116, 'Track_Bank_Left_Button'), track_bank_right_button=make_button(117, 'Track_Bank_Right_Button'), select_prev_button=make_button(114, 'Scene_Bank_Up_Button'), select_next_button=make_button(115, 'Scene_Bank_Down_Button'), clip_launch_buttons=ButtonMatrixElement(rows=[clip_launch_buttons]))
        scene = self._session.selected_scene()
        for index in range(8):
            clip_slot = scene.clip_slot(index)
            clip_slot.set_triggered_to_play_value(Colors.GREEN_BLINK)
            clip_slot.set_triggered_to_record_value(Colors.RED_BLINK)
            clip_slot.set_stopped_value(Colors.AMBER_FULL)
            clip_slot.set_started_value(Colors.GREEN_FULL)
            clip_slot.set_recording_value(Colors.RED_FULL)
            clip_slot.name = 'Selected_Clip_Slot_' + str(index)

        self._on_track_offset.subject = self._session

    def _init_device(self):
        make_button = partial(make_launch_control_button, channel=10)
        make_encoder = partial(make_launch_control_encoder, channel=10)
        bottom_encoders, top_encoders = make_all_encoders('Device', make_encoder)
        parameter_controls = top_encoders[:4] + bottom_encoders[:4]
        bank_buttons = [ make_button(identifier, 'Device_Bank_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ]
        for button in bank_buttons:
            button.set_on_off_values(Colors.LED_ON, Colors.LED_OFF)

        self._device_bank_registry = DeviceBankRegistry()
        self._device = DeviceComponent(device_bank_registry=self._device_bank_registry, name='Device')
        self._device.set_enabled(False)
        self._device.layer = Layer(parameter_controls=ButtonMatrixElement(rows=[parameter_controls]), bank_buttons=ButtonMatrixElement(rows=[bank_buttons]))
        self.set_device_component(self._device)
        self._device_navigation = DeviceNavigationComponent()
        self._device_navigation.set_enabled(False)
        self._device_navigation.name = 'Device_Navigation'
        self._device_navigation.layer = Layer(next_device_button=make_button(115, 'Next_Device_Button'), previous_device_button=make_button(114, 'Prev_Device_Button'))
        self._view_control = ViewControlComponent()
        self._view_control.set_enabled(False)
        self._view_control.name = 'View_Control'
        self._view_control.layer = Layer(next_track_button=make_button(117, 'Device_Next_Track_Button'), prev_track_button=make_button(116, 'Device_Prev_Track_Button'))

    def _init_modes(self):
        self._modes = ModesComponent(is_root=True)
        self._modes.add_mode('mixer', [partial(self._session.set_mixer, self._mixer),
         LayerMode(self._session, self._mixer_track_nav_layer),
         self._mixer,
         self._session,
         self._show_controlled_tracks_message])
        self._modes.add_mode('session', [partial(self._session.set_mixer, self._session_mixer),
         LayerMode(self._session, self._session_layer),
         self._session_mixer,
         self._session,
         self._show_controlled_tracks_message])
        self._modes.add_mode('device', [self._device, self._device_navigation, self._view_control])
        self._modes.add_mode('user', None)
        self._modes.selected_mode = 'mixer'
        self._modes.layer = Layer(mixer_button=ButtonSysexControl(Sysex.MIXER_MODE), session_button=ButtonSysexControl(Sysex.SESSION_MODE), device_button=ButtonSysexControl(Sysex.DEVICE_MODE))
        return

    @subject_slot('offset')
    def _on_track_offset(self):
        self._show_controlled_tracks_message()

    @subject_slot('selected_send_index')
    def _on_selected_send_index(self, index):
        self._show_controlled_sends_message()

    @subject_slot('selected_mixer_mode')
    def _on_selected_mixer_mode(self, mode):
        if mode == 'sends':
            self._show_controlled_sends_message()
        else:
            self.show_message('Controlling Pan and Volume')

    def _show_controlled_tracks_message(self):
        start = self._session.track_offset() + 1
        end = min(start + 8, len(self._session.tracks_to_use()))
        if start < end:
            self.show_message('Controlling Track %d to %d' % (start, end))
        else:
            self.show_message('Controlling Track %d' % start)

    def _show_controlled_sends_message(self):
        send_index = self._mixer.selected_send_index
        send_name1 = chr(ord('A') + send_index)
        if send_index + 1 < self._mixer.num_sends:
            send_name2 = chr(ord('A') + send_index + 1)
            self.show_message('Controlling Send %s and %s' % (send_name1, send_name2))
        else:
            self.show_message('Controlling Send %s' % send_name1)

    def handle_sysex(self, midi_bytes):
        super(LaunchControl, self).handle_sysex(midi_bytes)
        if self._is_user_mode_message(midi_bytes):
            self._modes.selected_mode = 'user'
            self.request_rebuild_midi_map()

    def _is_user_mode_message(self, midi_bytes):
        """
        True if midi_byes refer to a mode change, but none of the three
        predefined Live modes
        """
        return midi_bytes[:7] == Sysex.MODE_CHANGE_PREFIX and midi_bytes not in SYSEX_MODE_MAP
Ejemplo n.º 19
0
class Launchkey_MK2(OptimizedControlSurface):
    identity_request_delay = 0.5

    def __init__(self, c_instance, *a, **k):
        super(Launchkey_MK2, self).__init__(c_instance=c_instance, *a, **k)
        self._is_25_key_model = False
        self._is_in_control_on = True
        self._identity_response_pending = False
        with self.component_guard():
            self._skin = make_skin()
            with inject(skin=const(self._skin)).everywhere():
                self._create_controls()
        self._request_task = self._tasks.add(Task.sequence(Task.wait(self.identity_request_delay), Task.run(self._send_identity_request)))
        self._request_task.kill()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[ make_encoder(identifier, name=u'Encoder_%d' % (index,)) for index, identifier in enumerate(xrange(21, 29)) ]])
        self._top_pad_row = ButtonMatrixElement(rows=[[ make_button(identifier, name=u'Pad_0_%d' % (index,)) for index, identifier in enumerate(xrange(96, 104)) ]])
        self._bottom_pad_row_raw = [ make_button(identifier, name=u'Pad_1_%d' % (index,)) for index, identifier in enumerate(xrange(112, 120)) ]
        self._bottom_pad_row = ButtonMatrixElement(rows=[self._bottom_pad_row_raw])
        self._top_launch_button = make_button(104, name=u'Scene_Launch_Button')
        self._bottom_launch_button = make_button(120, name=u'Stop_All_Clips_Button')
        self._scene_up_button = make_button(112, MIDI_CC_TYPE, name=u'Scene_Up_Button')
        self._scene_down_button = make_button(113, MIDI_CC_TYPE, name=u'Scene_Down_Button')
        self._stop_button = make_button(114, MIDI_CC_TYPE, name=u'Stop_Button')
        self._play_button = make_button(115, MIDI_CC_TYPE, name=u'Play_Button')
        self._loop_button = make_button(116, MIDI_CC_TYPE, name=u'Loop_Button')
        self._record_button = make_button(117, MIDI_CC_TYPE, name=u'Record_Button')
        self._sliders = ButtonMatrixElement(rows=[[ make_slider(identifier, name=u'Slider_%d' % (index,)) for index, identifier in enumerate(xrange(41, 49)) ]])
        self._master_slider = make_slider(7, name=u'Master_Slider')
        self._25_key_slider = make_slider(7, name=u'Slider', channel=0)
        self._mute_buttons_raw = [ make_button(identifier, MIDI_CC_TYPE, name=u'Mute_Button_%d' % (index,)) for index, identifier in enumerate(xrange(51, 59)) ]
        self._mute_buttons = ButtonMatrixElement(rows=[self._mute_buttons_raw])
        self._master_button = make_button(59, MIDI_CC_TYPE, name=u'Master_Button')
        self._track_left_button = make_button(102, MIDI_CC_TYPE, name=u'Track_Left_Button')
        self._track_right_button = make_button(103, MIDI_CC_TYPE, name=u'Track_Right_Button')
        self._device_mode_button = self._bottom_pad_row_raw[0]
        self._pan_mode_button = self._bottom_pad_row_raw[1]
        self._send_mode_buttons = dict()
        for index in xrange(consts.MAX_SENDS):
            setattr(self, u'_send_%d_button' % (index,), self._bottom_pad_row_raw[index + 2])
            self._send_mode_buttons[u'send_%d_mode_button' % (index,)] = getattr(self, u'_send_%d_button' % (index,))

        self._extended_mode_button = make_button(12, name=u'Dummy_Extended_Mode_Button')
        self._extended_mode_button.add_value_listener(nop)
        self._encoder_incontrol_button = make_button(13, is_momentary=False, name=u'Encoder_InControl_Button')
        self._encoder_incontrol_button.add_value_listener(nop)
        self._slider_incontrol_button = make_button(14, is_momentary=False, name=u'Fader_InControl_Button')
        self._slider_incontrol_button.add_value_listener(nop)
        self._pad_incontrol_button = make_button(15, is_momentary=False, name=u'Pad_InControl_Button')
        self._pad_incontrol_button.add_value_listener(self._update_pads)
        self._encoder_incontrol_button2 = make_button(16, name=u'Encoder_InControl_Button')
        self._pad_in_control_status_button = make_button(11, name=u'Dummy_InControl_Button')

    def _create_session(self):
        self._session = SessionComponent(name=u'Session', is_enabled=False, num_tracks=self._top_pad_row.width(), num_scenes=self._top_pad_row.height(), enable_skinning=True, layer=Layer(clip_launch_buttons=self._top_pad_row, scene_launch_buttons=ButtonMatrixElement(rows=[[self._top_launch_button]]), stop_track_clip_buttons=self._bottom_pad_row, stop_all_clips_button=self._bottom_launch_button))
        self._session.set_rgb_mode(LIVE_COLORS_TO_MIDI_VALUES, RGB_COLOR_TABLE)
        self._session.set_mixer(self._mixer)
        self._session.set_enabled(True)

    def _setup_navigation(self):
        self._session_navigation = SessionNavigationComponent(is_enabled=False, name=u'Session_Navigation', layer=Layer(next_track_button=self._track_right_button, prev_track_button=self._track_left_button, next_scene_button=self._scene_down_button, prev_scene_button=self._scene_up_button))
        self._session_navigation.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(is_enabled=False, name=u'Transport', layer=Layer(play_button=self._play_button, stop_button=self._stop_button, loop_button=self._loop_button, record_button=self._record_button))
        self._transport.set_enabled(True)

    def _create_mixer(self):
        mixer_volume_layer = None
        if self._is_25_key_model:
            mixer_volume_layer = Layer(volume_control=self._25_key_slider)
        else:
            mixer_volume_layer = Layer(volume_controls=self._sliders)
        self._mixer = MixerComponent(is_enabled=False, name=u'Mixer', num_tracks=self._sliders.width(), layer=mixer_volume_layer)
        if not self._is_25_key_model:
            self._mixer.master_strip().layer = Layer(volume_control=self._master_slider)
        self._mixer.set_enabled(True)
        self._mute_button_modes = ModesComponent()
        mute_mode = AddLayerMode(self._mixer, Layer(mute_buttons=self._mute_buttons))
        solo_mode = AddLayerMode(self._mixer, Layer(solo_buttons=self._mute_buttons))
        self._mute_button_modes.add_mode(u'mute_mode', mute_mode)
        self._mute_button_modes.add_mode(u'solo_mode', solo_mode, behaviour=CancellableBehaviour())
        self._mute_button_modes.layer = Layer(solo_mode_button=self._master_button)
        self._mute_button_modes.selected_mode = u'mute_mode'
        self._mute_button_modes.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(name=u'Device', is_enabled=False, device_selection_follows_track_selection=True)
        self.set_device_component(self._device)
        self._device.set_enabled(True)

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

    def _create_encoder_modes(self):
        self._encoder_modes = DisablingModesComponent()
        self._encoder_modes.default_behaviour = mixin(SkinableBehaviourMixin, ImmediateBehaviour)()
        device_mode = LayerMode(self._device, Layer(parameter_controls=self._encoders, bank_buttons=self._top_pad_row))
        pan_mode = AddLayerMode(self._mixer, Layer(pan_controls=self._encoders))
        sends_mode = AddLayerMode(self._mixer, Layer(send_controls=self._encoders))
        background_mode = LayerMode(self._background, Layer(bank_buttons=self._top_pad_row))
        self._encoder_modes.add_mode(u'device_mode', device_mode, is_enabled=True)
        self._encoder_modes.add_mode(u'pan_mode', [pan_mode, background_mode], is_enabled=True)
        for index in xrange(6):
            self._encoder_modes.add_mode(u'send_%d_mode' % (index,), [sends_mode, partial(self._set_send_index, index), background_mode], is_enabled=False)

        self._encoder_modes.selected_mode = u'device_mode'
        self._encoder_modes.set_enabled(True)

    def _create_mode_selector(self):
        self._mode_selector = ModesComponent()
        mode_selection = LayerMode(self._encoder_modes, Layer(device_mode_button=self._device_mode_button, pan_mode_button=self._pan_mode_button, **self._send_mode_buttons))
        device_navigation = AddLayerMode(self._device, Layer(device_nav_left_button=self._track_left_button, device_nav_right_button=self._track_right_button))
        self._mode_selector.add_mode(u'mode_selection', [partial(self._toggle_in_control, True), mode_selection, device_navigation], behaviour=MomentaryBehaviour())
        session_control = AddLayerMode(self._session, Layer(clip_launch_buttons=self._top_pad_row))
        self._mode_selector.add_mode(u'session_mode', [partial(self._toggle_in_control, False), session_control])
        self._mode_selector.layer = Layer(mode_selection_button=self._encoder_incontrol_button2)

    def _create_in_control_status_listener(self):
        self._in_control_status = InControlStatusComponent(set_is_in_control_on=self._set_is_in_control_on, is_enabled=False, layer=Layer(in_control_status_button=self._pad_in_control_status_button))
        self._in_control_status.set_enabled(True)

    @subject_slot(u'value')
    def _update_pads(self, value):
        if value:
            self.update()

    @subject_slot(u'return_tracks')
    def _on_return_tracks_changed(self):
        num_sends = self._mixer.num_sends
        for index in xrange(6):
            self._encoder_modes.set_mode_enabled(u'send_%d_mode' % (index,), True if index < num_sends else False)

    def _set_send_index(self, index):
        self._mixer.send_index = index

    def _set_is_in_control_on(self, value):
        self._is_in_control_on = value

    def _toggle_in_control(self, value):
        if not self._is_in_control_on:
            self._send_midi(consts.DRUM_IN_CONTROL_ON_MESSAGE if value else consts.DRUM_IN_CONTROL_OFF_MESSAGE)

    def port_settings_changed(self):
        self._disconnect_and_unregister_all_components()
        self._request_task.restart()

    def handle_sysex(self, midi_bytes):
        if self._is_identity_response(midi_bytes):
            product_id_bytes = self._extract_product_id_bytes(midi_bytes)
            if self._is_identity_response_valid(product_id_bytes):
                self._set_model_type(product_id_bytes)
                self._request_task.kill()
                if self._identity_response_pending:
                    self.on_identified()
                    self._identity_response_pending = False
            else:
                self.log_message(u'MIDI device responded with wrong product id (%s).' % (str(product_id_bytes),))
        else:
            super(Launchkey_MK2, self).handle_sysex(midi_bytes)

    def _extract_product_id_bytes(self, midi_bytes):
        return midi_bytes[5:]

    def _is_identity_response(self, midi_bytes):
        return midi_bytes[3:5] == (6, 2)

    def _is_identity_response_valid(self, product_id_bytes):
        return product_id_bytes[:3] == consts.PRODUCT_ID_BYTE_PREFIX and product_id_bytes[3] in consts.PRODUCT_ID_BYTES

    def _set_model_type(self, product_id_bytes):
        self._is_25_key_model = product_id_bytes[3] == consts.LAUNCHKEY_25_ID_BYTE

    def _send_identity_request(self):
        self._identity_response_pending = True
        self._send_midi(consts.IDENTITY_REQUEST)

    def on_identified(self):
        self._extended_mode_button.turn_on()
        with self.component_guard():
            self._create_mixer()
            self._create_session()
            self._setup_navigation()
            self._create_transport()
            self._create_device()
            self._create_background()
            self._create_encoder_modes()
            self._create_mode_selector()
            self._create_in_control_status_listener()
            self._on_return_tracks_changed.subject = self.song()
            self._on_return_tracks_changed()
        self._mode_selector.selected_mode = u'session_mode'
        self.update()

    def disconnect(self):
        self._extended_mode_button.turn_off()
        super(Launchkey_MK2, self).disconnect()
Ejemplo n.º 20
0
class APC40_Selector(APC40):
    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_alt_session()
            self._create_mixer()
            self._create_device()
            self._create_detail_view_control()
            self._create_transport()
            self._create_global_control()
            self._create_session_switcher()
            self._create_delete_component()
            self._create_fallback_control_owner()
            self._session.set_mixer(self._mixer)
            self._alt_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 _on_handshake_successful(self):
        self._suppress_session_highlight = False
        for component in self.components:
            if hasattr(component, 'name') and not (
                    component.name.endswith('Session_Control')
                    or component.name.endswith('Session_Overview')):
                component.set_enabled(True)

        self._on_selected_track_changed()
        self._do_combine()

    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))
        self._session.link_with_track_offset(0)

    def _create_alt_session(self):
        self._alt_session = SelectingSessionComponent(
            self,
            SESSION_WIDTH,
            SESSION_HEIGHT,
            auto_name=True,
            enable_skinning=True,
            is_enabled=False,
            layer=Layer(
                priority=2,
                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,
            ))
        self._alt_session.name = 'Alt_Session_Control'
        self._alt_session_zoom = SessionZoomingComponent(
            self._alt_session,
            name='Alt_Session_Overview',
            enable_skinning=True,
            is_enabled=False,
            layer=Layer(priority=2,
                        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))
        self._alt_session.link_with_track_offset(0)

    def _create_session_switcher(self):
        self._session_switcher = ModesComponent(
            name='SessionSwitcher')  # is_enabled = False)
        self._session_switcher.add_mode('session',
                                        [self._session, self._session_zoom],
                                        toggle_value='DefaultButton.Off')
        self._session_switcher.add_mode('altsession', [
            self._alt_session, self._alt_session_zoom,
            tuple([self._enable_alt_session, self._disable_alt_session])
        ],
                                        toggle_value='DefaultButton.On')
        self._session_switcher.layer = Layer(
            toggle_button=self._detail_toggle_button)
        self._session_switcher.selected_mode = 'session'

    def _enable_alt_session(self):
        self.set_highlighting_session_component(self._alt_session)

    def _disable_alt_session(self):
        self.set_highlighting_session_component(self._session)

    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))

    def _create_delete_component(self):
        self._delete_component = ModesComponent(name='DeleteClipComponent')
        self._delete_component.add_mode('disabled', None)
        self._delete_component.add_mode(
            'enabled',
            [DelayMode(tuple([self._delete_on, self._delete_off]), delay=1.5)])
        self._delete_component.layer = Layer(
            toggle_button=self._selected_scene_launch_button)
        self._delete_component.selected_mode = 'disabled'

    def _delete_on(self):
        slot = self.song().view.highlighted_clip_slot
        if slot != None and slot.has_clip:
            slot.delete_clip()

    def _delete_off(self):
        pass

    def _create_global_control(self):
        super(APC40_Selector, self)._create_global_control()
Ejemplo n.º 21
0
class APC40_Mod(APC, OptimizedControlSurface):

    def __init__(self, *a, **k):
        super(APC40_Mod, self).__init__(*a, **k)
        self._color_skin = merge_skins(make_default_skin(), make_biled_skin())
        self._default_skin = make_default_skin()
        self._stop_button_skin = merge_skins(make_default_skin(), make_stop_button_skin())
        with self.component_guard():
            self._create_controls()
            self._create_session()
            self._create_mixer()
            self._create_transport()
            self._create_device()
            self._create_view_control()
            self._create_quantization_selection()
            self._init_track_modes()
            self._create_m4l_interface()
            self._session.set_mixer(self._mixer)
        self.set_highlighting_session_component(self._session)
        self.set_device_component(self._device)
        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)
        make_stop_button = partial(make_button, skin=self._stop_button_skin)

        self._shift_button = make_button(0, 98, name='Shift_Button', resource_type=PrioritizedResource)
        self._left_button = make_button(0, 97, name='Bank_Select_Left_Button')
        self._right_button = make_button(0, 96, name='Bank_Select_Right_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._stop_buttons = ButtonMatrixElement(rows=[[ make_stop_button(track, 52, name='%d_Stop_Button' % track) for track in xrange(NUM_TRACKS) ]], name="Stop_Buttons")
        self._stop_all_button = make_button(0, 81, name='Stop_All_Clips_Button')
        self._scene_launch_buttons_raw = [ make_color_button(0, scene + 82, name='Scene_%d_Launch_Button' % scene) for scene in xrange(NUM_SCENES) ]
        self._scene_launch_buttons = ButtonMatrixElement(rows=[self._scene_launch_buttons_raw], name="Scene_Launch_Buttons")
        self._matrix_rows_raw = [ [ make_color_button(track, 53 + scene, name='%d_Clip_%d_Button' % (track, scene)) for track in xrange(NUM_TRACKS) ] for scene in xrange(NUM_SCENES) ]
        self._session_matrix = ButtonMatrixElement(rows=self._matrix_rows_raw, name='Button_Matrix')
        self._pan_button = make_on_off_button(0, 87, name='Pan_Button')
        self._send_a_button = make_on_off_button(0, 88, name='Send_A_Button')
        self._send_b_button = make_on_off_button(0, 89, name='Send_B_Button')
        self._send_c_button = make_on_off_button(0, 90, name='Send_C_Button')
        self._mixer_encoders = ButtonMatrixElement(rows=[[ make_ring_encoder(48 + track, 56 + track, name='Track_Control_%d' % track) for track in xrange(NUM_TRACKS) ]], name="Track_Controls")
        self._volume_controls = ButtonMatrixElement(rows=[[ make_slider(track, 7, name='%d_Volume_Control' % track) for track in xrange(NUM_TRACKS) ]])
        self._master_volume_control = make_slider(0, 14, name='Master_Volume_Control')
        self._prehear_control = make_encoder(0, 47, name='Prehear_Volume_Control')
        self._crossfader_control = make_slider(0, 15, name='Crossfader')
        self._raw_select_buttons = [ make_on_off_button(channel, 51, name='%d_Select_Button' % channel) for channel in xrange(NUM_TRACKS) ]
        self._arm_buttons = ButtonMatrixElement(rows=[[ make_on_off_button(channel, 48, name='%d_Arm_Button' % channel) for channel in xrange(NUM_TRACKS) ]], name="Arm_Buttons")
        self._solo_buttons = ButtonMatrixElement(rows=[[ make_on_off_button(channel, 49, name='%d_Solo_Button' % channel) for channel in xrange(NUM_TRACKS) ]], name="Solo_Buttons")
        self._mute_buttons = ButtonMatrixElement(rows=[[ make_on_off_button(channel, 50, name='%d_Mute_Button' % channel) for channel in xrange(NUM_TRACKS) ]], name="Mute_Buttons")
        self._select_buttons = ButtonMatrixElement(rows=[self._raw_select_buttons], name="Select_Buttons")
        self._master_select_button = make_on_off_button(channel=0, identifier=80, name='Master_Select_Button')
        self._quantization_buttons = ButtonMatrixElement(rows=[[ ComboElement(button, modifiers=[self._shift_button]) for button in self._raw_select_buttons ]], name="Quantization_Buttons")
        self._play_button = make_on_off_button(0, 91, name='Play_Button')
        self._stop_button = make_on_off_button(0, 92, name='Stop_Button')
        self._record_button = make_on_off_button(0, 93, name='Record_Button')
        self._nudge_down_button = make_button(0, 101, name='Nudge_Down_Button')
        self._nudge_up_button = make_button(0, 100, name='Nudge_Up_Button')
        self._tap_tempo_button = make_button(0, 99, name='Tap_Tempo_Button')
        self._device_controls = ButtonMatrixElement(rows=[[ make_ring_encoder(16 + index, 24 + index, name='Device_Control_%d' % index) for index in xrange(8) ]], name="Device_Controls")
        self._device_control_buttons_raw = [ make_on_off_button(0, 58 + index) for index in xrange(8) ]
        self._device_bank_buttons = ButtonMatrixElement(rows=[[ DeviceBankButtonElement(button, modifiers=[self._shift_button]) for button in self._device_control_buttons_raw ]], name="Device_Bank_Buttons")
        self._device_clip_toggle_button = self._device_control_buttons_raw[0]
        self._device_clip_toggle_button.name = 'Clip_Device_Button'
        self._device_on_off_button = self._device_control_buttons_raw[1]
        self._device_on_off_button.name = 'Device_On_Off_Button'
        self._detail_left_button = self._device_control_buttons_raw[2]
        self._detail_left_button.name = 'Prev_Device_Button'
        self._detail_right_button = self._device_control_buttons_raw[3]
        self._detail_right_button.name = 'Next_Device_Button'
        self._detail_toggle_button = self._device_control_buttons_raw[4]
        self._detail_toggle_button.name = 'Detail_View_Button'
        self._rec_quantization_button = self._device_control_buttons_raw[5]
        self._rec_quantization_button.name ='Rec_Quantization_Button'
        self._overdub_button = self._device_control_buttons_raw[6]
        self._overdub_button.name = 'Overdub_Button'
        self._metronome_button = self._device_control_buttons_raw[7]
        self._metronome_button.name = 'Metronome_Button'
        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._shifted_matrix = ButtonMatrixElement(rows=recursive_map(self._with_shift, self._matrix_rows_raw), name="Shifted_Matrix")
        self._shifted_scene_buttons = ButtonMatrixElement(rows=[[ self._with_shift(button) for button in self._scene_launch_buttons_raw ]], name="Shifted_Scene_Buttons")

    def _create_session(self):
        self._session = SessionComponent(NUM_TRACKS, NUM_SCENES, auto_name=True, is_enabled=False, enable_skinning=True, 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_track_clip_buttons=self._stop_buttons, stop_all_clips_button=self._stop_all_button, 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_left_button=self._with_shift(self._left_button), nav_right_button=self._with_shift(self._right_button), nav_up_button=self._with_shift(self._up_button), nav_down_button=self._with_shift(self._down_button), scene_bank_buttons=self._shifted_scene_buttons))

    def _init_track_modes(self):
        self._track_modes = ModesComponent(name='Track_Modes', is_enabled=False)
        self._track_modes.default_behaviour = ImmediateBehaviour()
        self._track_modes.add_mode('pan', [AddLayerMode(self._mixer, Layer(pan_controls=self._mixer_encoders))])
        self._track_modes.add_mode('send_a', [AddLayerMode(self._mixer, Layer(send_controls=self._mixer_encoders)), partial(self._mixer.set_send_button_index, 0)])
        self._track_modes.add_mode('send_b', [AddLayerMode(self._mixer, Layer(send_controls=self._mixer_encoders)), partial(self._mixer.set_send_button_index, 1)])
        self._track_modes.add_mode('send_c', [AddLayerMode(self._mixer, Layer(send_controls=self._mixer_encoders)), partial(self._mixer.set_send_button_index, 2)])
        self._track_modes.layer = Layer(pan_button=self._pan_button, send_a_button=self._send_a_button, send_b_button=self._send_b_button, send_c_button=self._send_c_button)
        self._track_modes.selected_mode = 'pan'

    def _create_mixer(self):
        self._mixer = MixerComponent(NUM_TRACKS, 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, shift_button=self._shift_button, track_select_buttons=self._select_buttons, prehear_volume_control=self._prehear_control, crossfader_control=self._crossfader_control))
        self._mixer.master_strip().layer = Layer(volume_control=self._master_volume_control, select_button=self._master_select_button)

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

    def _create_device(self):
        self._device = DeviceComponent(name='Device', is_enabled=False, layer=Layer(parameter_controls=self._device_controls, bank_buttons=self._device_bank_buttons, on_off_button=self._device_on_off_button), device_selection_follows_track_selection=True)

    def _create_view_control(self):
        self._view_control = DetailViewCntrlComponent(name='View_Control', is_enabled=False, layer=Layer(device_nav_left_button=self._detail_left_button, device_nav_right_button=self._detail_right_button, device_clip_toggle_button=self._device_clip_toggle_button, detail_toggle_button=self._detail_toggle_button))
        self._view_control.device_clip_toggle_button.pressed_color = 'DefaultButton.On'

    def _create_quantization_selection(self):
        self._quantization_selection = QuantizationComponent(name='Quantization_Selection', is_enabled=False, layer=Layer(quantization_buttons=self._quantization_buttons))

    def _create_m4l_interface(self):
        self._m4l_interface = M4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard, priority=1)
        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 get_matrix_button(self, column, row):
        return self._matrix_rows_raw[row][column]

    def _product_model_id_byte(self):
        return 115
Ejemplo n.º 22
0
class AumTroll(Cntrlr):
    __module__ = __name__
    __doc__ = " MonOhmod companion controller script "

    def __init__(self, *a, **k):
        self._monohm = None
        self._aumpush = None
        self._shifted = False
        self._use_pedal = True
        self._suppress_next_mod_display = False
        self._monomod_version = 'b996'
        self._codec_version = 'b996'
        super(AumTroll, self).__init__(*a, **k)
        self._host_name = "AumTroll"
        with self.component_guard():
            self._setup_alt_device_control()
            self._setup_alt_mixer()
            #self._setup_device_selector()   #  Not sure why this was HERE, but removed 051314 because it was overriding mod grid updates
            #self._setup_alt_device_control()
        #self.schedule_message(3, self._session._do_show_highlight)
        self._send_midi(tuple(request_snapshot))

    """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_modes(self):
        super(AumTroll, self)._setup_modes()
        self._alt_shift_mode = ModesComponent()
        self._alt_shift_mode.add_mode(
            'alt_shift',
            tuple([self._enable_alt_shift, self._disable_alt_shift]),
            behaviour=CancellableBehaviourWithRelease())
        self._alt_shift_mode.set_mode_button('alt_shift', self._grid[15])

    def _enable_alt_shift(self):
        self._alt_shift_enabled = True
        self._on_shift_button_value(1)

    def _disable_alt_shift(self):
        self._alt_shift_enabled = False
        self._on_shift_button_value(0)

    def deassign_live_controls(self):

        self._leds_last = None
        self._device_selector.set_enabled(False)
        self._device._parameter_controls = None
        self._device1._parameter_controls = None
        self._device2._parameter_controls = None
        for index in range(8):
            self._mixer2.channel_strip(index).set_select_button(None)
            self._mixer2.channel_strip(index).set_volume_control(None)
        for index in range(4):
            self._mixer3.channel_strip(index).set_select_button(None)
            self._mixer3.channel_strip(index).set_volume_control(None)
            self._mixer3.return_strip(index).set_volume_control(None)
        #if self._aumpush:
        #	self._aumpush._host._set_bank_buttons(None)
        #self._on_shift_button_value.subject = None
        self._alt_shift_mode.set_mode_button('alt_shift', None)
        self._mixer.set_crossfader_control(None)
        """THIS SECTION IS MISSING FROM THE ORIGINAL SCRIPT AND NEEDS TO BE FIXED...THE ASSIGNMENTS WERE MADE AT __init__"""
        for index in range(4):
            self._mixer.channel_strip(index).set_volume_control(
                None
            )  #Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it
        for index in range(2):
            self._mixer.return_strip(index).set_volume_control(
                None
            )  #assign the right faders to control the volume of our return strips
        self._mixer.master_strip().set_volume_control(
            None
        )  #assign the far right fader to control our master channel strip
        self._mixer.set_prehear_volume_control(
            None
        )  #assign the remaining fader to control our prehear volume of the the master channel strip

        for index in range(4):  #for the left side of the mixer
            self._mixer.channel_strip(index).set_solo_button(
                None)  #remove the solo button assignments
            self._mixer.channel_strip(index).set_arm_button(
                None)  #remove the arm button assignments
            self._mixer.channel_strip(index).set_mute_button(
                None)  #remove the mute button assignments
            self._mixer.channel_strip(index).set_select_button(
                None)  #remove the select button assignments
        for column in range(4):
            for row in range(4):
                self._scene[row].clip_slot(column).set_launch_button(
                    None)  #remove the clip launch assignments
        self._send_reset.set_buttons(
            tuple([None for index in range(4)])
        )  #remove the send_reset button assignments - this has to be sent as a tuple
        self._session.set_stop_track_clip_buttons(
            None)  #remove the clip_stop button assignments
        self._session.set_track_bank_buttons(
            None, None
        )  #set the track bank buttons for the Session navigation controls
        self._session.set_scene_bank_buttons(
            None, None
        )  #set the scnee bank buttons for the Session navigation controls
        self._transport.set_play_button(
            None)  #remove the play button assignment
        self._transport.set_record_button(
            None)  #remove the record button assignment
        self._transport.set_stop_button(
            None)  #remove the stop button assignment
        for index in range(16):
            self._grid[index].set_on_off_values(
                127, 0)  #reset the on/off values of the grid buttons
            self._grid[index].reset()  #turn the buttons LEDs off
        for index in range(32):
            self._button[index].set_on_off_values(
                127, 0)  #reset the on/off values for the key buttons
            self._button[index].release_parameter(
            )  #remove the parameter assignment that was assigned to the keys
            self._button[index].send_value(0, True)  #turn the buttons LEDs off

        #self._device.set_parameter_controls(tuple([self._encoder[index+4] for index in range(8)]))			#assign the encoders from the device component controls - we are doing this here b
        self._device_navigator.set_nav_buttons(
            None, None)  #remove the assignment of the device nav buttons
        self._device_navigator.set_enabled(
            False)  #turn off the device navigator
        self._device.set_on_off_button(
            None
        )  #remove the assignment of the on/off button from the device component
        self._device.set_lock_button(
            None
        )  #remove the assignment of the lock button from the device component
        self._device.set_bank_nav_buttons(
            None, None
        )  #remove the assignment of the navigation buttons from the device component
        self._device.set_enabled(False)  #turn off the device component
        self._session.set_enabled(False)  #turn off the session component
        self._session_zoom.set_enabled(False)  #turn off the zoom component
        for index in range(16):
            self._grid[index].force_next_send(
            )  #set the last_sent value of the grid to -1, so that the next value it receives will always be transmitted to the CNTRLR
        for index in range(32):
            self._button[index].force_next_send(
            )  #set the last_sent value of the keys to -1, so that the next value it receives will always be transmitted to the CNTRLR
        for index in range(12):
            self._device._parameter_controls = None
            self._encoder[index].release_parameter()
            self._encoder[index].send_value(
                0, True
            )  #turn off all the encoder rings.  We send it the second argument, True, so that it is forced to update regardless of its last_sent property
            self._encoder[index].force_next_send(
            )  #set the last_sent value of the encoder rings to -1, so that the next value it receives will always be transmitted to the CNTRLR
        for index in range(8):
            self._encoder_button[index + 4].send_value(
                0, True
            )  #turn off all the encoder LEDs.  We send it the second argument, True, so that it is forced to update regardless of its last_sent property
            self._encoder_button[index + 4].force_next_send(
            )  #set the last_sent value of the encoder LEDs to -1, so that the next value it receives will always be transmitted to the CNTRLR
        for index in range(8):
            self._mixer2.channel_strip(index).set_select_button(None)
            self._mixer2.channel_strip(index).set_mute_button(None)
            self._mixer2.channel_strip(index).set_select_button(None)
        self._session_zoom.set_zoom_button(
            None
        )  #remove the assignment of the shift button from the ZoomingComponent
        self.request_rebuild_midi_map(
        )  #now that we've finished deassigning all of our controls, we tell the main script to rebuild its MIDI map and update the values in Live

    def assign_live_controls(self):
        """the following lines update all of the controls' last_sent properties, so that they forward the next value they receive regardless of whether or not it is the same as the last it recieved"""
        """we also reset the encoder rings and buttons, since the device component will not update them if it is not locked to a device in Live"""
        for index in range(16):
            self._grid[index].force_next_send()
        for index in range(32):
            self._button[index].force_next_send()
        for index in range(8):
            self._encoder_button[index + 4].send_value(0, True)
            self._encoder_button[index + 4].force_next_send()
        for index in range(12):
            self._encoder[index].send_value(0, True)
            self._encoder[index].force_next_send()
        """here we assign the left side of our mixer's buttons on the lower 32 keys"""
        if self._monohm == None and self._aumpush == None:
            for index in range(
                    4
            ):  #we set up a recursive loop to assign all four of our track channel strips' controls
                self._button[index].set_on_value(
                    SOLO[self._rgb])  #set the solo color from the Map.py
                self._mixer.channel_strip(index).set_solo_button(
                    self._button[index]
                )  #assign the solo buttons to our mixer channel strips
                self._button[index + 4].set_on_value(
                    ARM[self._rgb])  #set the arm color from the Map.py
                self._mixer.channel_strip(index).set_arm_button(
                    self._button[index + 4]
                )  #assign the arm buttons to our mixer channel strips
                self._button[index + 16].set_on_value(
                    MUTE[self._rgb])  #set the mute color from the Map.py
                self._mixer.channel_strip(index).set_mute_button(
                    self._button[index + 16]
                )  #assign the mute buttons to our mixer channel strips
                self._button[index + 20].set_on_value(
                    SELECT[self._rgb])  #set the select color from the Map.py
                self._mixer.channel_strip(index).set_select_button(
                    self._button[index + 20]
                )  #assign the select buttons to our mixer channel strips
            self._send_reset.set_buttons(
                tuple(self._button[index + 8] for index in range(4))
            )  #this is yet another way to quickly assign multiple elements conveniently in-place.  We are creating a recursion inside an assignment.  The tuple() method creates an immutable array.  It can't be modified until it gets where it's going and is unpacked.
            self._session.set_stop_track_clip_buttons(
                tuple(self._button[index + 24] for index in range(4))
            )  #these last two lines assign the send_reset buttons and the stop_clip buttons for each track
            for index in range(4):
                self._button[index + 8].send_value(
                    SEND_RESET[self._rgb], True
                )  #now we are going to send a message to turn the LEDs on for the send_reset buttons
                self._button[index + 24].set_on_off_values(
                    STOP_CLIP[self._rgb], STOP_CLIP[self._rgb]
                )  #this assigns the custom colors defined in the Map.py file to the stop_clip buttons.  They have seperate on/off values, but we assign them both the same value so we can always identify them
                self._button[index + 24].send_value(
                    STOP_CLIP[self._rgb], True
                )  #finally, we send the on/off colors out to turn the LEDs on for the stop clip buttons
            self._button[28].set_on_off_values(
                PLAY_ON[self._rgb], PLAY[self._rgb]
            )  #assing the on/off colors for play.  These are two seperate values, dependant upon whether play is engaged or not
            self._transport.set_play_button(
                self._button[28]
            )  #set the transports play control to the corresponding button on the CNTRLR
            self._button[30].set_on_off_values(
                RECORD_ON[self._rgb], RECORD[self._rgb]
            )  #set the on/off colors for the transport record buttons
            self._transport.set_record_button(
                self._button[30]
            )  #assign the correct button for the transport record control
            self._button[29].set_on_value(
                STOP[self._rgb])  #set the on value for the Stop button
            self._transport.set_stop_button(
                self._button[29]
            )  #assign the correct button for the transport stop control
            self._button[29].send_value(
                STOP_OFF[self._rgb],
                True)  #turn on the LED for the stop button
            for index in range(
                    4
            ):  #set up a for loop to generate an index for assigning the session nav buttons' colors
                self._button[index + 12].set_on_off_values(
                    SESSION_NAV[self._rgb], SESSION_NAV_OFF[self._rgb]
                )  #assign the colors from Map.py to the session nav buttons
            self._session.set_track_bank_buttons(
                self._button[15], self._button[14]
            )  #set the track bank buttons for the Session navigation controls
            self._session.set_scene_bank_buttons(
                self._button[13], self._button[12]
            )  #set the scnee bank buttons for the Session navigation controls
            """this section assigns the grid to the clip launch functionality of the SessionComponent"""
            for column in range(
                    4
            ):  #we need to set up a double recursion so that we can generate the indexes needed to assign the grid buttons
                for row in range(
                        4
                ):  #the first recursion passes the column index, the second the row index
                    self._scene[row].clip_slot(column).set_launch_button(
                        self._grid[(row * 4) + column]
                    )  #we use the indexes to grab the first the scene and then the clip we assigned above, and then we use them again to define the button held in the grid array that we want to assign to the clip slot from the session component
            """this section assigns the faders and knobs"""
            for index in range(2):
                self._mixer.return_strip(index).set_volume_control(
                    self._fader[index + 4]
                )  #assign the right faders to control the volume of our return strips
            self._mixer.master_strip().set_volume_control(
                self._fader[7]
            )  #assign the far right fader to control our master channel strip
            self._mixer.set_prehear_volume_control(
                self._fader[6]
            )  #assign the remaining fader to control our prehear volume of the the master channel strip
            for track in range(
                    4
            ):  #we set up a recursive loop to assign all four of our track channel strips' controls
                channel_strip_send_controls = [
                ]  #the channelstripcomponent requires that we pass the send controls in an array, so we create a local variable, channel_strip_send_controls, to hold them
                for control in range(
                        2
                ):  #since we are going to assign two controls to the sends, we create a recursion
                    channel_strip_send_controls.append(
                        self._dial_left[track + (control * 4)]
                    )  #then use the append __builtin__ method to add them to the array
                self._mixer.channel_strip(track).set_volume_control(
                    self._fader[track]
                )  #Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it
                self._mixer.channel_strip(track).set_send_controls(
                    tuple(channel_strip_send_controls)
                )  #now that we have an array containing the send controls, we pass it to the channelstrip component with its set_send_controls() method
                self._mixer.channel_strip(track).set_pan_control(
                    self._dial_left[
                        track + 8])  #now we set the pan control to the bottom
                self._mixer.track_eq(track).set_gain_controls(
                    tuple([
                        self._dial_right[track + 8],
                        self._dial_right[track + 4], self._dial_right[track]
                    ])
                )  #here's another way of doing the same thing, but instead of creating the array before hand, we define it in-place.  Its probably bad coding to mix styles like this, but I'll leave it for those of you trying to figure this stuff out
                self._mixer.track_eq(track).set_enabled(
                    True)  #turn the eq component on
            self._session_zoom.set_zoom_button(
                self._button[31]
            )  #assign the lower right key button to the shift function of the Zoom component
            self._session.update(
            )  #tell the Session component to update so that the grid will display the currently selected session region
            self._session.set_enabled(True)  #enable the Session Component
            self._session_zoom.set_enabled(True)  #enable the Session Zoom

        elif not self._aumpush == None:
            self.assign_aumpush_controls()

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

    """function mode callbacks"""
    """this method changes modes when we press a modButton.  It is also called from Monomod when it needs to update the modDial assignments"""

    def shift_update(self):
        super(AumTroll, self).shift_update()
        if self._shift_mode._mode_index == 0:
            if self._aumpush == None:
                for index in range(8):
                    self._mixer2.channel_strip(index).set_volume_control(
                        self._fader[index])
                self._mixer2.set_track_offset(TROLL_OFFSET)
                self._device1.set_parameter_controls(
                    tuple([self._knobs[index] for index in range(8)]))
                self._device2.set_parameter_controls(
                    tuple([self._knobs[index + 12] for index in range(8)]))
                self._device1.set_enabled(True)
                self._device2.set_enabled(True)
                self._find_devices()
                self._device1.update()
                self._device2.update()
            else:
                self.assign_aumpush_controls()

    def find_inputs(self):
        found_device = None
        tracks = self.song().tracks
        for track in tracks:
            if track.name == 'Inputs':
                for device in track.devices:
                    if bool(device.can_have_chains
                            ) and device.name == 'Inputs':
                        found_device = device
        return found_device

    def find_perc_crossfader(self):
        found_parameter = None
        tracks = self.song().tracks
        for track in tracks:
            if track.name == 'Perc':
                for device in track.devices:
                    if bool(device.can_have_chains) and device.name == 'Perc':
                        for parameter in device.parameters:
                            if parameter.name == 'XFade':
                                found_parameter = parameter
        return found_parameter

    def assign_aumpush_controls(self):
        if self._aumpush:
            inputs = self.find_inputs()
            if not inputs is None:
                for index in range(4):
                    self._knobs[index + 8].connect_to(inputs.parameters[index +
                                                                        1])

            #for index in range(3):
            #	self._mixer2.channel_strip(index+4).set_volume_control(self._knobs[index+20])
            self._mixer.set_crossfader_control(self._knobs[23])
            xfade = self.find_perc_crossfader()
            if not xfade is None:
                self._knobs[20].connect_to(xfade)
            for index in range(4):
                self._mixer3.return_strip(index).set_volume_control(
                    self._encoder[index + 4])
                self._encoder_button[index + 4].send_value(127, True)
            if self._shift_mode._mode_index is 0:
                #self._on_shift_button_value.subject = self._grid[15]
                self._alt_shift_mode.set_mode_button('alt_shift',
                                                     self._grid[15])
                #if self._aumpush._host._is_connected:
                #	self._aumpush._host._set_bank_buttons(tuple(self._button[4:12]+self._button[20:28]))
                #for index in range(8):
                #	self._button[index+4].set_on_off_values(SELECT[self._rgb], (5, 6)[int(index>3)])
                #	self._mixer2.channel_strip(index).set_select_button(self._button[index+4])
                for index in range(4):
                    self._send_reset.set_buttons(
                        tuple(self._encoder_button[4:8]))
                    self._button[index].set_on_off_values(SELECT[self._rgb], 1)
                    self._mixer.channel_strip(index).set_select_button(
                        self._button[index])
                    self._mixer.channel_strip(index).set_mute_button(
                        self._button[index + 16])
                    self._button[index + 12].set_on_off_values(
                        SELECT[self._rgb], 1)
                    self._mixer2.channel_strip(index).set_select_button(
                        self._button[index + 12])
                    self._mixer2.channel_strip(index).set_mute_button(
                        self._button[index + 28])
                if not self._shifted:
                    self._mixer.selected_strip().set_send_controls(
                        self._encoder[8:12])
                    for index in range(4):
                        self._encoder_button[index + 8].send_value(3, True)
                else:
                    self._mixer.return_strip(0).set_send_controls(
                        tuple([None, self._encoder[8]]))
                    self._mixer.return_strip(1).set_send_controls(
                        tuple([self._encoder[9], None]))
                    #self._mixer.set_crossfader_control(self._encoder[11])
                    self._mixer3.channel_strip(0).set_volume_control(
                        self._encoder[11])
                    self._encoder_button[8].send_value(5, True)
                    self._encoder_button[9].send_value(5, True)
                    self._encoder_button[11].send_value(1, True)
            for index in range(4):
                self._mixer.channel_strip(index).set_volume_control(
                    self._fader[index])
                self._mixer2.channel_strip(index).set_volume_control(
                    self._fader[index + 4])

            self._device1.set_parameter_controls(
                tuple([self._knobs[index] for index in range(8)]))
            self._device2.set_parameter_controls(
                tuple([self._knobs[index + 12] for index in range(8)]))
            self._device1.set_enabled(True)
            self._device2.set_enabled(True)
            self._find_devices()
            self._device1.update()
            self._device2.update()
            self._device_selector.set_buttons(self._grid[:15])
            self._device_selector.set_enabled(True)
            self._device_selector.update()
            self.request_rebuild_midi_map()

    """used to connect different control_surfaces so that they can communicate"""

    def connect_script_instances(self, instanciated_scripts):
        if AUMPUSH_LINK is True:
            link = False
            for s in instanciated_scripts:
                #self.log_message('script check' + str(s))
                if link == False:
                    #self.log_message(str(type(s)))
                    if '_cntrlr_version' in dir(s):
                        if s._cntrlr_version == self._monomod_version and s._host_name == 'AumPush':
                            link = True
                            with self.component_guard():
                                self._connect_aumpush(s)
                            break
        elif MONOHM_LINK is True:
            link = False
            for s in instanciated_scripts:
                #self.log_message('script check' + str(s))
                if link == False:
                    #self.log_message(str(type(s)))
                    if '_cntrlr_version' in dir(s):
                        if s._cntrlr_version == self._monomod_version:
                            link = True
                            with self.component_guard():
                                self._connect_monohm(s)
                            break

    """device component methods and overrides"""

    def _device_set_device(self, device_component):
        def set_device(device):
            is_monodevice = False
            for client in self._client:
                if (device != None) and (client.device == device):
                    is_monodevice = client
            if is_monodevice != False:
                #device = client._device_component._device
                #self.log_message('is monodevice' + str(device.name))
                assert ((device == None)
                        or isinstance(device, Live.Device.Device))
                if ((not device_component._locked_to_device)
                        and (device != device_component._device)):
                    if (device_component._device != None):
                        device_component._device.remove_name_listener(
                            device_component._on_device_name_changed)
                        device_component._device.remove_parameters_listener(
                            device_component._on_parameters_changed)
                        parameter = device_component._on_off_parameter()
                        if (parameter != None):
                            parameter.remove_value_listener(
                                device_component._on_on_off_changed)
                        if (device_component._parameter_controls != None):
                            for control in device_component._parameter_controls:
                                control.release_parameter()
                    device_component._device = device
                    if (device_component._device != None):
                        device_component._bank_index = 0
                        device_component._device.add_name_listener(
                            self._on_device_name_changed)
                        device_component._device.add_parameters_listener(
                            self._on_parameters_changed)
                        parameter = device_component._on_off_parameter()
                        if (parameter != None):
                            parameter.add_value_listener(
                                device_component._on_on_off_changed)
                    for key in device_component._device_bank_registry.keys():
                        if (key == device_component._device):
                            device_component._bank_index = device_component._device_bank_registry.get(
                                key, 0)
                            del device_component._device_bank_registry[key]
                            break
                    device_component._bank_name = '<No Bank>'  #added
                    device_component._bank_index = max(
                        is_monodevice._cntrl_offset,
                        device_component._bank_index)
                    device_component._on_device_name_changed()
                    device_component.update()
            else:
                DeviceComponent.set_device(device_component, device)

        return set_device

    """this closure replaces the default ChannelStripComponent _on_cf_assign_changed() method without requiring us to build an override class"""
    """it allows us to change different colors to its assigned controls based on the crossfade assignment, which the default _Framework doesn't support"""

    def mixer_on_cf_assign_changed(self, channel_strip):
        def _on_cf_assign_changed():
            if (channel_strip.is_enabled()
                    and (channel_strip._crossfade_toggle != None)):
                if (channel_strip._track !=
                        None) and (channel_strip._track
                                   in (channel_strip.song().tracks +
                                       channel_strip.song().return_tracks)):
                    if channel_strip._track.mixer_device.crossfade_assign == 1:  #modified
                        channel_strip._crossfade_toggle.turn_off()
                    elif channel_strip._track.mixer_device.crossfade_assign == 0:
                        channel_strip._crossfade_toggle.send_value(1)
                    else:
                        channel_strip._crossfade_toggle.send_value(2)

        return _on_cf_assign_changed

    """a closure fix for banking when we deassign the bank buttons and still want to change bank indexes"""

    def device_is_banking_enabled(self, device):
        def _is_banking_enabled():
            return True

        return _is_banking_enabled

    """this is called by connect_script_instances() when a AumPush script is found to be installed"""

    def _connect_aumpush(self, aumpush):
        self.log_message('AumTroll connecting to AumPush...')
        self._aumpush = aumpush
        self._aumpush._cntrlr = self
        with self.component_guard():
            self.deassign_live_controls()
            self.schedule_message(3, self.assign_live_controls)
        #self._device_selector.update = self._make_device_selector_update(self._device_selector)

    """these two secondary DeviceComponents are only set up if the MONOHM_LINK flag in .Map is turned on"""

    def _setup_alt_device_control(self):
        self._device1 = DeviceComponent()
        self._device1.name = 'Device_Component1'
        self._device2 = DeviceComponent()
        self._device2.name = 'Device_Component2'

    """this method is used to find the devices the alt controls will latch to"""

    def _find_devices(self):
        if self._device1:
            if len(self.song().return_tracks) > 0:
                if len(self.song().return_tracks[0].devices) > 0:
                    #self._device.set_device(self.song().return_tracks[0].devices[0])
                    if self._device1._locked_to_device:
                        self._device1.set_lock_to_device(
                            False, self._device1._device)
                    self._device1.set_lock_to_device(
                        True,
                        self.song().return_tracks[0].devices[0])
        if self._device2:
            if len(self.song().return_tracks) > 1:
                if len(self.song().return_tracks[1].devices) > 0:
                    #self._device2.set_device(self.song().return_tracks[1].devices[0])
                    if self._device2._locked_to_device:
                        self._device2.set_lock_to_device(
                            False, self._device2._device)
                    self._device2.set_lock_to_device(
                        True,
                        self.song().return_tracks[1].devices[0])
        #self.log_message('find devices')

    """this secondary MixerComponent is only set up if the MONOHM_LINK flag in .Map is turned on"""

    def _setup_alt_mixer(self):
        is_momentary = True
        self._num_tracks = (8)  #A mixer is one-dimensional
        self._mixer2 = MixerComponent(8, 0, False, False)
        self._mixer2.name = 'Mixer_2'
        self._mixer2.set_track_offset(
            4)  #Sets start point for mixer strip (offset from left)
        for index in range(8):
            self._mixer2.channel_strip(
                index).name = 'Mixer_2_ChannelStrip_' + str(index)
            self._mixer2.channel_strip(index)._invert_mute_feedback = True
        self._mixer3 = MixerComponent(4, 4, False, False)
        self._mixer3.name = 'Mixer_3'
        self._mixer3.set_track_offset(
            8)  #Sets start point for mixer strip (offset from left)
        for index in range(4):
            self._mixer3.channel_strip(
                index).name = 'Mixer_3_ChannelStrip_' + str(index)
            self._mixer3.channel_strip(index)._invert_mute_feedback = True

    @subject_slot('value')
    def _on_shift_button_value(self, value):
        shifted = value > 0
        if not self._shifted is shifted:
            self._shifted = shifted
            self.deassign_live_controls()
            self.assign_live_controls()
            if self._shifted and self._on_shift_button_value.subject:
                self._on_shift_button_value.subject.send_value(12, True)


#	a
Ejemplo n.º 23
0
class Roland_A_PRO(ControlSurface):

    def __init__(self, *a, **k):
        super(Roland_A_PRO, self).__init__(*a, **k)
        with self.component_guard():
            self._create_controls()
            self._create_transport()
            self._create_mixer()
            self._create_device()
            self._create_drums()
            self._create_modes()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[ EncoderElement(MIDI_CC_TYPE, 0, identifier, Live.MidiMap.MapMode.absolute, name='Encoder_%d' % index) for index, identifier in enumerate(ENCODER_IDS) ]])
        self._master_encoder = EncoderElement(MIDI_CC_TYPE, 0, 10, Live.MidiMap.MapMode.absolute, name='Master_Encoder')
        self._sliders = ButtonMatrixElement(rows=[[ SliderElement(MIDI_CC_TYPE, 0, identifier, name='Slider_%d' % index) for index, identifier in enumerate(SLIDER_IDS) ]])
        self._master_slider = SliderElement(MIDI_CC_TYPE, 0, 7, name='Master_Slider')
        self._play_button = ButtonElement(True, MIDI_CC_TYPE, 0, 26)
        self._stop_button = ButtonElement(True, MIDI_CC_TYPE, 0, 25)
        self._record_button = ButtonElement(True, MIDI_CC_TYPE, 0, 28)
        self._forward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 24)
        self._backward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 21)
        self._ff_button = ButtonElement(True, MIDI_CC_TYPE, 0, 23)
        self._rw_button = ButtonElement(True, MIDI_CC_TYPE, 0, 22)
        self._device_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 80)
        self._pan_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 81)
        self._send_a_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 82)
        self._send_b_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 83)
        self._pads = ButtonMatrixElement(rows=[ [ ButtonElement(True, MIDI_NOTE_TYPE, 0, identifier) for identifier in row ] for row in PAD_ROWS ])

    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))
        self._transport.set_enabled(True)

    def _create_mixer(self):
        mixer_size = self._sliders.width()
        self._mixer = MixerComponent(mixer_size, name='Mixer', is_enabled=False, layer=Layer(volume_controls=self._sliders, prehear_volume_control=self._master_encoder))
        self._mixer.master_strip().layer = Layer(volume_control=self._master_slider)
        self._mixer.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(device_selection_follows_track_selection=True)
        self._device_navigation = DeviceNavigationComponent()
        self._device.set_enabled(True)
        self._device_navigation.set_enabled(True)
        self.set_device_component(self._device)

    def _create_drums(self):
        self._drums = DrumRackComponent(name='Drum_Rack', is_enabled=False, layer=Layer(pads=self._pads))
        self._drums.set_enabled(True)

    def _create_modes(self):
        self._encoder_modes = ModesComponent()
        device_layer_mode = LayerMode(self._device, Layer(parameter_controls=self._encoders))
        device_navigation_layer_mode = LayerMode(self._device_navigation, Layer(device_nav_right_button=self._forward_button, device_nav_left_button=self._backward_button))
        self._encoder_modes.add_mode('device_mode', [device_layer_mode, device_navigation_layer_mode])
        self._encoder_modes.add_mode('pan_mode', AddLayerMode(self._mixer, Layer(pan_controls=self._encoders, bank_up_button=self._forward_button, bank_down_button=self._backward_button, track_up_button=self._ff_button, track_down_button=self._rw_button)))
        send_layer_mode = AddLayerMode(self._mixer, Layer(send_controls=self._encoders, bank_up_button=self._forward_button, bank_down_button=self._backward_button, track_up_button=self._ff_button, track_down_button=self._rw_button))
        self._encoder_modes.add_mode('send_a_mode', [send_layer_mode, partial(self._set_send_index, 0)])
        self._encoder_modes.add_mode('send_b_mode', [send_layer_mode, partial(self._set_send_index, 1)])
        self._encoder_modes.layer = Layer(device_mode_button=self._device_mode_button, pan_mode_button=self._pan_mode_button, send_a_mode_button=self._send_a_mode_button, send_b_mode_button=self._send_b_mode_button)
        self._encoder_modes.selected_mode = 'device_mode'
        self._encoder_modes.set_enabled(True)

    def _set_send_index(self, index):
        self._mixer.send_index = index
Ejemplo n.º 24
0
class APC40_MkII(APC, OptimizedControlSurface):
    def __init__(self, *a, **k):

        #pydevd.settrace('localhost', port=55983, stdoutToServer=True, stderrToServer=True)

        super(APC40_MkII, self).__init__(*a, **k)
        self._color_skin = make_rgb_skin()
        self._default_skin = make_default_skin()
        self._stop_button_skin = make_stop_button_skin()
        self._crossfade_button_skin = make_crossfade_button_skin()
        self._double_press_context = DoublePressContext()
        self._shift_button = None

        with self.component_guard():
            self._create_controls()
            self._create_bank_toggle()
            self._create_mixer()
            self._create_transport()
            self._create_view_control()
            self._create_quantization_selection()
            self._create_recording()

            self._skin = make_custom_skin()

            self._clip_creator = ClipCreator()

            self._init_background()
            self._init_instrument()
            self._init_step_sequencer()
            self._init_drum_component()
            self._init_note_repeat()
            self._create_session()
            self._session.set_mixer(self._mixer)

            self._init_matrix_modes()
            self._create_device()

            self.set_feedback_channels(FEEDBACK_CHANNELS)

        self.set_highlighting_session_component(self._session)
        self.set_device_component(self._device)

    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)

        def make_color_button(*a, **k):
            button = make_button(skin=self._color_skin, *a, **k)
            button.is_rgb = True
            button.num_delayed_messages = 2
            return button

        def make_matrix_button(track, scene):
            return make_color_button(0,
                                     32 + track - NUM_TRACKS * scene,
                                     name='%d_Clip_%d_Button' % (track, scene))

        def make_stop_button(track, prior=False):
            butt = make_button(track,
                               52,
                               name='%d_Stop_Button' % track,
                               skin=self._stop_button_skin)

            if prior:
                butt.resource_type = PrioritizedResource

            return butt

        self._shift_button = make_button(0,
                                         98,
                                         name='Shift_Button',
                                         resource_type=PrioritizedResource)
        self._bank_button = make_on_off_button(0, 103, name='Bank_Button')
        self._left_button = make_button(0, 97, name='Bank_Select_Left_Button')
        self._right_button = make_button(0,
                                         96,
                                         name='Bank_Select_Right_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._stop_buttons_raw = [
            make_stop_button(track) for track in xrange(NUM_TRACKS)
        ]
        self._stop_buttons = ButtonMatrixElement(rows=[self._stop_buttons_raw])

        self._shifted_stop_buttons = ButtonMatrixElement(rows=[[
            self._with_shift(button) for button in self._stop_buttons_raw
        ]])

        self._stop_all_button = make_button(0,
                                            81,
                                            name='Stop_All_Clips_Button')
        self._scene_launch_buttons_raw = [
            make_color_button(0,
                              scene + 82,
                              name='Scene_%d_Launch_Button' % scene)
            for scene in xrange(NUM_SCENES)
        ]
        self._scene_launch_buttons = ButtonMatrixElement(
            rows=[self._scene_launch_buttons_raw])
        self._matrix_rows_raw = [[
            make_matrix_button(track, scene) for track in xrange(NUM_TRACKS)
        ] for scene in xrange(NUM_SCENES)]
        self._session_matrix = ButtonMatrixElement(rows=self._matrix_rows_raw)
        self._pan_button = make_on_off_button(
            0, 87, name='Pan_Button', resource_type=PrioritizedResource)
        self._sends_button = make_on_off_button(
            0, 88, name='Sends_Button', resource_type=PrioritizedResource)
        self._user_button = make_on_off_button(
            0, 89, name='User_Button', resource_type=PrioritizedResource)
        self._mixer_encoders = ButtonMatrixElement(rows=[[
            make_ring_encoder(
                48 + track, 56 + track, name='Track_Control_%d' % track)
            for track in xrange(NUM_TRACKS)
        ]])
        self._volume_controls = ButtonMatrixElement(rows=[[
            make_slider(track, 7, name='%d_Volume_Control' % track)
            for track in xrange(NUM_TRACKS)
        ]])
        self._master_volume_control = make_slider(0,
                                                  14,
                                                  name='Master_Volume_Control')
        self._prehear_control = make_encoder(0,
                                             47,
                                             name='Prehear_Volume_Control')
        self._crossfader_control = make_slider(0, 15, name='Crossfader')
        self._raw_select_buttons = [
            make_on_off_button(channel, 51, name='%d_Select_Button' % channel)
            for channel in xrange(NUM_TRACKS)
        ]
        self._arm_buttons = ButtonMatrixElement(rows=[[
            make_on_off_button(channel, 48, name='%d_Arm_Button' % channel)
            for channel in xrange(NUM_TRACKS)
        ]])
        self._solo_buttons = ButtonMatrixElement(rows=[[
            make_on_off_button(channel, 49, name='%d_Solo_Button' % channel)
            for channel in xrange(NUM_TRACKS)
        ]])
        self._mute_buttons = ButtonMatrixElement(rows=[[
            make_on_off_button(channel, 50, name='%d_Mute_Button' % channel)
            for channel in xrange(NUM_TRACKS)
        ]])
        self._crossfade_buttons = ButtonMatrixElement(rows=[[
            make_button(channel,
                        66,
                        name='%d_Crossfade_Button' % channel,
                        skin=self._crossfade_button_skin)
            for channel in xrange(NUM_TRACKS)
        ]])
        self._select_buttons = ButtonMatrixElement(
            rows=[self._raw_select_buttons])
        self._master_select_button = make_on_off_button(
            channel=0, identifier=80, name='Master_Select_Button')
        self._send_select_buttons = ButtonMatrixElement(rows=[[
            ComboElement(button, modifiers=[self._sends_button])
            for button in self._raw_select_buttons
        ]])
        self._quantization_buttons = ButtonMatrixElement(rows=[[
            ComboElement(button, modifiers=[self._shift_button])
            for button in self._raw_select_buttons
        ]])
        self._metronome_button = make_on_off_button(0,
                                                    90,
                                                    name='Metronome_Button')
        self._play_button = make_on_off_button(0, 91, name='Play_Button')
        self._record_button = make_on_off_button(0, 93, name='Record_Button')
        self._session_record_button = make_on_off_button(
            0, 102, name='Session_Record_Button')
        self._nudge_down_button = make_button(0, 100, name='Nudge_Down_Button')
        self._nudge_up_button = make_button(0, 101, name='Nudge_Up_Button')
        self._tap_tempo_button = make_button(0, 99, name='Tap_Tempo_Button')
        self._tempo_control = make_encoder(0, 13, name='Tempo_Control')
        self._device_controls = ButtonMatrixElement(rows=[[
            make_ring_encoder(16 + index,
                              24 + index,
                              handler=self.value_changed,
                              name='Device_Control_%d' % index)
            for index in xrange(8)
        ]])

        self._device_control_buttons_raw = [
            make_on_off_button(0, 58 + index) for index in xrange(8)
        ]
        self._device_bank_buttons = ButtonMatrixElement(rows=[[
            DeviceBankButtonElement(button, modifiers=[self._shift_button])
            for button in self._device_control_buttons_raw
        ]])
        self._device_prev_bank_button = self._device_control_buttons_raw[2]
        self._device_prev_bank_button.name = 'Device_Prev_Bank_Button'
        self._device_next_bank_button = self._device_control_buttons_raw[3]
        self._device_next_bank_button.name = 'Device_Next_Bank_Button'
        self._device_on_off_button = self._device_control_buttons_raw[4]
        self._device_on_off_button.name = 'Device_On_Off_Button'
        self._device_lock_button = self._device_control_buttons_raw[5]
        self._device_lock_button.name = 'Device_Lock_Button'
        self._prev_device_button = self._device_control_buttons_raw[0]
        self._prev_device_button.name = 'Prev_Device_Button'
        self._next_device_button = self._device_control_buttons_raw[1]
        self._next_device_button.name = 'Next_Device_Button'
        self._clip_device_button = self._device_control_buttons_raw[6]
        self._clip_device_button.name = 'Clip_Device_Button'
        self._detail_view_button = self._device_control_buttons_raw[7]
        self._detail_view_button.name = 'Detail_View_Button'
        self._foot_pedal_button = DoublePressElement(
            make_pedal_button(64, name='Foot_Pedal'))
        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
        ]])

        self._grid_resolution = GridResolution()
        self._velocity_slider = ButtonSliderElement(
            tuple(self._scene_launch_buttons_raw[::-1]))
        #self._velocity_slider.resource_type = PrioritizedResource
        double_press_rows = recursive_map(DoublePressElement,
                                          self._matrix_rows_raw)
        self._double_press_matrix = ButtonMatrixElement(
            name='Double_Press_Matrix', rows=double_press_rows)
        self._double_press_event_matrix = ButtonMatrixElement(
            name='Double_Press_Event_Matrix',
            rows=recursive_map(lambda x: x.double_press, double_press_rows))
        self._playhead = PlayheadElement(self._c_instance.playhead)

    def _create_bank_toggle(self):
        self._bank_toggle = BankToggleComponent(
            is_enabled=False,
            layer=Layer(bank_toggle_button=self._bank_button))

    def _create_session(self):
        def when_bank_on(button):
            return self._bank_toggle.create_toggle_element(on_control=button)

        def when_bank_off(button):
            return self._bank_toggle.create_toggle_element(off_control=button)

        self._session = CustomSessionComponent(
            NUM_TRACKS,
            NUM_SCENES,
            auto_name=True,
            is_enabled=False,
            enable_skinning=True,
            layer=Layer(
                track_bank_left_button=when_bank_off(self._left_button),
                track_bank_right_button=when_bank_off(self._right_button),
                scene_bank_up_button=when_bank_off(self._up_button),
                scene_bank_down_button=when_bank_off(self._down_button),
                page_left_button=when_bank_on(self._left_button),
                page_right_button=when_bank_on(self._right_button),
                page_up_button=when_bank_on(self._up_button),
                page_down_button=when_bank_on(self._down_button),
                stop_track_clip_buttons=self._stop_buttons,
                stop_all_clips_button=self._stop_all_button,
                scene_launch_buttons=self._scene_launch_buttons,
                clip_launch_buttons=self._session_matrix))

        clip_color_table = Colors.LIVE_COLORS_TO_MIDI_VALUES.copy()
        clip_color_table[16777215] = 119
        self._session.set_rgb_mode(clip_color_table, Colors.RGB_COLOR_TABLE)
        self._session_zoom = SessionZoomingComponent(
            self._session,
            name='Session_Overview',
            enable_skinning=True,
            is_enabled=False,
            layer=Layer(button_matrix=self._shifted_matrix,
                        nav_left_button=self._with_shift(self._left_button),
                        nav_right_button=self._with_shift(self._right_button),
                        nav_up_button=self._with_shift(self._up_button),
                        nav_down_button=self._with_shift(self._down_button),
                        scene_bank_buttons=self._shifted_scene_buttons))
        self._session.set_delete_button(self._nudge_down_button)
        self._session.set_copy_button(self._nudge_up_button)

    def _create_mixer(self):
        self._mixer = MixerComponent(
            NUM_TRACKS,
            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,
                        shift_button=self._shift_button,
                        track_select_buttons=self._select_buttons,
                        prehear_volume_control=self._with_shift(
                            self._prehear_control),
                        crossfader_control=self._crossfader_control,
                        crossfade_buttons=self._crossfade_buttons))
        self._mixer.master_strip().layer = Layer(
            volume_control=self._master_volume_control,
            select_button=self._master_select_button)
        self._encoder_mode = ModesComponent(name='Encoder_Mode',
                                            is_enabled=False)
        self._encoder_mode.default_behaviour = ImmediateBehaviour()
        self._encoder_mode.add_mode('pan', [
            AddLayerMode(self._mixer, Layer(pan_controls=self._mixer_encoders))
        ])
        self._encoder_mode.add_mode('sends', [
            AddLayerMode(self._mixer,
                         Layer(send_controls=self._mixer_encoders)),
            DelayMode(
                AddLayerMode(
                    self._mixer,
                    Layer(send_select_buttons=self._send_select_buttons)))
        ])
        self._encoder_mode.add_mode('user', [
            AddLayerMode(self._mixer,
                         Layer(user_controls=self._mixer_encoders))
        ])
        self._encoder_mode.layer = Layer(pan_button=self._pan_button,
                                         sends_button=self._sends_button,
                                         user_button=self._user_button)
        self._encoder_mode.selected_mode = 'pan'

    def _create_transport(self):
        self._transport = TransportComponent(
            name='Transport',
            is_enabled=False,
            layer=Layer(
                shift_button=self._shift_button,
                play_button=self._play_button,
                stop_button=ComboElement(self._play_button,
                                         modifiers=[self._shift_button]),
                record_button=self._record_button,
                metronome_button=self._with_shift(self._tap_tempo_button),
                tap_tempo_button=self._tap_tempo_button,
                nudge_down_button=self._with_shift(self._nudge_down_button),
                nudge_up_button=self._with_shift(self._nudge_up_button),
                tempo_encoder=self._tempo_control),
            play_toggle_model_transform=lambda v: v)

    def _create_device(self):
        self._device = DeviceComponent(
            name=u'Device',
            is_enabled=False,
            layer=Layer(parameter_controls=self._device_controls,
                        bank_buttons=self._device_bank_buttons,
                        bank_prev_button=self._device_prev_bank_button,
                        bank_next_button=self._device_next_bank_button,
                        on_off_button=self._device_on_off_button,
                        lock_button=self._device_lock_button),
            device_selection_follows_track_selection=True)

    def _create_view_control(self):
        self._view_control = DetailViewCntrlComponent(
            name='View_Control',
            is_enabled=False,
            layer=Layer(device_nav_left_button=self._prev_device_button,
                        device_nav_right_button=self._next_device_button,
                        device_clip_toggle_button=self._clip_device_button,
                        detail_toggle_button=self._detail_view_button))
        self._view_control.device_clip_toggle_button.pressed_color = 'DefaultButton.On'

    def _create_quantization_selection(self):
        self._quantization_selection = QuantizationComponent(
            name='Quantization_Selection',
            is_enabled=False,
            layer=Layer(quantization_buttons=self._quantization_buttons))

    def _create_recording(self):
        record_button = MultiElement(self._session_record_button,
                                     self._foot_pedal_button.single_press)
        self._session_recording = SessionRecordingComponent(
            ClipCreator(),
            self._view_control,
            name='Session_Recording',
            is_enabled=False,
            layer=Layer(new_button=self._foot_pedal_button.double_press,
                        record_button=record_button,
                        _uses_foot_pedal=self._foot_pedal_button))

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

    def _product_model_id_byte(self):
        return 41

    def _init_background(self):
        self._background = BackgroundComponent(is_root=True)
        self._background.set_enabled(False)
        self._background.layer = Layer(
            stop_buttons=self._stop_buttons
        )  # , display_line2=self._display_line2, display_line3=self._display_line3, display_line4=self._display_line4, top_buttons=self._select_buttons, bottom_buttons=self._track_state_buttons, scales_button=self._scale_presets_button, octave_up=self._octave_up_button, octave_down=self._octave_down_button, side_buttons=self._side_buttons, repeat_button=self._repeat_button, accent_button=self._accent_button, double_button=self._double_button, in_button=self._in_button, out_button=self._out_button, param_controls=self._global_param_controls, param_touch=self._global_param_touch_buttons, tempo_control_tap=self._tempo_control_tap, master_control_tap=self._master_volume_control_tap, touch_strip=self._touch_strip_control, touch_strip_tap=self._touch_strip_tap, nav_up_button=self._nav_up_button, nav_down_button=self._nav_down_button, nav_left_button=self._nav_left_button, nav_right_button=self._nav_right_button, aftertouch=self._aftertouch_control, pad_parameters=self._pad_parameter_control, _notification=self._notification.use_single_line(2), priority=consts.BACKGROUND_PRIORITY)

        self._matrix_background = BackgroundComponent()
        self._matrix_background.set_enabled(False)
        self._matrix_background.layer = Layer(matrix=self._session_matrix)

        self._mod_background = ModifierBackgroundComponent(is_root=True)
        self._mod_background.layer = Layer(shift_button=self._shift_button)

    def _init_step_sequencer(self):
        self._step_sequencer = StepSeqComponent(
            grid_resolution=self._grid_resolution)
        self._step_sequencer.layer = self._create_step_sequencer_layer()

    def _create_step_sequencer_layer(self):
        return Layer(
            velocity_slider=self._velocity_slider,
            drum_matrix=self._session_matrix.submatrix[:4, 0:5],
            # [4, 1:5],  mess with this for possible future 32 pad drum rack :
            button_matrix=self._double_press_matrix.submatrix[
                4:8, 0:4],  # [4:8, 1:5],

            #  next_page_button = self._bank_button,

            #select_button=self._user_button,
            delete_button=self._stop_all_button,
            playhead=self._playhead,
            quantization_buttons=self._stop_buttons,
            shift_button=self._shift_button,
            loop_selector_matrix=self._double_press_matrix.submatrix[4:8, 4],
            # changed from [:8, :1] so as to enable bottem row of rack   . second value clip length rows
            short_loop_selector_matrix=self._double_press_event_matrix.
            submatrix[4:8, 4],
            # changed from [:8, :1] no change noticed as of yet
            drum_bank_up_button=self._up_button,
            drum_bank_down_button=self._down_button)

    #       capture_button = self._tap_tempo_button)

    def _init_drum_component(self):
        self._drum_component = DrumGroupComponent(name='Drum_Group',
                                                  is_enabled=False)
        self._drum_component.layer = Layer(
            drum_matrix=self._session_matrix,
            #    page_strip=self._touch_strip_control,
            #    scroll_strip=self._with_shift(self._touch_strip_control),
            #    solo_button=self._global_solo_button,
            #select_button=self._metronome_button,
            #    delete_button=self._delete_button,
            scroll_page_up_button=self._up_button,
            scroll_page_down_button=self._down_button,
            #    quantize_button=self._quantize_button,
            #    mute_button=self._global_mute_button,
            scroll_up_button=self._with_shift(self._up_button),
            scroll_down_button=self._with_shift(self._down_button))

    #    self._drum_component.select_drum_pad = self._selector.on_select_drum_pad
    #    self._drum_component.quantize_pitch = self._quantize.quantize_pitch

    def _init_instrument(self):
        instrument_basic_layer = Layer(
            # octave_strip=self._with_shift(self._touch_strip_control),
            #   capture_button = self._tap_tempo_button,
            #scales_toggle_button=self._metronome_button,
            octave_up_button=self._up_button,
            octave_down_button=self._down_button,
            scale_up_button=self._with_shift(self._up_button),
            scale_down_button=self._with_shift(self._down_button))

        self._instrument = MelodicComponent(
            skin=self._skin,
            is_enabled=False,
            clip_creator=self._clip_creator,
            name='Melodic_Component',
            grid_resolution=self._grid_resolution,
            note_editor_settings=self._add_note_editor_setting(),
            layer=self._create_instrument_layer(),
            instrument_play_layer=Layer(
                octave_up_button=self._up_button,
                octave_down_button=self._down_button,
                scale_up_button=self._with_shift(self._up_button),
                scale_down_button=self._with_shift(self._down_button),
                matrix=self._session_matrix),
            # touch_strip=self._touch_strip_control, touch_strip_indication=self._with_firmware_version(1, 16, ComboElement(self._touch_strip_control, modifiers=[self._select_button])),
            # touch_strip_toggle=self._with_firmware_version(1, 16, ComboElement(self._touch_strip_tap, modifiers=[self._select_button])),
            # aftertouch_control=self._aftertouch_control, delete_button=self._delete_button),
            instrument_sequence_layer=
            instrument_basic_layer  # + Layer(note_strip=self._touch_strip_control)
        )
        self._on_note_editor_layout_changed.subject = self._instrument

    def _create_instrument_layer(self):
        return Layer(
            playhead=self._playhead,
            velocity_slider=self._velocity_slider,
            # mute_button=self._global_mute_button,
            quantization_buttons=self._stop_buttons,
            loop_selector_matrix=self._double_press_matrix.submatrix[
                0:8, 0],  # [:, 0]
            short_loop_selector_matrix=self._double_press_event_matrix.
            submatrix[0:8, 0],  # [:, 0]
            #note_editor_matrices=ButtonMatrixElement(
            #    [[self._session_matrix.submatrix[:, 4 - row] for row in xrange(7)]]))
            note_editor_matrices=ButtonMatrixElement([[
                self._session_matrix.submatrix[:8, 4 - row]
                for row in xrange(4)
            ]]))

    def enter_note_mode_layout(self):
        self._matrix_modes.selected_mode = 'user'
        self._select_note_mode()

        #if self._user_modes.selected_mode == 'instrument':
        #    self._instrument._set_selected_mode(self._instrument.selected_mode)
        #el
        if self._user_modes.selected_mode == 'drums':
            self._drum_modes._set_selected_mode(self._drum_modes.selected_mode)

        self.reset_controlled_track()

    def exit_note_mode_layout(self):
        self.reset_controlled_track()

    def switch_note_mode_layout(self):
        self._matrix_modes.selected_mode = 'user'
        self._select_note_mode()

        #if self._user_modes.selected_mode == 'instrument':
        #   getattr(self._instrument, 'cycle_mode', nop)()
        #el
        if self._user_modes.selected_mode == 'drums':
            getattr(self._drum_modes, 'cycle_mode', nop)()

        self.reset_controlled_track()

    def _init_matrix_modes(self):
        """ Switch between Session and StepSequencer modes """
        """here we go trying to switch.... lew  05:53   21/10/17"""

        self._auto_arm = AutoArmComponent(name='Auto_Arm')

        self._matrix_modes = ModesComponent(name='Matrix_Modes', is_root=True)
        self._matrix_modes.default_behaviour = ImmediateBehaviour()
        self._matrix_modes.add_mode(
            'disable',
            [self._matrix_background, self._background, self._mod_background])
        self._matrix_modes.add_mode('sends', self._session_mode_layers())

        self._matrix_modes.add_mode('user', self._user_mode_layers())
        self._matrix_modes.add_mode('user2', self._user2_mode_layers())

        self._matrix_modes.add_mode('session', self._session_mode_layers())

        #self._matrix_modes.add_mode('user', [self._user_modes], behaviour=CustomReenterBehaviour(on_reenter=self.switch_note_mode_layout, on_enter=self.enter_note_mode_layout))

        #self._matrix_modes.add_mode('user', [self._drum_group_finder, self._view_control, self._user_modes],
        #                           behaviour=self._auto_arm.auto_arm_restore_behaviour(ReenterBehaviour,
        #                                                                               on_reenter=self.switch_note_mode_layout))

        self._matrix_modes.layer = Layer(session_button=self._pan_button,
                                         sends_button=self._sends_button,
                                         user_button=self._user_button,
                                         user2_button=self._metronome_button)

        self._on_matrix_mode_changed.subject = self._matrix_modes
        self._matrix_modes.selected_mode = 'session'

        #self._disable_mode = ModesComponent(name='Disable_Mode', is_enabled=False)
        #self._disable_mode.add_mode('disable', [self._matrix_background, self._background])

    def _session_mode_layers(self):
        return [self._session, self._view_control,
                self._session_zoom]  #, self._mixer

    def _user_mode_layers(self):
        self._drum_group_finder = DrumGroupFinderComponent()
        self._on_drum_group_changed.subject = self._drum_group_finder

        self._drum_modes = ModesComponent(name='Drum_Modes', is_enabled=False)
        self._drum_modes.add_mode('sequencer', self._step_sequencer)
        #self._drum_modes.add_mode('64pads', self._drum_component)  # added 15:18 subday 22/10/17     can maybe look into this. causes issues when trying to scroll.(drumcomp1)

        self._drum_modes.selected_mode = 'sequencer'

        #self._user_modes = ModesComponent(name='User_Modes', is_enabled=False)
        #self._user_modes.add_mode('drums', [self._drum_modes])
        #self._user_modes.add_mode('instrument', [self._note_repeat_enabler, self._instrument])
        #self._user_modes.selected_mode = 'drums'

        return [self._drum_modes, self._view_control,
                self._matrix_background]  # , self._mixer

    def _user2_mode_layers(self):

        self._user_modes = ModesComponent(name='Instrument_Modes',
                                          is_enabled=False)
        #self._user_modes.add_mode('drums', [self._drum_modes])
        self._user_modes.add_mode(
            'instrument', [self._note_repeat_enabler, self._instrument])
        self._user_modes.selected_mode = 'instrument'

        return [self._user_modes, self._view_control,
                self._matrix_background]  # , self._mixer

    def _init_note_repeat(self):
        self._note_repeat = NoteRepeatComponent(name='Note_Repeat')
        self._note_repeat.set_enabled(False)
        self._note_repeat.set_note_repeat(self._c_instance.note_repeat)
        self._note_repeat.layer = Layer(
            # aftertouch_control=self._aftertouch_control,
            select_buttons=self._shifted_stop_buttons
            # pad_parameters=self._pad_parameter_control
        )
        self._note_repeat.layer.priority = consts.DIALOG_PRIORITY
        self._note_repeat_enabler = EnablingModesComponent(
            name='Note_Repeat_Enabler',
            component=self._note_repeat,
            toggle_value='DefaultButton.Alert',
            disabled_value='DefaultButton.On')
        self._note_repeat_enabler.set_enabled(False)
        self._note_repeat_enabler.layer = Layer(
            toggle_button=self._with_shift(self._bank_button))

    def _select_note_mode(self):
        """
        Selects which note mode to use depending on the kind of
        current selected track and its device chain...
        """
        track = self.song().view.selected_track
        drum_device = self._drum_group_finder.drum_group
        self._step_sequencer.set_drum_group_device(drum_device)
        self._drum_component.set_drum_group_device(drum_device)
        if track == None or track.is_foldable or track in self.song(
        ).return_tracks or track == self.song(
        ).master_track or track.is_frozen:
            self._user_modes.selected_mode = 'disabled'
        elif track and track.has_audio_input:
            self._user_modes.selected_mode = 'disabled'
            #self._note_modes.selected_mode = 'looper'
        elif drum_device:
            self._user_modes.selected_mode = 'drums'
        #else:
        #    self._user_modes.selected_mode = 'instrument'
        #self.reset_controlled_track()

    @subject_slot('value')
    def value_changed(self, value):
        print('value_changed')
        print(value)
        '''if self.is_enabled() and not self._device_mode:
            if value > 0 or not self._bank_down_button.is_momentary():
                new_mode = max(self._mode_index - 1, 0)
                self.set_mode(new_mode)'''

    @subject_slot('drum_group')
    def _on_drum_group_changed(self):
        #self._shift_button.receive_value(127)
        #self.schedule_message(1, self.resetshift)
        self._matrix_background.set_enabled(True)
        self.schedule_message(1, self.disablebackground)

        if self._matrix_modes.selected_mode != 'session':
            pass
            #self._select_note_mode()

    def resetshift(self):
        self._shift_button.receive_value(0)

    def shiftmodedisable(self):
        self._matrix_modes.selected_mode = 'disabled'

    def disablebackground(self):
        self._matrix_background.set_enabled(False)

    @subject_slot('selected_mode')
    def _on_matrix_mode_changed(self, mode):
        #self._shift_button.receive_value(127)
        #self.schedule_message(1, self.resetshift)
        self._matrix_background.set_enabled(True)
        self.schedule_message(1, self.disablebackground)

        if self._matrix_modes.selected_mode != 'disabled':
            self._update_auto_arm(selected_mode=mode)
            self.reset_controlled_track()
        '''

        #if self._matrix_modes.selected_mode != mode and mode != 'session':
        #    self._select_note_mode()
        if mode == None:
            return

        if mode != 'disabled' and self.holdMode != mode:

            if mode != 'disabled':
                self.holdMode = mode
                self.schedule_message(3, self.shiftmode)

            else:
                self.holdMode = None

            #if self._matrix_modes.selected_mode != mode and self._matrix_modes.selected_mode == 'user':
            #    self._step_sequencer.set_enabled(False)

            #if self._matrix_modes.selected_mode != mode and mode == 'session':
            #    self._session.set_enabled(True)

                #self._disable_mode.selected_mode = 'disable'
                #self._session.set_enabled(True)

            if self._matrix_modes.selected_mode != 'disabled':
                self._update_auto_arm(selected_mode=mode)
                self.reset_controlled_track()

        else:
            if self._matrix_modes.selected_mode != self.holdMode:
                self.schedule_message(1, self.shiftmodehold)
            else:
                if self._matrix_modes.selected_mode != 'disabled':
                    self._update_auto_arm(selected_mode=mode)
                    self.reset_controlled_track()'''

    def _update_auto_arm(self, selected_mode=None):
        self._auto_arm.set_enabled(
            selected_mode or self._matrix_modes.selected_mode == 'user')

    @subject_slot('selected_mode')
    def _on_note_editor_layout_changed(self, mode):
        pass
        #self.reset_controlled_track(mode)

    def reset_controlled_track(self, mode=None):
        #if mode == None:
        #   mode = self._instrument.selected_mode
        #if self._instrument and self._instrument.is_enabled() and mode == 'sequence':
        #    self.release_controlled_track()
        #else:
        self.set_controlled_track(self.song().view.selected_track)

    def _add_note_editor_setting(self):
        return NoteEditorSettingsComponent(
            self._grid_resolution,
            Layer(initial_encoders=self._mixer_encoders),
            Layer(encoders=self._mixer_encoders))

    @contextmanager
    def component_guard(self):
        """ Customized to inject additional things """
        with super(APC40_MkII, self).component_guard():

            with self.make_injector().everywhere():
                yield

    def make_injector(self):
        """ Adds some additional stuff to the injector, used in BaseMessenger """
        return inject(double_press_context=const(self._double_press_context),
                      control_surface=const(self),
                      log_message=const(self.log_message))
Ejemplo n.º 25
0
class InstrumentComponent(ControlSurfaceComponent):
    """
	handles notes mode and switches between note, drum and dummy audio mode.
	"""
    def __init__(self, control_surface, drum_component=None, *a, **k):

        self._control_surface = control_surface
        self._drum_component = drum_component
        self._implicit_arm = True
        self._modes = ModesComponent(name='Instrument_Modes', is_enabled=False)
        self._modes.set_enabled = self.set_enabled
        self._feedback_channels = [
            consts.DR_MAP_CHANNEL, consts.DR_MAP_CHANNEL + 1,
            consts.DR_MAP_CHANNEL + 2, consts.DR_MAP_CHANNEL + 3,
            consts.DR_MAP_CHANNEL + 4
        ]
        self._non_feedback_channel = consts.DR_MAP_CHANNEL + 5

        self._common_component = CommonModeComponent(
            instrument_component=self, control_surface=self._control_surface)
        self._scale_component = ScaleComponent(
            control_surface=self._control_surface, enabled=True)
        self._note_component = NoteComponent(
            control_surface=self._control_surface,
            feedback_channels=self._feedback_channels,
            non_feedback_channel=self._non_feedback_channel,
            get_pattern=self._scale_component.get_pattern)

        super(InstrumentComponent, self).__init__(*a, **k)

    def set_layers(self, midimap):
        common_layer_mode = LayerMode(
            self._common_component,
            layer=Layer(
                arrow_left_button=midimap['Arrow_Left_Button'],
                arrow_right_button=midimap['Arrow_Right_Button'],
                arrow_up_button=midimap['Arrow_Up_Button'],
                arrow_down_button=midimap['Arrow_Down_Button'],
                scale_button=midimap['Scene_Launch_Button_Matrix_Raw'][0][0],
                scale_up_button=midimap['Scene_Launch_Button_Matrix_Raw'][0]
                [1],
                scale_down_button=midimap['Scene_Launch_Button_Matrix_Raw'][0]
                [2],
                dummy_button=midimap['Scene_Launch_Button_Matrix_Raw'][0][3],
                play_button=midimap['Scene_Launch_Button_Matrix_Raw'][0][6],
                stop_button=midimap['Scene_Launch_Button_Matrix_Raw'][0][7]))

        drum_group_layer_mode = LayerMode(
            self._control_surface._drum_group,
            layer=Layer(
                #scroll_up_button = midimap['Scene_Launch_Button_Matrix_Raw'][0][1],
                #scroll_down_button = midimap['Scene_Launch_Button_Matrix_Raw'][0][2],
                mute_button=midimap['Scene_Launch_Button_Matrix_Raw'][0][4],
                solo_button=midimap['Scene_Launch_Button_Matrix_Raw'][0][5],
                #scroll_up_button=midimap['Arrow_Left_Button'],
                #scroll_down_button=midimap['Arrow_Right_Button'],
                #scroll_page_up_button=midimap['Arrow_Up_Button'],
                #scroll_page_down_button=midimap['Arrow_Down_Button'],
                #drum_matrix = midimap['Drum_Button_Matrix']#,
                drum_matrix=midimap['Main_Button_Matrix']
                #select_button = midimap['Shift_Button'],
                #delete_button = midimap['Delete_Button']
            ))

        self._modes.add_mode(
            'drum_mode',
            [
                partial(self._control_surface._layout_setup,
                        consts.SESSION_LAYOUT_SYSEX_BYTE),
                partial(self._control_surface._layout_setup,
                        consts.USER_LAYOUT_SYSEX_BYTE,
                        consts.SYSEX_PARAM_BYTE_STANDALONE_LAYOUT),
                #partial(self._control_surface._layout_setup, consts.DRUM_LAYOUT_SYSEX_BYTE),
                self._control_surface._setup_drum_group(),
                drum_group_layer_mode,
                common_layer_mode  #,
                #drum_mode_note_matrix_translation
            ])

        scale_layer_mode = LayerMode(
            self._scale_component,
            layer=Layer(matrix=midimap['Main_Button_Matrix']))
        self._modes.add_mode(
            'scale_mode',
            [
                partial(self._control_surface._layout_setup,
                        consts.SESSION_LAYOUT_SYSEX_BYTE),
                partial(self._control_surface._layout_setup,
                        consts.USER_LAYOUT_SYSEX_BYTE,
                        consts.SYSEX_PARAM_BYTE_STANDALONE_LAYOUT),
                scale_layer_mode,
                common_layer_mode  #,
                #drum_mode_note_matrix_translation
            ])
        note_layer_mode = LayerMode(
            self._note_component,
            layer=Layer(
                matrix=midimap['Main_Button_Matrix']
                #select_button = midimap['Shift_Button'],
                #delete_button = midimap['Delete_Button']
            ))
        self._modes.add_mode(
            'note_mode',
            [
                partial(self._control_surface._layout_setup,
                        consts.SESSION_LAYOUT_SYSEX_BYTE),
                partial(self._control_surface._layout_setup,
                        consts.USER_LAYOUT_SYSEX_BYTE,
                        consts.SYSEX_PARAM_BYTE_STANDALONE_LAYOUT),
                note_layer_mode,
                common_layer_mode  #,
                #drum_mode_note_matrix_translation
            ])

        #Audio mode
        audio_layer_mode = LayerMode(
            AudioModeComponent(),
            layer=Layer(matrix=midimap['Main_Button_Matrix']))
        self._modes.add_mode(
            'audio_mode',
            [
                partial(self._control_surface._layout_setup,
                        consts.SESSION_LAYOUT_SYSEX_BYTE),
                partial(self._control_surface._layout_setup,
                        consts.DRUM_LAYOUT_SYSEX_BYTE,
                        consts.SYSEX_PARAM_BYTE_STANDALONE_LAYOUT),
                #partial(self._control_surface._layout_setup, consts.DRUM_LAYOUT_SYSEX_BYTE),#consts.AUDIO_LAYOUT_SYSEX_BYTE),
                self._control_surface._clip_delete_layer_mode,
                common_layer_mode,
                audio_layer_mode
            ])

    def set_enabled(self, enabled):
        if not enabled:
            self._do_implicit_arm(enabled)
        ControlSurfaceComponent.set_enabled(self, enabled)
        ModesComponent.set_enabled(self._modes, enabled)
        if enabled:
            self._do_implicit_arm(enabled)

    def _enter_scale_mode(self):
        self._previous_mode = self._modes.selected_mode
        self.set_mode('scale_mode')

    def _leave_scale_mode(self):
        self.set_mode(self._previous_mode)

    def _detect_mode(self):
        track = self._control_surface._target_track_component.target_track
        #drum_device = self._control_surface._drum_group_finder.drum_group
        self._control_surface._setup_drum_group()
        if track is None or track.is_foldable or track in self.song(
        ).return_tracks or track == self.song(
        ).master_track or track.is_frozen or track.has_audio_input:
            self.set_mode('audio_mode')
            self._scale_component._is_drumrack = False
        elif self._control_surface._drum_group._drum_group_device:
            self._scale_component._is_drumrack = True
            self.set_mode('drum_mode')
        else:
            self._scale_component._is_drumrack = False
            self.set_mode('note_mode')

    def get_pattern(self):
        return self._scale_component.get_pattern()

    def on_selected_track_changed(self):
        if self._implicit_arm:
            #self._control_surface._setup_drum_group()
            self._detect_mode()
            self._do_implicit_arm()

    def update(self):
        self._modes.update()

    def on_selected_scene_changed(self):
        #self._do_implicit_arm()
        self.update()

    def set_mode(self, mode):
        self._modes.selected_mode = mode
        self._modes.update()

    def get_mode(self):
        return self._modes.selected_mode

    def can_implicit_arm_track(self, track):
        #todo
        return track.can_be_armed and track.has_midi_input

    def _do_implicit_arm(self, arm=True):
        if self._is_enabled:
            if self._implicit_arm and arm:
                self._control_surface.set_feedback_channels(
                    self._feedback_channels)
                self._control_surface.set_controlled_track(
                    self._control_surface._target_track_component.target_track)
            else:
                self._control_surface.release_controlled_track()

            for track in self.song().tracks:
                if self.can_implicit_arm_track(track):
                    track.implicit_arm = self._is_enabled and self._implicit_arm and arm and self._control_surface._target_track_component.target_track == track
Ejemplo n.º 26
0
class AumTroll(Cntrlr):
	__module__ = __name__
	__doc__ = " MonOhmod companion controller script "


	def __init__(self, *a, **k):
		self._monohm = None
		self._aumpush = None
		self._shifted = False
		self._use_pedal = True
		self._suppress_next_mod_display = False
		self._monomod_version = 'b996'
		self._codec_version = 'b996'
		super(AumTroll, self).__init__(*a, **k)
		self._host_name = "AumTroll"
		with self.component_guard():
			self._setup_alt_device_control()
			self._setup_alt_mixer()
			#self._setup_device_selector()   #  Not sure why this was HERE, but removed 051314 because it was overriding mod grid updates
			#self._setup_alt_device_control()
		#self.schedule_message(3, self._session._do_show_highlight)
		self._send_midi(tuple(request_snapshot))

	

	"""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_modes(self):
		super(AumTroll, self)._setup_modes()
		self._alt_shift_mode = ModesComponent()
		self._alt_shift_mode.add_mode('alt_shift', tuple([self._enable_alt_shift, self._disable_alt_shift]), behaviour = CancellableBehaviourWithRelease())
		self._alt_shift_mode.set_mode_button('alt_shift', self._grid[15])
	

	def _enable_alt_shift(self):
		self._alt_shift_enabled = True
		self._on_shift_button_value(1)
	

	def _disable_alt_shift(self):
		self._alt_shift_enabled = False
		self._on_shift_button_value(0)
	

	def deassign_live_controls(self):

		self._leds_last = None
		self._device_selector.set_enabled(False)
		self._device._parameter_controls = None
		self._device1._parameter_controls = None
		self._device2._parameter_controls = None
		for index in range(8):
			self._mixer2.channel_strip(index).set_select_button(None)
			self._mixer2.channel_strip(index).set_volume_control(None)
		for index in range(4):
			self._mixer3.channel_strip(index).set_select_button(None)
			self._mixer3.channel_strip(index).set_volume_control(None)
			self._mixer3.return_strip(index).set_volume_control(None)
		#if self._aumpush:
		#	self._aumpush._host._set_bank_buttons(None)
		#self._on_shift_button_value.subject = None
		self._alt_shift_mode.set_mode_button('alt_shift', None)
		self._mixer.set_crossfader_control(None)


		"""THIS SECTION IS MISSING FROM THE ORIGINAL SCRIPT AND NEEDS TO BE FIXED...THE ASSIGNMENTS WERE MADE AT __init__"""
		for index in range(4):								
			self._mixer.channel_strip(index).set_volume_control(None)		#Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it						
		for index in range(2):
			self._mixer.return_strip(index).set_volume_control(None)	#assign the right faders to control the volume of our return strips
		self._mixer.master_strip().set_volume_control(None)					#assign the far right fader to control our master channel strip
		self._mixer.set_prehear_volume_control(None)							#assign the remaining fader to control our prehear volume of the the master channel strip

		for index in range(4):											#for the left side of the mixer
			self._mixer.channel_strip(index).set_solo_button(None)		#remove the solo button assignments
			self._mixer.channel_strip(index).set_arm_button(None)		#remove the arm button assignments
			self._mixer.channel_strip(index).set_mute_button(None)		#remove the mute button assignments
			self._mixer.channel_strip(index).set_select_button(None)	#remove the select button assignments
		for column in range(4):	
			for row in range(4):
				self._scene[row].clip_slot(column).set_launch_button(None)	#remove the clip launch assignments
		self._send_reset.set_buttons(tuple([None for index in range(4)]))	#remove the send_reset button assignments - this has to be sent as a tuple
		self._session.set_stop_track_clip_buttons(None)						#remove the clip_stop button assignments
		self._session.set_track_bank_buttons(None, None)		#set the track bank buttons for the Session navigation controls
		self._session.set_scene_bank_buttons(None, None)		#set the scnee bank buttons for the Session navigation controls
		self._transport.set_play_button(None)								#remove the play button assignment
		self._transport.set_record_button(None)								#remove the record button assignment
		self._transport.set_stop_button(None)								#remove the stop button assignment
		for index in range(16):
			self._grid[index].set_on_off_values(127, 0)						#reset the on/off values of the grid buttons
			self._grid[index].reset()										#turn the buttons LEDs off
		for index in range(32):
			self._button[index].set_on_off_values(127, 0)					#reset the on/off values for the key buttons
			self._button[index].release_parameter()							#remove the parameter assignment that was assigned to the keys
			self._button[index].send_value(0, True)										#turn the buttons LEDs off

		#self._device.set_parameter_controls(tuple([self._encoder[index+4] for index in range(8)]))			#assign the encoders from the device component controls - we are doing this here b
		self._device_navigator.set_nav_buttons(None, None) 			#remove the assignment of the device nav buttons
		self._device_navigator.set_enabled(False)							#turn off the device navigator
		self._device.set_on_off_button(None)								#remove the assignment of the on/off button from the device component
		self._device.set_lock_button(None)									#remove the assignment of the lock button from the device component	
		self._device.set_bank_nav_buttons(None, None) 						#remove the assignment of the navigation buttons from the device component
		self._device.set_enabled(False)										#turn off the device component
		self._session.set_enabled(False)									#turn off the session component
		self._session_zoom.set_enabled(False)								#turn off the zoom component
		for index in range(16):
			self._grid[index].force_next_send()							#set the last_sent value of the grid to -1, so that the next value it receives will always be transmitted to the CNTRLR
		for index in range(32):
			self._button[index].force_next_send()							#set the last_sent value of the keys to -1, so that the next value it receives will always be transmitted to the CNTRLR
		for index in range(12):
			self._device._parameter_controls = None
			self._encoder[index].release_parameter()
			self._encoder[index].send_value(0, True)						#turn off all the encoder rings.  We send it the second argument, True, so that it is forced to update regardless of its last_sent property
			self._encoder[index].force_next_send()							#set the last_sent value of the encoder rings to -1, so that the next value it receives will always be transmitted to the CNTRLR
		for index in range(8):
			self._encoder_button[index+4].send_value(0, True)				#turn off all the encoder LEDs.  We send it the second argument, True, so that it is forced to update regardless of its last_sent property
			self._encoder_button[index+4].force_next_send()				#set the last_sent value of the encoder LEDs to -1, so that the next value it receives will always be transmitted to the CNTRLR
		for index in range(8):
			self._mixer2.channel_strip(index).set_select_button(None)
			self._mixer2.channel_strip(index).set_mute_button(None)
			self._mixer2.channel_strip(index).set_select_button(None)
		self._session_zoom.set_zoom_button(None)							#remove the assignment of the shift button from the ZoomingComponent
		self.request_rebuild_midi_map()										#now that we've finished deassigning all of our controls, we tell the main script to rebuild its MIDI map and update the values in Live
		
	

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

		"""here we assign the left side of our mixer's buttons on the lower 32 keys"""
		if self._monohm == None and self._aumpush == None:
			for index in range(4):															#we set up a recursive loop to assign all four of our track channel strips' controls
				self._button[index].set_on_value(SOLO[self._rgb])							#set the solo color from the Map.py
				self._mixer.channel_strip(index).set_solo_button(self._button[index])		#assign the solo buttons to our mixer channel strips
				self._button[index+4].set_on_value(ARM[self._rgb])							#set the arm color from the Map.py
				self._mixer.channel_strip(index).set_arm_button(self._button[index+4])		#assign the arm buttons to our mixer channel strips
				self._button[index+16].set_on_value(MUTE[self._rgb])						#set the mute color from the Map.py
				self._mixer.channel_strip(index).set_mute_button(self._button[index+16])	#assign the mute buttons to our mixer channel strips
				self._button[index+20].set_on_value(SELECT[self._rgb])						#set the select color from the Map.py
				self._mixer.channel_strip(index).set_select_button(self._button[index+20])	#assign the select buttons to our mixer channel strips
			self._send_reset.set_buttons(tuple(self._button[index + 8] for index in range(4)))			#this is yet another way to quickly assign multiple elements conveniently in-place.  We are creating a recursion inside an assignment.  The tuple() method creates an immutable array.  It can't be modified until it gets where it's going and is unpacked.
			self._session.set_stop_track_clip_buttons(tuple(self._button[index+24] for index in range(4)))	#these last two lines assign the send_reset buttons and the stop_clip buttons for each track
			for index in range(4):
				self._button[index+8].send_value(SEND_RESET[self._rgb], True)				#now we are going to send a message to turn the LEDs on for the send_reset buttons
				self._button[index + 24].set_on_off_values(STOP_CLIP[self._rgb], STOP_CLIP[self._rgb])	#this assigns the custom colors defined in the Map.py file to the stop_clip buttons.  They have seperate on/off values, but we assign them both the same value so we can always identify them
				self._button[index+24].send_value(STOP_CLIP[self._rgb], True)				#finally, we send the on/off colors out to turn the LEDs on for the stop clip buttons
			self._button[28].set_on_off_values(PLAY_ON[self._rgb], PLAY[self._rgb])			#assing the on/off colors for play.  These are two seperate values, dependant upon whether play is engaged or not
			self._transport.set_play_button(self._button[28])								#set the transports play control to the corresponding button on the CNTRLR
			self._button[30].set_on_off_values(RECORD_ON[self._rgb], RECORD[self._rgb])		#set the on/off colors for the transport record buttons
			self._transport.set_record_button(self._button[30])								#assign the correct button for the transport record control
			self._button[29].set_on_value(STOP[self._rgb])									#set the on value for the Stop button
			self._transport.set_stop_button(self._button[29])								#assign the correct button for the transport stop control
			self._button[29].send_value(STOP_OFF[self._rgb], True)							#turn on the LED for the stop button
			for index in range(4):															#set up a for loop to generate an index for assigning the session nav buttons' colors
				self._button[index + 12].set_on_off_values(SESSION_NAV[self._rgb], SESSION_NAV_OFF[self._rgb])	#assign the colors from Map.py to the session nav buttons
			self._session.set_track_bank_buttons(self._button[15], self._button[14])		#set the track bank buttons for the Session navigation controls
			self._session.set_scene_bank_buttons(self._button[13], self._button[12])		#set the scnee bank buttons for the Session navigation controls

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

			"""this section assigns the faders and knobs"""
			for index in range(2):
				self._mixer.return_strip(index).set_volume_control(self._fader[index+4])	#assign the right faders to control the volume of our return strips
			self._mixer.master_strip().set_volume_control(self._fader[7])					#assign the far right fader to control our master channel strip
			self._mixer.set_prehear_volume_control(self._fader[6])							#assign the remaining fader to control our prehear volume of the the master channel strip
			for track in range(4):															#we set up a recursive loop to assign all four of our track channel strips' controls
				channel_strip_send_controls = []											#the channelstripcomponent requires that we pass the send controls in an array, so we create a local variable, channel_strip_send_controls, to hold them
				for control in range(2):													#since we are going to assign two controls to the sends, we create a recursion
					channel_strip_send_controls.append(self._dial_left[track + (control * 4)])		#then use the append __builtin__ method to add them to the array
				self._mixer.channel_strip(track).set_volume_control(self._fader[track])		#Since we gave our mixer 4 tracks above, we'll now assign our fader controls to it						
				self._mixer.channel_strip(track).set_send_controls(tuple(channel_strip_send_controls))	#now that we have an array containing the send controls, we pass it to the channelstrip component with its set_send_controls() method
				self._mixer.channel_strip(track).set_pan_control(self._dial_left[track + 8])		#now we set the pan control to the bottom 
				self._mixer.track_eq(track).set_gain_controls(tuple([self._dial_right[track+8], self._dial_right[track+4], self._dial_right[track]]))	#here's another way of doing the same thing, but instead of creating the array before hand, we define it in-place.  Its probably bad coding to mix styles like this, but I'll leave it for those of you trying to figure this stuff out
				self._mixer.track_eq(track).set_enabled(True)								#turn the eq component on
			self._session_zoom.set_zoom_button(self._button[31])							#assign the lower right key button to the shift function of the Zoom component
			self._session.update()															#tell the Session component to update so that the grid will display the currently selected session region
			self._session.set_enabled(True)													#enable the Session Component
			self._session_zoom.set_enabled(True)											#enable the Session Zoom

		elif not self._aumpush == None:
			self.assign_aumpush_controls()

		elif not self._monohm == None:
			for index in range(8):
				self._mixer2.channel_strip(index).set_volume_control(self._fader[index])
			self._mixer2.set_track_offset(TROLL_OFFSET)
			self._device_selector.set_buttons(self._grid)
			self._device_selector.set_enabled(True)
			if not self._shifted:
				self._assign_monomodular_controls()
			else:
				self._assign_shifted_controls()
			self._device1.set_parameter_controls(tuple([self._knobs[index] for index in range(8)]))
			self._device2.set_parameter_controls(tuple([self._knobs[index+12] for index in range(8)]))
			self._device1.set_enabled(True)
			self._device2.set_enabled(True)
			self._find_devices()
			self._device1.update()
			self._device2.update()

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

			"""now we turn on and update some of the components we've just made assignments to"""
			self._device.set_enabled(True)													#enable the Device Component
			self._device_navigator.set_enabled(True)										#enable the Device Navigator
			self._device.update()															#tell the Device component to update its assingments so that it will detect the currently selected device parameters and display them on the encoder rings
	

	"""function mode callbacks"""

	"""this method changes modes when we press a modButton.  It is also called from Monomod when it needs to update the modDial assignments"""
	def shift_update(self):
		super(AumTroll, self).shift_update()
		if self._shift_mode._mode_index == 0:
			if self._aumpush == None:
				for index in range(8):
					self._mixer2.channel_strip(index).set_volume_control(self._fader[index])
				self._mixer2.set_track_offset(TROLL_OFFSET)
				self._device1.set_parameter_controls(tuple([self._knobs[index] for index in range(8)]))
				self._device2.set_parameter_controls(tuple([self._knobs[index+12] for index in range(8)]))
				self._device1.set_enabled(True)
				self._device2.set_enabled(True)
				self._find_devices()
				self._device1.update()
				self._device2.update()
			else:
				self.assign_aumpush_controls()
	

	def find_inputs(self):
		found_device = None
		tracks = self.song().tracks
		for track in tracks:
			if track.name == 'Inputs':
				for device in track.devices:
					if bool(device.can_have_chains) and device.name == 'Inputs':
						found_device = device
		return found_device
	

	def find_perc_crossfader(self):
		found_parameter = None
		tracks = self.song().tracks
		for track in tracks:
			if track.name == 'Perc':
				for device in track.devices:
					if bool(device.can_have_chains) and device.name == 'Perc':
						for parameter in device.parameters:
							if parameter.name == 'XFade':
								found_parameter = parameter
		return found_parameter
	

	def assign_aumpush_controls(self):
		if self._aumpush:
			inputs = self.find_inputs()
			if not inputs is None:
				for index in range(4):
					self._knobs[index+8].connect_to(inputs.parameters[index+1])

			#for index in range(3):
			#	self._mixer2.channel_strip(index+4).set_volume_control(self._knobs[index+20])
			self._mixer.set_crossfader_control(self._knobs[23])
			xfade = self.find_perc_crossfader()
			if not xfade is None:
				self._knobs[20].connect_to(xfade)
			for index in range(4):
				self._mixer3.return_strip(index).set_volume_control(self._encoder[index+4])
				self._encoder_button[index+4].send_value(127, True)
			if self._shift_mode._mode_index is 0:
				#self._on_shift_button_value.subject = self._grid[15]
				self._alt_shift_mode.set_mode_button('alt_shift', self._grid[15])
				#if self._aumpush._host._is_connected:
				#	self._aumpush._host._set_bank_buttons(tuple(self._button[4:12]+self._button[20:28]))
				#for index in range(8):
				#	self._button[index+4].set_on_off_values(SELECT[self._rgb], (5, 6)[int(index>3)])
				#	self._mixer2.channel_strip(index).set_select_button(self._button[index+4])
				for index in range(4):
					self._send_reset.set_buttons(tuple(self._encoder_button[4:8]))
					self._button[index].set_on_off_values(SELECT[self._rgb], 1)
					self._mixer.channel_strip(index).set_select_button(self._button[index])
					self._mixer.channel_strip(index).set_mute_button(self._button[index+16])
					self._button[index+12].set_on_off_values(SELECT[self._rgb], 1)
					self._mixer2.channel_strip(index).set_select_button(self._button[index+12])
					self._mixer2.channel_strip(index).set_mute_button(self._button[index+28])
				if not self._shifted:
					self._mixer.selected_strip().set_send_controls(self._encoder[8:12])
					for index in range(4):
						self._encoder_button[index+8].send_value(3, True)
				else:
					self._mixer.return_strip(0).set_send_controls(tuple([None, self._encoder[8]]))
					self._mixer.return_strip(1).set_send_controls(tuple([self._encoder[9], None]))
					#self._mixer.set_crossfader_control(self._encoder[11])
					self._mixer3.channel_strip(0).set_volume_control(self._encoder[11])
					self._encoder_button[8].send_value(5, True)
					self._encoder_button[9].send_value(5, True)
					self._encoder_button[11].send_value(1, True)
			for index in range(4):
				self._mixer.channel_strip(index).set_volume_control(self._fader[index])
				self._mixer2.channel_strip(index).set_volume_control(self._fader[index+4])

			self._device1.set_parameter_controls(tuple([self._knobs[index] for index in range(8)]))
			self._device2.set_parameter_controls(tuple([self._knobs[index+12] for index in range(8)]))
			self._device1.set_enabled(True)
			self._device2.set_enabled(True)
			self._find_devices()
			self._device1.update()
			self._device2.update()
			self._device_selector.set_buttons(self._grid[:15])
			self._device_selector.set_enabled(True)
			self._device_selector.update()
			self.request_rebuild_midi_map()
	

	"""used to connect different control_surfaces so that they can communicate"""
	def connect_script_instances(self, instanciated_scripts):
		if AUMPUSH_LINK is True:
			link = False
			for s in instanciated_scripts:
				#self.log_message('script check' + str(s))
				if link == False:
					#self.log_message(str(type(s)))
					if '_cntrlr_version' in dir(s):
						if s._cntrlr_version == self._monomod_version and s._host_name == 'AumPush':
							link = True
							with self.component_guard():
								self._connect_aumpush(s)
							break
		elif MONOHM_LINK is True:
			link = False
			for s in instanciated_scripts:
				#self.log_message('script check' + str(s))
				if link == False:
					#self.log_message(str(type(s)))
					if '_cntrlr_version' in dir(s):
						if s._cntrlr_version == self._monomod_version:
							link = True
							with self.component_guard():
								self._connect_monohm(s)
							break

	

	"""device component methods and overrides"""

	def _device_set_device(self, device_component):
		def set_device(device):
			is_monodevice = False
			for client in self._client:
				if (device != None) and (client.device == device):
					is_monodevice = client
			if is_monodevice != False:
				#device = client._device_component._device
				#self.log_message('is monodevice' + str(device.name))
				assert ((device == None) or isinstance(device, Live.Device.Device))
				if ((not device_component._locked_to_device) and (device != device_component._device)):
					if (device_component._device != None):
						device_component._device.remove_name_listener(device_component._on_device_name_changed)
						device_component._device.remove_parameters_listener(device_component._on_parameters_changed)
						parameter = device_component._on_off_parameter()
						if (parameter != None):
							parameter.remove_value_listener(device_component._on_on_off_changed)
						if (device_component._parameter_controls != None):
							for control in device_component._parameter_controls:
								control.release_parameter()
					device_component._device = device
					if (device_component._device != None):
						device_component._bank_index = 0
						device_component._device.add_name_listener(self._on_device_name_changed)
						device_component._device.add_parameters_listener(self._on_parameters_changed)
						parameter = device_component._on_off_parameter()
						if (parameter != None):
							parameter.add_value_listener(device_component._on_on_off_changed)
					for key in device_component._device_bank_registry.keys():
						if (key == device_component._device):
							device_component._bank_index = device_component._device_bank_registry.get(key, 0)
							del device_component._device_bank_registry[key]
							break
					device_component._bank_name = '<No Bank>' #added
					device_component._bank_index = max(is_monodevice._cntrl_offset, device_component._bank_index)
					device_component._on_device_name_changed()
					device_component.update()	 
			else:
				DeviceComponent.set_device(device_component, device)
		return set_device
		
	

	"""this closure replaces the default ChannelStripComponent _on_cf_assign_changed() method without requiring us to build an override class"""
	"""it allows us to change different colors to its assigned controls based on the crossfade assignment, which the default _Framework doesn't support"""
	def mixer_on_cf_assign_changed(self, channel_strip):
		def _on_cf_assign_changed():
			if (channel_strip.is_enabled() and (channel_strip._crossfade_toggle != None)):
				if (channel_strip._track != None) and (channel_strip._track in (channel_strip.song().tracks + channel_strip.song().return_tracks)):
					if channel_strip._track.mixer_device.crossfade_assign == 1: #modified
						channel_strip._crossfade_toggle.turn_off()
					elif channel_strip._track.mixer_device.crossfade_assign == 0:
						channel_strip._crossfade_toggle.send_value(1)
					else:
						channel_strip._crossfade_toggle.send_value(2)
		return _on_cf_assign_changed
		
	

	"""a closure fix for banking when we deassign the bank buttons and still want to change bank indexes"""
	def device_is_banking_enabled(self, device):
		def _is_banking_enabled():
			return True
		return _is_banking_enabled
		
	


	"""this is called by connect_script_instances() when a AumPush script is found to be installed"""
	def _connect_aumpush(self, aumpush):
		self.log_message('AumTroll connecting to AumPush...')
		self._aumpush = aumpush
		self._aumpush._cntrlr = self
		with self.component_guard():
			self.deassign_live_controls()
			self.schedule_message(3, self.assign_live_controls)
		#self._device_selector.update = self._make_device_selector_update(self._device_selector)
	

	"""these two secondary DeviceComponents are only set up if the MONOHM_LINK flag in .Map is turned on"""
	def _setup_alt_device_control(self):
		self._device1 = DeviceComponent()
		self._device1.name = 'Device_Component1'
		self._device2 = DeviceComponent()
		self._device2.name = 'Device_Component2'
	

	"""this method is used to find the devices the alt controls will latch to"""
	def _find_devices(self):
		if self._device1:
			if len(self.song().return_tracks) > 0:
				if len(self.song().return_tracks[0].devices) > 0:
					#self._device.set_device(self.song().return_tracks[0].devices[0])
					if self._device1._locked_to_device:
						self._device1.set_lock_to_device(False, self._device1._device)
					self._device1.set_lock_to_device(True, self.song().return_tracks[0].devices[0])
		if self._device2:
			if len(self.song().return_tracks) > 1:
				if len(self.song().return_tracks[1].devices) > 0:
					#self._device2.set_device(self.song().return_tracks[1].devices[0])
					if self._device2._locked_to_device:
						self._device2.set_lock_to_device(False, self._device2._device)
					self._device2.set_lock_to_device(True, self.song().return_tracks[1].devices[0])
		#self.log_message('find devices')
	

	"""this secondary MixerComponent is only set up if the MONOHM_LINK flag in .Map is turned on"""
	def _setup_alt_mixer(self):
		is_momentary = True
		self._num_tracks = (8) #A mixer is one-dimensional
		self._mixer2 = MixerComponent(8, 0, False, False)
		self._mixer2.name = 'Mixer_2'
		self._mixer2.set_track_offset(4) #Sets start point for mixer strip (offset from left)
		for index in range(8):
			self._mixer2.channel_strip(index).name = 'Mixer_2_ChannelStrip_' + str(index)
			self._mixer2.channel_strip(index)._invert_mute_feedback = True
		self._mixer3 = MixerComponent(4, 4, False, False)
		self._mixer3.name = 'Mixer_3'
		self._mixer3.set_track_offset(8) #Sets start point for mixer strip (offset from left)
		for index in range(4):
			self._mixer3.channel_strip(index).name = 'Mixer_3_ChannelStrip_' + str(index)
			self._mixer3.channel_strip(index)._invert_mute_feedback = True


	

	@subject_slot('value')
	def _on_shift_button_value(self, value):
		shifted = value > 0
		if not self._shifted is shifted:
			self._shifted = shifted
			self.deassign_live_controls()
			self.assign_live_controls()
			if self._shifted and self._on_shift_button_value.subject:
				self._on_shift_button_value.subject.send_value(12, True)
	



#	a
Ejemplo n.º 27
0
class APSequencer(APC40_MkII):
    """ APC40Mk2 script with step sequencer mode """
    def __init__(self, *a, **k):
        self._double_press_context = DoublePressContext()
        APC40_MkII.__init__(self, *a, **k)
        with self.component_guard():

            self._skin = make_default_skin()
            self._clip_creator = ClipCreator()

            self._init_background()
            self._init_step_sequencer()
            self._init_instrument()

            self._init_matrix_modes()

            #      self._init_auto_arm()

            self._on_selected_track_changed()

        self.set_pad_translations(PAD_TRANSLATIONS)
        self.set_feedback_channels(FEEDBACK_CHANNELS)

    def _create_controls(self):
        """ Add some additional stuff baby """
        super(APSequencer, self)._create_controls()
        self._grid_resolution = GridResolution()
        self._velocity_slider = ButtonSliderElement(
            tuple(self._scene_launch_buttons_raw[::-1]))

        double_press_rows = recursive_map(DoublePressElement,
                                          self._matrix_rows_raw)
        self._double_press_matrix = ButtonMatrixElement(
            name='Double_Press_Matrix', rows=double_press_rows)
        self._double_press_event_matrix = ButtonMatrixElement(
            name='Double_Press_Event_Matrix',
            rows=recursive_map(lambda x: x.double_press, double_press_rows))
        self._playhead = PlayheadElement(self._c_instance.playhead)

        # Make these prioritized resources, which share between Layers() equally
        # Rather than building a stack
        self._pan_button._resource_type = PrioritizedResource
        self._user_button._resource_type = PrioritizedResource

        self._view_control = ViewControlComponent(name='View_Control')
        self._view_control.set_enabled(False)

    def _init_background(self):
        self._background = BackgroundComponent(is_root=True)
        self._background.layer = Layer(
            velocity_slider=self._velocity_slider
        )  #, display_line2=self._display_line2, display_line3=self._display_line3, display_line4=self._display_line4, top_buttons=self._select_buttons, bottom_buttons=self._track_state_buttons, scales_button=self._scale_presets_button, octave_up=self._octave_up_button, octave_down=self._octave_down_button, side_buttons=self._side_buttons, repeat_button=self._repeat_button, accent_button=self._accent_button, double_button=self._double_button, in_button=self._in_button, out_button=self._out_button, param_controls=self._global_param_controls, param_touch=self._global_param_touch_buttons, tempo_control_tap=self._tempo_control_tap, master_control_tap=self._master_volume_control_tap, touch_strip=self._touch_strip_control, touch_strip_tap=self._touch_strip_tap, nav_up_button=self._nav_up_button, nav_down_button=self._nav_down_button, nav_left_button=self._nav_left_button, nav_right_button=self._nav_right_button, aftertouch=self._aftertouch_control, pad_parameters=self._pad_parameter_control, _notification=self._notification.use_single_line(2), priority=consts.BACKGROUND_PRIORITY)
        self._matrix_background = BackgroundComponent()
        self._matrix_background.set_enabled(False)
        self._matrix_background.layer = Layer(matrix=self._session_matrix)

    #   self._mod_background = ModifierBackgroundComponent(is_root=True)
    #   self._mod_background.layer = Layer(shift_button=self._shift_button, select_button=self._select_button, delete_button=self._delete_button, duplicate_button=self._duplicate_button, quantize_button=self._quantize_button)

    def _init_step_sequencer(self):
        self._step_sequencer = StepSeqComponent(
            grid_resolution=self._grid_resolution)
        self._step_sequencer.layer = self._create_step_sequencer_layer()

    """lew saturday. works """
    #  def _init_instrument(self):
    #    self._instrument = MelodicComponent(grid_resolution = self._grid_resolution)
    #    self._instrument.layer = self._create_instument_layer()
    """lew sunday"""

    def _init_instrument(self):
        instrument_basic_layer = Layer(
            #octave_strip=self._with_shift(self._touch_strip_control),
            # scales_toggle_button=self._tap_tempo_button,
            octave_up_button=self._up_button,
            octave_down_button=self._down_button,
            scale_up_button=self._with_shift(self._up_button),
            scale_down_button=self._with_shift(self._down_button))
        self._instrument = MelodicComponent(
            skin=self._skin,
            is_enabled=False,
            clip_creator=self._clip_creator,
            name='Melodic_Component',
            grid_resolution=self._grid_resolution,
            #note_editor_settings=self._add_note_editor_setting(),
            layer=self._create_instrument_layer(),
            instrument_play_layer=instrument_basic_layer +
            Layer(matrix=self._session_matrix),
            #touch_strip=self._touch_strip_control, touch_strip_indication=self._with_firmware_version(1, 16, ComboElement(self._touch_strip_control, modifiers=[self._select_button])),
            #touch_strip_toggle=self._with_firmware_version(1, 16, ComboElement(self._touch_strip_tap, modifiers=[self._select_button])),
            #aftertouch_control=self._aftertouch_control, delete_button=self._delete_button),
            instrument_sequence_layer=instrument_basic_layer
        )  # + Layer(note_strip=self._touch_strip_control))
        self._on_note_editor_layout_changed.subject = self._instrument

    def _init_matrix_modes(self):
        """ Switch between Session and StepSequencer modes """
        """here we go trying to switch.... lew  05:53   21/10/17"""

        self._auto_arm = AutoArmComponent(name='Auto_Arm')

        self._drum_group_finder = DrumGroupFinderComponent()
        self._on_drum_group_changed.subject = self._drum_group_finder

        self._drum_modes = ModesComponent(name='Drum_Modes', is_enabled=False)
        self._drum_modes.add_mode('sequencer', self._step_sequencer)
        self._drum_modes.selected_mode = 'sequencer'

        self._note_modes = ModesComponent(
            name='Note_Modes')  #, is_enabled=False)
        self._note_modes.add_mode('drums', [self._drum_modes])
        self._drum_modes.selected_mode = 'sequencer'
        self._note_modes.add_mode(
            'looper', self._audio_loop
            if consts.PROTO_AUDIO_NOTE_MODE else self._matrix_background)
        self._note_modes.add_mode('instrument', self._instrument)
        self._note_modes.add_mode('disabled', self._matrix_background)
        self._note_modes.selected_mode = 'disabled'
        self._note_modes.set_enabled(False)

        #self._note_modes.add_mode('sequencer', self._step_sequencer)

        def switch_note_mode_layout():
            if self._note_modes.selected_mode == 'instrument':
                getattr(self._instrument, 'cycle_mode', nop)()
            elif self._note_modes.selected_mode == 'drums':
                getattr(self._drum_modes, 'cycle_mode', nop)()

        self._matrix_modes = ModesComponent(name='Matrix_Modes', is_root=True)
        self._matrix_modes.add_mode('session', self._session_mode_layers())
        self._matrix_modes.add_mode(
            'note',
            [self._drum_group_finder, self._view_control, self._note_modes],
            behaviour=self._auto_arm.auto_arm_restore_behaviour(
                ReenterBehaviour, on_reenter=switch_note_mode_layout))

        self._matrix_modes.selected_mode = 'note'
        self._matrix_modes.layer = Layer(session_button=self._pan_button,
                                         note_button=self._user_button)

        self._on_matrix_mode_changed.subject = self._matrix_modes  # (errors begin)
        self._matrix_modes.selected_mode = 'note'

        #added for looping capability
        #self._looper = LooperComponent(self)
        #self._looper.name = 'looper_Component'

    def _session_mode_layers(self):
        return [self._session, self._session_zoom]

    def _create_step_sequencer_layer(self):
        return Layer(
            velocity_slider=self._velocity_slider,
            drum_matrix=self._session_matrix.
            submatrix[:4, 1:
                      5],  # [4, 1:5],  mess with this for possible future 32 pad drum rack :
            button_matrix=self._double_press_matrix.submatrix[
                4:8, 1:5],  # [4:8, 1:5],

            #  next_page_button = self._bank_button,
            select_button=self._user_button,
            delete_button=self._stop_all_button,
            playhead=self._playhead,
            quantization_buttons=self._stop_buttons,
            shift_button=self._shift_button,
            loop_selector_matrix=self._double_press_matrix.
            submatrix[:4, :
                      1],  # changed from [:8, :1] so as to enable bottem row of rack   . second value clip length rows
            short_loop_selector_matrix=self._double_press_event_matrix.
            submatrix[:4, :
                      1],  # changed from [:8, :1] no change noticed as of yet   
            octave_up_button=self._up_button,
            octave_down_button=self._down_button
            #drum_bank_up_button = self._up_button,drum_bank_down_button = self._down_button
        )

    """lew saturday. works"""
    #  def _create_instument_layer(self):
    #          return Layer(
    #            playhead=self._playhead, #mute_button=self._global_mute_button,
    #            quantization_buttons=self._stop_buttons,
    #octave_up_button=self._nudge_up_button, octave_down_button=self._down_button,    #      keep commented out
    #            loop_selector_matrix=self._double_press_matrix.submatrix[:8, :2], #[:, 0],
    #            short_loop_selector_matrix=self._double_press_event_matrix.submatrix[:8, :1], #[:, 0],
    #            note_editor_matrices=ButtonMatrixElement([[ self._session_matrix.submatrix[:, 4 - row] for row in xrange(7) ]]))   #self._session_matrix.submatrix[:, 7 - row] for row in xrange(7)
    """lew sunday"""

    def _create_instrument_layer(self):
        return Layer(
            playhead=self._playhead,
            #mute_button=self._global_mute_button,
            quantization_buttons=self._stop_buttons,
            loop_selector_matrix=self._double_press_matrix.
            submatrix[:8, :1],  # [:, 0]
            short_loop_selector_matrix=self._double_press_event_matrix.
            submatrix[:, 0],  # [:, 0]
            note_editor_matrices=ButtonMatrixElement([[
                self._session_matrix.submatrix[:, 4 - row] for row in xrange(7)
            ]]))
        #note_editor_matrices=ButtonMatrixElement([[ self._session_matrix.submatrix[:, 7 - row] for row in xrange(7) ]]))

    def _session_layer(self):
        def when_bank_on(button):
            return self._bank_toggle.create_toggle_element(on_control=button)

        def when_bank_off(button):
            return self._bank_toggle.create_toggle_element(off_control=button)

        return Layer(track_bank_left_button=when_bank_off(self._left_button),
                     track_bank_right_button=when_bank_off(self._right_button),
                     scene_bank_up_button=when_bank_off(self._up_button),
                     scene_bank_down_button=when_bank_off(self._down_button),
                     page_left_button=when_bank_on(self._left_button),
                     page_right_button=when_bank_on(self._right_button),
                     page_up_button=when_bank_on(self._up_button),
                     page_down_button=when_bank_on(self._down_button),
                     stop_track_clip_buttons=self._stop_buttons,
                     stop_all_clips_button=self._stop_all_button,
                     scene_launch_buttons=self._scene_launch_buttons,
                     clip_launch_buttons=self._session_matrix)

    def _session_zoom_layer(self):
        return Layer(button_matrix=self._shifted_matrix,
                     nav_left_button=self._with_shift(self._left_button),
                     nav_right_button=self._with_shift(self._right_button),
                     nav_up_button=self._with_shift(self._up_button),
                     nav_down_button=self._with_shift(self._down_button),
                     scene_bank_buttons=self._shifted_scene_buttons)

    @subject_slot('selected_mode')
    def _on_matrix_mode_changed(self, mode):
        self._update_auto_arm(selected_mode=mode)

    def _update_auto_arm(self, selected_mode=None):
        self._auto_arm.set_enabled(
            selected_mode or self._matrix_modes.selected_mode == 'note')

#  def _init_auto_arm(self):                                                # swap above lew 22/10/17
#   self._auto_arm = AutoArmComponent(is_enabled = True)

    @subject_slot('drum_group')
    def _on_drum_group_changed(self):
        self._select_note_mode()

    def _select_note_mode(self):
        """
    Selects which note mode to use depending on the kind of
    current selected track and its device chain...
    """
        track = self.song().view.selected_track
        drum_device = self._drum_group_finder.drum_group
        self._step_sequencer.set_drum_group_device(drum_device)
        #self._drum_component.set_drum_group_device(drum_device)
        if track == None or track.is_foldable or track in self.song(
        ).return_tracks or track == self.song(
        ).master_track or track.is_frozen:
            self._note_modes.selected_mode = 'disabled'
        elif track and track.has_audio_input:
            self._note_modes.selected_mode = 'looper'
        elif drum_device:
            self._note_modes.selected_mode = 'drums'
        else:
            self._note_modes.selected_mode = 'instrument'
        self.reset_controlled_track()

    # added so as to have looping with pan_button held
#    self._select_modes = SelectComponent(self, tuple(self._raw_select_buttons), self._metronome_button, self._nudge_down_button, self._nudge_up_button, self._tap_tempo_button, self._transport, self._looper, self._session, self._session_matrix)
#    self._select_modes.name = 'Select_Modes'
#    self._select_modes.set_mode_toggle(self._pan_button)

# commented to test 0:47

# EVENT HANDLING FUNCTIONS
# def reset_controlled_track(self):
# self.set_controlled_track(self.song().view.selected_track)
    """lew sunday"""
    @subject_slot('selected_mode')
    def _on_note_editor_layout_changed(self, mode):
        self.reset_controlled_track(mode)

    def reset_controlled_track(self, mode=None):
        if mode == None:
            mode = self._instrument.selected_mode
        if self._instrument.is_enabled() and mode == 'sequence':
            self.release_controlled_track()
        else:
            self.set_controlled_track(self.song().view.selected_track)

        self.drum_pads_scroll_position

    def update(self):
        self.reset_controlled_track()
        self.set_feedback_channels(FEEDBACK_CHANNELS)  # push added line
        super(APSequencer, self).update()

    def _on_selected_track_changed(self):
        super(APSequencer, self)._on_selected_track_changed()
        self.reset_controlled_track()
        self._select_note_mode()

    #    self._main_modes.pop_groups(['add_effect'])
    #    self._note_repeat_enabler.selected_mode = 'disabled'

# apc orig

#  def _on_selected_track_changed(self):
#    self.reset_controlled_track()
#    if self._auto_arm.needs_restore_auto_arm:
#      self.schedule_message(1, self._auto_arm.restore_auto_arm)
#    super(APSequencer, self)._on_selected_track_changed()

    @contextmanager
    def component_guard(self):
        """ Customized to inject additional things """
        with super(APSequencer, self).component_guard():
            with self.make_injector().everywhere():
                yield

    def make_injector(self):
        """ Adds some additional stuff to the injector, used in BaseMessenger """
        return inject(double_press_context=const(self._double_press_context),
                      control_surface=const(self),
                      log_message=const(self.log_message))


# ##    ok from here 08:22 22/10/17
# ##
Ejemplo n.º 28
0
class MonoPedal(ControlSurface):
    def __init__(self, *a, **k):
        super(MonoPedal, self).__init__(*a, **k)
        self._monomod_version = 'b995'
        self._codec_version = 'b996'
        self._cntrlr_version = 'b996'
        self._cntrlr = None
        self._host_name = 'MonoPedal'
        self._color_type = 'OhmRGB'
        self.hosts = []
        self._timer = 0
        self.flash_status = 1
        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(8)]
        for index in range(7):
            self._pedal[index] = DoublePressElement(
                MonoButtonElement(True, MIDI_CC_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[7] = LoopPedalExpressionElement(
            self, MIDI_CC_TYPE, 0, 1, Live.MidiMap.MapMode.absolute)
        self._pedal[7].name = 'Pedal_' + str(7)
        self._pedal[7]._report = False
        self._leds = [None for index in range(4)]
        for index in range(4):
            red_led = ButtonElement(True, MIDI_NOTE_TYPE, 0, LED_DEFS[index])
            green_led = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                      LED_DEFS[index] + 4)
            blue_led = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                     LED_DEFS[index] + 8)
            self._leds[index] = RGB_LED(red_led, green_led, blue_led, True,
                                        MIDI_NOTE_TYPE, 0, index + 13,
                                        'LED_' + str(index), self)
        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]

    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],
            expression_pedal=self._pedal[7],
        )

    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],
            expression_pedal=self._pedal[7])

    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],
            expression_pedal=self._pedal[7])

    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.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(MonoPedal, 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)
Ejemplo n.º 29
0
class InstrumentComponent(ControlSurfaceComponent):
    """
	handles notes mode and switches between note, drum and dummy audio mode.
	"""

    def __init__(self, control_surface, drum_component=None, *a, **k):

        self._control_surface = control_surface
        self._drum_component = drum_component
        self._implicit_arm = True
        self._modes = ModesComponent(name="Instrument_Modes", is_enabled=False)
        self._modes.set_enabled = self.set_enabled
        self._feedback_channels = [
            consts.DR_MAP_CHANNEL,
            consts.DR_MAP_CHANNEL + 1,
            consts.DR_MAP_CHANNEL + 2,
            consts.DR_MAP_CHANNEL + 3,
            consts.DR_MAP_CHANNEL + 4,
        ]
        self._non_feedback_channel = consts.DR_MAP_CHANNEL + 5

        self._common_component = CommonModeComponent(instrument_component=self, control_surface=self._control_surface)
        self._scale_component = ScaleComponent(control_surface=self._control_surface, enabled=True)
        self._note_component = NoteComponent(
            control_surface=self._control_surface,
            feedback_channels=self._feedback_channels,
            non_feedback_channel=self._non_feedback_channel,
            get_pattern=self._scale_component.get_pattern,
        )

        super(InstrumentComponent, self).__init__(*a, **k)

    def set_layers(self, midimap):
        common_layer_mode = LayerMode(
            self._common_component,
            layer=Layer(
                arrow_left_button=midimap["Arrow_Left_Button"],
                arrow_right_button=midimap["Arrow_Right_Button"],
                arrow_up_button=midimap["Arrow_Up_Button"],
                arrow_down_button=midimap["Arrow_Down_Button"],
                scale_button=midimap["Scene_Launch_Button_Matrix_Raw"][0][0],
                scale_up_button=midimap["Scene_Launch_Button_Matrix_Raw"][0][1],
                scale_down_button=midimap["Scene_Launch_Button_Matrix_Raw"][0][2],
                dummy_button=midimap["Scene_Launch_Button_Matrix_Raw"][0][3],
                play_button=midimap["Scene_Launch_Button_Matrix_Raw"][0][6],
                stop_button=midimap["Scene_Launch_Button_Matrix_Raw"][0][7],
            ),
        )

        drum_group_layer_mode = LayerMode(
            self._control_surface._drum_group,
            layer=Layer(
                # scroll_up_button = midimap['Scene_Launch_Button_Matrix_Raw'][0][1],
                # scroll_down_button = midimap['Scene_Launch_Button_Matrix_Raw'][0][2],
                mute_button=midimap["Scene_Launch_Button_Matrix_Raw"][0][4],
                solo_button=midimap["Scene_Launch_Button_Matrix_Raw"][0][5],
                # scroll_up_button=midimap['Arrow_Left_Button'],
                # scroll_down_button=midimap['Arrow_Right_Button'],
                # scroll_page_up_button=midimap['Arrow_Up_Button'],
                # scroll_page_down_button=midimap['Arrow_Down_Button'],
                # drum_matrix = midimap['Drum_Button_Matrix']#,
                drum_matrix=midimap["Main_Button_Matrix"]
                # select_button = midimap['Shift_Button'],
                # delete_button = midimap['Delete_Button']
            ),
        )

        self._modes.add_mode(
            "drum_mode",
            [
                partial(self._control_surface._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
                partial(
                    self._control_surface._layout_setup,
                    consts.USER_LAYOUT_SYSEX_BYTE,
                    consts.SYSEX_PARAM_BYTE_STANDALONE_LAYOUT,
                ),
                # partial(self._control_surface._layout_setup, consts.DRUM_LAYOUT_SYSEX_BYTE),
                self._control_surface._setup_drum_group(),
                drum_group_layer_mode,
                common_layer_mode  # ,
                # drum_mode_note_matrix_translation
            ],
        )

        scale_layer_mode = LayerMode(self._scale_component, layer=Layer(matrix=midimap["Main_Button_Matrix"]))
        self._modes.add_mode(
            "scale_mode",
            [
                partial(self._control_surface._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
                partial(
                    self._control_surface._layout_setup,
                    consts.USER_LAYOUT_SYSEX_BYTE,
                    consts.SYSEX_PARAM_BYTE_STANDALONE_LAYOUT,
                ),
                scale_layer_mode,
                common_layer_mode  # ,
                # drum_mode_note_matrix_translation
            ],
        )
        note_layer_mode = LayerMode(
            self._note_component,
            layer=Layer(
                matrix=midimap["Main_Button_Matrix"]
                # select_button = midimap['Shift_Button'],
                # delete_button = midimap['Delete_Button']
            ),
        )
        self._modes.add_mode(
            "note_mode",
            [
                partial(self._control_surface._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
                partial(
                    self._control_surface._layout_setup,
                    consts.USER_LAYOUT_SYSEX_BYTE,
                    consts.SYSEX_PARAM_BYTE_STANDALONE_LAYOUT,
                ),
                note_layer_mode,
                common_layer_mode  # ,
                # drum_mode_note_matrix_translation
            ],
        )

        # Audio mode
        audio_layer_mode = LayerMode(AudioModeComponent(), layer=Layer(matrix=midimap["Main_Button_Matrix"]))
        self._modes.add_mode(
            "audio_mode",
            [
                partial(self._control_surface._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
                partial(
                    self._control_surface._layout_setup,
                    consts.DRUM_LAYOUT_SYSEX_BYTE,
                    consts.SYSEX_PARAM_BYTE_STANDALONE_LAYOUT,
                ),
                # partial(self._control_surface._layout_setup, consts.DRUM_LAYOUT_SYSEX_BYTE),#consts.AUDIO_LAYOUT_SYSEX_BYTE),
                self._control_surface._clip_delete_layer_mode,
                common_layer_mode,
                audio_layer_mode,
            ],
        )

    def set_enabled(self, enabled):
        if not enabled:
            self._do_implicit_arm(enabled)
        ControlSurfaceComponent.set_enabled(self, enabled)
        ModesComponent.set_enabled(self._modes, enabled)
        if enabled:
            self._do_implicit_arm(enabled)

    def _enter_scale_mode(self):
        self._previous_mode = self._modes.selected_mode
        self.set_mode("scale_mode")

    def _leave_scale_mode(self):
        self.set_mode(self._previous_mode)

    def _detect_mode(self):
        track = self._control_surface._target_track_component.target_track
        # drum_device = self._control_surface._drum_group_finder.drum_group
        self._control_surface._setup_drum_group()
        if (
            track is None
            or track.is_foldable
            or track in self.song().return_tracks
            or track == self.song().master_track
            or track.is_frozen
            or track.has_audio_input
        ):
            self.set_mode("audio_mode")
            self._scale_component._is_drumrack = False
        elif self._control_surface._drum_group._drum_group_device:
            self._scale_component._is_drumrack = True
            self.set_mode("drum_mode")
        else:
            self._scale_component._is_drumrack = False
            self.set_mode("note_mode")

    def get_pattern(self):
        return self._scale_component.get_pattern()

    def on_selected_track_changed(self):
        if self._implicit_arm:
            # self._control_surface._setup_drum_group()
            self._detect_mode()
            self._do_implicit_arm()

    def update(self):
        self._modes.update()

    def on_selected_scene_changed(self):
        # self._do_implicit_arm()
        self.update()

    def set_mode(self, mode):
        self._modes.selected_mode = mode
        self._modes.update()

    def get_mode(self):
        return self._modes.selected_mode

    def can_implicit_arm_track(self, track):
        # todo
        return track.can_be_armed and track.has_midi_input

    def _do_implicit_arm(self, arm=True):
        if self._is_enabled:
            if self._implicit_arm and arm:
                self._control_surface.set_feedback_channels(self._feedback_channels)
                self._control_surface.set_controlled_track(self._control_surface._target_track_component.target_track)
            else:
                self._control_surface.release_controlled_track()

            for track in self.song().tracks:
                if self.can_implicit_arm_track(track):
                    track.implicit_arm = (
                        self._is_enabled
                        and self._implicit_arm
                        and arm
                        and self._control_surface._target_track_component.target_track == track
                    )
Ejemplo n.º 30
0
class OhmModHandler(ModHandler):


	def __init__(self, *a, **k):
		super(OhmModHandler, self).__init__(*a, **k)
		self._shift_mode = ModesComponent()
		self._color_type = 'RGB'
		self._shift_mode.add_mode('shift', tuple([self._enable_shift, self._disable_shift]), behaviour = CancellableBehaviourWithRelease())
		self.nav_box = self.register_component(NavigationBox(self, 16, 16, 8, 8, self.set_offset))
		self._mod_button = None
	

	def _enable_shift(self):
		self._shift_value(1)
	

	def _disable_shift(self):
		self._shift_value(0)
	

	def set_shift_button(self, button):
		self._shift_mode.set_mode_button('shift', button)
	

	def set_nav_matrix(self, matrix):
		self.nav_box.set_matrix(matrix)
	

	def _receive_grid(self, x, y, value, *a, **k):
		#self._receive_grid(x, y, value, *a, **k)
		legacy = self.active_mod().legacy
		if self._active_mod:
			if not self._grid_value.subject is None:
				if legacy:
					x = x - self.x_offset 
					y = y - self.y_offset 
				if x in range(8) and y in range(8):
					try:
						self._grid_value.subject.send_value(x, y, self._colors[value], True)
					except:
						pass
	

	def set_device_selector_matrix(self, matrix):
		self._device_selector.set_matrix(matrix)
	


	@subject_slot('value')
	def _grid_value(self, value, x, y, *a, **k):
		#self.log_message('_base_grid_value ' + str(x) + str(y) + str(value))
		if self.active_mod():
			if self.active_mod().legacy:
				x += self.x_offset
				y += self.y_offset
			self._active_mod.send('grid', x, y, value)
	

	@subject_slot('value')
	def _shift_value(self, value, *a, **k):
		self._is_shifted = not value is 0
		mod = self.active_mod()
		if mod:
			mod.send('shift', value)
		if self._is_shifted:
			self.shift_mode.enter_mode()
			if mod and mod.legacy:
				self.legacy_shift_mode.enter_mode()
		else:
			self.legacy_shift_mode.leave_mode()
			self.shift_mode.leave_mode()
		self.update()
	

	def set_mod_button(self, button):
		self._mod_button = button
	

	def update(self, *a, **k): 
		mod = self.active_mod()
		if self.is_enabled():
			if not mod is None:
				mod.restore()
			else:
				if not self._grid_value.subject is None:
					self._grid_value.subject.reset()
				if not self._keys_value.subject is None:
					self._keys_value.subject.reset()
			self._alt_value.subject and self._alt_value.subject.send_value(2 + int(self.is_alted())*7, True)
			if self._on_lock_value.subject:
				self._on_lock_value.subject.send_value(1 + (int(self.is_locked())*4), True)
			else:
				self._mod_button and self._mod_button.send_value(7 + (not self.active_mod() is None)*7, True)
			
		else:
			self._mod_button and self._mod_button.send_value((not self.active_mod() is None)*3, True)
class Launchpad_Pro(IdentifiableControlSurface, OptimizedControlSurface):

    def __init__(self, c_instance, *a, **k):
        product_id_bytes = consts.MANUFACTURER_ID + consts.DEVICE_CODE
        super(Launchpad_Pro, self).__init__(c_instance=c_instance, product_id_bytes=product_id_bytes, *a, **k)
        self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143
        with self.component_guard():
            self._skin = make_default_skin()
            with inject(skin=const(self._skin)).everywhere():
                self._midimap = MidiMap()
            self._target_track_component = TargetTrackComponent(name='Target_Track')
            self._create_background()
            self._create_global_component()
            self._last_sent_mode_byte = None
            with inject(layout_setup=const(self._layout_setup), should_arm=const(self._should_arm_track)).everywhere():
                self._create_session()
                self._create_recording()
                self._create_actions()
                self._create_drums()
                self._create_mixer()
                self._create_device()
                self._create_modes()
                self._create_m4l_interface()
            self._on_session_record_changed.subject = self.song()
        self.set_highlighting_session_component(self._session)
        self.set_device_component(self._device)
        self._device_selection_follows_track_selection = True
        self._on_session_record_changed()

    def disconnect(self):
        self._send_midi(consts.TURN_OFF_LEDS)
        self._send_midi(consts.QUIT_MESSAGE)
        super(Launchpad_Pro, self).disconnect()

    def _create_background(self):
        self._modifier_background_component = ModifierBackgroundComponent(name='Background_Component', is_enabled=False, layer=Layer(shift_button=self._midimap['Shift_Button']))
        self._shifted_background = BackgroundComponent(name='No_Op_Shifted_Buttons', is_enabled=False, layer=Layer(click_bitton=self._midimap.with_shift('Click_Button'), delete_button=self._midimap.with_shift('Delete_Button'), duplicate_button=self._midimap.with_shift('Duplicate_Button'), double_button=self._midimap.with_shift('Double_Loop_Button'), session_record_button=self._midimap.with_shift('Session_Record_Button')))

    def _create_global_component(self):
        self._actions_component = ActionsComponent(name='Global_Actions', is_enabled=False, layer=Layer(undo_button=self._midimap['Undo_Button'], redo_button=self._midimap.with_shift('Undo_Button'), metronome_button=self._midimap['Click_Button'], quantization_on_button=self._midimap.with_shift('Quantize_Button')))

    def _create_session(self):
        self._session = SessionComponent(NUM_TRACKS, NUM_SCENES, auto_name=True, is_enabled=False, enable_skinning=True, layer=Layer(track_bank_left_button=self._midimap['Arrow_Left_Button'], track_bank_right_button=self._midimap['Arrow_Right_Button'], scene_bank_up_button=self._midimap['Arrow_Up_Button'], scene_bank_down_button=self._midimap['Arrow_Down_Button']))
        self._session.set_enabled(True)
        self._session.set_rgb_mode(CLIP_COLOR_TABLE, RGB_COLOR_TABLE)
        SpecialClipSlotComponent.quantization_component = self._actions_component
        for scene_index in xrange(NUM_SCENES):
            scene = self._session.scene(scene_index)
            scene.layer = Layer(select_button=self._midimap['Shift_Button'], delete_button=self._midimap['Delete_Button'], duplicate_button=self._midimap['Duplicate_Button'])
            for track_index in xrange(NUM_TRACKS):
                slot = scene.clip_slot(track_index)
                slot.layer = Layer(select_button=self._midimap['Shift_Button'], delete_button=self._midimap['Delete_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_loop_button=self._midimap['Double_Loop_Button'], quantize_button=self._midimap['Quantize_Button'])

        self._session_zoom = SessionZoomingComponent(self._session, name='Session_Overview', is_enabled=True, enable_skinning=True)

    def _create_recording(self):
        self._session_record = SpecialSessionRecordingComponent(self._target_track_component, name='Session_Recording', is_enabled=False, layer=Layer(record_button=self._midimap['Session_Record_Button']))

    def _create_actions(self):
        self._clip_actions_component = ClipActionsComponent(self._target_track_component, name='Clip_Actions', is_enabled=False, layer=Layer(duplicate_button=self._midimap['Duplicate_Button'], double_button=self._midimap['Double_Loop_Button'], quantize_button=self._midimap['Quantize_Button']))
        ClipActionsComponent.quantization_component = self._actions_component

    def _create_drums(self):
        self._drum_group_finder = DrumGroupFinderComponent(self._target_track_component, name='Drum_Group_Finder', is_enabled=False, layer=None)
        self._on_drum_group_changed.subject = self._drum_group_finder
        self._drum_group_finder.set_enabled(True)
        self._drum_group = DrumGroupComponent(self._clip_actions_component, name='Drum_Group_Control', translation_channel=consts.DR_MAP_CHANNEL)
        self._drum_group.set_enabled(True)

    def _create_mixer(self):
        self._mixer = SpecialMixerComponent(NUM_TRACKS, auto_name=True, is_enabled=True, invert_mute_feedback=True)
        self._mixer.name = 'Mixer_Control'
        self._session.set_mixer(self._mixer)

    def _create_device(self):
        self._device = SpecialDeviceComponent(name='Device_Control', is_enabled=False)
        self._device_navigation = DeviceNavigationComponent(name='Device_Navigation')
        self._device_background = BackgroundComponent(name='Device_Background_Component')

    def _setup_drum_group(self):
        self._drum_group.set_drum_group_device(self._drum_group_finder.drum_group)

    def _create_translation(self, comp_name, channel, button_layer, should_enable = True, should_reset = True):
        translation_component = TranslationComponent(name=comp_name, translated_channel=channel, should_enable=should_enable, should_reset=should_reset, is_enabled=False, layer=button_layer)
        setattr(self, '_' + comp_name.lower(), translation_component)
        return translation_component

    def _create_modes(self):
        self._modes = ModesComponent(name='Launchpad_Modes', is_enabled=False)
        self._session_layer_mode = AddLayerMode(self._session, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix'], clip_launch_buttons=self._midimap['Main_Button_Matrix'], delete_button=self._midimap['Delete_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_button=self._midimap['Double_Loop_Button'], quantize_button=self._midimap['Quantize_Button']))
        action_button_background = BackgroundComponent(name='No_Op_Buttons')
        self._action_button_background_layer_mode = LayerMode(action_button_background, Layer(delete_button=self._midimap['Delete_Button'], quantize_button=self._midimap['Quantize_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_button=self._midimap['Double_Loop_Button']))
        self._clip_delete_layer_mode = AddLayerMode(self._clip_actions_component, layer=Layer(delete_button=self._midimap['Delete_Button']))
        self._create_session_zooming_modes()
        self._create_session_mode()
        self._create_note_modes()
        self._create_device_mode()
        self._create_user_mode()
        self._create_record_arm_mode()
        self._create_track_select_mode()
        self._create_mute_mode()
        self._create_solo_mode()
        self._create_volume_mode()
        self._create_pan_mode()
        self._create_sends_mode()
        self._create_stop_clips_mode()
        self._modes.layer = Layer(session_mode_button=self._midimap['Session_Mode_Button'], note_mode_button=self._midimap['Note_Mode_Button'], device_mode_button=self._midimap['Device_Mode_Button'], user_mode_button=self._midimap['User_Mode_Button'], record_arm_mode_button=self._midimap['Record_Arm_Mode_Button'], track_select_mode_button=self._midimap['Track_Select_Mode_Button'], mute_mode_button=self._midimap['Mute_Mode_Button'], solo_mode_button=self._midimap['Solo_Mode_Button'], volume_mode_button=self._midimap['Volume_Mode_Button'], pan_mode_button=self._midimap['Pan_Mode_Button'], sends_mode_button=self._midimap['Sends_Mode_Button'], stop_clip_mode_button=self._midimap['Stop_Clip_Mode_Button'])
        self._modes.selected_mode = 'session_mode'
        self._on_layout_changed.subject = self._modes

    def _create_session_zooming_modes(self):
        session_zoom_layer = Layer(button_matrix=self._midimap['Main_Button_Matrix'], nav_left_button=self._midimap['Arrow_Left_Button'], nav_right_button=self._midimap['Arrow_Right_Button'], nav_up_button=self._midimap['Arrow_Up_Button'], nav_down_button=self._midimap['Arrow_Down_Button'])
        session_zooming_layer_mode = LayerMode(self._session_zoom, session_zoom_layer)
        self._session_zooming_manager = SessionZoomingManagerComponent(self._modes, is_enabled=False)
        session_zooming_button_layer_mode = LayerMode(self._session_zooming_manager, Layer(session_zooming_button=self._midimap['Session_Mode_Button']))
        self._prioritized_session_zooming_button_layer_mode = LayerMode(self._session_zooming_manager, Layer(session_zooming_button=self._midimap['Session_Mode_Button'], priority=1))
        self._session_zooming_background = BackgroundComponent(name='Session_Zooming_Background')
        session_zooming_background_layer_mode = LayerMode(self._session_zooming_background, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix'], delete_button=self._midimap['Delete_Button'], quantize_button=self._midimap['Quantize_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_loop_button=self._midimap['Double_Loop_Button']))
        self._modes.add_mode('session_zooming_mode', [self._session_zooming_manager,
         session_zooming_button_layer_mode,
         session_zooming_layer_mode,
         session_zooming_background_layer_mode])
        self._modes.add_mode('prioritized_session_zooming_mode', [partial(self._layout_switch, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         session_zooming_layer_mode,
         session_zooming_background_layer_mode,
         self.update])

    def _create_session_mode(self):
        self._modes.add_mode('session_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE), self._session_layer_mode, self._session.update_navigation_buttons], behaviour=CancelingReenterBehaviour('session_zooming_mode'))

    def _create_note_modes(self):
        note_mode_matrix_translation = self._create_translation('Note_Mode_Matrix_Translation', consts.CHROM_MAP_CHANNEL, Layer(button_matrix=self._midimap['Main_Button_Matrix'], note_button_matrix=self._midimap['Note_Button_Matrix'], drum_matrix=self._midimap['Drum_Button_Matrix'], mixer_button_matrix=self._midimap['Mixer_Button_Matrix']), should_enable=False)
        note_mode_scene_launch_translation = self._create_translation('Note_Mode_Scene_Launch_Translation', consts.CHROM_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        drum_mode_note_matrix_translation = self._create_translation('Drum_Mode_Note_Button_Translation', 0, Layer(note_button_matrix=self._midimap['Note_Button_Matrix']), should_enable=False, should_reset=False)
        drum_group_layer_mode = LayerMode(self._drum_group, layer=Layer(scroll_up_button=self._midimap['Arrow_Left_Button'], scroll_down_button=self._midimap['Arrow_Right_Button'], scroll_page_up_button=self._midimap['Arrow_Up_Button'], scroll_page_down_button=self._midimap['Arrow_Down_Button'], drum_matrix=self._midimap['Drum_Button_Matrix'], select_button=self._midimap['Shift_Button'], delete_button=self._midimap['Delete_Button']))
        self._note_modes = SpecialModesComponent(name='Note_Modes')
        self._note_modes.add_mode('chromatic_mode', [partial(self._layout_setup, consts.NOTE_LAYOUT_SYSEX_BYTE), self._clip_delete_layer_mode, note_mode_matrix_translation])
        self._note_modes.add_mode('drum_mode', [partial(self._layout_setup, consts.DRUM_LAYOUT_SYSEX_BYTE),
         self._setup_drum_group,
         drum_group_layer_mode,
         drum_mode_note_matrix_translation])
        self._note_modes.add_mode('audio_mode', [partial(self._layout_setup, consts.AUDIO_LAYOUT_SYSEX_BYTE), self._clip_delete_layer_mode])
        self._note_modes.set_enabled(False)
        self._modes.add_mode('note_mode', [note_mode_scene_launch_translation,
         self._note_modes,
         self._select_note_mode,
         self._select_target_track,
         self._clip_actions_component,
         self._show_playing_clip,
         self._set_clip_actions_type], behaviour=ReenterBehaviour(self.toggle_detail_view))
        self._session_record.set_modes_component(self._modes)
        self._session_record.set_note_mode_name('note_mode')

    def _create_device_mode(self):
        device_mode_scene_launch_translation = self._create_translation('Device_Mode_Scene_Launch_Translation', consts.DEVICE_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        device_layer_mode = LayerMode(self._device, layer=Layer(parameter_controls=self._midimap['Slider_Button_Matrix']))
        device_nav_layer_mode = LayerMode(self._device_navigation, layer=Layer(device_nav_left_button=self._midimap['Arrow_Left_Button'], device_nav_right_button=self._midimap['Arrow_Right_Button']))
        device_background_layer_mode = LayerMode(self._device_background, layer=Layer(arrow_up_button=self._midimap['Arrow_Up_Button'], arrow_down_button=self._midimap['Arrow_Down_Button']))
        self._modes.add_mode('device_mode', [partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         self._device,
         device_layer_mode,
         device_nav_layer_mode,
         device_background_layer_mode,
         self._clip_actions_component,
         self._clip_delete_layer_mode,
         device_mode_scene_launch_translation,
         self._show_playing_clip,
         self._set_clip_actions_type], behaviour=ReenterBehaviour(self.toggle_detail_view))

    def _create_user_mode(self):
        self._modes.add_mode('user_mode', [partial(self._layout_setup, consts.USER_LAYOUT_SYSEX_BYTE)])

    def _create_record_arm_mode(self):
        arm_layer_mode = LayerMode(self._mixer, layer=Layer(arm_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('record_arm_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         arm_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_track_select_mode(self):
        track_select_layer_mode = LayerMode(self._mixer, layer=Layer(track_select_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('track_select_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         track_select_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_mute_mode(self):
        mute_layer_mode = LayerMode(self._mixer, layer=Layer(mute_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('mute_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         mute_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_solo_mode(self):
        solo_layer_mode = LayerMode(self._mixer, layer=Layer(solo_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('solo_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         solo_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_volume_mode(self):
        volume_mode_scene_launch_translation = self._create_translation('Volume_Mode_Scene_Launch_Translation', consts.VOLUME_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        volume_layer_mode = LayerMode(self._mixer, layer=Layer(volume_controls=self._midimap['Slider_Button_Matrix']))
        self._modes.add_mode('volume_mode', [partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         volume_layer_mode,
         self._action_button_background_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         volume_mode_scene_launch_translation,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_pan_mode(self):
        pan_mode_scene_launch_translation = self._create_translation('Pan_Mode_Scene_Launch_Translation', consts.PAN_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        pan_layer_mode = LayerMode(self._mixer, layer=Layer(pan_controls=self._midimap['Slider_Button_Matrix']))
        self._modes.add_mode('pan_mode', [partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         pan_layer_mode,
         self._action_button_background_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         pan_mode_scene_launch_translation,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_sends_mode(self):
        send_layer_mode = LayerMode(self._mixer, layer=Layer(send_controls=self._midimap['Slider_Button_Matrix'], send_select_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        self._modes.add_mode('sends_mode', [partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         send_layer_mode,
         self._action_button_background_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_stop_clips_mode(self):
        stop_layer_mode = AddLayerMode(self._session, Layer(stop_track_clip_buttons=self._midimap['Mixer_Button_Matrix'], stop_scene_clip_buttons=self._midimap['Scene_Stop_Button_Matrix'], stop_all_clips_button=self._midimap['Stop_All_Clips_Button']))
        self._modes.add_mode('stop_clip_mode', [partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         stop_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_m4l_interface(self):
        self._m4l_interface = M4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard, priority=1)
        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 toggle_detail_view(self):
        view = self.application().view
        if view.is_view_visible('Detail'):
            if view.is_view_visible('Detail/DeviceChain'):
                view.show_view('Detail/Clip')
            else:
                view.show_view('Detail/DeviceChain')

    @subject_slot('drum_group')
    def _on_drum_group_changed(self):
        if self._note_modes.selected_mode == 'drum_mode':
            self._drum_group.set_drum_group_device(self._drum_group_finder.drum_group)
        if self._modes.selected_mode == 'note_mode':
            self._select_note_mode()
        else:
            self.release_controlled_track()
        self._update_note_mode_button(self._drum_group_finder.drum_group is not None)

    def _select_note_mode(self):
        """
        Selects which note mode to use depending on the kind of
        current target track and its device chain.  Will also
        select the target if specified.
        """
        track = self._target_track_component.target_track
        drum_device = self._drum_group_finder.drum_group
        if track is None or track.is_foldable or track in self.song().return_tracks or track == self.song().master_track or track.is_frozen or track.has_audio_input:
            self._note_modes.selected_mode = 'audio_mode'
        elif drum_device:
            self._note_modes.selected_mode = 'drum_mode'
        else:
            self._note_modes.selected_mode = 'chromatic_mode'
        self._modes.update()
        if self._note_modes.selected_mode == 'audio_mode':
            self.release_controlled_track()
        else:
            self.set_controlled_track(self._target_track_component.target_track)

    def _select_target_track(self):
        track = self._target_track_component.target_track
        if track != self.song().view.selected_track:
            self.song().view.selected_track = track

    def _update_note_mode_button(self, focused_track_is_drum_track):
        button = self._midimap['Note_Mode_Button']
        if focused_track_is_drum_track:
            button.default_states = {True: 'Mode.Drum.On',
             False: 'Mode.Drum.Off'}
        else:
            button.default_states = {True: 'Mode.Chromatic.On',
             False: 'Mode.Chromatic.Off'}
        button.reset_state()
        self._modes.update()

    def _show_playing_clip(self):
        track = None
        if self._use_sel_track():
            track = self.song().view.selected_track
        else:
            track = self._target_track_component.target_track
        if track in self.song().tracks:
            slot_index = track.fired_slot_index
            if slot_index < 0:
                slot_index = track.playing_slot_index
            if slot_index >= 0:
                clip_slot = track.clip_slots[slot_index]
                self.song().view.highlighted_clip_slot = clip_slot

    def _set_clip_actions_type(self):
        self._clip_actions_component.use_selected_track(self._use_sel_track())
        self._clip_actions_component.update()

    def _use_sel_track(self):
        return self._modes.selected_mode == 'device_mode'

    def _should_arm_track(self):
        return self._modes.selected_mode == 'record_arm_mode'

    @subject_slot('selected_mode')
    def _on_layout_changed(self, mode):
        if mode == 'note_mode':
            self.set_controlled_track(self._target_track_component.target_track)
        else:
            self.release_controlled_track()
        self._session_record.set_enabled(mode != 'user_mode')

    @subject_slot('session_record')
    def _on_session_record_changed(self):
        status = self.song().session_record
        feedback_color = int(self._skin['Instrument.FeedbackRecord'] if status else self._skin['Instrument.Feedback'])
        self._c_instance.set_feedback_velocity(feedback_color)

    def _clear_send_cache(self):
        with self.component_guard():
            for control in self.controls:
                control.clear_send_cache()

    def _update_global_components(self):
        self._actions_component.update()
        self._session_record.update()
        self._modifier_background_component.update()

    def _layout_setup(self, mode):
        self._layout_switch(mode)
        self._clear_send_cache()
        self._update_global_components()

    def _layout_switch(self, mode):
        prefix = consts.SYSEX_STANDARD_PREFIX + consts.SYSEX_PARAM_BYTE_LAYOUT
        suffix = consts.SYSEX_STANDARD_SUFFIX
        self._send_midi(prefix + mode + suffix)
        self._last_sent_mode_byte = mode

    def _send_identity_request(self):
        self._send_midi(consts.SYSEX_IDENTITY_REQUEST)

    def on_identified(self):
        self._send_challenge()

    def _send_challenge(self):
        challenge_bytes = []
        for index in range(4):
            challenge_bytes.append(self._challenge >> 8 * index & 127)

        challenge = consts.CHALLENGE_PREFIX + tuple(challenge_bytes) + (247,)
        self._send_midi(challenge)

    def _on_handshake_successful(self):
        self._do_send_midi(consts.LIVE_MODE_SWITCH_REQUEST)
        with self.component_guard():
            self._modes.set_enabled(True)
            self._actions_component.set_enabled(True)
            self._session_record.set_enabled(True)
            self._modifier_background_component.set_enabled(True)
            self._shifted_background.set_enabled(True)
            self.release_controlled_track()
            self.set_feedback_channels(consts.FEEDBACK_CHANNELS)
        if self._last_sent_mode_byte is not None:
            self._layout_setup(self._last_sent_mode_byte)
        self.update()

    def _is_challenge_response(self, midi_bytes):
        return len(midi_bytes) == 10 and midi_bytes[:7] == consts.SYSEX_STANDARD_PREFIX + consts.SYSEX_CHALLENGE_RESPONSE_BYTE

    def _is_response_valid(self, midi_bytes):
        response = long(midi_bytes[7])
        response += long(midi_bytes[8] << 8)
        return response == Live.Application.encrypt_challenge2(self._challenge)

    def handle_sysex(self, midi_bytes):
        if len(midi_bytes) < 7:
            pass
        if self._is_challenge_response(midi_bytes) and self._is_response_valid(midi_bytes):
            self._on_handshake_successful()
        elif midi_bytes[6] in (consts.SYSEX_STATUS_BYTE_MODE, consts.SYSEX_STATUS_BYTE_LAYOUT):
            pass
        else:
            super(Launchpad_Pro, self).handle_sysex(midi_bytes)
Ejemplo n.º 32
0
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 APC40_MkII(APC, OptimizedControlSurface):

    def __init__(self, *a, **k):
        super(APC40_MkII, self).__init__(*a, **k)
        self._color_skin = make_rgb_skin()
        self._default_skin = make_default_skin()
        self._stop_button_skin = make_stop_button_skin()
        self._crossfade_button_skin = make_crossfade_button_skin()
        with self.component_guard():
            self._create_controls()
            self._create_bank_toggle()
            self._create_session()
            self._create_mixer()
            self._create_transport()
            self._create_device()
            self._create_view_control()
            self._create_quantization_selection()
            self._create_recording()
            self._create_m4l_interface()
            self._session.set_mixer(self._mixer)
        self.set_highlighting_session_component(self._session)
        self.set_device_component(self._device)
        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)

        def make_color_button(*a, **k):
            button = make_button(skin=self._color_skin, *a, **k)
            button.is_rgb = True
            button.num_delayed_messages = 2
            return button

        def make_matrix_button(track, scene):
            return make_color_button(0, 32 + track - NUM_TRACKS * scene, name='%d_Clip_%d_Button' % (track, scene))

        def make_stop_button(track):
            return make_button(track, 52, name='%d_Stop_Button' % track, skin=self._stop_button_skin)

        self._shift_button = make_button(0, 98, name='Shift_Button', resource_type=PrioritizedResource)
        self._bank_button = make_on_off_button(0, 103, name='Bank_Button')
        self._left_button = make_button(0, 97, name='Bank_Select_Left_Button')
        self._right_button = make_button(0, 96, name='Bank_Select_Right_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._stop_buttons = ButtonMatrixElement(rows=[[ make_stop_button(track) for track in xrange(NUM_TRACKS) ]])
        self._stop_all_button = make_button(0, 81, name='Stop_All_Clips_Button')
        self._scene_launch_buttons_raw = [ make_color_button(0, scene + 82, name='Scene_%d_Launch_Button' % scene) for scene in xrange(NUM_SCENES) ]
        self._scene_launch_buttons = ButtonMatrixElement(rows=[self._scene_launch_buttons_raw])
        self._matrix_rows_raw = [ [ make_matrix_button(track, scene) for track in xrange(NUM_TRACKS) ] for scene in xrange(NUM_SCENES) ]
        self._session_matrix = ButtonMatrixElement(rows=self._matrix_rows_raw)
        self._pan_button = make_on_off_button(0, 87, name='Pan_Button')
        self._sends_button = make_on_off_button(0, 88, name='Sends_Button', resource_type=PrioritizedResource)
        self._user_button = make_on_off_button(0, 89, name='User_Button')
        self._mixer_encoders = ButtonMatrixElement(rows=[[ make_ring_encoder(48 + track, 56 + track, name='Track_Control_%d' % track) for track in xrange(NUM_TRACKS) ]])
        self._volume_controls = ButtonMatrixElement(rows=[[ make_slider(track, 7, name='%d_Volume_Control' % track) for track in xrange(NUM_TRACKS) ]])
        self._master_volume_control = make_slider(0, 14, name='Master_Volume_Control')
        self._prehear_control = make_encoder(0, 47, name='Prehear_Volume_Control')
        self._crossfader_control = make_slider(0, 15, name='Crossfader')
        self._raw_select_buttons = [ make_on_off_button(channel, 51, name='%d_Select_Button' % channel) for channel in xrange(NUM_TRACKS) ]
        self._arm_buttons = ButtonMatrixElement(rows=[[ make_on_off_button(channel, 48, name='%d_Arm_Button' % channel) for channel in xrange(NUM_TRACKS) ]])
        self._solo_buttons = ButtonMatrixElement(rows=[[ make_on_off_button(channel, 49, name='%d_Solo_Button' % channel) for channel in xrange(NUM_TRACKS) ]])
        self._mute_buttons = ButtonMatrixElement(rows=[[ make_on_off_button(channel, 50, name='%d_Mute_Button' % channel) for channel in xrange(NUM_TRACKS) ]])
        self._crossfade_buttons = ButtonMatrixElement(rows=[[ make_button(channel, 66, name='%d_Crossfade_Button' % channel, skin=self._crossfade_button_skin) for channel in xrange(NUM_TRACKS) ]])
        self._select_buttons = ButtonMatrixElement(rows=[self._raw_select_buttons])
        self._master_select_button = make_on_off_button(channel=0, identifier=80, name='Master_Select_Button')
        self._send_select_buttons = ButtonMatrixElement(rows=[[ ComboElement(button, modifiers=[self._sends_button]) for button in self._raw_select_buttons ]])
        self._quantization_buttons = ButtonMatrixElement(rows=[[ ComboElement(button, modifiers=[self._shift_button]) for button in self._raw_select_buttons ]])
        self._metronome_button = make_on_off_button(0, 90, name='Metronome_Button')
        self._play_button = make_on_off_button(0, 91, name='Play_Button')
        self._record_button = make_on_off_button(0, 93, name='Record_Button')
        self._session_record_button = make_on_off_button(0, 102, name='Session_Record_Button')
        self._nudge_down_button = make_button(0, 100, name='Nudge_Down_Button')
        self._nudge_up_button = make_button(0, 101, name='Nudge_Up_Button')
        self._tap_tempo_button = make_button(0, 99, name='Tap_Tempo_Button')
        self._tempo_control = make_encoder(0, 13, name='Tempo_Control')
        self._device_controls = ButtonMatrixElement(rows=[[ make_ring_encoder(16 + index, 24 + index, name='Device_Control_%d' % index) for index in xrange(8) ]])
        self._device_control_buttons_raw = [ make_on_off_button(0, 58 + index) for index in xrange(8) ]
        self._device_bank_buttons = ButtonMatrixElement(rows=[[ DeviceBankButtonElement(button, modifiers=[self._shift_button]) for button in self._device_control_buttons_raw ]])
        self._device_prev_bank_button = self._device_control_buttons_raw[2]
        self._device_prev_bank_button.name = 'Device_Prev_Bank_Button'
        self._device_next_bank_button = self._device_control_buttons_raw[3]
        self._device_next_bank_button.name = 'Device_Next_Bank_Button'
        self._device_on_off_button = self._device_control_buttons_raw[4]
        self._device_on_off_button.name = 'Device_On_Off_Button'
        self._device_lock_button = self._device_control_buttons_raw[5]
        self._device_lock_button.name = 'Device_Lock_Button'
        self._prev_device_button = self._device_control_buttons_raw[0]
        self._prev_device_button.name = 'Prev_Device_Button'
        self._next_device_button = self._device_control_buttons_raw[1]
        self._next_device_button.name = 'Next_Device_Button'
        self._clip_device_button = self._device_control_buttons_raw[6]
        self._clip_device_button.name = 'Clip_Device_Button'
        self._detail_view_button = self._device_control_buttons_raw[7]
        self._detail_view_button.name = 'Detail_View_Button'
        self._foot_pedal_button = DoublePressElement(make_pedal_button(64, name='Foot_Pedal'))
        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_bank_toggle(self):
        self._bank_toggle = BankToggleComponent(is_enabled=False, layer=Layer(bank_toggle_button=self._bank_button))

    def _create_session(self):

        def when_bank_on(button):
            return self._bank_toggle.create_toggle_element(on_control=button)

        def when_bank_off(button):
            return self._bank_toggle.create_toggle_element(off_control=button)

        self._session = SessionComponent(NUM_TRACKS, NUM_SCENES, auto_name=True, is_enabled=False, enable_skinning=True, layer=Layer(track_bank_left_button=when_bank_off(self._left_button), track_bank_right_button=when_bank_off(self._right_button), scene_bank_up_button=when_bank_off(self._up_button), scene_bank_down_button=when_bank_off(self._down_button), page_left_button=when_bank_on(self._left_button), page_right_button=when_bank_on(self._right_button), page_up_button=when_bank_on(self._up_button), page_down_button=when_bank_on(self._down_button), stop_track_clip_buttons=self._stop_buttons, stop_all_clips_button=self._stop_all_button, scene_launch_buttons=self._scene_launch_buttons, clip_launch_buttons=self._session_matrix))
        clip_color_table = colors.CLIP_COLOR_TABLE.copy()
        clip_color_table[16777215] = 119
        self._session.set_rgb_mode(clip_color_table, colors.RGB_COLOR_TABLE)
        self._session_zoom = SessionZoomingComponent(self._session, name='Session_Overview', enable_skinning=True, is_enabled=False, layer=Layer(button_matrix=self._shifted_matrix, nav_left_button=self._with_shift(self._left_button), nav_right_button=self._with_shift(self._right_button), nav_up_button=self._with_shift(self._up_button), nav_down_button=self._with_shift(self._down_button), scene_bank_buttons=self._shifted_scene_buttons))

    def _create_mixer(self):
        self._mixer = MixerComponent(NUM_TRACKS, 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, shift_button=self._shift_button, track_select_buttons=self._select_buttons, prehear_volume_control=self._prehear_control, crossfader_control=self._crossfader_control, crossfade_buttons=self._crossfade_buttons))
        self._mixer.master_strip().layer = Layer(volume_control=self._master_volume_control, select_button=self._master_select_button)
        self._encoder_mode = ModesComponent(name='Encoder_Mode', is_enabled=False)
        self._encoder_mode.default_behaviour = ImmediateBehaviour()
        self._encoder_mode.add_mode('pan', [AddLayerMode(self._mixer, Layer(pan_controls=self._mixer_encoders))])
        self._encoder_mode.add_mode('sends', [AddLayerMode(self._mixer, Layer(send_controls=self._mixer_encoders)), DelayMode(AddLayerMode(self._mixer, Layer(send_select_buttons=self._send_select_buttons)))])
        self._encoder_mode.add_mode('user', [AddLayerMode(self._mixer, Layer(user_controls=self._mixer_encoders))])
        self._encoder_mode.layer = Layer(pan_button=self._pan_button, sends_button=self._sends_button, user_button=self._user_button)
        self._encoder_mode.selected_mode = 'pan'

    def _create_transport(self):
        self._transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(shift_button=self._shift_button, play_button=self._play_button, stop_button=ComboElement(self._play_button, modifiers=[self._shift_button]), record_button=self._record_button, metronome_button=self._metronome_button, tap_tempo_button=self._tap_tempo_button, nudge_down_button=self._nudge_down_button, nudge_up_button=self._nudge_up_button, tempo_encoder=self._tempo_control), play_toggle_model_transform=lambda v: v)

    def _create_device(self):
        self._device = DeviceComponent(name='Device', is_enabled=False, layer=Layer(parameter_controls=self._device_controls, bank_buttons=self._device_bank_buttons, bank_prev_button=self._device_prev_bank_button, bank_next_button=self._device_next_bank_button, on_off_button=self._device_on_off_button, lock_button=self._device_lock_button))

    def _create_view_control(self):
        self._view_control = DetailViewCntrlComponent(name='View_Control', is_enabled=False, layer=Layer(device_nav_left_button=self._prev_device_button, device_nav_right_button=self._next_device_button, device_clip_toggle_button=self._clip_device_button, detail_toggle_button=self._detail_view_button))
        self._view_control.device_clip_toggle_button.pressed_color = 'DefaultButton.On'

    def _create_quantization_selection(self):
        self._quantization_selection = QuantizationComponent(name='Quantization_Selection', is_enabled=False, layer=Layer(quantization_buttons=self._quantization_buttons))

    def _create_recording(self):
        record_button = MultiElement(self._session_record_button, self._foot_pedal_button.single_press)
        self._session_recording = SessionRecordingComponent(ClipCreator(), self._view_control, name='Session_Recording', is_enabled=False, layer=Layer(new_button=self._foot_pedal_button.double_press, record_button=record_button, _uses_foot_pedal=self._foot_pedal_button))

    def _create_m4l_interface(self):
        self._m4l_interface = M4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard, priority=1)
        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 get_matrix_button(self, column, row):
        return self._matrix_rows_raw[row][column]

    def _product_model_id_byte(self):
        return 41
Ejemplo n.º 34
0
class Crate(ControlSurface):
    __module__ = __name__
    __doc__ = " Monomodular controller script for Crate "

    def __init__(self, *a, **k):
        super(Crate, self).__init__(*a, **k)
        self._host_name = 'Crate'
        self._version_check = '1.0'
        self._rgb = 0
        self._timer = 0
        self._touched = 0
        self.flash_status = 1
        with self.component_guard():
            self._setup_monobridge()
            self._setup_controls()
            self._setup_session()
            self._setup_next_buttons()
            self._setup_tempo()
            self._setup_modes()
            self._create_fallback_control_owner()
        self.schedule_message(1, self._open_log)
        self.schedule_message(3, self._initialize_surface)

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

    def _initialize_surface(self):
        debug('setting to main mode')
        #self._main_modes.selected_mod = 'Main'
        #self._session.set_enabled(True)

    def port_settings_changed(self):
        debug('port settings changed!')
        self._connected = False
        super(Crate, self).port_settings_changed()

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

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

    def _setup_controls(self):
        self._button = [
            CrateButtonElement(True,
                               MIDI_NOTE_TYPE,
                               0,
                               index,
                               name='Button_' + str(index),
                               script=self) for index in range(20)
        ]
        self._track_button = [
            CrateButtonElement(True,
                               MIDI_NOTE_TYPE,
                               0,
                               index + 50,
                               name='Button_' + str(index + 50),
                               script=self) for index in range(6)
        ]
        self._next_button = [
            CrateButtonElement(True,
                               MIDI_NOTE_TYPE,
                               0,
                               index + 60,
                               name='Button_' + str(index + 60),
                               script=self) for index in range(2)
        ]
        self._crate_button = [
            CrateButtonElement(True,
                               MIDI_NOTE_TYPE,
                               0,
                               index + 70,
                               name='Button_' + str(index + 70),
                               script=self) for index in range(3)
        ]
        #self._tempo_slider = EncoderElement(MIDI_CC_TYPE, 0, 0, Live.MidiMap.MapMode.absolute, name = 'Slider')

        self._matrix = ButtonMatrixElement(name='Matrix',
                                           rows=[[self._button[index]]
                                                 for index in range(20)])

        self._left_matrix = ButtonMatrixElement(name='Left_Matrix',
                                                rows=[[self._button[index]]
                                                      for index in range(10)])
        self._right_matrix = ButtonMatrixElement(
            name='Right_Matrix',
            rows=[[self._button[index + 10]] for index in range(10)])

        self._track_select_matrix = ButtonMatrixElement(
            name='Track_Matrix', rows=[self._track_button])

    def _setup_session(self):
        self._left_session = CrateSessionComponent(
            script=self,
            name='Session_Component_A',
            num_tracks=1,
            num_scenes=20,
            autonaming=True,
            is_enabled=False,
            layer=Layer(priority=1,
                        clip_launch_buttons=self._matrix,
                        track_nav_buttons=self._track_select_matrix))
        self._left_session.set_group_track('DECK A')
        self._left_session_zooming = SessionZoomingComponent(
            session=self._left_session)

        self._right_session = CrateSessionComponent(
            script=self,
            name='Session_Component_B',
            num_tracks=1,
            num_scenes=20,
            autonaming=True,
            is_enabled=False,
            layer=Layer(priority=1,
                        clip_launch_buttons=self._matrix,
                        track_nav_buttons=self._track_select_matrix))
        self._right_session.set_group_track('DECK B')
        self._right_session_zooming = SessionZoomingComponent(
            session=self._right_session)

        self._left_set_session = CrateSetSessionComponent(
            script=self,
            name='Session_Component_SETA',
            num_tracks=1,
            num_scenes=10,
            autonaming=True,
            is_enabled=False,
            layer=Layer(priority=1, clip_launch_buttons=self._left_matrix))
        self._left_set_session.set_group_track('SET A')
        self._left_set_session_zooming = SessionZoomingComponent(
            session=self._left_set_session)

        self._right_set_session = CrateSetSessionComponent(
            script=self,
            name='Session_Component_SETB',
            num_tracks=1,
            num_scenes=10,
            autonaming=True,
            is_enabled=False,
            layer=Layer(priority=1, clip_launch_buttons=self._right_matrix))
        self._right_set_session.set_group_track('SET B')
        self._right_set_session_zooming = SessionZoomingComponent(
            session=self._right_set_session)

    def _setup_next_buttons(self):
        self._next_a_button = FireNextClipComponent()
        self._next_a_button.set_track('SET A')
        self._next_a_button.layer = Layer(button=self._next_button[0])

        self._next_b_button = FireNextClipComponent()
        self._next_b_button.set_track('SET B')
        self._next_b_button.layer = Layer(button=self._next_button[1])

    def _setup_tempo(self):
        self._on_tempo_changed.subject = self.song()
        self._on_tempo_changed()

    @subject_slot('value')
    def _on_tempo_slider_value(self, value):
        self.song().tempo = ((value / 127.) * 979.) + 20.

    @subject_slot('tempo')
    def _on_tempo_changed(self, *a, **k):
        debug('on tempo changed:', self.song().tempo)
        new_tempo = self.song().tempo
        #self._on_tempo_slider_value.subject and self._on_tempo_slider_value.subject.send_value(((new_tempo-20)/979)*127)
        self.send_tempo('Tempo ' + str(new_tempo))

    def _setup_modes(self):

        next_buttons = CompoundMode(self._next_a_button, self._next_a_button)
        self._main_modes = ModesComponent(name='MainModes')
        self._main_modes.add_mode('disabled', None)
        self._main_modes.add_mode('left_session',
                                  [self._left_session, next_buttons])
        self._main_modes.add_mode('right_session',
                                  [self._right_session, next_buttons])
        self._main_modes.add_mode(
            'set_session',
            [self._left_set_session, self._right_set_session, next_buttons])
        self._main_modes.layer = Layer(
            priority=6,
            left_session_button=self._crate_button[0],
            right_session_button=self._crate_button[1],
            set_session_button=self._crate_button[2])
        self._main_modes.selected_mode = 'set_session'
        self._main_modes.set_enabled(True)

        #self._next_a_button.set_enabled(True)
        #self._next_b_button.set_enabled(True)

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

    def update_display(self):
        super(Crate, 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)

    @subject_slot('appointed_device')
    def _on_device_changed(self):
        debug('appointed device changed, script')

    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 += ' '
        ret = ret.replace(' ', '_')
        assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
        return ret

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

    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 handle_sysex(self, midi_bytes):
        pass

    def disconnect(self):
        self.log_message("<<<<<<<<<<<<<<<<<<<<<<<<< " + str(self._host_name) +
                         " log closed >>>>>>>>>>>>>>>>>>>>>>>>>")
        super(Crate, self).disconnect()

    def handle_sysex(self, midi_bytes):
        #debug('sysex: ', str(midi_bytes))
        pass

    def clip_name(self, sender, name):
        offset = self._button.index(sender)
        shortname = encode_name_to_sysex(name)
        display_sysex = (240, 0, 0, 102, 1,
                         offset) + tuple(shortname) + (247, )
        self._do_send_midi(display_sysex)

    def track_name(self, offset, name):
        shortname = encode_name_to_sysex(name)
        display_sysex = (240, 0, 0, 102, 2,
                         offset) + tuple(shortname) + (247, )
        self._do_send_midi(display_sysex)

    def send_tempo(self, tempo):
        shortname = encode_name_to_sysex(tempo)
        display_sysex = (
            240,
            0,
            0,
            102,
            3,
        ) + tuple(shortname) + (247, )
        self._do_send_midi(display_sysex)


#	a
Ejemplo n.º 35
0
class Roland_A_PRO(ControlSurface):
    def __init__(self, *a, **k):
        super(Roland_A_PRO, self).__init__(*a, **k)
        with self.component_guard():
            self._create_controls()
            self._create_transport()
            self._create_mixer()
            self._create_device()
            self._create_drums()
            self._create_modes()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[
            EncoderElement(MIDI_CC_TYPE,
                           0,
                           identifier,
                           Live.MidiMap.MapMode.absolute,
                           name='Encoder_%d' % index)
            for index, identifier in enumerate(ENCODER_IDS)
        ]])
        self._master_encoder = EncoderElement(MIDI_CC_TYPE,
                                              0,
                                              10,
                                              Live.MidiMap.MapMode.absolute,
                                              name='Master_Encoder')
        self._sliders = ButtonMatrixElement(rows=[[
            SliderElement(
                MIDI_CC_TYPE, 0, identifier, name='Slider_%d' % index)
            for index, identifier in enumerate(SLIDER_IDS)
        ]])
        self._master_slider = SliderElement(MIDI_CC_TYPE,
                                            0,
                                            7,
                                            name='Master_Slider')
        self._play_button = ButtonElement(True, MIDI_CC_TYPE, 0, 26)
        self._stop_button = ButtonElement(True, MIDI_CC_TYPE, 0, 25)
        self._record_button = ButtonElement(True, MIDI_CC_TYPE, 0, 28)
        self._forward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 24)
        self._backward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 21)
        self._ff_button = ButtonElement(True, MIDI_CC_TYPE, 0, 23)
        self._rw_button = ButtonElement(True, MIDI_CC_TYPE, 0, 22)
        self._device_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 80)
        self._pan_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 81)
        self._send_a_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 82)
        self._send_b_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 83)
        self._pads = ButtonMatrixElement(rows=[[
            ButtonElement(True, MIDI_NOTE_TYPE, 0, identifier)
            for identifier in row
        ] for row in PAD_ROWS])

    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))
        self._transport.set_enabled(True)

    def _create_mixer(self):
        mixer_size = self._sliders.width()
        self._mixer = MixerComponent(
            mixer_size,
            name='Mixer',
            is_enabled=False,
            layer=Layer(volume_controls=self._sliders,
                        prehear_volume_control=self._master_encoder))
        self._mixer.master_strip().layer = Layer(
            volume_control=self._master_slider)
        self._mixer.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(
            device_selection_follows_track_selection=True)
        self._device_navigation = DeviceNavigationComponent()
        self._device.set_enabled(True)
        self._device_navigation.set_enabled(True)
        self.set_device_component(self._device)

    def _create_drums(self):
        self._drums = DrumRackComponent(name='Drum_Rack',
                                        is_enabled=False,
                                        layer=Layer(pads=self._pads))
        self._drums.set_enabled(True)

    def _create_modes(self):
        self._encoder_modes = ModesComponent()
        device_layer_mode = LayerMode(self._device,
                                      Layer(parameter_controls=self._encoders))
        device_navigation_layer_mode = LayerMode(
            self._device_navigation,
            Layer(device_nav_right_button=self._forward_button,
                  device_nav_left_button=self._backward_button))
        self._encoder_modes.add_mode(
            'device_mode', [device_layer_mode, device_navigation_layer_mode])
        self._encoder_modes.add_mode(
            'pan_mode',
            AddLayerMode(
                self._mixer,
                Layer(pan_controls=self._encoders,
                      bank_up_button=self._forward_button,
                      bank_down_button=self._backward_button,
                      track_up_button=self._ff_button,
                      track_down_button=self._rw_button)))
        send_layer_mode = AddLayerMode(
            self._mixer,
            Layer(send_controls=self._encoders,
                  bank_up_button=self._forward_button,
                  bank_down_button=self._backward_button,
                  track_up_button=self._ff_button,
                  track_down_button=self._rw_button))
        self._encoder_modes.add_mode(
            'send_a_mode', [send_layer_mode,
                            partial(self._set_send_index, 0)])
        self._encoder_modes.add_mode(
            'send_b_mode', [send_layer_mode,
                            partial(self._set_send_index, 1)])
        self._encoder_modes.layer = Layer(
            device_mode_button=self._device_mode_button,
            pan_mode_button=self._pan_mode_button,
            send_a_mode_button=self._send_a_mode_button,
            send_b_mode_button=self._send_b_mode_button)
        self._encoder_modes.selected_mode = 'device_mode'
        self._encoder_modes.set_enabled(True)

    def _set_send_index(self, index):
        self._mixer.send_index = index
Ejemplo n.º 36
0
class LaunchControl(ControlSurface):
    def __init__(self, c_instance):
        super(LaunchControl, self).__init__(c_instance)
        with self.component_guard():
            self._init_mixer()
            self._init_session()
            self._init_device()
            self._init_modes()
            self._refresh_state_task = self._tasks.add(
                Task.sequence(Task.delay(3), Task.run(self._do_refresh_state)))
            self._refresh_state_task.kill()
        self.log_message('Launch Control script loaded')

    def disconnect(self):
        super(LaunchControl, self).disconnect()
        for channel in range(16):
            self._send_midi((CC_STATUS + channel, 0, 0))

    def refresh_state(self):
        self._refresh_state_task.restart()

    def _do_refresh_state(self):
        self._send_current_mode()
        self._update_hardware()
        self.schedule_message(3, super(LaunchControl, self).refresh_state)

    def _update_hardware(self):
        for channel in range(8, 11):
            self._send_midi(Sysex.make_automatic_flashing_message(channel))

    def _send_current_mode(self):
        try:
            self._send_midi(MODE_SYSEX_MAP[self._modes.selected_mode])
        except KeyError:
            pass

    def _init_mixer(self):
        make_button = partial(make_launch_control_button, channel=8)
        make_encoder = partial(make_launch_control_encoder, channel=8)
        bottom_encoders, top_encoders = make_all_encoders(
            'Mixer', make_encoder)
        pan_volume_layer = Layer(
            volume_controls=ButtonMatrixElement(rows=[bottom_encoders]),
            pan_controls=ButtonMatrixElement(rows=[top_encoders]))
        sends_layer = Layer(sends_controls=ButtonMatrixElement(
            rows=[bottom_encoders, top_encoders]))
        modes_layer = Layer(pan_volume_button=(make_button(
            114, 'Pan_Volume_Mode_Button')),
                            sends_button=(make_button(115,
                                                      'Sends_Mode_Button')))
        self._mixer = SpecialMixerComponent(8, modes_layer, pan_volume_layer,
                                            sends_layer)
        self._mixer.set_enabled(False)
        self._mixer.name = 'Mixer'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer_track_nav_layer = Layer(
            track_bank_left_button=(make_button(116,
                                                'Mixer_Track_Left_Button')),
            track_bank_right_button=(make_button(117,
                                                 'Mixer_Track_Right_Button')))
        for index in range(8):
            strip = self._mixer.channel_strip(index)
            strip.name = 'Channel_Strip_' + str(index)
            strip.empty_color = Colors.LED_OFF
            strip.set_invert_mute_feedback(True)
            mute_button = make_button((pad_identifiers[index]),
                                      ('Track_Mute_Button_' + str(index)),
                                      is_pad=True)
            mute_button.set_on_off_values(Colors.AMBER_FULL,
                                          Colors.AMBER_THIRD)
            strip.set_mute_button(mute_button)

        self._on_selected_send_index.subject = self._mixer
        self._on_selected_mixer_mode.subject = self._mixer

    def _init_session(self):
        make_button = partial(make_launch_control_button, channel=9)
        make_encoder = partial(make_launch_control_encoder, channel=9)
        bottom_encoders, top_encoders = make_all_encoders(
            'Session_Mixer', make_encoder)
        pan_volume_layer = Layer(
            volume_controls=ButtonMatrixElement(rows=[bottom_encoders]),
            pan_controls=ButtonMatrixElement(rows=[top_encoders]))
        self._session_mixer = SpecialMixerComponent(8, Layer(),
                                                    pan_volume_layer, Layer())
        self._session_mixer.set_enabled(False)
        self._session_mixer.name = 'Session_Mixer'
        clip_launch_buttons = [
            make_button(identifier, ('Clip_Launch_Button_' + str(i)),
                        is_pad=True)
            for i, identifier in enumerate(pad_identifiers)
        ]
        self._session = SpecialSessionComponent(num_tracks=8,
                                                num_scenes=0,
                                                name='Session')
        self._session.set_enabled(False)
        self._session.set_mixer(self._session_mixer)
        self._session_layer = Layer(
            track_bank_left_button=(make_button(116,
                                                'Track_Bank_Left_Button')),
            track_bank_right_button=(make_button(117,
                                                 'Track_Bank_Right_Button')),
            select_prev_button=(make_button(114, 'Scene_Bank_Up_Button')),
            select_next_button=(make_button(115, 'Scene_Bank_Down_Button')),
            clip_launch_buttons=ButtonMatrixElement(
                rows=[clip_launch_buttons]))
        scene = self._session.selected_scene()
        for index in range(8):
            clip_slot = scene.clip_slot(index)
            clip_slot.set_triggered_to_play_value(Colors.GREEN_BLINK)
            clip_slot.set_triggered_to_record_value(Colors.RED_BLINK)
            clip_slot.set_stopped_value(Colors.AMBER_FULL)
            clip_slot.set_started_value(Colors.GREEN_FULL)
            clip_slot.set_recording_value(Colors.RED_FULL)
            clip_slot.name = 'Selected_Clip_Slot_' + str(index)

        self._on_track_offset.subject = self._session

    def _init_device(self):
        make_button = partial(make_launch_control_button, channel=10)
        make_encoder = partial(make_launch_control_encoder, channel=10)
        bottom_encoders, top_encoders = make_all_encoders(
            'Device', make_encoder)
        parameter_controls = top_encoders[:4] + bottom_encoders[:4]
        bank_buttons = [
            make_button(identifier, ('Device_Bank_Button_' + str(i)),
                        is_pad=True)
            for i, identifier in enumerate(pad_identifiers)
        ]
        for button in bank_buttons:
            button.set_on_off_values(Colors.LED_ON, Colors.LED_OFF)

        self._device_bank_registry = DeviceBankRegistry()
        self._device = DeviceComponent(
            device_bank_registry=(self._device_bank_registry),
            name='Device',
            device_selection_follows_track_selection=True)
        self._device.set_enabled(False)
        self._device.layer = Layer(
            parameter_controls=ButtonMatrixElement(rows=[parameter_controls]),
            bank_buttons=ButtonMatrixElement(rows=[bank_buttons]))
        self.set_device_component(self._device)
        self._device_navigation = DeviceNavigationComponent()
        self._device_navigation.set_enabled(False)
        self._device_navigation.name = 'Device_Navigation'
        self._device_navigation.layer = Layer(
            next_device_button=(make_button(115, 'Next_Device_Button')),
            previous_device_button=(make_button(114, 'Prev_Device_Button')))
        self._view_control = ViewControlComponent()
        self._view_control.set_enabled(False)
        self._view_control.name = 'View_Control'
        self._view_control.layer = Layer(
            next_track_button=(make_button(117, 'Device_Next_Track_Button')),
            prev_track_button=(make_button(116, 'Device_Prev_Track_Button')))

    def _init_modes(self):
        self._modes = ModesComponent(is_root=True)
        self._modes.add_mode('mixer', [
            partial(self._session.set_mixer, self._mixer),
            LayerMode(self._session, self._mixer_track_nav_layer), self._mixer,
            self._session, self._show_controlled_tracks_message
        ])
        self._modes.add_mode('session', [
            partial(self._session.set_mixer, self._session_mixer),
            LayerMode(self._session, self._session_layer), self._session_mixer,
            self._session, self._show_controlled_tracks_message
        ])
        self._modes.add_mode(
            'device',
            [self._device, self._device_navigation, self._view_control])
        self._modes.add_mode('user', None)
        self._modes.selected_mode = 'mixer'
        self._modes.layer = Layer(
            mixer_button=(ButtonSysexControl(Sysex.MIXER_MODE)),
            session_button=(ButtonSysexControl(Sysex.SESSION_MODE)),
            device_button=(ButtonSysexControl(Sysex.DEVICE_MODE)))

    @subject_slot('offset')
    def _on_track_offset(self):
        self._show_controlled_tracks_message()

    @subject_slot('selected_send_index')
    def _on_selected_send_index(self, index):
        self._show_controlled_sends_message()

    @subject_slot('selected_mixer_mode')
    def _on_selected_mixer_mode(self, mode):
        if mode == 'sends':
            self._show_controlled_sends_message()
        else:
            self.show_message('Controlling Pan and Volume')

    def _show_controlled_tracks_message(self):
        start = self._session.track_offset() + 1
        end = min(start + 8, len(self._session.tracks_to_use()))
        if start < end:
            self.show_message('Controlling Track %d to %d' % (start, end))
        else:
            self.show_message('Controlling Track %d' % start)

    def _show_controlled_sends_message(self):
        send_index = self._mixer.selected_send_index
        send_name1 = chr(ord('A') + send_index)
        if send_index + 1 < self._mixer.num_sends:
            send_name2 = chr(ord('A') + send_index + 1)
            self.show_message('Controlling Send %s and %s' %
                              (send_name1, send_name2))
        else:
            self.show_message('Controlling Send %s' % send_name1)

    def handle_sysex(self, midi_bytes):
        super(LaunchControl, self).handle_sysex(midi_bytes)
        if self._is_user_mode_message(midi_bytes):
            self._modes.selected_mode = 'user'
            self.request_rebuild_midi_map()

    def _is_user_mode_message(self, midi_bytes):
        return midi_bytes[:7] == Sysex.MODE_CHANGE_PREFIX and midi_bytes not in SYSEX_MODE_MAP
class Launchpad_Pro(IdentifiableControlSurface, OptimizedControlSurface):
    identity_request = consts.SYSEX_IDENTITY_REQUEST

    def __init__(self, c_instance, *a, **k):
        product_id_bytes = consts.MANUFACTURER_ID + consts.DEVICE_CODE
        super(Launchpad_Pro, self).__init__(c_instance=c_instance, product_id_bytes=product_id_bytes, *a, **k)
        self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143
        with self.component_guard():
            self._skin = make_default_skin()
            with inject(skin=const(self._skin)).everywhere():
                self._midimap = MidiMap()
            self._target_track_component = TargetTrackComponent(name='Target_Track')
            self._create_background()
            self._create_global_component()
            self._last_sent_mode_byte = None
            with inject(layout_setup=const(self._layout_setup), should_arm=const(self._should_arm_track)).everywhere():
                self._create_session()
                self._create_recording()
                self._create_actions()
                self._create_drums()
                self._create_mixer()
                self._create_device()
                self._create_modes()
                self._create_user()
            self._on_session_record_changed.subject = self.song()
        self.set_device_component(self._device)
        self._on_session_record_changed()
        return

    def disconnect(self):
        self._send_midi(consts.TURN_OFF_LEDS)
        self._send_midi(consts.QUIT_MESSAGE)
        super(Launchpad_Pro, self).disconnect()

    def _create_background(self):
        self._modifier_background_component = ModifierBackgroundComponent(name='Background_Component', is_enabled=False, layer=Layer(shift_button=self._midimap['Shift_Button']))
        self._shifted_background = BackgroundComponent(name='No_Op_Shifted_Buttons', is_enabled=False, layer=Layer(click_bitton=self._midimap.with_shift('Click_Button'), delete_button=self._midimap.with_shift('Delete_Button'), duplicate_button=self._midimap.with_shift('Duplicate_Button'), double_button=self._midimap.with_shift('Double_Loop_Button'), session_record_button=self._midimap.with_shift('Session_Record_Button')))

    def _create_global_component(self):
        self._actions_component = ActionsComponent(name='Global_Actions', is_enabled=False, layer=Layer(undo_button=self._midimap['Undo_Button'], redo_button=self._midimap.with_shift('Undo_Button'), metronome_button=self._midimap['Click_Button'], quantization_on_button=self._midimap.with_shift('Quantize_Button')))

    def _create_session(self):
        self._session = SessionComponent(NUM_TRACKS, NUM_SCENES, auto_name=True, is_enabled=False, enable_skinning=True, layer=Layer(track_bank_left_button=self._midimap['Arrow_Left_Button'], track_bank_right_button=self._midimap['Arrow_Right_Button'], scene_bank_up_button=self._midimap['Arrow_Up_Button'], scene_bank_down_button=self._midimap['Arrow_Down_Button']))
        self._session.set_enabled(True)
        self._session.set_rgb_mode(LIVE_COLORS_TO_MIDI_VALUES, RGB_COLOR_TABLE)
        SpecialClipSlotComponent.quantization_component = self._actions_component
        for scene_index in xrange(NUM_SCENES):
            scene = self._session.scene(scene_index)
            scene.layer = Layer(select_button=self._midimap['Shift_Button'], delete_button=self._midimap['Delete_Button'], duplicate_button=self._midimap['Duplicate_Button'])
            for track_index in xrange(NUM_TRACKS):
                slot = scene.clip_slot(track_index)
                slot.layer = Layer(select_button=self._midimap['Shift_Button'], delete_button=self._midimap['Delete_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_loop_button=self._midimap['Double_Loop_Button'], quantize_button=self._midimap['Quantize_Button'])

        self._session_zoom = SessionZoomingComponent(self._session, name='Session_Overview', is_enabled=True, enable_skinning=True)

    def _create_recording(self):
        self._session_record = SpecialSessionRecordingComponent(self._target_track_component, name='Session_Recording', is_enabled=False, layer=Layer(record_button=self._midimap['Session_Record_Button']))

    def _create_actions(self):
        self._clip_actions_component = ClipActionsComponent(self._target_track_component, name='Clip_Actions', is_enabled=False, layer=Layer(duplicate_button=self._midimap['Duplicate_Button'], double_button=self._midimap['Double_Loop_Button'], quantize_button=self._midimap['Quantize_Button']))
        ClipActionsComponent.quantization_component = self._actions_component

    def _create_drums(self):
        self._drum_group_finder = DrumGroupFinderComponent(self._target_track_component, name='Drum_Group_Finder', is_enabled=False, layer=None)
        self._on_drum_group_changed.subject = self._drum_group_finder
        self._drum_group_finder.set_enabled(True)
        self._drum_group = DrumGroupComponent(self._clip_actions_component, name='Drum_Group_Control', translation_channel=consts.DR_MAP_CHANNEL)
        self._drum_group.set_enabled(True)
        return

    def _create_mixer(self):
        self._mixer = SpecialMixerComponent(NUM_TRACKS, auto_name=True, is_enabled=True, invert_mute_feedback=True)
        self._mixer.name = 'Mixer_Control'
        self._session.set_mixer(self._mixer)

    def _create_device(self):
        self._device = SpecialDeviceComponent(name='Device_Control', is_enabled=False, device_selection_follows_track_selection=True)
        self._device_navigation = DeviceNavigationComponent(name='Device_Navigation')
        self._device_background = BackgroundComponent(name='Device_Background_Component')

    def _setup_drum_group(self):
        self._drum_group.set_drum_group_device(self._drum_group_finder.drum_group)

    def _create_translation(self, comp_name, channel, button_layer, should_enable=True, should_reset=True):
        translation_component = TranslationComponent(name=comp_name, translated_channel=channel, should_enable=should_enable, should_reset=should_reset, is_enabled=False, layer=button_layer)
        setattr(self, '_' + comp_name.lower(), translation_component)
        return translation_component

    def _create_modes(self):
        self._modes = ModesComponent(name='Launchpad_Modes', is_enabled=False)
        self._session_layer_mode = AddLayerMode(self._session, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix'], clip_launch_buttons=self._midimap['Main_Button_Matrix'], delete_button=self._midimap['Delete_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_button=self._midimap['Double_Loop_Button'], quantize_button=self._midimap['Quantize_Button']))
        action_button_background = BackgroundComponent(name='No_Op_Buttons')
        self._action_button_background_layer_mode = LayerMode(action_button_background, Layer(delete_button=self._midimap['Delete_Button'], quantize_button=self._midimap['Quantize_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_button=self._midimap['Double_Loop_Button']))
        self._clip_delete_layer_mode = AddLayerMode(self._clip_actions_component, layer=Layer(delete_button=self._midimap['Delete_Button']))
        self._create_session_zooming_modes()
        self._create_session_mode()
        self._create_note_modes()
        self._create_device_mode()
        self._create_user_mode()
        self._create_record_arm_mode()
        self._create_track_select_mode()
        self._create_mute_mode()
        self._create_solo_mode()
        self._create_volume_mode()
        self._create_pan_mode()
        self._create_sends_mode()
        self._create_stop_clips_mode()
        self._modes.layer = Layer(session_mode_button=self._midimap['Session_Mode_Button'], note_mode_button=self._midimap['Note_Mode_Button'], device_mode_button=self._midimap['Device_Mode_Button'], user_mode_button=self._midimap['User_Mode_Button'], record_arm_mode_button=self._midimap['Record_Arm_Mode_Button'], track_select_mode_button=self._midimap['Track_Select_Mode_Button'], mute_mode_button=self._midimap['Mute_Mode_Button'], solo_mode_button=self._midimap['Solo_Mode_Button'], volume_mode_button=self._midimap['Volume_Mode_Button'], pan_mode_button=self._midimap['Pan_Mode_Button'], sends_mode_button=self._midimap['Sends_Mode_Button'], stop_clip_mode_button=self._midimap['Stop_Clip_Mode_Button'])
        self._modes.selected_mode = 'session_mode'
        self._on_layout_changed.subject = self._modes

    def _create_session_zooming_modes(self):
        session_zoom_layer = Layer(button_matrix=self._midimap['Main_Button_Matrix'], nav_left_button=self._midimap['Arrow_Left_Button'], nav_right_button=self._midimap['Arrow_Right_Button'], nav_up_button=self._midimap['Arrow_Up_Button'], nav_down_button=self._midimap['Arrow_Down_Button'])
        session_zooming_layer_mode = LayerMode(self._session_zoom, session_zoom_layer)
        self._session_zooming_manager = SessionZoomingManagerComponent(self._modes, is_enabled=False)
        session_zooming_button_layer_mode = LayerMode(self._session_zooming_manager, Layer(session_zooming_button=self._midimap['Session_Mode_Button']))
        self._prioritized_session_zooming_button_layer_mode = LayerMode(self._session_zooming_manager, Layer(session_zooming_button=self._midimap['Session_Mode_Button'], priority=1))
        self._session_zooming_background = BackgroundComponent(name='Session_Zooming_Background')
        session_zooming_background_layer_mode = LayerMode(self._session_zooming_background, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix'], delete_button=self._midimap['Delete_Button'], quantize_button=self._midimap['Quantize_Button'], duplicate_button=self._midimap['Duplicate_Button'], double_loop_button=self._midimap['Double_Loop_Button']))
        self._modes.add_mode('session_zooming_mode', [
         self._session_zooming_manager,
         session_zooming_button_layer_mode,
         session_zooming_layer_mode,
         session_zooming_background_layer_mode])
        self._modes.add_mode('prioritized_session_zooming_mode', [
         partial(self._layout_switch, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         session_zooming_layer_mode,
         session_zooming_background_layer_mode,
         self.update])

    def _create_session_mode(self):
        self._modes.add_mode('session_mode', [
         partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         self._session.update_navigation_buttons], behaviour=CancelingReenterBehaviour('session_zooming_mode'))

    def _create_note_modes(self):
        note_mode_matrix_translation = self._create_translation('Note_Mode_Matrix_Translation', consts.CHROM_MAP_CHANNEL, Layer(button_matrix=self._midimap['Main_Button_Matrix'], note_button_matrix=self._midimap['Note_Button_Matrix'], drum_matrix=self._midimap['Drum_Button_Matrix'], mixer_button_matrix=self._midimap['Mixer_Button_Matrix']), should_enable=False)
        note_mode_scene_launch_translation = self._create_translation('Note_Mode_Scene_Launch_Translation', consts.CHROM_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        scale_setup_mode_button_lighting = LedLightingComponent(name='LED_Lighting_Component', is_enabled=False, layer=Layer(button=self._midimap.with_shift('Note_Mode_Button')))
        drum_mode_note_matrix_translation = self._create_translation('Drum_Mode_Note_Button_Translation', 0, Layer(note_button_matrix=self._midimap['Note_Button_Matrix']), should_enable=False, should_reset=False)
        drum_group_layer_mode = LayerMode(self._drum_group, layer=Layer(scroll_up_button=self._midimap['Arrow_Left_Button'], scroll_down_button=self._midimap['Arrow_Right_Button'], scroll_page_up_button=self._midimap['Arrow_Up_Button'], scroll_page_down_button=self._midimap['Arrow_Down_Button'], drum_matrix=self._midimap['Drum_Button_Matrix'], select_button=self._midimap['Shift_Button'], delete_button=self._midimap['Delete_Button']))
        self._note_modes = SpecialModesComponent(name='Note_Modes')
        self._note_modes.add_mode('chromatic_mode', [
         partial(self._layout_setup, consts.NOTE_LAYOUT_SYSEX_BYTE),
         self._clip_delete_layer_mode,
         note_mode_matrix_translation,
         scale_setup_mode_button_lighting])
        self._note_modes.add_mode('drum_mode', [
         partial(self._layout_setup, consts.DRUM_LAYOUT_SYSEX_BYTE),
         self._setup_drum_group,
         drum_group_layer_mode,
         drum_mode_note_matrix_translation])
        self._note_modes.add_mode('audio_mode', [
         partial(self._layout_setup, consts.AUDIO_LAYOUT_SYSEX_BYTE),
         self._clip_delete_layer_mode])
        self._note_modes.set_enabled(False)
        self._modes.add_mode('note_mode', [
         note_mode_scene_launch_translation,
         self._note_modes,
         self._select_note_mode,
         self._select_target_track,
         self._clip_actions_component,
         self._show_playing_clip,
         self._set_clip_actions_type], behaviour=ReenterBehaviour(self.toggle_detail_view))
        self._session_record.set_modes_component(self._modes)
        self._session_record.set_note_mode_name('note_mode')

    def _create_device_mode(self):
        device_mode_scene_launch_translation = self._create_translation('Device_Mode_Scene_Launch_Translation', consts.DEVICE_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        device_layer_mode = LayerMode(self._device, layer=Layer(parameter_controls=self._midimap['Slider_Button_Matrix']))
        device_nav_layer_mode = LayerMode(self._device_navigation, layer=Layer(device_nav_left_button=self._midimap['Arrow_Left_Button'], device_nav_right_button=self._midimap['Arrow_Right_Button']))
        device_background_layer_mode = LayerMode(self._device_background, layer=Layer(arrow_up_button=self._midimap['Arrow_Up_Button'], arrow_down_button=self._midimap['Arrow_Down_Button']))
        self._modes.add_mode('device_mode', [
         partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         self._device,
         device_layer_mode,
         device_nav_layer_mode,
         device_background_layer_mode,
         self._clip_actions_component,
         self._clip_delete_layer_mode,
         device_mode_scene_launch_translation,
         self._show_playing_clip,
         self._set_clip_actions_type], behaviour=ReenterBehaviour(self.toggle_detail_view))

    def _create_user_mode(self):
        self._modes.add_mode('user_mode', [
         partial(self._layout_setup, consts.USER_LAYOUT_SYSEX_BYTE)])

    def _create_record_arm_mode(self):
        arm_layer_mode = LayerMode(self._mixer, layer=Layer(arm_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('record_arm_mode', [
         partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         arm_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_track_select_mode(self):
        track_select_layer_mode = LayerMode(self._mixer, layer=Layer(track_select_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('track_select_mode', [
         partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         track_select_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_mute_mode(self):
        mute_layer_mode = LayerMode(self._mixer, layer=Layer(mute_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('mute_mode', [
         partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         mute_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_solo_mode(self):
        solo_layer_mode = LayerMode(self._mixer, layer=Layer(solo_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('solo_mode', [
         partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         solo_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_volume_mode(self):
        volume_mode_scene_launch_translation = self._create_translation('Volume_Mode_Scene_Launch_Translation', consts.VOLUME_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        volume_layer_mode = LayerMode(self._mixer, layer=Layer(volume_controls=self._midimap['Slider_Button_Matrix']))
        self._modes.add_mode('volume_mode', [
         partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         volume_layer_mode,
         self._action_button_background_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         volume_mode_scene_launch_translation,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_pan_mode(self):
        pan_mode_scene_launch_translation = self._create_translation('Pan_Mode_Scene_Launch_Translation', consts.PAN_MAP_CHANNEL, Layer(scene_launch_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        pan_layer_mode = LayerMode(self._mixer, layer=Layer(pan_controls=self._midimap['Slider_Button_Matrix']))
        self._modes.add_mode('pan_mode', [
         partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         pan_layer_mode,
         self._action_button_background_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         pan_mode_scene_launch_translation,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_sends_mode(self):
        send_layer_mode = LayerMode(self._mixer, layer=Layer(send_controls=self._midimap['Slider_Button_Matrix'], send_select_buttons=self._midimap['Scene_Launch_Button_Matrix']))
        self._modes.add_mode('sends_mode', [
         partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
         send_layer_mode,
         self._action_button_background_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_stop_clips_mode(self):
        stop_layer_mode = AddLayerMode(self._session, Layer(stop_track_clip_buttons=self._midimap['Mixer_Button_Matrix'], stop_scene_clip_buttons=self._midimap['Scene_Stop_Button_Matrix'], stop_all_clips_button=self._midimap['Stop_All_Clips_Button']))
        self._modes.add_mode('stop_clip_mode', [
         partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
         self._session_layer_mode,
         stop_layer_mode,
         self._session_zooming_manager,
         self._prioritized_session_zooming_button_layer_mode,
         self._session.update_navigation_buttons], behaviour=SpecialReenterBehaviour('session_mode'))

    def toggle_detail_view(self):
        view = self.application().view
        if view.is_view_visible('Detail'):
            if view.is_view_visible('Detail/DeviceChain'):
                view.show_view('Detail/Clip')
            else:
                view.show_view('Detail/DeviceChain')

    def _create_user(self):
        self._user_matrix_component = UserMatrixComponent(name='User_Matrix_Component', is_enabled=False, layer=Layer(user_button_matrix_ch_6=self._midimap['User_Button_Matrix_Ch_6'], user_button_matrix_ch_7=self._midimap['User_Button_Matrix_Ch_7'], user_button_matrix_ch_8=self._midimap['User_Button_Matrix_Ch_8'], user_button_matrix_ch_14=self._midimap['User_Button_Matrix_Ch_14'], user_button_matrix_ch_15=self._midimap['User_Button_Matrix_Ch_15'], user_button_matrix_ch_16=self._midimap['User_Button_Matrix_Ch_16'], user_left_side_button_matrix_ch_6=self._midimap['User_Left_Side_Button_Matrix_Ch_6'], user_left_side_button_matrix_ch_7=self._midimap['User_Left_Side_Button_Matrix_Ch_7'], user_left_side_button_matrix_ch_8=self._midimap['User_Left_Side_Button_Matrix_Ch_8'], user_left_side_button_matrix_ch_14=self._midimap['User_Left_Side_Button_Matrix_Ch_14'], user_left_side_button_matrix_ch_15=self._midimap['User_Left_Side_Button_Matrix_Ch_15'], user_left_side_button_matrix_ch_16=self._midimap['User_Left_Side_Button_Matrix_Ch_16'], user_right_side_button_matrix_ch_6=self._midimap['User_Right_Side_Button_Matrix_Ch_6'], user_right_side_button_matrix_ch_7=self._midimap['User_Right_Side_Button_Matrix_Ch_7'], user_right_side_button_matrix_ch_8=self._midimap['User_Right_Side_Button_Matrix_Ch_8'], user_right_side_button_matrix_ch_14=self._midimap['User_Right_Side_Button_Matrix_Ch_14'], user_right_side_button_matrix_ch_15=self._midimap['User_Right_Side_Button_Matrix_Ch_15'], user_right_side_button_matrix_ch_16=self._midimap['User_Right_Side_Button_Matrix_Ch_16'], user_bottom_button_matrix_ch_6=self._midimap['User_Bottom_Button_Matrix_Ch_6'], user_bottom_button_matrix_ch_7=self._midimap['User_Bottom_Button_Matrix_Ch_7'], user_bottom_button_matrix_ch_8=self._midimap['User_Bottom_Button_Matrix_Ch_8'], user_bottom_button_matrix_ch_14=self._midimap['User_Bottom_Button_Matrix_Ch_14'], user_bottom_button_matrix_ch_15=self._midimap['User_Bottom_Button_Matrix_Ch_15'], user_bottom_button_matrix_ch_16=self._midimap['User_Bottom_Button_Matrix_Ch_16'], user_arrow_button_matrix_ch_6=self._midimap['User_Arrow_Button_Matrix_Ch_6'], user_arrow_button_matrix_ch_7=self._midimap['User_Arrow_Button_Matrix_Ch_7'], user_arrow_button_matrix_ch_8=self._midimap['User_Arrow_Button_Matrix_Ch_8'], user_arrow_button_matrix_ch_14=self._midimap['User_Arrow_Button_Matrix_Ch_14'], user_arrow_button_matrix_ch_15=self._midimap['User_Arrow_Button_Matrix_Ch_15'], user_arrow_button_matrix_ch_16=self._midimap['User_Arrow_Button_Matrix_Ch_16']))
        self._user_matrix_component.set_enabled(True)

    @subject_slot('drum_group')
    def _on_drum_group_changed(self):
        if self._note_modes.selected_mode == 'drum_mode':
            self._drum_group.set_drum_group_device(self._drum_group_finder.drum_group)
        if self._modes.selected_mode == 'note_mode':
            self._select_note_mode()
        else:
            self.release_controlled_track()
        self._update_note_mode_button(self._drum_group_finder.drum_group is not None)
        return

    def _select_note_mode(self):
        u"""
        Selects which note mode to use depending on the kind of
        current target track and its device chain.  Will also
        select the target if specified.
        """
        track = self._target_track_component.target_track
        drum_device = self._drum_group_finder.drum_group
        if track is None or track.is_foldable or track in self.song().return_tracks or track == self.song().master_track or track.is_frozen or track.has_audio_input:
            self._note_modes.selected_mode = 'audio_mode'
        else:
            if drum_device:
                self._note_modes.selected_mode = 'drum_mode'
            else:
                self._note_modes.selected_mode = 'chromatic_mode'
        self._modes.update()
        if self._note_modes.selected_mode == 'audio_mode':
            self.release_controlled_track()
        else:
            self.set_controlled_track(self._target_track_component.target_track)
        return

    def _select_target_track(self):
        track = self._target_track_component.target_track
        if track != self.song().view.selected_track:
            self.song().view.selected_track = track

    def _update_note_mode_button(self, focused_track_is_drum_track):
        button = self._midimap['Note_Mode_Button']
        if focused_track_is_drum_track:
            button.default_states = {True: 'Mode.Drum.On', False: 'Mode.Drum.Off'}
        else:
            button.default_states = {True: 'Mode.Chromatic.On', False: 'Mode.Chromatic.Off'}
        button.reset_state()
        self._modes.update()

    def _show_playing_clip(self):
        track = None
        if self._use_sel_track():
            track = self.song().view.selected_track
        else:
            track = self._target_track_component.target_track
        if track in self.song().tracks:
            slot_index = track.fired_slot_index
            if slot_index < 0:
                slot_index = track.playing_slot_index
            if slot_index >= 0:
                clip_slot = track.clip_slots[slot_index]
                self.song().view.highlighted_clip_slot = clip_slot
        return

    def _set_clip_actions_type(self):
        self._clip_actions_component.use_selected_track(self._use_sel_track())
        self._clip_actions_component.update()

    def _use_sel_track(self):
        return self._modes.selected_mode == 'device_mode'

    def _should_arm_track(self):
        return self._modes.selected_mode == 'record_arm_mode'

    @subject_slot('selected_mode')
    def _on_layout_changed(self, mode):
        if mode == 'note_mode':
            self.set_controlled_track(self._target_track_component.target_track)
        else:
            self.release_controlled_track()
        self._session_record.set_enabled(mode != 'user_mode')

    @subject_slot('session_record')
    def _on_session_record_changed(self):
        status = self.song().session_record
        feedback_color = int(self._skin['Instrument.FeedbackRecord'] if status else self._skin['Instrument.Feedback'])
        self._c_instance.set_feedback_velocity(feedback_color)

    def _clear_send_cache(self):
        with self.component_guard():
            for control in self.controls:
                control.clear_send_cache()

    def _update_hardware(self):
        self._clear_send_cache()
        self.update()

    def _update_global_components(self):
        self._actions_component.update()
        self._session_record.update()
        self._modifier_background_component.update()

    def _layout_setup(self, mode):
        self._layout_switch(mode)
        self._clear_send_cache()
        self._update_global_components()

    def _layout_switch(self, mode):
        prefix = consts.SYSEX_STANDARD_PREFIX + consts.SYSEX_PARAM_BYTE_LAYOUT
        suffix = consts.SYSEX_STANDARD_SUFFIX
        self._send_midi(prefix + mode + suffix)
        self._last_sent_mode_byte = mode

    def port_settings_changed(self):
        self.set_highlighting_session_component(None)
        super(Launchpad_Pro, self).port_settings_changed()
        return

    def on_identified(self):
        self._send_challenge()

    def _send_challenge(self):
        challenge_bytes = []
        for index in range(4):
            challenge_bytes.append(self._challenge >> 8 * index & 127)

        challenge = consts.CHALLENGE_PREFIX + tuple(challenge_bytes) + (247, )
        self._send_midi(challenge)

    def _on_handshake_successful(self):
        self._do_send_midi(consts.LIVE_MODE_SWITCH_REQUEST)
        with self.component_guard():
            self._modes.set_enabled(True)
            self._actions_component.set_enabled(True)
            self._session_record.set_enabled(True)
            self._modifier_background_component.set_enabled(True)
            self._shifted_background.set_enabled(True)
            self.release_controlled_track()
            self.set_feedback_channels(consts.FEEDBACK_CHANNELS)
        if self._last_sent_mode_byte is not None:
            self._layout_setup(self._last_sent_mode_byte)
        self.set_highlighting_session_component(self._session)
        self.update()
        return

    def _is_challenge_response(self, midi_bytes):
        return len(midi_bytes) == 10 and midi_bytes[:7] == consts.SYSEX_STANDARD_PREFIX + consts.SYSEX_CHALLENGE_RESPONSE_BYTE

    def _is_response_valid(self, midi_bytes):
        response = long(midi_bytes[7])
        response += long(midi_bytes[8] << 8)
        return response == Live.Application.encrypt_challenge2(self._challenge)

    def handle_sysex(self, midi_bytes):
        if len(midi_bytes) < 7:
            pass
        else:
            if self._is_challenge_response(midi_bytes) and self._is_response_valid(midi_bytes):
                self._on_handshake_successful()
            else:
                if midi_bytes[6] == consts.SYSEX_STATUS_BYTE_LAYOUT and midi_bytes[7] == consts.NOTE_LAYOUT_SYSEX_BYTE[0]:
                    self._update_hardware()
                else:
                    if midi_bytes[6] in (consts.SYSEX_STATUS_BYTE_MODE,
                     consts.SYSEX_STATUS_BYTE_LAYOUT):
                        pass
                    else:
                        super(Launchpad_Pro, self).handle_sysex(midi_bytes)
Ejemplo n.º 38
0
class Launchkey_MK2(OptimizedControlSurface):
    identity_request_delay = 0.5

    def __init__(self, c_instance, *a, **k):
        super(Launchkey_MK2, self).__init__(c_instance=c_instance, *a, **k)
        self._is_25_key_model = False
        self._is_in_control_on = True
        with self.component_guard():
            self._skin = make_skin()
            with inject(skin=const(self._skin)).everywhere():
                self._create_controls()
        self._request_task = self._tasks.add(Task.sequence(Task.wait(self.identity_request_delay), Task.run(self._send_identity_request)))
        self._request_task.kill()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[ make_encoder(identifier, name='Encoder_%d' % (index,)) for index, identifier in enumerate(xrange(21, 29)) ]])
        self._top_pad_row = ButtonMatrixElement(rows=[[ make_button(identifier, name='Pad_0_%d' % (index,)) for index, identifier in enumerate(xrange(96, 104)) ]])
        self._bottom_pad_row_raw = [ make_button(identifier, name='Pad_1_%d' % (index,)) for index, identifier in enumerate(xrange(112, 120)) ]
        self._bottom_pad_row = ButtonMatrixElement(rows=[self._bottom_pad_row_raw])
        self._top_launch_button = make_button(104, name='Scene_Launch_Button')
        self._bottom_launch_button = make_button(120, name='Stop_All_Clips_Button')
        self._scene_up_button = make_button(112, MIDI_CC_TYPE, name='Scene_Up_Button')
        self._scene_down_button = make_button(113, MIDI_CC_TYPE, name='Scene_Down_Button')
        self._stop_button = make_button(114, MIDI_CC_TYPE, name='Stop_Button')
        self._play_button = make_button(115, MIDI_CC_TYPE, name='Play_Button')
        self._loop_button = make_button(116, MIDI_CC_TYPE, name='Loop_Button')
        self._record_button = make_button(117, MIDI_CC_TYPE, name='Record_Button')
        self._sliders = ButtonMatrixElement(rows=[[ make_slider(identifier, name='Slider_%d' % (index,)) for index, identifier in enumerate(xrange(41, 49)) ]])
        self._master_slider = make_slider(7, name='Master_Slider')
        self._25_key_slider = make_slider(7, name='Slider', channel=0)
        self._mute_buttons_raw = [ make_button(identifier, MIDI_CC_TYPE, name='Mute_Button_%d' % (index,)) for index, identifier in enumerate(xrange(51, 59)) ]
        self._mute_buttons = ButtonMatrixElement(rows=[self._mute_buttons_raw])
        self._master_button = make_button(59, MIDI_CC_TYPE, name='Master_Button')
        self._track_left_button = make_button(102, MIDI_CC_TYPE, name='Track_Left_Button')
        self._track_right_button = make_button(103, MIDI_CC_TYPE, name='Track_Right_Button')
        self._device_mode_button = self._bottom_pad_row_raw[0]
        self._pan_mode_button = self._bottom_pad_row_raw[1]
        self._send_mode_buttons = dict()
        for index in xrange(consts.MAX_SENDS):
            setattr(self, '_send_%d_button' % (index,), self._bottom_pad_row_raw[index + 2])
            self._send_mode_buttons['send_%d_mode_button' % (index,)] = getattr(self, '_send_%d_button' % (index,))

        self._extended_mode_button = make_button(12, name='Dummy_Extended_Mode_Button')
        self._extended_mode_button.add_value_listener(nop)
        self._encoder_incontrol_button = make_button(13, is_momentary=False, name='Encoder_InControl_Button')
        self._encoder_incontrol_button.add_value_listener(nop)
        self._slider_incontrol_button = make_button(14, is_momentary=False, name='Fader_InControl_Button')
        self._slider_incontrol_button.add_value_listener(nop)
        self._pad_incontrol_button = make_button(15, is_momentary=False, name='Pad_InControl_Button')
        self._pad_incontrol_button.add_value_listener(self._update_pads)
        self._encoder_incontrol_button2 = make_button(16, name='Encoder_InControl_Button')
        self._pad_in_control_status_button = make_button(11, name='Dummy_InControl_Button')

    def _create_session(self):
        self._session = SessionComponent(name='Session', is_enabled=False, num_tracks=self._top_pad_row.width(), num_scenes=self._top_pad_row.height(), enable_skinning=True, layer=Layer(clip_launch_buttons=self._top_pad_row, scene_launch_buttons=ButtonMatrixElement(rows=[[self._top_launch_button]]), stop_track_clip_buttons=self._bottom_pad_row, stop_all_clips_button=self._bottom_launch_button))
        self._session.set_rgb_mode(CLIP_COLOR_TABLE, RGB_COLOR_TABLE)
        self._session.set_mixer(self._mixer)
        self._session.set_enabled(True)

    def _setup_navigation(self):
        self._session_navigation = SessionNavigationComponent(is_enabled=False, name='Session_Navigation', layer=Layer(next_track_button=self._track_right_button, prev_track_button=self._track_left_button, next_scene_button=self._scene_down_button, prev_scene_button=self._scene_up_button))
        self._session_navigation.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(is_enabled=False, name='Transport', layer=Layer(play_button=self._play_button, stop_button=self._stop_button, loop_button=self._loop_button, record_button=self._record_button))
        self._transport.set_enabled(True)

    def _create_mixer(self):
        mixer_volume_layer = None
        if self._is_25_key_model:
            mixer_volume_layer = Layer(volume_control=self._25_key_slider)
        else:
            mixer_volume_layer = Layer(volume_controls=self._sliders)
        self._mixer = MixerComponent(is_enabled=False, name='Mixer', num_tracks=self._sliders.width(), layer=mixer_volume_layer)
        if not self._is_25_key_model:
            self._mixer.master_strip().layer = Layer(volume_control=self._master_slider)
        self._mixer.set_enabled(True)
        self._mute_button_modes = ModesComponent()
        mute_mode = AddLayerMode(self._mixer, Layer(mute_buttons=self._mute_buttons))
        solo_mode = AddLayerMode(self._mixer, Layer(solo_buttons=self._mute_buttons))
        self._mute_button_modes.add_mode('mute_mode', mute_mode)
        self._mute_button_modes.add_mode('solo_mode', solo_mode, behaviour=CancellableBehaviour())
        self._mute_button_modes.layer = Layer(solo_mode_button=self._master_button)
        self._mute_button_modes.selected_mode = 'mute_mode'
        self._mute_button_modes.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(name='Device', is_enabled=False, device_selection_follows_track_selection=True)
        self.set_device_component(self._device)
        self._device.set_enabled(True)

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

    def _create_encoder_modes(self):
        self._encoder_modes = DisablingModesComponent()
        self._encoder_modes.default_behaviour = mixin(SkinableBehaviourMixin, ImmediateBehaviour)()
        device_mode = LayerMode(self._device, Layer(parameter_controls=self._encoders, bank_buttons=self._top_pad_row))
        pan_mode = AddLayerMode(self._mixer, Layer(pan_controls=self._encoders))
        sends_mode = AddLayerMode(self._mixer, Layer(send_controls=self._encoders))
        background_mode = LayerMode(self._background, Layer(bank_buttons=self._top_pad_row))
        self._encoder_modes.add_mode('device_mode', device_mode, is_enabled=True)
        self._encoder_modes.add_mode('pan_mode', [pan_mode, background_mode], is_enabled=True)
        for index in xrange(6):
            self._encoder_modes.add_mode('send_%d_mode' % (index,), [sends_mode, partial(self._set_send_index, index), background_mode], is_enabled=False)

        self._encoder_modes.selected_mode = 'device_mode'
        self._encoder_modes.set_enabled(True)

    def _create_mode_selector(self):
        self._mode_selector = ModesComponent()
        mode_selection = LayerMode(self._encoder_modes, Layer(device_mode_button=self._device_mode_button, pan_mode_button=self._pan_mode_button, **self._send_mode_buttons))
        device_navigation = AddLayerMode(self._device, Layer(device_nav_left_button=self._track_left_button, device_nav_right_button=self._track_right_button))
        self._mode_selector.add_mode('mode_selection', [partial(self._toggle_in_control, True), mode_selection, device_navigation], behaviour=MomentaryBehaviour())
        session_control = AddLayerMode(self._session, Layer(clip_launch_buttons=self._top_pad_row))
        self._mode_selector.add_mode('session_mode', [partial(self._toggle_in_control, False), session_control])
        self._mode_selector.layer = Layer(mode_selection_button=self._encoder_incontrol_button2)

    def _create_in_control_status_listener(self):
        self._in_control_status = InControlStatusComponent(set_is_in_control_on=self._set_is_in_control_on, is_enabled=False, layer=Layer(in_control_status_button=self._pad_in_control_status_button))
        self._in_control_status.set_enabled(True)

    @subject_slot('value')
    def _update_pads(self, value):
        if value:
            self.update()

    @subject_slot('return_tracks')
    def _on_return_tracks_changed(self):
        num_sends = self._mixer.num_sends
        for index in xrange(6):
            self._encoder_modes.set_mode_enabled('send_%d_mode' % (index,), True if index < num_sends else False)

    def _set_send_index(self, index):
        self._mixer.send_index = index

    def _set_is_in_control_on(self, value):
        self._is_in_control_on = value

    def _toggle_in_control(self, value):
        if not self._is_in_control_on:
            self._send_midi(consts.DRUM_IN_CONTROL_ON_MESSAGE if value else consts.DRUM_IN_CONTROL_OFF_MESSAGE)

    def port_settings_changed(self):
        self._disconnect_and_unregister_all_components()
        self._request_task.restart()

    def handle_sysex(self, midi_bytes):
        if self._is_identity_response(midi_bytes):
            product_id_bytes = self._extract_product_id_bytes(midi_bytes)
            if self._is_identity_response_valid(product_id_bytes):
                self._set_model_type(product_id_bytes)
                self._request_task.kill()
                self.on_identified()
            else:
                self.log_message('MIDI device responded with wrong product id (%s).' % (str(product_id_bytes),))
        else:
            super(Launchkey_MK2, self).handle_sysex(midi_bytes)

    def _extract_product_id_bytes(self, midi_bytes):
        return midi_bytes[5:]

    def _is_identity_response(self, midi_bytes):
        return midi_bytes[3:5] == (6, 2)

    def _is_identity_response_valid(self, product_id_bytes):
        return product_id_bytes[:3] == consts.PRODUCT_ID_BYTE_PREFIX and product_id_bytes[3] in consts.PRODUCT_ID_BYTES

    def _set_model_type(self, product_id_bytes):
        self._is_25_key_model = product_id_bytes[3] == consts.LAUNCHKEY_25_ID_BYTE

    def _send_identity_request(self):
        self._send_midi(consts.IDENTITY_REQUEST)

    def on_identified(self):
        self._extended_mode_button.turn_on()
        with self.component_guard():
            self._create_mixer()
            self._create_session()
            self._setup_navigation()
            self._create_transport()
            self._create_device()
            self._create_background()
            self._create_encoder_modes()
            self._create_mode_selector()
            self._create_in_control_status_listener()
            self._on_return_tracks_changed.subject = self.song()
            self._on_return_tracks_changed()
        self._mode_selector.selected_mode = 'session_mode'
        self.update()

    def disconnect(self):
        self._extended_mode_button.turn_off()
        super(Launchkey_MK2, self).disconnect()
Ejemplo n.º 39
0
class APC40_MkII(APC, OptimizedControlSurface):
    def __init__(self, *a, **k):
        super(APC40_MkII, self).__init__(*a, **k)
        self._color_skin = make_rgb_skin()
        self._default_skin = make_default_skin()
        self._stop_button_skin = make_stop_button_skin()
        self._crossfade_button_skin = make_crossfade_button_skin()
        with self.component_guard():
            self._create_controls()
            self._create_bank_toggle()
            self._create_session()
            self._create_mixer()
            self._create_transport()
            self._create_device()
            self._create_view_control()
            self._create_quantization_selection()
            self._create_recording()
            self._session.set_mixer(self._mixer)
        self.set_highlighting_session_component(self._session)
        self.set_device_component(self._device)

    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)

        def make_color_button(*a, **k):
            button = make_button(skin=self._color_skin, *a, **k)
            button.is_rgb = True
            button.num_delayed_messages = 2
            return button

        def make_matrix_button(track, scene):
            return make_color_button(0,
                                     32 + track - NUM_TRACKS * scene,
                                     name=u'%d_Clip_%d_Button' %
                                     (track, scene))

        def make_stop_button(track):
            return make_button(track,
                               52,
                               name=u'%d_Stop_Button' % track,
                               skin=self._stop_button_skin)

        self._shift_button = make_button(0,
                                         98,
                                         name=u'Shift_Button',
                                         resource_type=PrioritizedResource)
        self._bank_button = make_on_off_button(0, 103, name=u'Bank_Button')
        self._left_button = make_button(0, 97, name=u'Bank_Select_Left_Button')
        self._right_button = make_button(0,
                                         96,
                                         name=u'Bank_Select_Right_Button')
        self._up_button = make_button(0, 94, name=u'Bank_Select_Up_Button')
        self._down_button = make_button(0, 95, name=u'Bank_Select_Down_Button')
        self._stop_buttons = ButtonMatrixElement(
            rows=[[make_stop_button(track) for track in xrange(NUM_TRACKS)]])
        self._stop_all_button = make_button(0,
                                            81,
                                            name=u'Stop_All_Clips_Button')
        self._scene_launch_buttons_raw = [
            make_color_button(0,
                              scene + 82,
                              name=u'Scene_%d_Launch_Button' % scene)
            for scene in xrange(NUM_SCENES)
        ]
        self._scene_launch_buttons = ButtonMatrixElement(
            rows=[self._scene_launch_buttons_raw])
        self._matrix_rows_raw = [[
            make_matrix_button(track, scene) for track in xrange(NUM_TRACKS)
        ] for scene in xrange(NUM_SCENES)]
        self._session_matrix = ButtonMatrixElement(rows=self._matrix_rows_raw)
        self._pan_button = make_on_off_button(0, 87, name=u'Pan_Button')
        self._sends_button = make_on_off_button(
            0, 88, name=u'Sends_Button', resource_type=PrioritizedResource)
        self._user_button = make_on_off_button(0, 89, name=u'User_Button')
        self._mixer_encoders = ButtonMatrixElement(rows=[[
            make_ring_encoder(
                48 + track, 56 + track, name=u'Track_Control_%d' % track)
            for track in xrange(NUM_TRACKS)
        ]])
        self._volume_controls = ButtonMatrixElement(rows=[[
            make_slider(track, 7, name=u'%d_Volume_Control' % track)
            for track in xrange(NUM_TRACKS)
        ]])
        self._master_volume_control = make_slider(
            0, 14, name=u'Master_Volume_Control')
        self._prehear_control = make_encoder(0,
                                             47,
                                             name=u'Prehear_Volume_Control')
        self._crossfader_control = make_slider(0, 15, name=u'Crossfader')
        self._raw_select_buttons = [
            make_on_off_button(channel, 51, name=u'%d_Select_Button' % channel)
            for channel in xrange(NUM_TRACKS)
        ]
        self._arm_buttons = ButtonMatrixElement(rows=[[
            make_on_off_button(channel, 48, name=u'%d_Arm_Button' % channel)
            for channel in xrange(NUM_TRACKS)
        ]])
        self._solo_buttons = ButtonMatrixElement(rows=[[
            make_on_off_button(channel, 49, name=u'%d_Solo_Button' % channel)
            for channel in xrange(NUM_TRACKS)
        ]])
        self._mute_buttons = ButtonMatrixElement(rows=[[
            make_on_off_button(channel, 50, name=u'%d_Mute_Button' % channel)
            for channel in xrange(NUM_TRACKS)
        ]])
        self._crossfade_buttons = ButtonMatrixElement(rows=[[
            make_button(channel,
                        66,
                        name=u'%d_Crossfade_Button' % channel,
                        skin=self._crossfade_button_skin)
            for channel in xrange(NUM_TRACKS)
        ]])
        self._select_buttons = ButtonMatrixElement(
            rows=[self._raw_select_buttons])
        self._master_select_button = make_on_off_button(
            channel=0, identifier=80, name=u'Master_Select_Button')
        self._send_select_buttons = ButtonMatrixElement(rows=[[
            ComboElement(button, modifiers=[self._sends_button])
            for button in self._raw_select_buttons
        ]])
        self._quantization_buttons = ButtonMatrixElement(rows=[[
            ComboElement(button, modifiers=[self._shift_button])
            for button in self._raw_select_buttons
        ]])
        self._metronome_button = make_on_off_button(0,
                                                    90,
                                                    name=u'Metronome_Button')
        self._play_button = make_on_off_button(0, 91, name=u'Play_Button')
        self._record_button = make_on_off_button(0, 93, name=u'Record_Button')
        self._session_record_button = make_on_off_button(
            0, 102, name=u'Session_Record_Button')
        self._nudge_down_button = make_button(0,
                                              100,
                                              name=u'Nudge_Down_Button')
        self._nudge_up_button = make_button(0, 101, name=u'Nudge_Up_Button')
        self._tap_tempo_button = make_button(0, 99, name=u'Tap_Tempo_Button')
        self._tempo_control = make_encoder(0, 13, name=u'Tempo_Control')
        self._device_controls = ButtonMatrixElement(rows=[[
            make_ring_encoder(
                16 + index, 24 + index, name=u'Device_Control_%d' % index)
            for index in xrange(8)
        ]])
        self._device_control_buttons_raw = [
            make_on_off_button(0, 58 + index) for index in xrange(8)
        ]
        self._device_bank_buttons = ButtonMatrixElement(rows=[[
            DeviceBankButtonElement(button, modifiers=[self._shift_button])
            for button in self._device_control_buttons_raw
        ]])
        self._device_prev_bank_button = self._device_control_buttons_raw[2]
        self._device_prev_bank_button.name = u'Device_Prev_Bank_Button'
        self._device_next_bank_button = self._device_control_buttons_raw[3]
        self._device_next_bank_button.name = u'Device_Next_Bank_Button'
        self._device_on_off_button = self._device_control_buttons_raw[4]
        self._device_on_off_button.name = u'Device_On_Off_Button'
        self._device_lock_button = self._device_control_buttons_raw[5]
        self._device_lock_button.name = u'Device_Lock_Button'
        self._prev_device_button = self._device_control_buttons_raw[0]
        self._prev_device_button.name = u'Prev_Device_Button'
        self._next_device_button = self._device_control_buttons_raw[1]
        self._next_device_button.name = u'Next_Device_Button'
        self._clip_device_button = self._device_control_buttons_raw[6]
        self._clip_device_button.name = u'Clip_Device_Button'
        self._detail_view_button = self._device_control_buttons_raw[7]
        self._detail_view_button.name = u'Detail_View_Button'
        self._foot_pedal_button = DoublePressElement(
            make_pedal_button(64, name=u'Foot_Pedal'))
        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_bank_toggle(self):
        self._bank_toggle = BankToggleComponent(
            is_enabled=False,
            layer=Layer(bank_toggle_button=self._bank_button))

    def _create_session(self):
        def when_bank_on(button):
            return self._bank_toggle.create_toggle_element(on_control=button)

        def when_bank_off(button):
            return self._bank_toggle.create_toggle_element(off_control=button)

        self._session = SessionComponent(
            NUM_TRACKS,
            NUM_SCENES,
            auto_name=True,
            is_enabled=False,
            enable_skinning=True,
            layer=Layer(
                track_bank_left_button=when_bank_off(self._left_button),
                track_bank_right_button=when_bank_off(self._right_button),
                scene_bank_up_button=when_bank_off(self._up_button),
                scene_bank_down_button=when_bank_off(self._down_button),
                page_left_button=when_bank_on(self._left_button),
                page_right_button=when_bank_on(self._right_button),
                page_up_button=when_bank_on(self._up_button),
                page_down_button=when_bank_on(self._down_button),
                stop_track_clip_buttons=self._stop_buttons,
                stop_all_clips_button=self._stop_all_button,
                scene_launch_buttons=self._scene_launch_buttons,
                clip_launch_buttons=self._session_matrix))
        clip_color_table = Colors.LIVE_COLORS_TO_MIDI_VALUES.copy()
        clip_color_table[16777215] = 119
        self._session.set_rgb_mode(clip_color_table, Colors.RGB_COLOR_TABLE)
        self._session_zoom = SessionZoomingComponent(
            self._session,
            name=u'Session_Overview',
            enable_skinning=True,
            is_enabled=False,
            layer=Layer(button_matrix=self._shifted_matrix,
                        nav_left_button=self._with_shift(self._left_button),
                        nav_right_button=self._with_shift(self._right_button),
                        nav_up_button=self._with_shift(self._up_button),
                        nav_down_button=self._with_shift(self._down_button),
                        scene_bank_buttons=self._shifted_scene_buttons))

    def _create_mixer(self):
        self._mixer = MixerComponent(
            NUM_TRACKS,
            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,
                        shift_button=self._shift_button,
                        track_select_buttons=self._select_buttons,
                        prehear_volume_control=self._prehear_control,
                        crossfader_control=self._crossfader_control,
                        crossfade_buttons=self._crossfade_buttons))
        self._mixer.master_strip().layer = Layer(
            volume_control=self._master_volume_control,
            select_button=self._master_select_button)
        self._encoder_mode = ModesComponent(name=u'Encoder_Mode',
                                            is_enabled=False)
        self._encoder_mode.default_behaviour = ImmediateBehaviour()
        self._encoder_mode.add_mode(u'pan', [
            AddLayerMode(self._mixer, Layer(pan_controls=self._mixer_encoders))
        ])
        self._encoder_mode.add_mode(u'sends', [
            AddLayerMode(self._mixer,
                         Layer(send_controls=self._mixer_encoders)),
            DelayMode(
                AddLayerMode(
                    self._mixer,
                    Layer(send_select_buttons=self._send_select_buttons)))
        ])
        self._encoder_mode.add_mode(u'user', [
            AddLayerMode(self._mixer,
                         Layer(user_controls=self._mixer_encoders))
        ])
        self._encoder_mode.layer = Layer(pan_button=self._pan_button,
                                         sends_button=self._sends_button,
                                         user_button=self._user_button)
        self._encoder_mode.selected_mode = u'pan'

    def _create_transport(self):
        self._transport = TransportComponent(
            name=u'Transport',
            is_enabled=False,
            layer=Layer(shift_button=self._shift_button,
                        play_button=self._play_button,
                        stop_button=ComboElement(
                            self._play_button, modifiers=[self._shift_button]),
                        record_button=self._record_button,
                        metronome_button=self._metronome_button,
                        tap_tempo_button=self._tap_tempo_button,
                        nudge_down_button=self._nudge_down_button,
                        nudge_up_button=self._nudge_up_button,
                        tempo_encoder=self._tempo_control),
            play_toggle_model_transform=lambda v: v)

    def _create_device(self):
        self._device = DeviceComponent(
            name=u'Device',
            is_enabled=False,
            layer=Layer(parameter_controls=self._device_controls,
                        bank_buttons=self._device_bank_buttons,
                        bank_prev_button=self._device_prev_bank_button,
                        bank_next_button=self._device_next_bank_button,
                        on_off_button=self._device_on_off_button,
                        lock_button=self._device_lock_button),
            device_selection_follows_track_selection=True)

    def _create_view_control(self):
        self._view_control = DetailViewCntrlComponent(
            name=u'View_Control',
            is_enabled=False,
            layer=Layer(device_nav_left_button=self._prev_device_button,
                        device_nav_right_button=self._next_device_button,
                        device_clip_toggle_button=self._clip_device_button,
                        detail_toggle_button=self._detail_view_button))
        self._view_control.device_clip_toggle_button.pressed_color = u'DefaultButton.On'

    def _create_quantization_selection(self):
        self._quantization_selection = QuantizationComponent(
            name=u'Quantization_Selection',
            is_enabled=False,
            layer=Layer(quantization_buttons=self._quantization_buttons))

    def _create_recording(self):
        record_button = MultiElement(self._session_record_button,
                                     self._foot_pedal_button.single_press)
        self._session_recording = SessionRecordingComponent(
            ClipCreator(),
            self._view_control,
            name=u'Session_Recording',
            is_enabled=False,
            layer=Layer(new_button=self._foot_pedal_button.double_press,
                        record_button=record_button,
                        _uses_foot_pedal=self._foot_pedal_button))

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

    def _product_model_id_byte(self):
        return 41
Ejemplo n.º 40
0
class APC40_Selector(APC40):



	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_alt_session()
			self._create_mixer()
			self._create_device()
			self._create_detail_view_control()
			self._create_transport()
			self._create_global_control()
			self._create_session_switcher()
			self._create_delete_component()
			self._create_fallback_control_owner()
			self._session.set_mixer(self._mixer)
			self._alt_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 _on_handshake_successful(self):
		self._suppress_session_highlight = False
		for component in self.components:
			if hasattr(component, 'name') and not (component.name.endswith('Session_Control') or component.name.endswith('Session_Overview')):
				component.set_enabled(True)

		self._on_selected_track_changed()
		self._do_combine()
	

	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))
		self._session.link_with_track_offset(0)
	

	def _create_alt_session(self):
		self._alt_session = SelectingSessionComponent(self, SESSION_WIDTH, SESSION_HEIGHT, auto_name=True, enable_skinning=True, is_enabled=False, layer=Layer(priority = 2, 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,))
		self._alt_session.name = 'Alt_Session_Control'
		self._alt_session_zoom = SessionZoomingComponent(self._alt_session, name='Alt_Session_Overview', enable_skinning=True, is_enabled=False, layer=Layer(priority = 2, 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))
		self._alt_session.link_with_track_offset(0)
	

	def _create_session_switcher(self):
		self._session_switcher =  ModesComponent(name = 'SessionSwitcher')  # is_enabled = False)
		self._session_switcher.add_mode('session', [self._session, self._session_zoom], toggle_value = 'DefaultButton.Off')
		self._session_switcher.add_mode('altsession', [self._alt_session, self._alt_session_zoom, tuple([self._enable_alt_session, self._disable_alt_session])], toggle_value = 'DefaultButton.On')
		self._session_switcher.layer = Layer(toggle_button = self._detail_toggle_button)
		self._session_switcher.selected_mode = 'session'
	

	def _enable_alt_session(self):
		self.set_highlighting_session_component(self._alt_session)
	

	def _disable_alt_session(self):
		self.set_highlighting_session_component(self._session)
	

	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))
	

	def _create_delete_component(self):
		self._delete_component =  ModesComponent(name = 'DeleteClipComponent')
		self._delete_component.add_mode('disabled', None)
		self._delete_component.add_mode('enabled', [DelayMode(tuple([self._delete_on, self._delete_off]), delay = 1.5) ])
		self._delete_component.layer = Layer(toggle_button = self._selected_scene_launch_button)
		self._delete_component.selected_mode = 'disabled'
	

	def _delete_on(self):
		slot = self.song().view.highlighted_clip_slot
		if slot != None and slot.has_clip:
			slot.delete_clip()
	

	def _delete_off(self):
		pass
	

	def _create_global_control(self):
		super(APC40_Selector, self)._create_global_control()