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
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
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
class MonoWing(ControlSurface): def __init__(self, *a, **k): super(MonoWing, self).__init__(*a, **k) self._monomod_version = 'b995' self._codec_version = 'b996' self._cntrlr_version = 'b996' self._cntrlr = None self._host_name = 'MonoWing' self._color_type = 'OhmRGB' self.hosts = [] self._timer = 0 self.flash_status = 0 self._touched = 0 self._last_main_mode = 'looper' with self.component_guard(): self._setup_monobridge() self._setup_controls() self._setup_looper() self._setup_launcher() self._setup_device_control() self._setup_modes() self.schedule_message(1, self._open_log) #self._loop_selector.set_enabled(True) """script initialization methods""" def _open_log(self): self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) + " " + str(self._monomod_version) + " log opened =>>>>>>>>>>>>>>>>>>>") self.show_message(str(self._host_name) + ' Control Surface Loaded') def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_controls(self): self._pedal = [None for index in range(12)] for index in range(9): self._pedal[index] = DoublePressElement(MonoButtonElement(True, MIDI_NOTE_TYPE, 0, PEDAL_DEFS[index], 'Pedal_'+str(index), self)) #is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self self._pedal[index].name = 'Pedal_'+str(index) self._pedal[index]._report = False self._pedal[9] = LoopPedalExpressionElement(self, MIDI_CC_TYPE, 0, 3, Live.MidiMap.MapMode.absolute) self._pedal[9].name = 'Pedal_'+str(9) self._pedal[9]._report = False self._pedal[10] = LoopPedalExpressionElement(self, MIDI_CC_TYPE, 0, 1, Live.MidiMap.MapMode.absolute) self._pedal[10].name = 'Pedal_'+str(10) self._pedal[10]._report = False self._pedal[11] = LoopPedalExpressionElement(self, MIDI_CC_TYPE, 0, 2, Live.MidiMap.MapMode.absolute) self._pedal[11].name = 'Pedal_'+str(11) self._pedal[11]._report = False self._leds = [self._pedal[6], self._pedal[5], self._pedal[4], self._pedal[3]] self._side_buttons = [MonoButtonElement(True, MIDI_NOTE_TYPE, 0, SIDE_DEFS[index], 'Side_Button_'+str(index), self) for index in range(4)] self._select_buttons = ButtonMatrixElement() self._select_buttons.name = 'SelectMatrix' self._select_buttons.add_row([self._pedal[6], self._pedal[5], self._pedal[4], self._pedal[3]]) self._doublepress_select_buttons = ButtonMatrixElement() self._doublepress_select_buttons.name = 'DoublepressSelectMatrix' self._doublepress_select_buttons.add_row([self._pedal[6].double_press, self._pedal[5].double_press, self._pedal[4].double_press, self._pedal[3].double_press]) self._record_button = self._pedal[1] self._mute_button = self._pedal[2] self._overdub_button = self._pedal[0] self._clear_button = self._pedal[7] self._reverse_button = self._pedal[8] self._record_button.turn_off() self._mute_button.turn_off() self._overdub_button.turn_off() self._clear_button.turn_off() self._reverse_button.turn_off() def _setup_looper(self): self._looper = MonolooperComponent(self._leds, self) self._looper.layer = Layer(select_buttons = self._select_buttons, doublepress_select_buttons = self._doublepress_select_buttons, overdub_button = self._pedal[2], record_button = self._pedal[1], mute_button = self._pedal[0], clear_button = self._pedal[7], reverse_button = self._pedal[8], expression_pedal = self._pedal[9],) def _setup_launcher(self): self._launcher = LauncherComponent(self._leds, self) self._launcher.set_enabled(False) self._launcher.layer = Layer(select_buttons = self._select_buttons, doublepress_select_buttons = self._doublepress_select_buttons, fire1_button = self._pedal[2], fire2_button = self._pedal[1], fire3_button = self._pedal[0], fire4_button = self._pedal[8], expression_pedal = self._pedal[9]) def _setup_device_control(self): self._device_control = DeviceControlComponent(self._leds, self) self._device_control.set_enabled(False) self._device_control.layer = Layer(select_buttons = self._select_buttons, doublepress_select_buttons = self._doublepress_select_buttons, toggle1_button = self._pedal[2], toggle2_button = self._pedal[1], toggle3_button = self._pedal[0], toggle4_button = self._pedal[8], expression_pedal = self._pedal[9], expression2 = self._pedal[10], expression3 = self._pedal[11]) def _setup_modes(self): self._button_modes = ModesComponent(name='Button_Modes') self._button_modes.add_mode('launcher', self._launcher) self._button_modes.add_mode('looper', self._looper) self._button_modes.add_mode('device', self._device_control) self._button_modes.selected_mode = 'looper' self._button_modes.layer = Layer(looper_button = self._side_buttons[0], launcher_button = self._side_buttons[1], device_button = self._side_buttons[2]) self._button_modes.set_enabled(True) def receive_led(self, button, value): #self.log_message('receive led: ' + str(index) + ' ' + str(value)) pass def toggle_mode(self): self._button_modes.selected_mode = 'launcher' if self._button_modes.selected_mode is 'looper' else 'looper' self._last_main_mode = self._button_modes.selected_mode #self.log_message('toggle mode to: ' + str(self._button_modes.selected_mode)) def toggle_device_control(self, x): self._button_modes.selected_mode = 'device' if not self._button_modes.selected_mode is 'device' else self._last_main_mode if self._button_modes.selected_mode is 'device': self._device_control.set_bank(x) """called on timer""" def update_display(self): super(MonoWing, self).update_display() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if(self.flash_status > 0): for control in self.controls: if isinstance(control, MonoButtonElement): control.flash(self._timer)
class 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
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
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))
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
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()
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()
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
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
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
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))
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
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
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 # ##
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)
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 )
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)
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
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
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
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)
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()
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
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()