def _create_session_mode(self): session_modes = ModesComponent(is_enabled=False) session_modes.add_mode('session', self._session_mode) session_modes.add_mode('overview', self._session_overview_mode) session_modes.layer = Layer(cycle_mode_button='layout_button') session_modes.selected_mode = 'session' return [session_modes, self._session_navigation]
def _create_clip_mode(self): base_loop_layer = Layer(shift_button='shift_button', loop_button='track_state_buttons_raw[1]') self._loop_controller = LoopSettingsControllerComponent(is_enabled=False) self._model.loopSettingsView = self._loop_controller audio_clip_layer = Layer(warp_mode_encoder='parameter_controls_raw[5]', transpose_encoder='parameter_controls_raw[6]', detune_encoder=self._with_shift('parameter_controls_raw[6]'), gain_encoder='parameter_controls_raw[7]', shift_button='shift_button') audio_clip_controller = AudioClipSettingsControllerComponent(is_enabled=False) self._model.audioClipSettingsView = audio_clip_controller clip_control_mode_selector = ModesComponent(is_enabled=False) clip_control_mode_selector.add_mode('midi', [make_freeze_aware(self._loop_controller, base_loop_layer + Layer(encoders=self.elements.global_param_controls.submatrix[:3, :]))]) clip_control_mode_selector.add_mode('audio', [make_freeze_aware(self._loop_controller, base_loop_layer + Layer(encoders=self.elements.global_param_controls.submatrix[1:4, :], zoom_encoder='fine_grain_param_controls_raw[0]')), make_freeze_aware(audio_clip_controller, audio_clip_layer)]) clip_control_mode_selector.add_mode('no_clip', []) clip_control_mode_selector.selected_mode = 'no_clip' clip_control = ClipControlComponent(loop_controller=self._loop_controller, audio_clip_controller=audio_clip_controller, mode_selector=clip_control_mode_selector, decorator_factory=self._clip_decorator_factory, is_enabled=False) self._model.clipView = clip_control return [partial(self._view_control.show_view, 'Detail/Clip'), clip_control_mode_selector, clip_control]
class Push(PushBase): """ Push controller script. Disclaimer: Any use of the Push control surface code (the "Code") or parts thereof for commercial purposes or in a commercial context is not allowed. Though we do not grant a license for non-commercial use of the Code, you may use it in this regard but should be aware that (1) we reserve the right to deny the future use any time and (2) you need to check whether the use is allowed under the national law applicable to your use. """ input_target_name_for_auto_arm = 'Push Input' def __init__(self, *a, **k): super(Push, self).__init__(*a, **k) with self.component_guard(): self.initialize() logger.info('Push script loaded') self._send_midi(sysex.WELCOME_MESSAGE) def disconnect(self): super(Push, self).disconnect() logger.info('Push script unloaded') self._send_midi(sysex.GOOD_BYE_MESSAGE) def port_settings_changed(self): super(Push, self).port_settings_changed() self._start_handshake_task.restart() def on_select_clip_slot(self, clip_slot): self._selector.on_select_clip(clip_slot) def on_select_scene(self, scene): self._selector.on_select_scene(scene) def on_select_track(self, track): self._selector.on_select_track(track) def _create_components(self): self._init_handshake() self._init_selector() super(Push, self)._create_components() self._init_browser() self._init_track_modes() def _create_settings(self): settings = create_settings(preferences=self.preferences) self.__on_pad_curve.subject = settings['curve'] self.__on_pad_threshold.subject = settings['threshold'] self.__on_aftertouch_threshold.subject = settings['aftertouch_threshold'] return settings def _init_settings(self): super(Push, self)._init_settings() self._init_global_pad_parameters() self._update_pad_params() def _init_selector(self): self._selector = SelectComponent(name='Selector', is_root=True) self._selector.layer = Layer(select_button='select_button') self._selector.selection_display_layer = Layer(display_line='display_line3', priority=consts.DIALOG_PRIORITY) def _init_handshake(self): dongle_message, dongle = make_dongle_message(sysex.DONGLE_ENQUIRY_PREFIX) identity_control = create_sysex_element(sysex.IDENTITY_PREFIX, sysex.IDENTITY_ENQUIRY) dongle_control = create_sysex_element(sysex.DONGLE_PREFIX, dongle_message) presentation_control = create_sysex_element(sysex.DONGLE_PREFIX, sysex.make_presentation_message(self.application())) self._handshake = HandshakeComponent(identity_control=identity_control, dongle_control=dongle_control, presentation_control=presentation_control, dongle=dongle, is_root=True) self._on_handshake_success.subject = self._handshake self._on_handshake_failure.subject = self._handshake self._start_handshake_task = self._tasks.add(task.sequence(task.wait(HANDSHAKE_DELAY), task.run(self._start_handshake))) self._start_handshake_task.kill() def _init_user(self): super(Push, self)._init_user() self._on_push_hardware_mode_changed.subject = self._user self._update_pad_params() def _with_firmware_version(self, major_version, minor_version, control_element): return MinimumFirmwareVersionElement(major_version, minor_version, control_element, self._handshake) def _start_handshake(self): self._start_handshake_task.kill() self.elements.playhead_element.proxied_object = self._c_instance.playhead self._note_repeat.set_note_repeat(self._c_instance.note_repeat) self._accent_component.set_full_velocity(self._c_instance.full_velocity) for control in self.controls: receive_value_backup = getattr(control, '_receive_value_backup', nop) if receive_value_backup != nop: control.receive_value = receive_value_backup send_midi_backup = getattr(control, '_send_midi_backup', nop) if send_midi_backup != nop: control.send_midi = send_midi_backup self._handshake._start_handshake() self.update() @listens('success') def _on_handshake_success(self): logger.info('Handshake succeded with firmware version %.2f!' % self._handshake.firmware_version) self.update() self._c_instance.set_firmware_version(self._handshake.firmware_version) if self._handshake.has_version_requirements(1, 16): self._user.settings = self._settings else: settings = copy(self._settings) del settings['aftertouch_threshold'] self._user.settings = settings @listens('failure') def _on_handshake_failure(self, bootloader_mode): logger.error('Handshake failed, performing harakiri!') if bootloader_mode: self._c_instance.set_firmware_version(0.0) self._c_instance.playhead.enabled = False self.elements.playhead_element.proxied_object = NullPlayhead() self._note_repeat.set_note_repeat(None) self._accent_component.set_full_velocity(None) for control in self.controls: receive_value_backup = getattr(control, 'receive_value', nop) send_midi_backup = getattr(control, 'send_midi', nop) try: control.receive_value = nop if receive_value_backup != nop: control._receive_value_backup = receive_value_backup control.send_midi = nop if send_midi_backup != nop: control._send_midi_backup = send_midi_backup except AttributeError: pass @listens('mode') def _on_push_hardware_mode_changed(self, mode): if mode == LIVE_MODE: if self._start_handshake_task.is_running: self._start_handshake() elif self._handshake.handshake_succeeded: self.update() def _create_background_layer(self): return super(Push, self)._create_background_layer() + Layer(display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', in_button='in_button', out_button='out_button', pad_parameters=self._pad_parameter_control) def _create_message_box_background_layer(self): return super(Push, self)._create_message_box_background_layer() + BackgroundLayer('in_button', 'out_button', priority=consts.MESSAGE_BOX_PRIORITY) def _create_track_frozen_layer(self): return Layer(display='display_line2', _notification=self._notification.use_full_display(1)) def _create_notification_component(self): return NotificationComponent(display_lines='display_lines', is_root=True, is_enabled=True) def _create_message_box_layer(self): return Layer(display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', cancel_button='select_buttons_raw[-1]', priority=consts.MESSAGE_BOX_PRIORITY) def _create_clip_mode(self): return [self._track_modes, (self._mixer, self._mixer_layer)] + super(Push, self)._create_clip_mode() def _create_clip_loop_layer(self): return super(Push, self)._create_clip_loop_layer() + Layer(name_display=self.elements.display_line1.subdisplay[:36], value_display=self.elements.display_line2.subdisplay[:36]) def _create_clip_audio_layer(self): return super(Push, self)._create_clip_audio_layer() + Layer(name_display=self.elements.display_line1.subdisplay[36:], value_display=self.elements.display_line2.subdisplay[36:]) def _create_clip_name_layer(self): return super(Push, self)._create_clip_name_layer() + Layer(display='display_line3') def _create_session_recording(self): return FixedLengthSessionRecordingComponent(fixed_length_setting=self._fixed_length_setting, clip_creator=self._clip_creator, view_controller=self._view_control, name='Session_Recording', is_root=True) def _init_track_modes(self): self._track_modes = ModesComponent(name='Track_Modes') self._track_modes.set_enabled(False) self._track_modes.add_mode('stop', AddLayerMode(self._stop_clips, self._stop_track_clips_layer)) self._track_modes.add_mode('solo', AddLayerMode(self._mixer, self._mixer_solo_layer)) self._track_modes.add_mode('mute', AddLayerMode(self._mixer, self._mixer_mute_layer)) self._track_modes.layer = self._create_track_modes_layer() self._track_modes.selected_mode = 'mute' def _browser_back_to_top(self): self._browser_mode.component.back_to_top() def _browser_reset_load_memory(self): self._browser_mode.component.reset_load_memory() def _init_browser(self): class BrowserMode(MultiEntryMode): def __init__(self, create_browser = nop, *a, **k): super(BrowserMode, self).__init__(LazyComponentMode(create_browser), *a, **k) def enter_mode(browser_mode_self): super(BrowserMode, browser_mode_self).enter_mode() self._scales_enabler.selected_mode = 'disabled' @property def component(self): return self._mode.component self._browser_mode = BrowserMode(self._create_browser) self._browser_hotswap_mode = MultiEntryMode(BrowserHotswapMode(application=self.application())) self._on_browse_mode_changed.subject = self.application().view def _init_browse_mode(self): self._main_modes.add_mode('browse', [self._when_track_is_not_frozen(self._enable_stop_mute_solo_as_modifiers, partial(self._view_control.show_view, 'Browser'), self._browser_back_to_top, self._browser_hotswap_mode, self._browser_mode, self._browser_reset_load_memory)], groups=['add_effect', 'add_track', 'browse'], behaviour=mixin(DynamicBehaviourMixin, CancellableBehaviour)(lambda : not self._browser_hotswap_mode._mode.can_hotswap() and 'add_effect_left')) self._main_modes.add_mode('add_effect_right', [self._when_track_is_not_frozen(self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyComponentMode(self._create_create_device_right))], behaviour=mixin(ExcludingBehaviourMixin, CancellableBehaviour)(['add_track', 'browse']), groups=['add_effect']) self._main_modes.add_mode('add_effect_left', [self._when_track_is_not_frozen(self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyComponentMode(self._create_create_device_left))], behaviour=mixin(ExcludingBehaviourMixin, CancellableBehaviour)(['add_track', 'browse']), groups=['add_effect']) self._main_modes.add_mode('add_instrument_track', [self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyComponentMode(self._create_create_instrument_track)], behaviour=mixin(ExcludingBehaviourMixin, AlternativeBehaviour)(excluded_groups=['browse', 'add_effect'], alternative_mode='add_default_track'), groups=['add_track']) self._main_modes.add_mode('add_default_track', [self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyComponentMode(self._create_create_default_track)], groups=['add_track']) self._main_modes.add_effect_right_button.mode_unselected_color = self._main_modes.add_effect_left_button.mode_unselected_color = self._main_modes.add_instrument_track_button.mode_unselected_color = 'DefaultButton.On' @listens('browse_mode') def _on_browse_mode_changed(self): if not self.application().browser.hotswap_target: if self._main_modes.selected_mode == 'browse' or self._browser_hotswap_mode.is_entered: self._main_modes.selected_mode = 'device' def _create_browser(self): state_buttons = self.elements.track_state_buttons.submatrix[:7, :] browser = BrowserComponent(name='Browser', is_enabled=False, layer=Layer(encoder_controls='global_param_controls', display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', enter_button='in_button', exit_button='out_button', select_buttons='select_buttons', state_buttons=state_buttons, shift_button=WithPriority(consts.SHARED_PRIORITY, 'shift_button'), prehear_button='track_state_buttons_raw[7]', _notification=self._notification.use_full_display(2)), make_browser_model=make_browser_model, preferences=self.preferences) return browser def _create_create_device_right(self): return CreateDeviceComponent(name='Create_Device_Right', browser_component=self._browser_mode.component, browser_mode=self._browser_mode, browser_hotswap_mode=self._browser_hotswap_mode, insert_left=False, is_enabled=False) def _create_create_device_left(self): return CreateDeviceComponent(name='Create_Device_Right', browser_component=self._browser_mode.component, browser_mode=self._browser_mode, browser_hotswap_mode=self._browser_hotswap_mode, insert_left=True, is_enabled=False) def _create_create_default_track(self): create_default_track = CreateDefaultTrackComponent(name='Create_Default_Track', is_enabled=False) create_default_track.options.layer = Layer(display_line='display_line4', label_display_line='display_line3', blank_display_line2='display_line2', blank_display_line1='display_line1', select_buttons='select_buttons', state_buttons='track_state_buttons', priority=consts.DIALOG_PRIORITY) return create_default_track def _create_create_instrument_track(self): return CreateInstrumentTrackComponent(name='Create_Instrument_Track', browser_component=self._browser_mode.component, browser_mode=self._browser_mode, browser_hotswap_mode=self._browser_hotswap_mode, is_enabled=False) def _create_device_mode(self): return [self._when_track_is_not_frozen(self._enable_stop_mute_solo_as_modifiers, partial(self._view_control.show_view, 'Detail/DeviceChain'), self._device_parameter_component, self._device_navigation, self._device_note_editor_mode)] def _create_scales(self): scales = InstrumentScalesComponent(note_layout=self._note_layout, is_enabled=False, name='Scales', layer=(BackgroundLayer('display_line1', 'display_line2', priority=consts.DIALOG_PRIORITY), Layer(scale_line1=self.elements.display_line1.subdisplay[:18], scale_line2=self.elements.display_line2.subdisplay[:18], scale_line3=self.elements.display_line3.subdisplay[:9], scale_line4=self.elements.display_line4.subdisplay[:9], top_display_line=self.elements.display_line3.subdisplay[9:], bottom_display_line=self.elements.display_line4.subdisplay[9:], top_buttons='select_buttons', bottom_buttons='track_state_buttons', encoder_controls='global_param_controls', _notification=self._notification.use_single_line(0, get_slice[18:], align_right), priority=consts.DIALOG_PRIORITY), Layer(presets_toggle_button='shift_button'))) scales.presets_layer = (BackgroundLayer('track_state_buttons', 'global_param_controls', 'display_line1', 'display_line2', priority=consts.DIALOG_PRIORITY), Layer(top_display_line='display_line3', bottom_display_line='display_line4', top_buttons='select_buttons', _notification=self._notification.use_single_line(0), priority=consts.DIALOG_PRIORITY)) return scales def _create_scales_enabler(self): return EnablingModesComponent(component=self._create_scales(), enabled_color='DefaultButton.On', is_enabled=False, layer=Layer(cycle_mode_button='scale_presets_button')) def _create_drum_component(self): return DrumGroupComponent(name='Drum_Group', is_enabled=False, notification_formatter=self._drum_pad_notification_formatter(), quantizer=self._quantize, selector=self._selector) def _init_note_settings_component(self): self._note_settings_component = NoteSettingsComponent(grid_resolution=self._grid_resolution, is_enabled=False, layer=Layer(top_display_line='display_line1', bottom_display_line='display_line2', info_display_line='display_line3', clear_display_line='display_line4', full_velocity_button='accent_button', priority=consts.MOMENTARY_DIALOG_PRIORITY)) def _create_note_editor_mode_selector_layer(self): return super(Push, self)._create_note_editor_mode_selector_layer() + Layer(display_line='display_line4', priority=consts.MOMENTARY_DIALOG_PRIORITY) def _create_note_editor_track_automation_layer(self): return super(Push, self)._create_note_editor_track_automation_layer() + Layer(name_display_line='display_line1', graphic_display_line='display_line2', value_display_line='display_line3', priority=consts.MOMENTARY_DIALOG_PRIORITY) def _create_note_editor_device_automation_layer(self): return super(Push, self)._create_note_editor_device_automation_layer() + Layer(name_display_line='display_line1', value_display_line='display_line2', graphic_display_line='display_line3', priority=consts.MOMENTARY_DIALOG_PRIORITY) def _init_stop_clips_action(self): self._stop_clips = StopClipComponent(session_ring=self._session_ring, name='Stop_Clip', is_root=True) self._stop_clips.layer = Layer(stop_all_clips_button=self._with_shift('global_track_stop_button')) self._stop_track_clips_layer = Layer(stop_track_clips_buttons='track_state_buttons') def _init_quantize_actions(self): self._quantize_settings = QuantizationSettingsComponent(is_enabled=False, layer=(BackgroundLayer('global_param_controls', 'select_buttons', 'track_state_buttons', priority=consts.MOMENTARY_DIALOG_PRIORITY), Layer(swing_amount_encoder='parameter_controls_raw[0]', quantize_to_encoder='parameter_controls_raw[1]', quantize_amount_encoder='parameter_controls_raw[2]', record_quantization_encoder='parameter_controls_raw[7]', record_quantization_toggle_button='track_state_buttons_raw[7]', display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', priority=consts.MOMENTARY_DIALOG_PRIORITY))) self._quantize = self._for_non_frozen_tracks(QuantizationComponent(name='Selected_Clip_Quantize', settings=self._quantize_settings, is_enabled=False, layer=Layer(action_button='quantize_button')), is_root=True) def _init_fixed_length(self): super(Push, self)._init_fixed_length() self._fixed_length_settings_component.layer = (BackgroundLayer('track_state_buttons', 'display_line1', 'display_line2', priority=consts.MOMENTARY_DIALOG_PRIORITY), Layer(length_option_buttons='select_buttons', label_display_line='display_line3', option_display_line='display_line4', _notification=self._notification.use_single_line(1), priority=consts.MOMENTARY_DIALOG_PRIORITY)) def _create_note_repeat_layer(self): return super(Push, self)._create_note_repeat_layer() + Layer(pad_parameters=self._pad_parameter_control, priority=consts.DIALOG_PRIORITY) def _create_user_component(self): sysex_control = create_sysex_element(sysex.MODE_CHANGE) user = UserComponent(value_control=sysex_control, is_root=True) user.layer = Layer(action_button='user_button') user.settings_layer = Layer(display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', encoders='global_param_controls') user.settings_layer.priority = consts.DIALOG_PRIORITY return user def _init_value_components(self): super(Push, self)._init_value_components() self._swing_amount.display.layer = (BackgroundLayer('display_line4', priority=consts.DIALOG_PRIORITY), Layer(label_display='display_line1', value_display='display_line3', graphic_display='display_line2', priority=consts.DIALOG_PRIORITY)) self._tempo.display.layer = (BackgroundLayer('display_line3', 'display_line4', priority=consts.DIALOG_PRIORITY), Layer(label_display='display_line1', value_display='display_line2', priority=consts.DIALOG_PRIORITY)) self._master_vol.display.layer = (BackgroundLayer('display_line4', priority=consts.DIALOG_PRIORITY), Layer(label_display='display_line1', value_display='display_line3', graphic_display='display_line2', priority=consts.DIALOG_PRIORITY)) self._master_cue_vol.display.layer = (BackgroundLayer('display_line4', priority=consts.DIALOG_PRIORITY), Layer(label_display='display_line1', value_display='display_line3', graphic_display='display_line2', priority=consts.DIALOG_PRIORITY)) def _create_note_mode(self): return super(Push, self)._create_note_mode() + [self._global_pad_parameters] def _create_note_mode_behaviour(self): return self._auto_arm.auto_arm_restore_behaviour(ReenterBehaviour, on_reenter=self._switch_note_mode_layout) def _create_session_mode(self): return [self._session_overview_mode, self._session_mode, self._session_navigation] def _create_session_overview_layer(self): return Layer(button_matrix='shifted_matrix') def _set_session_skin(self, session): session.set_rgb_mode(CLIP_COLOR_TABLE, RGB_COLOR_TABLE, clip_slots_only=True) def _on_selected_track_changed(self): super(Push, self)._on_selected_track_changed() self._main_modes.pop_groups(['add_effect']) def _init_main_modes(self): super(Push, self)._init_main_modes() self.__on_main_mode_button_value.replace_subjects([self.elements.vol_mix_mode_button, self.elements.pan_send_mix_mode_button, self.elements.single_track_mix_mode_button, self.elements.clip_mode_button, self.elements.device_mode_button, self.elements.browse_mode_button]) def _create_mixer_layer(self): return super(Push, self)._create_mixer_layer() + Layer(track_names_display='display_line4') def _create_mixer_pan_send_layer(self): return super(Push, self)._create_mixer_pan_send_layer() + Layer(track_names_display='display_line4', pan_send_names_display='display_line1', pan_send_graphics_display='display_line2', selected_track_name_display='display_line3', pan_send_values_display=ComboElement('display_line3', 'any_touch_button')) def _create_mixer_volume_layer(self): return super(Push, self)._create_mixer_volume_layer() + Layer(track_names_display='display_line4', volume_names_display='display_line1', volume_graphics_display='display_line2', selected_track_name_display='display_line3', volume_values_display=ComboElement('display_line3', 'any_touch_button')) def _create_mixer_track_layer(self): return super(Push, self)._create_mixer_track_layer() + Layer(selected_track_name_display='display_line3', track_names_display='display_line4') def _create_track_mixer_layer(self): return super(Push, self)._create_track_mixer_layer() + Layer(name_display_line='display_line1', graphic_display_line='display_line2', value_display_line=ComboElement('display_line3', 'any_touch_button')) def _create_device_parameter_layer(self): return super(Push, self)._create_device_parameter_layer() + Layer(name_display_line='display_line1', value_display_line='display_line2', graphic_display_line=ComboElement('display_line3', 'any_touch_button')) def _create_device_navigation(self): return DeviceNavigationComponent(device_bank_registry=self._device_bank_registry, is_enabled=False, session_ring=self._session_ring, layer=Layer(enter_button='in_button', exit_button='out_button', select_buttons='select_buttons', state_buttons='track_state_buttons', display_line='display_line4', _notification=self._notification.use_single_line(2)), info_layer=Layer(display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', _notification=self._notification.use_full_display(2)), delete_handler=self._delete_component) @listens_group('value') def __on_main_mode_button_value(self, value, sender): if not value: self._scales_enabler.selected_mode = 'disabled' def _create_controls(self): self._create_pad_sensitivity_update() class Deleter(object): @property def is_deleting(_): return self._delete_default_component.is_deleting def delete_clip_envelope(_, param): return self._delete_default_component.delete_clip_envelope(param) self.elements = Elements(deleter=Deleter(), undo_handler=self.song, pad_sensitivity_update=self._pad_sensitivity_update, playhead=self._c_instance.playhead) def _create_pad_sensitivity_update(self): all_pad_sysex_control = create_sysex_element(sysex.ALL_PADS_SENSITIVITY_PREFIX) pad_sysex_control = create_sysex_element(sysex.PAD_SENSITIVITY_PREFIX) sensitivity_sender = pad_parameter_sender(all_pad_sysex_control, pad_sysex_control) self._pad_sensitivity_update = PadUpdateComponent(all_pads=range(64), parameter_sender=sensitivity_sender, default_profile=action_pad_sensitivity, update_delay=TIMER_DELAY, is_root=True) def _init_global_pad_parameters(self): self._pad_parameter_control = self._with_firmware_version(1, 16, create_sysex_element(sysex.PAD_PARAMETER_PREFIX, default_value=sysex.make_pad_parameter_message())) aftertouch_threshold = self._settings['aftertouch_threshold'].value self._global_pad_parameters = GlobalPadParameters(aftertouch_threshold=aftertouch_threshold, is_enabled=False, layer=Layer(pad_parameter=self._pad_parameter_control)) @listens('value') def __on_pad_curve(self, _value): self._update_pad_params() @listens('value') def __on_pad_threshold(self, value): self._user.set_settings_info_text('' if value >= CRITICAL_THRESHOLD_LIMIT else consts.MessageBoxText.STUCK_PAD_WARNING) self._update_pad_params() @listens('value') def __on_aftertouch_threshold(self, value): self._global_pad_parameters.aftertouch_threshold = value def _update_pad_params(self): new_pad_parameters = make_pad_parameters(self._settings['curve'].value, self._settings['threshold'].value) self._pad_sensitivity_update.set_profile('instrument', new_pad_parameters) self._pad_sensitivity_update.set_profile('drums', new_pad_parameters) def _update_calibration(self): self._send_midi(sysex.CALIBRATION_SET) def update(self): self._update_calibration() super(Push, self).update()
class MonoPedal(ControlSurface): def __init__(self, *a, **k): self.log_message = logger.warning super(MonoPedal, self).__init__(*a, **k) self._monomod_version = 'b996' 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(is_momentary = True, msg_type = MIDI_CC_TYPE, channel = 0, identifier = PEDAL_DEFS[index], name = 'Pedal_'+str(index), script = self)) self._pedal[index]._report = False self._pedal[7] = LoopPedalExpressionElement(script = self, msg_type = MIDI_CC_TYPE, channel = 0, identifier = 1, map_mode = 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, is_momentary = True, msg_type = MIDI_NOTE_TYPE, channel = 0, identifier = index+13, name = 'LED_' + str(index), script = 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 Minim(LividControlSurface): _sysex_id = 18 _model_name = 'Minim' def __init__(self, c_instance, *a, **k): super(Minim, self).__init__(c_instance, *a, **k) self._shift_latching = LatchingShiftedBehaviour if SHIFT_LATCHING else ShiftedBehaviour self._skin = Skin(MinimColors) with self.component_guard(): self._define_sysex() self._setup_monobridge() self._setup_controls() self._setup_background() self._setup_autoarm() self._setup_viewcontrol() self._setup_session() self._setup_mixer() self._setup_transport() self._setup_recorder() self._setup_instrument() self._setup_modes() self._setup_m4l_interface() self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Minim log opened >>>>>>>>>>>>>>>>>>>>>>>>>') self.show_message('Minim Control Surface Loaded') self._background.set_enabled(True) def _check_connection(self): if not self._connected: debug(self._model_name, '_check_connection') self._livid_settings.new_query_surface() #self._connection_routine.restart() self.schedule_message(5, self._check_connection) def _initialize_hardware(self): debug('sending local control off') self.local_control_off.enter_mode() def _initialize_script(self): self._on_device_changed.subject = self._device_provider self._main_modes.set_enabled(True) self._main_modes.selected_mode = 'session' self._session_ring._update_highlight() self.refresh_state() def _setup_controls(self): is_momentary = True optimized = False resource = PrioritizedResource self._fader = MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = MINIM_SLIDER, name = 'Fader', script = self, mapping_feedback_delay = -1, optimized_send_midi = optimized, resource_type = resource) self._pad = [[MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MINIM_PADS[row][column], name = 'Pad_' + str(column) + '_' + str(row), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource) for column in range(4)] for row in range(2)] self._button = [[MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MINIM_BUTTONS[row][column], name = 'Button_' + str(column) + '_' + str(row), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource) for column in range(4)] for row in range(2)] self._side_button = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MINIM_SIDE_BUTTONS[index], name = 'Side_Button_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource) for index in range(5)] self._top_button = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MINIM_TOP_BUTTONS[index], name = 'Top_Button_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource) for index in range(2)] self._bottom_button = MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = MINIM_BOTTOM_BUTTON, name = 'Bottom_Button', script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource) self._matrix = ButtonMatrixElement(name = 'Pad_Matrix', rows = [self._button[:][0], self._pad[:][0], self._pad[:][1],self._button[:][1]]) self._side_button_matrix = ButtonMatrixElement(name = 'Side_Button_Matrix', rows = [self._side_button]) self._top_button_matrix = ButtonMatrixElement(name = 'Button_Matrix', rows = [self._top_button]) def _setup_background(self): self._background = BackgroundComponent() self._background.layer = Layer(priority = 3, matrix = self._matrix.submatrix[:,:], side_buttons = self._side_button_matrix, top_buttons = self._top_button_matrix.submatrix[:,:], bottom_button = self._bottom_button) self._background.set_enabled(False) def _define_sysex(self): self._livid_settings = LividSettings(model = 18, control_surface = self) self.local_control_off = SendLividSysexMode(livid_settings = self._livid_settings, call = 'set_local_control', message = [42, 42]) def _setup_autoarm(self): self._auto_arm = AutoArmComponent(name='Auto_Arm') self._auto_arm.can_auto_arm_track = self._can_auto_arm_track self._auto_arm._update_notification = lambda: None def _setup_viewcontrol(self): self._viewcontrol = ViewControlComponent() self._viewcontrol.layer = Layer(priority = 4, prev_track_button = self._top_button[0], next_track_button = self._top_button[1]) self._viewcontrol.set_enabled(False) def _setup_transport(self): self._transport = TransportComponent(name = 'Transport') self._transport.layer = Layer(priority = 4, play_button = self._side_button[0]) #, overdub_button = self._side_button[1]) self._transport.set_enabled(False) def _setup_mixer(self): self._mixer = MonoMixerComponent(name = 'Mixer',tracks_provider = self._session_ring, track_assigner = simple_track_assigner, invert_mute_feedback = True, auto_name = True, enable_skinning = True) self._mixer._selected_strip.layer = Layer(priority = 4, volume_control = self._fader) self._mixer.solo_mute_record_stop_layer = AddLayerMode(self._mixer, Layer(priority = 4, mute_buttons = self._matrix.submatrix[:, 0], solo_buttons = self._matrix.submatrix[:, 1], arm_buttons = self._matrix.submatrix[:, 2], )) self._mixer.select_layer = AddLayerMode(self._mixer, Layer(priority = 4, arming_track_select_buttons = self._matrix.submatrix[:, 3])) self._mixer.mute_layer = AddLayerMode(self._mixer, Layer(priority = 4, mute_buttons = self._matrix.submatrix[:, 3])) def _setup_session(self): self._session_ring = SessionRingComponent(name = 'Session_Ring', num_tracks = 4, num_scenes = 4) self._session = SessionComponent(name = 'Session', session_ring = self._session_ring, auto_name = True) self._session.cliplaunch_layer = AddLayerMode(self._session, Layer(priority = 4, clip_launch_buttons = self._matrix.submatrix[:,:])) self._session.stop_layer = AddLayerMode(self._session, Layer(priority = 4, stop_track_clip_buttons = self._matrix.submatrix[:,3])) self._session_navigation = SessionNavigationComponent(name = 'Session_Navigation', session_ring = self._session_ring) self._session_navigation._horizontal_layer = AddLayerMode(self._session_navigation, Layer(priority = 4, left_button = self._top_button[0], right_button = self._top_button[1])) self._session_navigation._vertical_layer = AddLayerMode(self._session_navigation, Layer(priority = 4, up_button = self._top_button[0], down_button = self._top_button[1])) self._session_navigation.set_enabled(False) def _setup_recorder(self): self._recorder = SessionRecordingComponent(view_controller = self._viewcontrol) self._recorder.layer = Layer(priority = 4, new_button = self._side_button[2], record_button = self._side_button[1]) self._recorder.set_enabled(False) def _setup_instrument(self): self._grid_resolution = GridResolution() self._c_instance.playhead.enabled = True self._playhead_element = PlayheadElement(self._c_instance.playhead) self._drum_group_finder = PercussionInstrumentFinder(device_parent=self.song.view.selected_track) self._instrument = MinimMonoInstrumentComponent(name = 'InstrumentComponent', script = self, skin = self._skin, drum_group_finder = self._drum_group_finder, grid_resolution = self._grid_resolution, settings = DEFAULT_INSTRUMENT_SETTINGS, device_provider = self._device_provider, parent_task_group = self._task_group) self._instrument._drumpad._drumgroup._button_coordinates_to_pad_index = lambda first_note, coordinates: coordinates[1] + (abs(coordinates[0]-1)*4) + first_note self._instrument._drumpad._drumgroup.create_translation_entry = lambda button: (button.coordinate[1], button.coordinate[0]+2, button.identifier, button.channel) self._instrument.layer = Layer(priority = 6, shift_button = self._side_button[3]) self._instrument.keypad_options_layer = AddLayerMode(self._instrument, Layer(priority = 6, scale_up_button = self._button[0][3], scale_down_button = self._button[0][2], offset_up_button = self._button[0][1], offset_down_button = self._button[0][0],)) #vertical_offset_up_button = self._top_button[1], #vertical_offset_down_button = self._top_button[0])) self._instrument.drumpad_options_layer = AddLayerMode(self._instrument, Layer(priority = 6, scale_up_button = self._button[0][3], scale_down_button = self._button[0][2], drum_offset_up_button = self._button[0][1], drum_offset_down_button = self._button[0][0],)) self._instrument._keypad.main_layer = LayerMode(self._instrument._keypad, Layer(priority = 6, keypad_matrix = self._matrix.submatrix[:,1:3])) self._instrument._keypad.select_layer = LayerMode(self._instrument._keypad, Layer(priority = 6, keypad_select_matrix = self._matrix.submatrix[:, 1:3])) self._instrument._drumpad.main_layer = LayerMode(self._instrument._drumpad, Layer(priority = 6, drumpad_matrix = self._matrix.submatrix[:,1:3])) self._instrument._drumpad.select_layer = LayerMode(self._instrument._drumpad, Layer(priority = 6, drumpad_select_matrix = self._matrix.submatrix[:,1:3])) self._instrument._main_modes = ModesComponent(name = 'InstrumentModes') self._instrument._main_modes.add_mode('disabled', []) self._instrument._main_modes.add_mode('drumpad', [self._instrument._drumpad, self._instrument._drumpad.main_layer, self._instrument.drumpad_options_layer]) self._instrument._main_modes.add_mode('drumpad_shifted', [self._instrument._drumpad, self._instrument._drumpad.select_layer, self._instrument.drumpad_options_layer]) self._instrument._main_modes.add_mode('keypad', [self._instrument._keypad, self._instrument._keypad.main_layer, self._instrument.keypad_options_layer]) self._instrument._main_modes.add_mode('keypad_shifted', [self._instrument._keypad, self._instrument._keypad.select_layer, self._instrument.keypad_options_layer]) self._instrument.register_component(self._instrument._main_modes) self._instrument.set_enabled(False) #self._instrument.audioloop_layer = LayerMode(self._instrument, Layer(priority = 6, loop_selector_matrix = self._base_grid)) def _setup_modes(self): self._main_modes = ModesComponent(name = 'MainModes') self._main_modes.add_mode('disabled', []) self._main_modes.add_mode('session_shifted', [self._recorder, self._mixer, self._mixer.solo_mute_record_stop_layer, self._session, self._session.stop_layer, self._session_navigation, self._session_navigation._vertical_layer, self._transport], groups = ['shifted'], behaviour = self._shift_latching(color = 'Mode.Session')) self._main_modes.add_mode('session', [self._recorder, self._mixer, self._session, self._session.cliplaunch_layer, self._session_navigation, self._session_navigation._horizontal_layer, self._transport], behaviour = self._shift_latching(color = 'Mode.Session')) self._main_modes.add_mode('instrument_shifted', [self._recorder, self._mixer, self._mixer.mute_layer, self._viewcontrol, self._instrument, self._transport], groups = ['shifted'], behaviour = self._shift_latching(color = 'Mode.Instrument')) self._main_modes.add_mode('instrument', [self._recorder, self._mixer, self._mixer.select_layer, self._viewcontrol, self._instrument, self._transport], behaviour = self._shift_latching(color = 'Mode.Instrument')) self._main_modes.layer = Layer(priority = 6, session_button = self._side_button[4], instrument_button = self._side_button[3]) self._main_modes.set_enabled(False) self._main_modes.selected_mode = 'disabled' def _can_auto_arm_track(self, track): routing = track.current_input_routing return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith('Livid Minim Input') def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard) self.get_control_names = self._m4l_interface.get_control_names self.get_control = self._m4l_interface.get_control self.grab_control = self._m4l_interface.grab_control self.release_control = self._m4l_interface.release_control @listens('device') def _on_device_changed(self): pass def disconnect(self): self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Minim log closed >>>>>>>>>>>>>>>>>>>>>>>>>') super(Minim, self).disconnect() def handle_sysex(self, midi_bytes): #debug('sysex: ', str(midi_bytes)) #debug('matching:', midi_bytes[1:5], 'to', tuple([0, 1, 97] + [self._sysex_id])) if len(midi_bytes)==9 and midi_bytes[1:5] == tuple([0, 1, 97] + [self._sysex_id]): if not self._connected: #debug('connecting from sysex...') self._connected = True self._initialize_hardware() self._initialize_script()
def _create_slicing_modes(self): slicing_modes = ModesComponent(name='Slicing_Modes', is_enabled=False) slicing_modes.add_mode('64pads', [AddLayerMode(self._slicing_component, Layer(matrix='matrix')), LayerMode(self._pitch_mod_touch_strip, self._pitch_mod_touch_strip_layer)]) slicing_modes.add_mode('sequencer', [self._slice_step_sequencer, self._note_editor_settings_component, AddLayerMode(self._slicing_component, Layer(matrix=self.elements.matrix.submatrix[:4, 4:8], page_strip='touch_strip_control', scroll_strip=self._with_shift('touch_strip_control')))]) slicing_modes.selected_mode = '64pads' return slicing_modes
class Launchpad_Mini_MK3(NovationBase): model_family_code = ids.LP_MINI_MK3_FAMILY_CODE element_class = Elements skin = skin def __init__(self, *a, **k): self._last_layout_byte = sysex.SESSION_LAYOUT_BYTE super(Launchpad_Mini_MK3, self).__init__(*a, **k) def on_identified(self, midi_bytes): self._elements.firmware_mode_switch.send_value(sysex.DAW_MODE_BYTE) self._elements.layout_switch.send_value(self._last_layout_byte) super(Launchpad_Mini_MK3, self).on_identified(midi_bytes) def _create_components(self): super(Launchpad_Mini_MK3, self)._create_components() self._create_background() self._create_stop_solo_mute_modes() self._create_session_modes() self.__on_layout_switch_value.subject = self._elements.layout_switch def _create_session_layer(self): return super(Launchpad_Mini_MK3, self)._create_session_layer() + Layer( scene_launch_buttons=u'scene_launch_buttons') def _create_stop_solo_mute_modes(self): self._stop_solo_mute_modes = ModesComponent( name=u'Stop_Solo_Mute_Modes', is_enabled=False, support_momentary_mode_cycling=False, layer=Layer( cycle_mode_button=self._elements.scene_launch_buttons_raw[7])) bottom_row = self._elements.clip_launch_matrix.submatrix[:, 7:8] self._stop_solo_mute_modes.add_mode( u'launch', None, cycle_mode_button_color=u'Mode.Launch.On') self._stop_solo_mute_modes.add_mode( u'stop', AddLayerMode(self._session, Layer(stop_track_clip_buttons=bottom_row)), cycle_mode_button_color=u'Session.StopClip') self._stop_solo_mute_modes.add_mode( u'solo', AddLayerMode(self._mixer, Layer(solo_buttons=bottom_row)), cycle_mode_button_color=u'Mixer.SoloOn') self._stop_solo_mute_modes.add_mode( u'mute', AddLayerMode(self._mixer, Layer(mute_buttons=bottom_row)), cycle_mode_button_color=u'Mixer.MuteOff') self._stop_solo_mute_modes.selected_mode = u'launch' self._stop_solo_mute_modes.set_enabled(True) def _create_session_modes(self): self._session_overview = SessionOverviewComponent( name=u'Session_Overview', is_enabled=False, session_ring=self._session_ring, enable_skinning=True, layer=Layer(button_matrix=u'clip_launch_matrix')) self._session_modes = SessionModesComponent( name=u'Session_Modes', is_enabled=False, layer=Layer( cycle_mode_button=u'session_mode_button', mode_button_color_control=u'session_button_color_element')) self._session_modes.add_mode(u'launch', None) (self._session_modes.add_mode( u'overview', (self._session_overview, AddLayerMode( self._session_navigation, Layer(page_up_button=u'up_button', page_down_button=u'down_button', page_left_button=u'left_button', page_right_button=u'right_button')), AddLayerMode( self._background, Layer(scene_launch_buttons=u'scene_launch_buttons')))), ) self._session_modes.selected_mode = u'launch' self._session_modes.set_enabled(True) self.__on_session_mode_changed.subject = self._session_modes def _create_background(self): self._background = NotifyingBackgroundComponent( name=u'Background', is_enabled=False, add_nop_listeners=True, layer=Layer(drums_mode_button=u'drums_mode_button', keys_mode_button=u'keys_mode_button', user_mode_button=u'user_mode_button')) self._background.set_enabled(True) self.__on_background_control_value.subject = self._background @listens(u'selected_mode') def __on_session_mode_changed(self, _): self._elements.layout_switch.enquire_value() @listens(u'value') def __on_background_control_value(self, control, value): if value and u'Mode' in control.name: self._elements.layout_switch.enquire_value() @listens(u'value') def __on_layout_switch_value(self, value): self._last_layout_byte = value
class AumPush2(Push2): device_component_class = AumPush2DeviceComponent device_provider_class = ModDeviceProvider def __init__(self, c_instance, model): self._monomod_version = 'b996' self._cntrlr_version = 'b996' self._host_name = 'AumPush2' self._color_type = 'Push' self._auto_arm_calls = 0 self.log_message = logger.warning super(AumPush2, self).__init__(c_instance, model) with self.component_guard(): self._hack_stuff() #self._on_selected_track_changed.subject = self.song.view #self._on_main_mode_changed.subject = self._main_modes self.log_message('<<<<<<<<<<<<<<<<<<<<<<<< AumPush2 ' + str(self._monomod_version) + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>') def _create_components(self): self._remove_pedal() super(AumPush2, self)._create_components() def _create_skin(self): return self.register_disconnectable(make_default_skin()) def _setup_mod(self): def get_monomodular(host): if isinstance(__builtins__, dict): if not 'monomodular' in __builtins__.keys() or not isinstance( __builtins__['monomodular'], ModRouter): __builtins__['monomodular'] = ModRouter( song=self.song, register_component=self._register_component) else: if not hasattr(__builtins__, 'monomodular') or not isinstance( __builtins__['monomodular'], ModRouter): setattr( __builtins__, 'monomodular', ModRouter(song=self.song, register_component=self._register_component)) monomodular = __builtins__['monomodular'] if not monomodular.has_host(): monomodular.set_host(host) return monomodular self.monomodular = get_monomodular(self) self.monomodular.name = 'monomodular_switcher' with inject(register_component=const(self._register_component), song=const(self.song)).everywhere(): self.modhandler = PushModHandler( self ) ## song = self.song, register_component = self._register_component) self.modhandler.name = 'ModHandler' self.modhandler.layer = Layer( priority=6, lock_button=self.elements.note_mode_button, grid=self.elements.matrix, nav_up_button=self.elements.octave_up_button, nav_down_button=self.elements.octave_down_button, nav_left_button=self.elements.in_button, nav_right_button=self.elements.out_button, key_buttons=self.elements.side_buttons, ) self.modhandler.alt_shift_layer = AddLayerMode( self.modhandler, Layer(Shift_button=self.elements.shift_button, Alt_button=self.elements.select_button)) self.modhandler.legacy_shift_layer = AddLayerMode( self.modhandler, Layer( priority=7, device_selector_matrix=self.elements.matrix.submatrix[:, :1], channel_buttons=self.elements.matrix.submatrix[:, 1:2], nav_matrix=self.elements.matrix.submatrix[4:8, 2:6], )) self.modhandler.shift_layer = AddLayerMode( self.modhandler, Layer( priority=7, device_selector_matrix=self.elements.matrix.submatrix[:, :1], )) #lock_button = self.elements.master_select_button, #)) self.modhandler.alt_layer = AddLayerMode(self.modhandler, Layer(priority=7, )) #key_buttons = self.elements.select_buttons)) #key_buttons = self.elements.track_state_buttons)) self._device_provider.restart_mod() def _init_matrix_modes(self): super(AumPush2, self)._init_matrix_modes() #self._setup_monoinstrument() self._setup_mod() self._note_modes.add_mode('mod', [ self.modhandler, self.modhandler.alt_shift_layer, DelayMode(delay=.1, mode=self.modhandler.nav_update) ]) self._note_modes.add_mode('looperhack', [self._audio_loop]) """ def _create_device_component(self): return self.device_component_class(script = self, device_decorator_factory=self._device_decorator_factory, device_bank_registry=self._device_bank_registry, banking_info=self._banking_info, name='DeviceComponent', is_enabled=True, is_root=True) """ def _create_device_component(self): device_component_layer = Layer( parameter_touch_buttons=ButtonMatrixElement( rows=[self.elements.global_param_touch_buttons_raw]), shift_button=u'shift_button') return DeviceComponentProvider( device_component_layer=device_component_layer, device_decorator_factory=self._device_decorator_factory, device_bank_registry=self._device_bank_registry, banking_info=self._banking_info, name=u'DeviceComponent', is_enabled=False, delete_button=self.elements.delete_button) def _create_main_mixer_modes(self): self._mixer_control = MixerControlComponent( name='Global_Mix_Component', view_model=self._model.mixerView, tracks_provider=self._session_ring, is_enabled=False, layer=Layer(controls='fine_grain_param_controls', volume_button='track_state_buttons_raw[0]', panning_button='track_state_buttons_raw[1]', send_slot_one_button='track_state_buttons_raw[2]', send_slot_two_button='track_state_buttons_raw[3]', send_slot_three_button='track_state_buttons_raw[4]', send_slot_four_button='track_state_buttons_raw[5]', send_slot_five_button='track_state_buttons_raw[6]', cycle_sends_button='track_state_buttons_raw[7]')) self._model.mixerView.realtimeMeterData = self._mixer_control.real_time_meter_handlers track_mixer_control = TrollMixerControlComponent( script=self, troll_submodes=self._troll_submodes, name='Track_Mix_Component', is_enabled=False, tracks_provider=self._session_ring, layer=Layer(controls='fine_grain_param_controls', scroll_left_button='track_state_buttons_raw[6]', scroll_right_button='track_state_buttons_raw[7]')) self._track_mixer_control = track_mixer_control #track_mixer_control = TrackMixerControlComponent(name='Track_Mix_Component', is_enabled=False, tracks_provider=self._session_ring, layer=Layer(controls='fine_grain_param_controls', scroll_left_button='track_state_buttons_raw[6]', scroll_right_button='track_state_buttons_raw[7]')) routing_control = RoutingControlComponent( is_enabled=False, layer=Layer(monitor_state_encoder='parameter_controls_raw[0]')) track_mix_or_routing_chooser = TrackOrRoutingControlChooserComponent( tracks_provider=self._session_ring, track_mixer_component=track_mixer_control, routing_control_component=routing_control, is_enabled=False, layer=Layer(mix_button='track_state_buttons_raw[0]', routing_button='track_state_buttons_raw[1]')) self._model.mixerView.trackControlView = track_mix_or_routing_chooser self._mix_modes = ModesComponent(is_enabled=False) self._mix_modes.add_mode('global', self._mixer_control) self._mix_modes.add_mode('track', track_mix_or_routing_chooser) self._mix_modes.selected_mode = 'global' self._model.mixerSelectView = self._mixer_control self._model.trackMixerSelectView = track_mixer_control class MixModeBehaviour(ReenterBehaviour): def press_immediate(behaviour_self, component, mode): if self._is_on_master( ) and self._mix_modes.selected_mode != 'track': self._mix_modes.selected_mode = 'track' super(MixModeBehaviour, behaviour_self).press_immediate(component, mode) def on_reenter(behaviour_self): if not self._is_on_master(): self._mix_modes.cycle_mode() self._main_modes.add_mode('mix', [ self._mix_modes, SetAttributeMode(obj=self._note_editor_settings_component, attribute='parameter_provider', value=self._track_parameter_provider) ], behaviour=MixModeBehaviour()) def _with_select(self, button): return ComboElement(button, [self.elements.select_button]) def _hack_stuff(self): crossfader_strip = TouchStripControllerComponent() crossfader_strip.layer = Layer( touch_strip=self.elements.touch_strip_control) crossfader_strip.set_enabled(False) self._crossfader_control = AumPushCrossfader( strip_controller=crossfader_strip, task_group=self._task_group) self._crossfader_control.set_enabled(False) self._device_selector = DeviceSelectorComponent(self) self._device_selector._off_value = 64 self._device_selector.layer = Layer( priority=9, matrix=self.elements.matrix.submatrix[:, :4]) self._device_selector.set_enabled(False) self._send_reset = AumPushResetSendsComponent(self) self._send_reset.layer = Layer( priority=9, send_a_button=self._with_select( self.elements.track_state_buttons_raw[4]), send_b_button=self._with_select( self.elements.track_state_buttons_raw[5]), send_c_button=self._with_select( self.elements.track_state_buttons_raw[6]), send_d_button=self._with_select( self.elements.track_state_buttons_raw[7])) self._send_reset.set_enabled(False) self._tagged_defaults = TaggedDefaultsComponent(self) self._tagged_defaults.layer = Layer(priority=9, reset_button='side_buttons_raw[7]') self._tagged_defaults.set_enabled(False) self._troll_submodes = ModesComponent() self._troll_submodes.add_mode('Strip', []) self._troll_submodes.add_mode('FX1', []) self._troll_submodes.add_mode('FX2', []) self._troll_submodes.add_mode('Inputs', []) self._troll_submodes.layer = Layer(priority=8, Strip_button='side_buttons_raw[0]', FX1_button='side_buttons_raw[1]', FX2_button='side_buttons_raw[2]', Inputs_button='side_buttons_raw[3]') self._troll_submodes.selected_mode = 'Strip' self._troll_submodes.set_enabled(False) static_modes = CompoundMode(self._crossfader_control, self._device_selector, self._send_reset, self._troll_submodes, self._tagged_defaults) self._troll_modes = ModesComponent() self._troll_modes.add_mode('disabled', [], cycle_mode_button_color='DefaultButton.Off') self._troll_modes.add_mode( 'enabled', [ static_modes, tuple([ self._grab_track_mode, self._release_track_mode, ]) ], cycle_mode_button_color='DefaultButton.Alert') self._troll_modes.layer = Layer( cycle_mode_button='master_select_button') self._troll_modes.selected_mode = 'disabled' @listens('selected_mode') def _on_main_mode_changed(self, mode): debug('main_mode selected mode is now:', mode) #if self._troll_modes.selected_mode is 'enabled' and not mode is 'device': # self._troll_modes.selected_mode = 'disabled' def _init_main_modes(self): super(AumPush2, self)._init_main_modes() self._on_main_mode_changed.subject = self._main_modes def _grab_track_mode(self): debug('grab device mode') """self._main_modes.pop_unselected_modes() if not self._main_modes.selected_mode is 'device': self._main_modes.push_mode('device') self._device_component._update_parameters()""" self._track_mixer_control._mode_on_troll_entrance = self._mix_modes.selected_mode self._track_mixer_control._main_offset = self._track_mixer_control.scroll_offset self._track_mixer_control._scroll_offset = self._track_mixer_control._troll_offset if self._main_modes.selected_mode is 'mix': self._check_track_mixer_entry() def _release_track_mode(self): debug('release device mode') """if self._troll_modes.selected_mode is 'enabled': self._troll_modes.selected_mode = 'disabled' if len(self._main_modes.active_modes) > 1: self._main_modes.pop_mode('device') self._device_component._update_parameters()""" self._track_mixer_control._troll_offset = self._track_mixer_control.scroll_offset self._track_mixer_control._scroll_offset = self._track_mixer_control._main_offset if self._main_modes.selected_mode is 'mix': self._mix_modes.selected_mode = self._track_mixer_control._mode_on_troll_entrance if self._track_mixer_control._mode_on_troll_entrance is 'track': self._track_mixer_control.notify_scroll_offset() self._track_mixer_control.update() def _check_track_mixer_entry(self): debug('_check_track_mixer_entry') if self._troll_modes.selected_mode is 'enabled': if not self._mix_modes.selected_mode is 'track': #self._mix_modes.push_mode('track') self._mix_modes.selected_mode = 'track' self._track_mixer_control.notify_scroll_offset() self._track_mixer_control.update() def _check_track_mixer_exit(self): debug('_check_track_mixer_exit') def _disable_troll(self): #self._troll_modes.selected_mode = 'disabled' debug('disable troll') def _init_mute_solo_stop(self): super(AumPush2, self)._init_mute_solo_stop() self._master_selector.layer = Layer( toggle_button=self._with_select('master_select_button')) def _grab_crossfader(self): self._crossfader_strip.set_parameter( self.song.master_track.mixer_device.crossfader) def _release_crossfader(self): self._crossfader_strip.set_parameter(None) def _remove_pedal(self): #self.real_foot_pedal_button = self.elements.foot_pedal_button self.elements.foot_pedal_button = DoublePressElement( create_button(127, name='Foot_Pedal', skin=self._skin, is_rgb=True)) for control in self.controls: if isinstance( control, ButtonElement) and control._original_identifier is 69: self.log_message('found control: ' + str(control)) self.controls.remove(control) break self.request_rebuild_midi_map() #in progress: this will allow viewing returns on right side of channel selectors when trollmode is engaged. def right_align_return_tracks_track_assigner(song, tracks_provider): if self._troll_modes.selected_mode == 'disabled': offset = tracks_provider.track_offset tracks = tracks_provider.tracks_to_use() return_tracks = list(song.return_tracks) size = tracks_provider.num_tracks num_empty_tracks = max(0, size + offset - len(tracks)) track_list = size * [None] for i in xrange(size): track_index = i + offset if len(tracks) > track_index: track = tracks[track_index] empty_offset = 0 if tracks[ track_index] not in return_tracks else num_empty_tracks track_list[i + empty_offset] = track else: offset = tracks_provider.track_offset tracks = tracks_provider.tracks_to_use() return_tracks = list(song.return_tracks) size = tracks_provider.num_tracks num_empty_tracks = max(0, size + offset - len(tracks)) track_list = size * [None] for i in xrange(size): track_index = i + offset if len(tracks) > track_index: track = tracks[track_index] empty_offset = 0 if tracks[ track_index] not in return_tracks else num_empty_tracks track_list[i + empty_offset] = track return track_list """ @listens('device') def _on_device_changed(self): debug('_on_device_changed') #self.schedule_message(1, self._select_note_mode) #self._select_note_mode() @listens('selected_track') def _on_selected_track_changed(self): #if self._troll_modes.selected_mode is 'enabled': # self._device_component._update_parameters() pass """ def _select_note_mode(self, mod_device=None): track = self.song.view.selected_track drum_device, sliced_simpler = self._percussion_instruments_for_track( track) self._drum_component.set_drum_group_device(drum_device) self._slicing_component.set_simpler(sliced_simpler) debug('select_note_mode: ', self.modhandler.is_locked(), self.modhandler.active_mod(), len(track.devices)) if not (self._note_modes.selected_mode is 'mod' and self.modhandler.is_locked()): 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 self.modhandler.active_mod(): self._note_modes.selected_mode = 'mod' elif track and track.has_audio_input: self._note_modes.selected_mode = 'looperhack' elif drum_device: self._note_modes.selected_mode = 'drums' elif sliced_simpler: self._note_modes.selected_mode = 'slicing' else: self._note_modes.selected_mode = 'instrument' self.reset_controlled_track() def disconnect(self): self.log_message('<<<<<<<<<<<<<<<<<<<<<<<< AumPush2 ' + str(self._monomod_version) + ' log closed >>>>>>>>>>>>>>>>>>>>>>>>') super(AumPush2, self).disconnect() def _can_auto_arm_track(self, track): routing = track.current_input_routing return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith( 'AumPush2')
class KeyLabEssential(ControlSurface): mixer_component_type = MixerComponent session_component_type = SessionComponent view_control_component_type = ViewControlComponent hardware_settings_component_type = HardwareSettingsComponent channel_strip_component_type = ChannelStripComponent def __init__(self, *a, **k): super(KeyLabEssential, self).__init__(*a, **k) with self.component_guard(): with inject(skin=const(default_skin)).everywhere(): self._create_controls() self._create_hardware_settings() self._on_focused_view_changed.subject = self.application.view self._hardware_settings.set_hardware_live_mode_enabled(True) self._on_memory_preset_changed_on_hardware.subject = self._hardware_settings self._hardware_settings.select_memory_preset( sysex.DAW_MEMORY_PRESET_INDEX) with self.component_guard(): self._create_transport() self._create_undo() self._create_session() self._create_navigation() self._create_mixer() self._create_view_control() self._create_arrangement() self._create_jogwheel_modes() def port_settings_changed(self): super(KeyLabEssential, self).port_settings_changed() self._hardware_settings.set_hardware_live_mode_enabled(True) def _create_controls(self): self._hardware_live_mode_switch = SysexElement( send_message_generator=lambda b: sysex.LIVE_MODE_MESSAGE_HEADER + (b, sysex.END_BYTE), default_value=sysex.OFF_VALUE, name=u'Hardware_Live_Mode_Switch') self._memory_preset_switch = SysexElement( send_message_generator=lambda b: sysex. MEMORY_PRESET_SWITCH_MESSAGE_HEADER + (b, sysex.END_BYTE), sysex_identifier=sysex.MEMORY_PRESET_SWITCH_MESSAGE_HEADER, name=u'Memory_Preset_Switch') self._memory_preset_select_mode_switch = SysexElement( sysex_identifier=sysex.MEMORY_PRESET_SELECT_MODE_MESSAGE_HEADER, name=u'Memory_Preset_Select_Mode') self._play_button = create_button(94, u'Play_Button') self._stop_button = create_button(93, u'Stop_Button') self._punch_in_button = create_button(87, u'Punch_In_Button') self._punch_out_button = create_button(88, u'Punch_Out_Button') self._metronome_button = create_button(89, u'Metronome_Button') self._loop_button = create_button(86, u'Loop_Button') self._rwd_button = create_button(91, u'Rewind_Button') self._ff_button = create_button(92, u'Fast_Forward_Button') self._record_button = create_button(95, u'Record_Button') self._undo_button = create_button(81, u'Undo_Button') self._bank_left_button = create_button(46, u'Bank_Left_Button') self._bank_right_button = create_button(47, u'Bank_Right_Button') self._left_button = create_button(48, u'Left_Button') self._right_button = create_button(49, u'Right_Button') self._left_arrow_button = create_button(98, u'Left_Arrow_Button') self._right_arrow_button = create_button(99, u'Right_Arrow_Button') self._marker_button = create_button(84, u'Marker_Button') self._pads = ButtonMatrixElement(rows=[[ create_button(col + 36, u'Pad_%d' % (col, ), channel=10) for col in range(8) ]], name=u'Pad_Matrix') self._pad_leds = ButtonMatrixElement(rows=[[ create_pad_led(column + 112, u'Pad_LED_%d' % (column, )) for column in range(8) ]], name=u'Pad_LED_Matrix') self._faders = ButtonMatrixElement(rows=[[ SliderElement(msg_type=MIDI_PB_TYPE, channel=index, identifier=None, name=u'Fader_%d' % (index, )) for index in range(8) ]], name=u'Faders') self._master_fader = SliderElement(MIDI_PB_TYPE, 8, identifier=None, name=u'Master_Fader') self._encoders = ButtonMatrixElement(rows=[[ create_ringed_encoder(index + 16, index + 48, u'Device_Encoder_%d' % (index, )) for index in range(8) ]]) self._jogwheel = EncoderElement( MIDI_CC_TYPE, 0, 60, Live.MidiMap.MapMode.relative_smooth_signed_bit, name=u'Jogwheel') def _create_hardware_settings(self): self._hardware_settings = self.hardware_settings_component_type( is_enabled=False, layer=Layer( hardware_live_mode_switch=self._hardware_live_mode_switch, memory_preset_switch=self._memory_preset_switch, memory_preset_select_mode_switch=self. _memory_preset_select_mode_switch), name=u'Hardware_Settings') self._hardware_settings.set_enabled(True) def _create_transport(self): self._transport = TransportComponent( is_enabled=False, layer=Layer(play_button=self._play_button, stop_button=self._stop_button, punch_in_button=self._punch_in_button, punch_out_button=self._punch_out_button, loop_button=self._loop_button, metronome_button=self._metronome_button, record_button=self._record_button)) self._transport.set_seek_buttons(self._ff_button, self._rwd_button) self._transport.set_enabled(True) def _create_undo(self): self._undo = UndoComponent(is_enabled=False, layer=Layer(undo_button=self._undo_button)) self._undo.set_enabled(True) def _create_session(self): self._session_ring = SessionRingComponent( num_tracks=self._pads.width(), num_scenes=self._pads.height(), name=u'Session_Ring') self._session_ring.set_enabled(False) self._session = self.session_component_type( session_ring=self._session_ring, name=u'Session', is_enabled=False, layer=Layer(clip_launch_buttons=self._pads, clip_slot_leds=self._pad_leds)) self._session.set_enabled(True) def _create_navigation(self): self._session_navigation = SessionNavigationComponent( session_ring=self._session_ring, is_enabled=False, layer=Layer(page_left_button=self._bank_left_button, page_right_button=self._bank_right_button, left_button=self._left_button, right_button=self._right_button), name=u'Session_Navigation') self._session_navigation.set_enabled(True) def _create_mixer(self): # self._mixer = self.mixer_component_type(tracks_provider=self._session_ring, channel_strip_component_type=self.channel_strip_component_type, is_enabled=False, layer=Layer(volume_controls=self._faders, pan_controls=self._encoders)) self._mixer = self.mixer_component_type( tracks_provider=self._session_ring, channel_strip_component_type=self.channel_strip_component_type, is_enabled=False, layer=Layer(volume_controls=self._faders)) self._mixer.master_strip().set_volume_control(self._master_fader) self._mixer.set_enabled(True) def _create_view_control(self): self._view_control = self.view_control_component_type( is_enabled=False, layer=Layer(prev_track_button=self._left_arrow_button, next_track_button=self._right_arrow_button, scene_scroll_encoder=self._jogwheel), name=u'View_Control') self._view_control.set_enabled(True) def _create_arrangement(self): self._arrangement = ArrangementComponent( is_enabled=False, layer=Layer(set_or_delete_cue_button=self._marker_button), name=u'Arrangement') self._arrangement.set_enabled(True) def _create_jogwheel_modes(self): self._jogwheel_modes = ModesComponent() self._jogwheel_modes.add_mode( u'Session', AddLayerMode(self._view_control, Layer(scene_scroll_encoder=self._jogwheel))) self._jogwheel_modes.add_mode( u'Arranger', AddLayerMode(self._arrangement, Layer(jump_encoder=self._jogwheel))) self._on_focused_view_changed() @listens(u'focused_document_view') def _on_focused_view_changed(self): view = self.application.view.focused_document_view if self._jogwheel_modes: self._jogwheel_modes.selected_mode = view @listens(u'daw_preset') def _on_memory_preset_changed_on_hardware(self, is_daw_preset_on): self._session.set_allow_update(is_daw_preset_on) if is_daw_preset_on: for control in self.controls: control.clear_send_cache() self._session.set_enabled(is_daw_preset_on)
class Launchpad_Pro_MK3(InstrumentControlMixin, NovationBase): model_family_code = ids.LP_PRO_MK3_FAMILY_CODE element_class = Elements session_class = SessionComponent mixer_class = MixerComponent channel_strip_class = ChannelStripComponent skin = skin suppress_layout_switch = False track_recording_class = FixedLengthTrackRecordingComponent def __init__(self, *a, **k): self._layout_to_restore = None self._can_restore_layout = False self._last_layout_bytes = ids.SESSION_LAYOUT_BYTES (super(Launchpad_Pro_MK3, self).__init__)(*a, **k) def disconnect(self): super(Launchpad_Pro_MK3, self).disconnect() self._auto_arm.set_enabled(False) self._elements.scale_feedback_switch.send_value(Rgb.GREEN.midi_value) def on_identified(self, midi_bytes): self._elements.firmware_mode_switch.send_value(sysex.DAW_MODE_BYTE) self._elements.layout_switch.send_value(self._last_layout_bytes) self._target_track_changed() self._drum_group_changed() self.set_feedback_channels( [DRUM_FEEDBACK_CHANNEL, SCALE_FEEDBACK_CHANNEL]) self._setup_faders() super(Launchpad_Pro_MK3, self).on_identified(midi_bytes) def port_settings_changed(self): self._auto_arm.set_enabled(False) super(Launchpad_Pro_MK3, self).port_settings_changed() def _setup_faders(self): for i, fader_mode in enumerate(FADER_MODES): orientation, polarity = ( sysex.FADER_HORIZONTAL_ORIENTATION, sysex.FADER_BIPOLAR) if fader_mode == 'pan' else ( sysex.FADER_VERTICAL_ORIENTATION, sysex.FADER_UNIPOLAR) self._elements.fader_setup_element.send_value( i, orientation, polarity) def _create_components(self): self._fixed_length_setting = FixedLengthSetting() self._fixed_length_recording = FixedLengthRecording( self.song, self._fixed_length_setting) self._create_quantization() with inject(fixed_length_recording=(const( self._fixed_length_recording)), quantization_component=(const( self._quantization))).everywhere(): super(Launchpad_Pro_MK3, self)._create_components() self._create_recording_modes() self._create_session_overview() self._create_auto_arm() self._create_background() self._create_device_navigation() self._create_device_parameters() self._create_print_to_clip() self._create_undo_redo() self._create_transport() self._create_clip_actions() self._create_fixed_length() self._create_drum_group() self._create_scale_pad_translator() self._create_mixer_modes() self._create_session_modes() self._create_note_modes() self._create_main_modes() self._Launchpad_Pro_MK3__on_layout_switch_value.subject = self._elements.layout_switch def _create_session_overview(self): self._session_overview = SessionOverviewComponent( name='Session_Overview', is_enabled=False, session_ring=(self._session_ring), enable_skinning=True, layer=Layer(button_matrix='clip_launch_matrix')) def _create_auto_arm(self): self._auto_arm = AutoArmComponent(name='Auto_Arm', is_enabled=False) def _create_background(self): self._background = BackgroundComponent( name='Background', is_enabled=False, add_nop_listeners=True, layer=(Layer( clear_button='clear_button', duplicate_button='duplicate_button', quantize_button='quantize_button', scene_launch_buttons='scene_launch_buttons', priority=(-1) ) + Layer( duplicate_button_with_shift='duplicate_button_with_shift', track_select_buttons_with_shift= 'track_select_buttons_with_shift', up_button_with_shift='up_button_with_shift', down_button_with_shift='down_button_with_shift', left_button_with_shift='left_button_with_shift', right_button_with_shift='right_button_with_shift', double_button='duplicate_button_with_shift', clear_button_with_shift='clear_button_with_shift', volume_button_with_shift='volume_button_with_shift', pan_button_with_shift='pan_button_with_shift', sends_button_with_shift='sends_button_with_shift', device_button_with_shift='device_button_with_shift', stop_clip_button_with_shift='stop_clip_button_with_shift', fixed_length_button_with_shift='fixed_length_button_with_shift' ))) self._background.set_enabled(True) def _create_print_to_clip(self): self._print_to_clip = PrintToClipComponent( name='Print_To_Clip', is_enabled=False, layer=Layer(print_to_clip_control='print_to_clip_element', print_to_clip_enabler='print_to_clip_enabler_element')) self._print_to_clip.set_enabled(True) def _create_undo_redo(self): self._undo_redo = UndoRedoComponent( name='Undo_Redo', is_enabled=False, layer=Layer(undo_button='record_arm_button_with_shift', redo_button='mute_button_with_shift')) self._undo_redo.undo_button.color = 'Action.Undo' self._undo_redo.undo_button.pressed_color = 'Action.UndoPressed' self._undo_redo.redo_button.color = 'Action.Redo' self._undo_redo.redo_button.pressed_color = 'Action.RedoPressed' self._undo_redo.set_enabled(True) def _create_transport(self): self._transport = TransportComponent( name='Transport', is_enabled=False, layer=Layer(play_button='play_button', continue_playing_button='play_button_with_shift', metronome_button='solo_button_with_shift', capture_midi_button='record_button_with_shift', tap_tempo_button='sends_button_with_shift')) self._transport.tap_tempo_button.color = 'Transport.TapTempo' self._transport.set_enabled(True) def _create_clip_actions(self): self._clip_actions = ClipActionsComponent( name='Clip_Actions', quantization_component=(self._quantization), is_enabled=False, layer=Layer(duplicate_button='duplicate_button', quantize_button='quantize_button', double_loop_button='duplicate_button_with_shift')) def _create_quantization(self): self._quantization = QuantizationComponent( name='Quantization', is_enabled=False, layer=Layer( quantization_toggle_button='quantize_button_with_shift')) self._quantization.set_enabled(True) def _create_fixed_length(self): self._fixed_length = FixedLengthComponent( fixed_length_setting=(self._fixed_length_setting), name='Fixed_Length', is_enabled=False, layer=Layer(fixed_length_button='fixed_length_button')) self._fixed_length.settings_component.layer = Layer( length_option_buttons='track_select_buttons') self._fixed_length.set_enabled(True) def _create_drum_group(self): self._drum_group = DrumGroupComponent( (self._clip_actions), name='Drum_Group', is_enabled=False, translation_channel=DRUM_FEEDBACK_CHANNEL, layer=Layer(matrix='drum_pads')) self._drum_group.set_enabled(True) def _create_device_parameters(self): self._device_parameters = SimpleDeviceParameterComponent( name='Device_Parameters', is_enabled=False, device_bank_registry=(self._device_bank_registry), layer=Layer( parameter_controls='device_button_faders', static_color_controls='device_button_fader_color_elements', stop_fader_control='stop_fader_element'), static_color_value=(Rgb.DARK_BLUE.midi_value)) self._device_parameters.set_enabled(True) def _create_device_navigation(self): self._device_navigation = SimpleDeviceNavigationComponent( name='Device_Navigation') def _create_scale_pad_translator(self): self._scale_pad_translator = ConfigurablePlayableComponent( SCALE_FEEDBACK_CHANNEL, name='Scale_Pads', is_enabled=False, layer=Layer(matrix='scale_pads')) self._scale_pad_translator.set_enabled(True) def _create_mixer_modes(self): self._mixer_modes = ModesComponent(name='Mixer_Modes', is_enabled=False, enable_skinning=True, layer=Layer( arm_button='record_arm_button', mute_button='mute_button', solo_button='solo_button', volume_button='volume_button', pan_button='pan_button', sends_button='sends_button', device_button='device_button', stop_button='stop_clip_button')) self._mixer.layer = Layer(volume_controls='volume_button_faders', pan_controls='pan_button_faders', send_controls='sends_button_faders') reselect_track_select_mode = partial(setattr, self._mixer_modes, 'selected_mode', 'track_select') def restore_main_layout(): if self._can_restore_layout: if self._layout_to_restore: self._elements.layout_switch.send_value( self._layout_to_restore) def add_track_select_button_mode(name, control=None, component=self._mixer): control_key = control if control else '{}_buttons'.format(name) control_dict = {control_key: 'track_select_buttons'} self._mixer_modes.add_mode( name, (AddLayerMode(component, Layer(**control_dict)), DelayMode(restore_main_layout, delay=0.1)), behaviour=ReenterBehaviour( on_reenter=reselect_track_select_mode)) add_track_select_button_mode('track_select') add_track_select_button_mode('arm') add_track_select_button_mode('mute') add_track_select_button_mode('solo') add_track_select_button_mode('stop', control='stop_track_clip_buttons', component=(self._session)) def switch_to_fader_layout(bank): fader_layout_bytes = (ids.FADER_LAYOUT_BYTE, bank, 0) self._elements.layout_switch.send_value(fader_layout_bytes) def add_fader_mode(name, bank, add_layer_mode, static_color=None): self._mixer_modes.add_mode( name, (add_layer_mode, AddLayerMode( self._mixer, Layer(track_select_buttons='track_select_buttons')), partial(self._mixer._update_send_control_colors), partial(self._mixer.set_static_color_value, static_color), partial(switch_to_fader_layout, bank)), behaviour=ReenterBehaviour( on_reenter=reselect_track_select_mode)) add_fader_mode( 'volume', 0, (AddLayerMode( self._mixer, Layer( static_color_controls='volume_button_fader_color_elements') )), static_color=(Rgb.GREEN.midi_value)) add_fader_mode( 'pan', 1, AddLayerMode( self._mixer, Layer(track_color_controls='pan_button_fader_color_elements'))) add_fader_mode( 'sends', 2, AddLayerMode( self._mixer, Layer(send_select_buttons='scene_launch_buttons', return_track_color_controls= 'sends_button_fader_color_elements', stop_fader_control='stop_fader_element'))) add_fader_mode( 'device', 3, (AddLayerMode( self._background, Layer(up_button='up_button', down_button='down_button')), AddLayerMode( self._device_navigation, Layer(prev_button='left_button', next_button='right_button')), AddLayerMode(self._device_parameters, Layer(bank_select_buttons='scene_launch_buttons')))) self._mixer_modes.selected_mode = 'track_select' self._mixer_modes.set_enabled(True) def _create_session_modes(self): self._session_modes = ModesComponent( name='Session_Modes', is_enabled=False, layer=Layer(overview_button='session_mode_button')) self._session_modes.add_mode( 'launch', AddLayerMode( self._session, Layer(managed_select_button='shift_button', managed_delete_button='clear_button', managed_duplicate_button='duplicate_button', managed_quantize_button='quantize_button', managed_double_button='duplicate_button_with_shift', scene_launch_buttons='scene_launch_buttons'))) self._session_modes.add_mode( 'overview', (self._session_overview, AddLayerMode( self._session_navigation, Layer(page_up_button='up_button', page_down_button='down_button', page_left_button='left_button', page_right_button='right_button'))), behaviour=(MomentaryBehaviour())) self._session_modes.selected_mode = 'launch' def _create_note_modes(self): self._note_modes = ModesComponent(name='Note_Modes', is_enabled=False) self._note_modes.add_mode( 'scale', AddLayerMode(self._clip_actions, Layer(delete_button='clear_button'))) self._note_modes.add_mode( 'drum', AddLayerMode( self._drum_group, Layer(scroll_up_button='left_button', scroll_down_button='right_button', scroll_page_up_button='up_button', scroll_page_down_button='down_button', delete_button='clear_button'))) def _create_main_modes(self): self._main_modes = ModesComponent(name='Main_Modes', is_enabled=False) suppressed_arrow_button_mode = (AddLayerMode( self._background, Layer(left_button='left_button', right_button='right_button', up_button='up_button', down_button='down_button')), ) self._main_modes.add_mode('none', suppressed_arrow_button_mode) self._main_modes.add_mode('fader', None) self._main_modes.add_mode('session', self._session_modes) self._main_modes.add_mode('note', (self._note_modes, self._clip_actions)) self._main_modes.add_mode('chord', suppressed_arrow_button_mode) self._main_modes.selected_mode = 'session' self._main_modes.set_enabled(True) self._Launchpad_Pro_MK3__on_main_mode_changed.subject = self._main_modes @listens('selected_mode') def __on_main_mode_changed(self, mode): if mode == 'session': self._session_modes.selected_mode = 'launch' self._recording_modes.selected_mode = 'session' if mode == 'session' else 'track' self._update_controlled_track() self._auto_arm.set_enabled(self._is_instrument_mode()) @listens('value') def __on_layout_switch_value(self, value): self._can_restore_layout = value[0] in LIVE_LAYOUT_BYTES if not self._can_restore_layout: return if value[0] == ids.FADER_LAYOUT_BYTE: self._main_modes.selected_mode = 'fader' else: self._layout_to_restore = value if self._mixer_modes.selected_mode in FADER_MODES: self._mixer_modes.selected_mode = 'track_select' if value in LAYOUT_BYTES_TO_MODE_NAMES_MAP: self._main_modes.selected_mode = LAYOUT_BYTES_TO_MODE_NAMES_MAP[ value] else: self._main_modes.selected_mode = 'none' self._last_layout_bytes = value def _drum_group_changed(self): drum_group = self._drum_group_finder.drum_group drum_group_valid = liveobj_valid(drum_group) self._drum_group.set_drum_group_device(drum_group) self._elements.layout_switch.send_value( ids.DRUM_LAYOUT_BYTES if drum_group_valid else ids. SCALE_LAYOUT_BYTES) self._note_modes.selected_mode = 'drum' if drum_group_valid else 'scale' def _is_instrument_mode(self): return self._main_modes.selected_mode in NOTE_MODE_NAMES def _feedback_velocity_changed(self, feedback_velocity): self._elements.scale_feedback_switch.send_value(feedback_velocity)
class Launchpad_X(InstrumentControlMixin, NovationBase): model_family_code = ids.LP_X_FAMILY_CODE element_class = Elements channel_strip_class = ChannelStripComponent session_recording_class = mixin(SessionRecordingMixin, SessionRecordingComponent) track_recording_class = mixin(SessionRecordingMixin, TrackRecordingComponent) target_track_class = ArmedTargetTrackComponent skin = skin def __init__(self, *a, **k): self._last_layout_byte = sysex.SESSION_LAYOUT_BYTE super(Launchpad_X, self).__init__(*a, **k) def on_identified(self, midi_bytes): self._elements.firmware_mode_switch.send_value(sysex.DAW_MODE_BYTE) self._elements.layout_switch.send_value(self._last_layout_byte) self._target_track_changed() self._drum_group_changed() self.set_feedback_channels( [DRUM_FEEDBACK_CHANNEL, SCALE_FEEDBACK_CHANNEL]) super(Launchpad_X, self).on_identified(midi_bytes) def _create_components(self): super(Launchpad_X, self)._create_components() self._background = BackgroundComponent(name='Background', add_nop_listeners=True) self._session_layout_mode = partial( self._elements.layout_switch.send_value, sysex.SESSION_LAYOUT_BYTE) self._create_recording_modes() self._create_mixer_modes() self._create_session_modes() self._create_note_modes() self._create_main_modes() self._mixer.set_send_controls = nop self.__on_layout_switch_value.subject = self._elements.layout_switch def _create_mixer_modes(self): self._mixer_modes = ModesComponent( name='Mixer_Modes', is_enabled=False, enable_skinning=True, layer=Layer( volume_button=self._elements.scene_launch_buttons_raw[0], pan_button=self._elements.scene_launch_buttons_raw[1], send_a_button=self._elements.scene_launch_buttons_raw[2], send_b_button=self._elements.scene_launch_buttons_raw[3], stop_button=self._elements.scene_launch_buttons_raw[4], mute_button=self._elements.scene_launch_buttons_raw[5], solo_button=self._elements.scene_launch_buttons_raw[6], arm_button=self._elements.scene_launch_buttons_raw[7])) bottom_row = self._elements.clip_launch_matrix.submatrix[:, 7:8] select_none_mode = partial(setattr, self._mixer_modes, 'selected_mode', 'none') self._mixer_modes.add_mode('none', self._session_layout_mode) button_fader_layout_mode = partial( self._elements.layout_switch.send_value, sysex.FADERS_LAYOUT_BYTE) def add_fader_mode(name, color, is_pan=False): control_dict = {('{}_controls').format(name): 'button_faders'} if is_pan: control_dict[ 'track_color_controls'] = 'button_fader_color_elements' else: control_dict[ 'static_color_controls'] = 'button_fader_color_elements' self._mixer_modes.add_mode( name, (partial( self._elements.button_fader_setup_element.send_value, sysex.FADER_HORIZONTAL_ORIENTATION if is_pan else sysex.FADER_VERTICAL_ORIENTATION, sysex.FADER_BIPOLAR if is_pan else sysex.FADER_UNIPOLAR), partial(self._mixer.set_static_color_value, color), self._clear_send_cache_of_button_fader_color_elements, AddLayerMode(self._mixer, Layer(**control_dict)), button_fader_layout_mode), behaviour=ReenterBehaviour(on_reenter=select_none_mode)) add_fader_mode('volume', Rgb.GREEN.midi_value) add_fader_mode('pan', 0, True) add_fader_mode('send_a', Rgb.VIOLET.midi_value) add_fader_mode('send_b', Rgb.DARK_BLUE.midi_value) self._mixer_modes.add_mode( 'stop', (self._session_layout_mode, AddLayerMode(self._session, Layer(stop_track_clip_buttons=bottom_row))), behaviour=ReenterBehaviour(on_reenter=select_none_mode)) self._mixer_modes.add_mode( 'mute', (self._session_layout_mode, AddLayerMode(self._mixer, Layer(mute_buttons=bottom_row))), behaviour=ReenterBehaviour(on_reenter=select_none_mode)) self._mixer_modes.add_mode( 'solo', (self._session_layout_mode, AddLayerMode(self._mixer, Layer(solo_buttons=bottom_row))), behaviour=ReenterBehaviour(on_reenter=select_none_mode)) self._mixer_modes.add_mode( 'arm', (self._session_layout_mode, AddLayerMode(self._mixer, Layer(arm_buttons=bottom_row))), behaviour=ReenterBehaviour(on_reenter=select_none_mode)) self._mixer_modes.selected_mode = 'none' def _clear_send_cache_of_button_fader_color_elements(self): for element in self._elements.button_fader_color_elements_raw: element.clear_send_cache() def _create_session_modes(self): self._session_overview = SessionOverviewComponent( name='Session_Overview', is_enabled=False, session_ring=self._session_ring, enable_skinning=True, layer=Layer(button_matrix='clip_launch_matrix')) self._session_modes = SessionModesComponent( name='Session_Modes', is_enabled=False, layer=Layer( cycle_mode_button='session_mode_button', mode_button_color_control='session_button_color_element')) self._session_modes.add_mode( 'launch', AddLayerMode(self._session, Layer(scene_launch_buttons='scene_launch_buttons'))) self._session_modes.add_mode( 'mixer', DelayMode(self._mixer_modes, SESSION_MODES_SWITCH_DELAY)) (self._session_modes.add_mode( 'overview', (self._session_layout_mode, self._session_overview, AddLayerMode( self._session_navigation, Layer(page_up_button='up_button', page_down_button='down_button', page_left_button='left_button', page_right_button='right_button')), AddLayerMode( self._background, Layer(scene_launch_buttons='scene_launch_buttons')))), ) self._session_modes.selected_mode = 'launch' def _create_note_modes(self): self._drum_group = DrumGroupComponent( name='Drum_Group', is_enabled=False, translation_channel=DRUM_FEEDBACK_CHANNEL, layer=Layer(matrix='drum_pads', scroll_up_button='left_button', scroll_down_button='right_button', scroll_page_up_button='up_button', scroll_page_down_button='down_button')) self._scale_pad_translator = ConfigurablePlayableComponent( SCALE_FEEDBACK_CHANNEL, name='Scale_Pads', is_enabled=False, layer=Layer(matrix='scale_pads')) self._note_modes = ModesComponent(name='Note_Modes', is_enabled=False) self._note_modes.add_mode( 'scale', (self._scale_pad_translator, AddLayerMode(self._background, layer=Layer(up_button='up_button', down_button='down_button', left_button='left_button', right_button='right_button')))) self._note_modes.add_mode('drum', self._drum_group) self._note_modes.selected_mode = 'scale' self.__on_note_mode_changed.subject = self._note_modes def _create_main_modes(self): self._main_modes = ModesComponent( name='Main_Modes', is_enabled=False, layer=Layer(session_button='session_mode_button', note_button='note_mode_button', custom_button='custom_mode_button')) self._main_modes.add_mode('session', self._session_modes, behaviour=ImmediateBehaviour()) self._main_modes.add_mode('note', self._note_modes, behaviour=ImmediateBehaviour()) self._main_modes.add_mode('custom', None, behaviour=ImmediateBehaviour()) self._main_modes.selected_mode = 'session' self._main_modes.set_enabled(True) self.__on_main_mode_changed.subject = self._main_modes return @listens('selected_mode') def __on_main_mode_changed(self, mode): self._recording_modes.selected_mode = 'track' if mode == 'note' else 'session' if mode == 'session': self._session_modes.revert_to_main_mode() self._update_controlled_track() self._elements.layout_switch.enquire_value() @listens('selected_mode') def __on_note_mode_changed(self, mode): if self._note_modes.is_enabled(): self._update_controlled_track() @listens('value') def __on_layout_switch_value(self, value): self._last_layout_byte = value def _drum_group_changed(self): drum_group = self._drum_group_finder.drum_group drum_groud_valid = liveobj_valid(drum_group) self._drum_group.set_drum_group_device(drum_group) self._elements.note_layout_switch.send_value( sysex.DRUM_LAYOUT_BYTE if drum_groud_valid else sysex. SCALE_LAYOUT_BYTE) self._note_modes.selected_mode = 'drum' if drum_groud_valid else 'scale' def _is_instrument_mode(self): return self._main_modes.selected_mode == 'note' def _feedback_velocity_changed(self, feedback_velocity): self._elements.scale_feedback_switch.send_value(feedback_velocity)
class MonoInstrumentComponent(Component): _keypad_class = MonoScaleComponent _drumpad_class = MonoDrumpadComponent _scale_settings_component_class = ScaleTaggedSetting _toggle_settings_component_class = ToggledTaggedSetting _shifted = False def __init__(self, script, skin, grid_resolution, drum_group_finder, device_provider, parent_task_group, settings=DEFAULT_INSTRUMENT_SETTINGS, *a, **k): super(MonoInstrumentComponent, self).__init__(*a, **k) self._settings = settings self._parent_task_group = parent_task_group self._scalenames = settings['ScaleNames'] self._device_provider = device_provider self._script = script self._skin = skin self._grid_resolution = grid_resolution self._drum_group_finder = drum_group_finder self._setup_selected_session_control() self._setup_shift_mode() #self._scale_offset_component = self.register_component(self._scale_settings_component_class(name = 'VerticalOffset', attribute_tag = 'scale', parent_task_group = parent_task_group, value_dict = self._scalenames, default_value_index = self._scalenames.index(DEFAULT_SCALE), default_channel = 0, on_color = 'MonoInstrument.ScaleOffsetOnValue', off_color = 'MonoInstrument.ScaleOffsetOffValue')) self._scale_offset_component = self._scale_settings_component_class( parent=self, name='VerticalOffset', attribute_tag='scale', parent_task_group=parent_task_group, value_dict=self._scalenames, default_value_index=self._scalenames.index(DEFAULT_SCALE), default_channel=0, on_color='MonoInstrument.ScaleOffsetOnValue', off_color='MonoInstrument.ScaleOffsetOffValue') self._scale_offset_value.subject = self._scale_offset_component self.set_scale_up_button = self._scale_offset_component.up_button.set_control_element self.set_scale_down_button = self._scale_offset_component.down_button.set_control_element #self._mode_component = self.register_component(self._toggle_settings_component_class(name = 'SplitModeOffset', attribute_tag = 'mode', parent_task_group = parent_task_group,)) self._mode_component = self._toggle_settings_component_class( parent=self, name='SplitModeOffset', attribute_tag='mode', parent_task_group=parent_task_group, ) self._mode_value.subject = self._mode_component self.set_split_button = self._mode_component.split_toggle.set_control_element self.set_sequencer_button = self._mode_component.seq_toggle.set_control_element #self._keypad = self.register_component(self._keypad_class(parent = self, control_surface = script, skin = skin, grid_resolution = grid_resolution, parent_task_group = parent_task_group, settings = self._settings)) self._keypad = self._keypad_class(parent=self, control_surface=script, skin=skin, grid_resolution=grid_resolution, parent_task_group=parent_task_group, settings=self._settings) self.set_vertical_offset_up_button = self._keypad._vertical_offset_component.up_button.set_control_element self.set_vertical_offset_down_button = self._keypad._vertical_offset_component.down_button.set_control_element self.set_offset_up_button = self._keypad._offset_component.up_button.set_control_element self.set_offset_down_button = self._keypad._offset_component.down_button.set_control_element self.set_octave_up_button = self._keypad._offset_component.bank_up_button.set_control_element self.set_octave_down_button = self._keypad._offset_component.bank_down_button.set_control_element #self._drumpad = self.register_component(self._drumpad_class(parent = self, control_surface = script, skin = skin, grid_resolution = grid_resolution, parent_task_group = parent_task_group, settings = self._settings)) self._drumpad = self._drumpad_class( parent=self, control_surface=script, skin=skin, grid_resolution=grid_resolution, parent_task_group=parent_task_group, settings=self._settings) self.set_drum_offset_up_button = self._drumpad._drum_offset_component.up_button.set_control_element self.set_drum_offset_down_button = self._drumpad._drum_offset_component.down_button.set_control_element self.set_drum_octave_up_button = self._drumpad._drum_offset_component.bank_up_button.set_control_element self.set_drum_octave_down_button = self._drumpad._drum_offset_component.bank_down_button.set_control_element self.set_drumpad_mute_button = self._drumpad._drumgroup.mute_button.set_control_element self.set_drumpad_solo_button = self._drumpad._drumgroup.solo_button.set_control_element self._audio_loop = LoopSelectorComponent(follow_detail_clip=True, measure_length=1.0, name='Loop_Selector', default_size=8) self.set_loop_selector_matrix = self._audio_loop.set_loop_selector_matrix #self._main_modes = self.register_component(ModesComponent()) self._main_modes = ModesComponent() #parent = self) self._main_modes.add_mode('disabled', []) self._main_modes.add_mode('audioloop', [self._audio_loop]) self._main_modes.set_enabled(True) self._on_device_changed.subject = self._device_provider self.on_selected_track_changed.subject = self.song.view self.on_selected_track_changed() def _setup_selected_session_control(self): self._session_ring = SessionRingComponent(num_tracks=1, num_scenes=32) self._selected_session = ScaleSessionComponent( name="SelectedSession", session_ring=self._session_ring, auto_name=True, is_enabled=False) self._selected_session.set_enabled(False) def _setup_shift_mode(self): self._shifted = False #self._shift_mode = self.register_component(ModesComponent()) self._shift_mode = ModesComponent() #parent = self) self._shift_mode.add_mode('disabled', []) self._shift_mode.add_mode( 'shift', tuple([ lambda a: self._on_shift_value(True), lambda a: self._on_shift_value(False) ]), behaviour=ShiftCancellableBehaviourWithRelease()) def set_shift_button(self, button): debug('shift_button:', button) self._on_shift_value.subject = button self._shifted = 0 def set_shift_mode_button(self, button): self._on_shift_value.subject = None self._shifted = 0 self._shift_mode.shift_button.set_control_element(button) @listens('value') def _on_shift_value(self, value): #debug('on shift value:', value) self._shifted = bool(value) self.update() def set_octave_enable_button(self, button): self._keypad._offset_component.shift_button.set_control_element(button) self._drumpad._drum_offset_component.shift_button.set_control_element( button) @listens('value') def _on_octave_enable_value(self, value): value and self._keypad._offset_component.shift_button._press_button( ) or self._keypad._offset_component.shift_button._release_button() value and self._drumpad._drum_offset_component.shift_button._press_button( ) or self._drumpad._drum_offset_component.shift_button._release_button( ) @listens('value') def _mode_value(self, value): self.update() @listens('value') def _scale_offset_value(self, value): #debug('_scale_offset_value', value) value = self._settings['DefaultAutoScale'] if value is 'Auto' else value self._keypad._keygroup.scale = value self._scale_offset_component.buttons_are_pressed( ) and self._script.show_message('New scale is ' + str(value)) self.update() @listens('instrument') def _on_drum_group_changed(self): drum_device = self._drum_group_finder.drum_group #debug('monoinstrument _on_drum_group_changed', drum_device) self._drumpad._step_sequencer.set_drum_group_device(drum_device) @listens('device') def _on_device_changed(self): #debug('monoinstrument _on_device_changed') self._script.schedule_message(1, self.update) #self.update() @listens('selected_track') def on_selected_track_changed(self): self._selected_session.update_current_track() self.update() def update(self): super(MonoInstrumentComponent, self).update() self._main_modes.selected_mode = 'disabled' #if self.is_enabled(): new_mode = 'disabled' drum_device = find_drum_group_device(self.song.view.selected_track) #debug('instrument update, drum device:', drum_device.name if drum_device else None) self._drumpad._drumgroup.set_drum_group_device(drum_device) cur_track = self.song.view.selected_track if cur_track.has_audio_input and cur_track in self.song.visible_tracks: new_mode = 'audioloop' elif cur_track.has_midi_input: scale, mode = self._scale_offset_component.value, self._mode_component.value new_mode = get_instrument_type(cur_track, scale, self._settings) if mode is 'split': new_mode += '_split' elif mode is 'seq': new_mode += '_sequencer' if self._shifted: new_mode += '_shifted' self._script.set_feedback_channels( [self._scale_offset_component.channel]) self._script.set_controlled_track(self.song.view.selected_track) #debug('trying to set mode:', new_mode) if new_mode in self._main_modes._mode_map or new_mode is None: self._main_modes.selected_mode = new_mode self._script.set_controlled_track(self.song.view.selected_track) else: self._main_modes.selected_mode = 'disabled' self._script.set_controlled_track(self.song.view.selected_track)
class Morph(ControlSurface): _model_name = 'Morph' bank_definitions = BANK_DEFINITIONS def __init__(self, c_instance, *a, **k): self.log_message = logger.info super(Morph, self).__init__(c_instance, *a, **k) self._skin = Skin(MorphColors) with self.component_guard(): self._setup_controls() self._setup_background() #self._setup_button_background() self._setup_drum_group() self._setup_drum_group2() self._setup_keys_group() self._setup_piano_group() self._setup_autoarm() self._setup_device() self._setup_session() self._setup_session2() self._setup_session3() self._setup_mixer() self._setup_transport() self._setup_viewcontrol() self._setup_recorder() self._setup_translations() self._setup_modes() self._on_device_changed.subject = self._device_provider self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Morph ' + VERSION + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>') self.show_message('Morph ' + VERSION + ' Control Surface Loaded') self.schedule_message(2, self._init_surface) #debug('device:', self._device._get_device()) def _init_surface(self): #self._main_modes.selected_mode = 'Main' self._send_midi(CHECK_MAPS) self._send_midi(MAGNET_VALUES_CALL) def port_settings_changed(self): super(Morph, self).port_settings_changed() self._init_surface() def _setup_controls(self): is_momentary = True optimized = False resource = ExclusiveResource #PrioritizedResource self._pad = [[ ButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=MORPH_PADS[row][column], name='Pad_' + str(column) + '_' + str(row), skin=self._skin, resource_type=resource) for column in range(4) ] for row in range(4)] for row in self._pad: for pad in row: pad.enabled = False self._button = [ ButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=MORPH_BUTTONS[index], name='Button_' + str(index), skin=self._skin, resource_type=resource) for index in range(8) ] for button in self._button: button.set_enabled = False self._key = [ MorphButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=MORPH_KEYS[index], name='Key_' + str(index), skin=self._skin, resource_type=resource) for index in range(25) ] self._dials = [ MorphEncoderElement(msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=MORPH_DIALS[index], map_mode=Live.MidiMap.MapMode.absolute, name='Dial_' + str(index), resource_type=resource) for index in range(8) ] self._slider = [ MorphEncoderElement(msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=MORPH_SLIDERS[index], map_mode=Live.MidiMap.MapMode.absolute, name='Slider_' + str(index), resource_type=resource) for index in range(2) ] self._send_pressure = [ MorphEncoderElement(msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=MORPH_SEND_PRESSURE[index], map_mode=Live.MidiMap.MapMode.absolute, name='SendPressure_' + str(index), resource_type=resource) for index in range(2) ] self._thunder_slider = [ MorphEncoderElement(msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=MORPH_THUNDER_SLIDERS[index], map_mode=Live.MidiMap.MapMode.absolute, name='Slider_' + str(index), resource_type=resource) for index in range(6) ] self._pad_matrix = ButtonMatrixElement(name='PadMatrix', rows=self._pad) self._dial_matrix = ButtonMatrixElement(name='DialMatrix', rows=[self._dials]) self._button_matrix = ButtonMatrixElement(name='ButtonMatrix', rows=[self._button]) self._key_matrix = ButtonMatrixElement(name='KeyMatrix', rows=[self._key[:14]]) self._key_shift_matrix = ButtonMatrixElement(name='KeyShiftMatrix', rows=[self._key[2:11]]) self._slider_matrix = ButtonMatrixElement(name='SliderMatrix', rows=[self._slider]) self._send_pressure_matrix = ButtonMatrixElement( name='SendAMatrix', rows=[self._send_pressure]) self._thunder_slider_matrix = ButtonMatrixElement( name='ThunderSliderMatrix', rows=[self._thunder_slider]) #self._shift_send_pressure_matrix = ButtonMatrixElement(name = 'ShiftSendMatrix', rows = [ [None, None, self._send_pressure[0], self._send_pressure[1]] ]) self._piano_button = [ MorphButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=PIANO_BUTTONS[index], name='PianoButton_' + str(index), skin=self._skin, resource_type=resource) for index in range(4) ] for button in self._piano_button: button.enabled = False #self._piano_key = [MorphButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = PIANO_CHANNEL, identifier = PIANO_KEYS[index], name = 'PianoKey_' + str(index), skin = self._skin, resource_type = resource) for index in range(25)] self._piano_matrix = ButtonMatrixElement(name='PianoMatrix', rows=[self._key]) self._piano_session_matrix = ButtonMatrixElement( name='PianoSessionMatrix', rows=[ self._key[0:4], self._key[4:8], self._key[8:12], self._key[12:16] ]) #self._drum_session_matrix = ButtonMatrixElement(name = 'DrumSessionMatrix', rows = ) def _setup_background(self): self._background = BackgroundComponent() self._background.layer = Layer(priority=1, pads=self._pad_matrix, buttons=self._button_matrix, keys=self._key_matrix, dials=self._dial_matrix, sliders=self._slider_matrix) self._background.set_enabled(False) def _setup_drum_group(self): self._drum_group = MorphDrumGroup( set_pad_translations=self.set_pad_translations, translation_channel=PAD_TRANSLATION_CHANNEL) self._drum_group.main_layer = AddLayerMode( self._drum_group, Layer(priority=2, matrix=self._pad_matrix)) self._drum_group.nav_layer = AddLayerMode( self._drum_group, Layer(priority=2, scroll_up_button=self._key[1], scroll_down_button=self._key[0])) self._drum_group.set_enabled(False) def _setup_drum_group2(self): self._drum_group2 = MorphDrumGroup( set_pad_translations=self.set_pad_translations, translation_channel=DRUM_TRANSLATION_CHANNEL) self._drum_group2.main_layer = AddLayerMode( self._drum_group2, Layer(priority=2, matrix=self._pad_matrix)) self._drum_group2.nav_layer = AddLayerMode( self._drum_group2, Layer(priority=2, scroll_up_button=self._key[1], scroll_down_button=self._key[0])) self._drum_group2.set_enabled(False) def _setup_keys_group(self): self._keys_group = MorphKeysGroup( translation_channel=KEY_TRANSLATION_CHANNEL) self._keys_group.main_layer = AddLayerMode( self._keys_group, Layer(priority=2, matrix=self._key_matrix)) self._keys_group.shift_layer = AddLayerMode( self._keys_group, Layer(priority=2, matrix=self._key_shift_matrix, scroll_up_button=self._key[12], scroll_down_button=self._key[11])) self._keys_group.set_enabled(False) def _setup_piano_group(self): self._piano_group = MorphKeysGroup( translation_channel=PIANO_TRANSLATION_CHANNEL) self._piano_group._hi_limit = 8 self._piano_group.main_layer = AddLayerMode( self._piano_group, Layer(priority=2, matrix=self._piano_matrix, scroll_up_button=self._piano_button[1], scroll_down_button=self._piano_button[0])) #self._piano_group.shift_layer = AddLayerMode(self._piano_group, Layer(matrix = self._piano_shift_matrix, scroll_up_button = self._pian0[12], scroll_down_button = self._key[11])) self._piano_group.set_enabled(False) def _setup_autoarm(self): self._auto_arm = AutoArmComponent(name='Auto_Arm') self._auto_arm.can_auto_arm_track = self._can_auto_arm_track self._auto_arm._update_notification = lambda: None def _setup_transport(self): self._transport = TransportComponent(name='Transport') self._transport.layer = Layer(priority=2, play_button=self._button[4], stop_button=self._button[5], overdub_button=self._button[6]) self._transport.set_enabled(False) def _setup_translations(self): self._translations = TranslationComponent(name='Translations', channel=USER_CHANNEL, controls=self._dials + self._slider) self._translations.set_enabled(False) def _setup_device(self): self._device = MorphDeviceComponent( device_decorator_factory=DeviceDecoratorFactory(), banking_info=BankingInfo(self.bank_definitions), device_provider=self._device_provider, device_bank_registry=DeviceBankRegistry()) self._device_parameters = DeviceParameterComponent(self._device) self._device_parameters.layer = Layer( priority=2, parameter_controls=self._dial_matrix) self._device.set_enabled(False) self._device_parameters.set_enabled(False) self._device2 = MorphDeviceComponent( device_decorator_factory=DeviceDecoratorFactory(), banking_info=BankingInfo(self.bank_definitions), device_provider=self._device_provider, device_bank_registry=DeviceBankRegistry()) self._device_parameters2 = DeviceParameterComponent(self._device2) self._device_parameters2.layer = Layer( priority=2, parameter_controls=self._thunder_slider_matrix) self._device2.set_enabled(False) self._device_parameters2.set_enabled(False) def _setup_session(self): self._session_ring = SessionRingComponent(name='Session_Ring', num_tracks=4, num_scenes=4) self._session = SessionComponent(name='Session', session_ring=self._session_ring, auto_name=True) self._session.layer = Layer( priority=2, clip_launch_buttons=self._pad_matrix, ) # stop_all_clips_button = self._button[5]) self._session.set_enabled(False) self._session_navigation = SessionNavigationComponent( name='Session_Navigation', session_ring=self._session_ring) self._session_navigation.layer = Layer(priority=2, left_button=self._button[0], right_button=self._button[1]) self._session_navigation.set_enabled(False) def _setup_session2(self): self._session2 = SessionComponent(name='Session2', session_ring=self._session_ring, auto_name=True) self._session2.layer = Layer( priority=2, clip_launch_buttons=self._piano_session_matrix) self._session2.set_enabled(False) def _setup_session3(self): self._session3 = SessionComponent(name='Session3', session_ring=self._session_ring, auto_name=True) self._session3.layer = Layer(priority=2, clip_launch_buttons=self._pad_matrix) self._session3.set_enabled(False) def _setup_mixer(self): self._mixer = MorphMixerComponent( tracks_provider=self._session_ring, track_assigner=SimpleTrackAssigner(), auto_name=True, invert_mute_feedback=False, channel_strip_component_type=MorphChannelStripComponent) self._mixer._selected_strip.main_layer = AddLayerMode( self._mixer._selected_strip, Layer(priority=2, send_controls=self._send_pressure_matrix)) self._mixer._selected_strip.shift_layer = AddLayerMode( self._mixer._selected_strip, Layer(priority=2, stop_button=self._button[5])) #self._mixer._selected_strip.shift_layer = AddLayerMode(self._mixer, Layer(send_controls = self._shift_send_pressure_matrix.submatrix[:,])) def _setup_viewcontrol(self): self._viewcontrol = ViewControlComponent() self._viewcontrol.layer = Layer(priority=2, prev_track_button=self._button[0], next_track_button=self._button[1]) self._viewcontrol.set_enabled(False) def _setup_recorder(self): self._recorder = SessionRecordingComponent( view_controller=ViewControlComponent()) self._recorder.layer = Layer(priority=2, record_button=self._button[6]) self._recorder.set_enabled(False) def _assign_crossfader(self): self._slider[1].connect_to( self.song.master_track.mixer_device.crossfader) debug('_assign_crossfader:', self._slider[1]._parameter_to_map_to) def _deassign_crossfader(self): self._slider[1].release_parameter() debug('_assign_crossfader:', self._slider[1]._parameter_to_map_to) def _setup_modes(self): self._production_modes = ModesComponent(name='ProductionModes') self._production_modes.add_mode('Main', [ self._mixer, self._mixer._selected_strip.main_layer, self._viewcontrol, self._drum_group, self._drum_group.main_layer, self._keys_group, self._keys_group.main_layer, self._device, self._device_parameters, self._transport, self._assign_crossfader ]) self._production_modes.add_mode('Shift', [ self._mixer, self._mixer._selected_strip.shift_layer, self._session, self._session_navigation, self._drum_group, self._drum_group.nav_layer, self._keys_group, self._keys_group.shift_layer, self._deassign_crossfader, self._recorder, self._translations ], behaviour=MomentaryBehaviour()) self._production_modes.layer = Layer(Shift_button=self._button[7]) self._production_modes.selected_mode = 'Main' self._production_modes.set_enabled(False) self._piano_modes = ModesComponent(name='PianoModes') self._piano_modes.add_mode('Main', [ self._piano_group, self._piano_group.main_layer, self._mixer, self._mixer._selected_strip.main_layer, self._viewcontrol, self._device, self._device_parameters, self._transport, self._assign_crossfader ]) self._piano_modes.add_mode('Shift', [ self._mixer, self._mixer._selected_strip.shift_layer, self._session2, self._session_navigation, self._recorder ], behaviour=MomentaryBehaviour()) self._piano_modes.layer = Layer(Shift_button=self._button[7]) self._piano_modes.selected_mode = 'Main' self._piano_modes.set_enabled(False) self._drumpad_modes = ModesComponent(name='DrumpadModes') self._drumpad_modes.add_mode('Main', [ self._mixer, self._mixer._selected_strip.main_layer, self._viewcontrol, self._drum_group2, self._drum_group2.main_layer, self._transport, self._assign_crossfader ]) self._drumpad_modes.add_mode('Shift', [ self._mixer, self._mixer._selected_strip.shift_layer, self._session3, self._session_navigation, self._recorder ], behaviour=MomentaryBehaviour()) self._drumpad_modes.layer = Layer(Shift_button=self._button[7]) self._drumpad_modes.selected_mode = 'Main' self._drumpad_modes.set_enabled(False) self._thunder_modes = ModesComponent(name='ThunderModes') self._thunder_modes.add_mode('Main', [ self._mixer, self._mixer._selected_strip.main_layer, self._viewcontrol, self._transport, self._assign_crossfader, self._device2, self._device_parameters2 ]) self._thunder_modes.add_mode('Shift', [ self._mixer, self._mixer._selected_strip.shift_layer, self._recorder, self._device2, self._device_parameters2 ], behaviour=MomentaryBehaviour()) self._thunder_modes.layer = Layer(Shift_button=self._button[7]) self._thunder_modes.selected_mode = 'Main' self._thunder_modes.set_enabled(False) self._main_modes = ModesComponent(name='MainModes') self._main_modes.add_mode('disabled', self._background) self._main_modes.add_mode('ProductionMode', [self._production_modes]) self._main_modes.add_mode('PianoMode', [self._piano_modes]) self._main_modes.add_mode('DrumpadMode', [self._drumpad_modes]) self._main_modes.add_mode('ThunderMode', [self._thunder_modes]) self._report_mode.subject = self._main_modes self._main_modes.selected_mode = 'disabled' @listens('selected_mode') def _report_mode(self, *a, **k): debug('Modes:', self._main_modes.selected_mode, self._production_modes.selected_mode, self._piano_modes.selected_mode, self._drumpad_modes.selected_mode, self._thunder_modes.selected_mode) def _can_auto_arm_track(self, track): routing = track.current_input_routing return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith( 'Sensel') or routing.startswith('Morph') @listens('device') def _on_device_changed(self): debug('_on_device_changed:', self._device_provider.device) self._drum_group.set_drum_group_device(self._device_provider.device) def disconnect(self): self.log_message( '<<<<<<<<<<<<<<<<<<<<<<<<< Morph log closed >>>>>>>>>>>>>>>>>>>>>>>>>' ) super(Morph, self).disconnect() def process_midi_bytes(self, midi_bytes, midi_processor): super(Morph, self).process_midi_bytes(midi_bytes, midi_processor) if midi.is_sysex(midi_bytes): self.handle_sysex(midi_bytes) def handle_sysex(self, midi_bytes): debug('sysex: ', str(midi_bytes)) #debug('matching:', midi_bytes[1:5], 'to', tuple([0, 1, 97] + [self._sysex_id])) if len(midi_bytes) == 9 and midi_bytes[1:5] == tuple([0, 1, 97] + [self._sysex_id]): if not self._connected: #debug('connecting from sysex...') self._connected = True self._initialize_hardware() self._initialize_script() if len(midi_bytes) == 11: if midi_bytes == PIANO_OVERLAY: debug('piano overlay...') self._main_modes.selected_mode = 'PianoMode' elif midi_bytes == PRODUCTION_OVERLAY: debug('production overlay...') self._main_modes.selected_mode = 'ProductionMode' elif midi_bytes == DRUM_OVERLAY: debug('drum overlay...') self._main_modes.selected_mode = 'DrumpadMode' elif midi_bytes == THUNDER_OVERLAY: debug('thunder overlay...') self._main_modes.selected_mode = 'ThunderMode' elif midi_bytes == NO_OVERLAY: debug('no overlay...') self._main_modes.selected_mode = 'disabled'
class Cntrlr(LividControlSurface): __module__ = __name__ __doc__ = " Monomodular controller script for Livid CNTRLR " _sysex_id = 8 _model_name = 'Cntrlr' _host_name = 'Cntrlr' _version_check = 'b996' monomodular = None device_provider_class = ModDeviceProvider def __init__(self, *a, **k): super(Cntrlr, self).__init__(*a, **k) 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_background() self._setup_translations() #self._setup_autoarm() self._setup_session_control() self._setup_send_reset_controls() self._setup_mixer_control() self._setup_transport_control() self._setup_device_control() self._setup_mod_device_control() self._setup_device_selector() #self._setup_session_recording_component() #self._setup_viewcontrol() #self._setup_instrument() self._setup_mod() self._setup_modswitcher() self._setup_translations() self._setup_modes() self._setup_m4l_interface() self._on_device_changed.subject = self.song #self.set_feedback_channels(range(14, 15)) def _initialize_script(self): super(Cntrlr, self)._initialize_script() self._connected = True self._main_modes.selected_mode = 'MixMode' self._main_modes.set_enabled(True) #self._instrument.set_enabled(True) #self._main_modes.selected_mode = 'disabled' #self._main_modes.selected_mode = 'MixMode' self._session_ring._update_highlight() self._session_ring.track_offset = 0 if liveobj_valid(self.song.visible_tracks[0]): self.song.view.selected_track = self.song.visible_tracks[0] def _initialize_hardware(self): super(Cntrlr, self)._initialize_hardware() for index in range(4): self._encoder[index].send_value(0) def port_settings_changed(self): self._main_modes.selected_mode = 'disabled' super(Cntrlr, self).port_settings_changed() def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_controls(self): is_momentary = True optimized = True resource = PrioritizedResource self._fader = [MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = CNTRLR_FADERS[index], name = 'Fader_' + str(index), num = index, script = self, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(8)] self._dial_left = [MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = CNTRLR_KNOBS_LEFT[index], name = 'Dial_Left_' + str(index), num = CNTRLR_KNOBS_LEFT[index], script = self, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(12)] self._dial_right = [MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = CNTRLR_KNOBS_RIGHT[index], name = 'Dial_Right_' + str(index), num = CNTRLR_KNOBS_RIGHT[index], script = self, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(12)] self._encoder = [CodecEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = CNTRLR_DIALS[index], name = 'Encoder_' + str(index), num = CNTRLR_DIALS[index], script = self, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(12)] self._encoder_button = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = CNTRLR_DIAL_BUTTONS[index], name = 'Encoder_Button_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(12)] self._grid = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = CNTRLR_GRID[index], name = 'Grid_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(16)] self._button = [MonoButtonElement(is_momentary = is_momentary,msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = CNTRLR_BUTTONS[index], name = 'Button_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) 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._grid + self._button def _setup_background(self): self._background = BackgroundComponent(name = 'Background') self._background.layer = Layer(priority = 3, matrix = self._matrix.submatrix[:,:], faders = self._fader_matrix.submatrix[:,:], left_knobs = self._knob_left_matrix.submatrix[:,:], right_knobs = self._knob_right_matrix.submatrix[:,:], dials = self._dial_matrix, dial_buttons = self._dial_button_matrix.submatrix[:,:], keys = self._key_matrix.submatrix[:,:]) self._background.set_enabled(True) def _define_sysex(self): self.encoder_navigation_on = SendLividSysexMode(livid_settings = self._livid_settings, call = 'set_encoder_encosion_mode', message = [0, 0, 0, 0]) def _setup_transport_control(self): self._transport = CntrlrTransportComponent(name = 'Transport') self._transport._play_toggle.view_transform = lambda value: 'Transport.PlayOn' if value else 'Transport.PlayOff' self._transport._record_toggle.view_transform = lambda value: 'Transport.RecordOn' if value else 'Transport.RecordOff' self._transport.layer = Layer(priority = 4, play_button = self._button[28], stop_button = self._button[29], record_button = self._button[30]) self._transport.set_enabled(False) def _setup_autoarm(self): self._auto_arm = CntrlrAutoArmComponent(name='Auto_Arm') #self._auto_arm._update_notification = lambda a: None 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 = FixedLengthSessionRecordingComponent(clip_creator = self._clip_creator, view_controller = ViewControlComponent(), name = 'SessionRecorder') # is_enabled = False) self._recorder.main_layer = AddLayerMode(self._recorder, Layer(priority = 4, record_button = self._button[29])) self._recorder.shift_layer = AddLayerMode(self._recorder, Layer(priority = 4, automation_button = self._button[29])) self._recorder.set_enabled(False) def _setup_session_control(self): self._session_ring = SessionRingComponent(num_tracks = 4, num_scenes = 4) self._session_ring.set_enabled(False) self._session_navigation = CntrlrSessionNavigationComponent(name = 'SessionNavigation', session_ring = self._session_ring) self._session_navigation._vertical_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._vertical_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation.layer = Layer(priority = 4, down_button = self._button[14], up_button = self._button[15], left_button = self._button[12], right_button = self._button[13]) self._session_navigation.set_enabled(False) self._session = SessionComponent(session_ring = self._session_ring, auto_name = True) hasattr(self._session, '_enable_skinning') and self._session._enable_skinning() self._session.layer = Layer(priority = 4, clip_launch_buttons = self._matrix.submatrix[:,:]) self._session.set_enabled(False) self._session_zoom = SessionOverviewComponent(name = 'SessionZoom', session_ring = self._session_ring, enable_skinning = True) self._session_zoom.layer = Layer(priority = 4, button_matrix = self._matrix.submatrix[:,:]) self._session_zoom.set_enabled(False) def _setup_send_reset_controls(self): self._send_reset = ResetSendsComponent(script = self) self._send_reset.layer = Layer(priority = 4, buttons = self._key_matrix.submatrix[8:12, :1]) self._send_reset.set_enabled(False) def _setup_mixer_control(self): self._mixer = MonoMixerComponent(name = 'Mixer', num_returns = 2,tracks_provider = self._session_ring, track_assigner = SimpleTrackAssigner(), invert_mute_feedback = True, auto_name = True, enable_skinning = True) self._mixer.fader_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], send_controls = self._knob_left_matrix, eq_gain_controls = self._knob_right_matrix)) self._mixer.button_layer = AddLayerMode(self._mixer, Layer(priority = 4, mute_buttons = self._key_matrix.submatrix[:4, 1:], stop_clip_buttons = self._key_matrix.submatrix[8:12, 1:], solo_buttons = self._key_matrix.submatrix[:4, :1], arm_buttons = self._key_matrix.submatrix[4:8, :1], track_select_buttons = self._key_matrix.submatrix[4:8, 1:],)) self._mixer.master_strip().layer = Layer(priority = 4, volume_control = self._fader[7],) self._mixer.set_enabled(False) def _setup_device_control(self): self._device_selection_follows_track_selection = FOLLOW self._device = CntrlrDeviceComponent(script = self, name = 'Device_Component', device_provider = self._device_provider, device_bank_registry = DeviceBankRegistry()) self._device.layer = Layer(priority = 4, parameter_controls = self._dial_matrix.submatrix[:, 1:], on_off_button = self._encoder_button[4], bank_prev_button = self._encoder_button[8], bank_next_button = self._encoder_button[9],) #lock_button = self._encoder_button[7]) self._device.set_enabled(False) self._device_navigator = DeviceNavigator(self._device_provider, self._mixer, self) self._device_navigator.name = 'Device_Navigator' self._device_navigator.layer = Layer(priority = 4, prev_button = self._encoder_button[10], next_button = self._encoder_button[11],) self._device_navigator.set_enabled(False) def _setup_mod_device_control(self): self._mod_device = SpecialCntrlrDeviceComponent(script = self, name = 'Device_Component', device_provider = self._device_provider, device_bank_registry = DeviceBankRegistry()) self._mod_device.layer = Layer(priority = 4, parameter_controls = self._dial_matrix.submatrix[:, :],) self._mod_device.set_enabled(False) def _setup_device_selector(self): self._device_selector = CntrlrDeviceSelector(self) self._device_selector.name = 'Device_Selector' #self._device_selector.select_layer = AddLayerMode(self._device_selector, Layer(priority = 6 , matrix = self._matrix.submatrix[:, :])) #self._device_selector.select_layer = AddLayerMode(self._device_selector, Layer(priority = 6, matrix = ButtonMatrixElement(rows = [self._grid[:4],self._grid[4:8],self._grid[8:12],self._grid[12:14]]))) #self._device_selector.assign_layer = AddLayerMode(self._device_selector, Layer(priority = 7, assign_button = self._grid[14])) 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._color = 127 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, device_provider = self._device_provider) # is_enabled = False) self.modhandler.name = 'ModHandler' self.modhandler.lock_layer = AddLayerMode(self.modhandler, Layer(priority=8, lock_button=self._grid[15])) self.modhandler.layer = Layer(priority = 8, cntrlr_encoder_button_grid = self._dial_button_matrix.submatrix[:,:], cntrlr_grid = self._matrix.submatrix[:,:], cntrlr_keys = self._key_matrix.submatrix[:,:],) #parameter_controls = self._dial_matrix.submatrix[:,:]) self.modhandler.set_enabled(False) def _setup_modswitcher(self): self._modswitcher = ModesComponent(name = 'ModSwitcher') # is_enabled = False) self._modswitcher.set_enabled(False) def _setup_viewcontrol(self): self._view_control = CntrlrViewControlComponent(name='View_Control') self._view_control.main_layer = AddLayerMode(self._view_control, Layer(scene_select_dial = self._encoder[2], track_select_dial = self._encoder[3],)) #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) def _setup_modes(self): self._modswitcher = ModesComponent(name = 'ModSwitcher') self._modswitcher.add_mode('mod', [self._mixer, self._mixer.fader_layer, self.modhandler, self._mod_device, self._device_selector,]) self._modswitcher.add_mode('translations', [self._translations, self._device, self._mixer, self._mixer.fader_layer, self._device_navigator, self._device_selector]) self._modswitcher.selected_mode = 'translations' self._modswitcher.set_enabled(False) self._session_modes = ModesComponent(name = 'SessionModes') self._session_modes.add_mode('Launch', [self._session]) self._session_modes.add_mode('Zoom', [self._session_zoom]) self._session_modes.layer = Layer(priority = 4, cycle_mode_button = self._button[31]) self._session_modes.set_enabled(False) self._main_modes = ModesComponent(name = 'MainModes') self._main_modes.add_mode('disabled', [self._background, self.encoder_navigation_on]) self._main_modes.add_mode('MixMode', [self._mixer, self._mixer.fader_layer, self._mixer.button_layer, self._session_modes, self._session_navigation, self._session_ring, self._device, self._device_navigator, self._send_reset, self._transport]) self._main_modes.add_mode('ModMode1', [self._modswitcher, self._choose_mod, DelayMode(self._update_modswitcher, delay = .1, parent_task_group = self._task_group), DelayMode(self.modhandler.update, delay = .2, parent_task_group = self._task_group)], behaviour = DefaultedBehaviour(default_mode = 'MixMode')) self._main_modes.add_mode('ModMode2', [self._modswitcher, self._choose_mod, DelayMode(self._update_modswitcher, delay = .1, parent_task_group = self._task_group), DelayMode(self.modhandler.update, delay = .2, parent_task_group = self._task_group)], behaviour = DefaultedBehaviour(default_mode = 'MixMode')) self._main_modes.add_mode('ModMode3', [self._modswitcher, self._choose_mod, DelayMode(self._update_modswitcher, delay = .1, parent_task_group = self._task_group), DelayMode(self.modhandler.update, delay = .2, parent_task_group = self._task_group)], behaviour = DefaultedBehaviour(default_mode = 'MixMode')) self._main_modes.add_mode('ModMode4', [self._modswitcher, self._choose_mod, DelayMode(self._update_modswitcher, delay = .1, parent_task_group = self._task_group), DelayMode(self.modhandler.update, delay = .2, parent_task_group = self._task_group)], behaviour = DefaultedBehaviour(default_mode = 'MixMode')) self._main_modes.layer = Layer(priority = 4, ModMode1_button = self._encoder_button[0], ModMode2_button = self._encoder_button[1], ModMode3_button = self._encoder_button[2], ModMode4_button = self._encoder_button[3]) #, self._main_modes.selected_mode = 'disabled' self._main_modes.set_enabled(True) def _choose_mod(self): modes = ('ModMode1', 'ModMode2', 'ModMode3', 'ModMode4') mode = self._main_modes.selected_mode debug('choose_mod:', self._main_modes.selected_mode) if mode in modes: index = modes.index(mode) self._translations._channel = index + self._translations._user_channel_offset self._translations.update() self._device_selector.select_device(index) def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent(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') @listens('appointed_device') def _on_device_changed(self): debug('appointed device changed, script') #self._main_modes.selected_mode is 'ModSwitcher' and self._update_modswitcher() def _on_selected_track_changed(self): super(Cntrlr, self)._on_selected_track_changed() #self._drum_group_finder.device_parent = self.song.veiw.selected_track #if not len(self.song.view.selected_track.devices): # self._main_modes.selected_mode is 'ModSwitcher' and self._update_modswitcher() def _update_modswitcher(self): debug('update modswitcher', self.modhandler.active_mod()) if self.modhandler.active_mod() and self._device_selector.has_mod_entry(['ModMode1', 'ModMode2', 'ModMode3', 'ModMode4'].index(self._main_modes.selected_mode)): self._modswitcher.selected_mode = 'mod' else: self._modswitcher.selected_mode = 'translations' def update_display(self): super(Cntrlr, self).update_display() self.modhandler.send_ring_leds() def restart_monomodular(self): #debug('restart monomodular') self.modhandler.disconnect() with self.component_guard(): self._setup_mod()
class Twister(LividControlSurface): __module__ = __name__ __doc__ = " Monomodular controller script for Livid CNTRLR " _sysex_id = 8 _model_name = 'Twister' _host_name = 'Twister' _version_check = 'b996' monomodular = None device_provider_class = ModDeviceProvider def __init__(self, *a, **k): super(Twister, self).__init__(*a, **k) self._skin = Skin(TwisterColors) self._device_selection_follows_track_selection = True with self.component_guard(): self._setup_monobridge() self._setup_controls() #self._define_sysex() self._setup_background() self._setup_m4l_interface() self._setup_mod() self._setup_device_control() self._setup_modes() self._on_device_changed.subject = self.song self._on_selected_track_changed.subject = self.song.view def _initialize_script(self): super(Twister, self)._initialize_script() self._connected = True def _setup_controls(self): is_momentary = True optimized = True resource = PrioritizedResource self._encoder = [CodecEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = TWISTER_DIALS[index], name = 'Encoder_' + str(index), num = TWISTER_DIALS[index], script = self, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(16)] self._encoder_button = [TwisterButtonElement(is_momentary = is_momentary, msg_type = MIDI_CC_TYPE, channel = 1, identifier = TWISTER_DIAL_BUTTONS[index], name = 'Encoder_Button_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(16)] self._dial_matrix = ButtonMatrixElement(name = 'Dial_Matrix', rows = [self._encoder[index*4:(index*4)+4] for index in range(4)]) self._dial_button_matrix = ButtonMatrixElement(name = 'Dial_Button_Matrix', rows = [self._encoder_button[index*4:(index*4)+4] for index in range(4)]) def _setup_background(self): self._background = BackgroundComponent(name = 'Background') self._background.layer = Layer(priority = 3, dials = self._dial_matrix, dial_buttons = self._dial_button_matrix.submatrix[:,:]) self._background.set_enabled(True) def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent(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 _define_sysex(self): pass def _check_connection(self): self._connected = True self._initialize_hardware() self._initialize_script() def _setup_mixer_control(self): self._mixer_session_ring = SessionRingComponent(num_tracks = 4, num_scenes = 4) self._mixer = MonoMixerComponent(name = 'Mixer', tracks_provider = self._mixer_session_ring, track_assigner = simple_track_assigner, invert_mute_feedback = True, auto_name = True, enable_skinning = True) self._mixer.layer = Layer(priority = 4, solo_buttons = self._dial_button_matrix.submatrix[:,0], stop_clip_buttons = self._dial_button_matrix.submatrix[:,1], track_select_buttons = self._dial_button_matrix.submatrix[:,2]) self._mixer.set_enabled(True) def _setup_device_control(self): self._device = SpecialDeviceComponent(name = 'Device_Component', device_provider = self._device_provider, device_bank_registry = DeviceBankRegistry(), script = self) self._device.layer = Layer(priority = 4, parameter_controls = self._dial_matrix.submatrix[:,:],) self._device.bank_layer = AddLayerMode(self._device, Layer(priority = 4, bank_prev_button = self._encoder_button[12], bank_next_button = self._encoder_button[13])) self._device.set_enabled(False) def _setup_mod(self): self.monomodular = get_monomodular(self) self.monomodular.name = 'monomodular_switcher' self.modhandler = TwisterModHandler(self, device_provider = self._device_provider) self.modhandler.name = 'ModHandler' self.modhandler.layer = Layer(priority = 8, twister_encoder_button_grid = self._dial_button_matrix.submatrix[:,:],) #twister_encoder_grid = self._dial_matrix.submatrix[:,:],) self.modhandler.set_enabled(False) def _setup_modes(self): self._modswitcher = ModesComponent(name = 'ModSwitcher') self._modswitcher.add_mode('mod', [self.modhandler, self._device]) self._modswitcher.add_mode('device', [self._device, self._device.bank_layer]) self._modswitcher.selected_mode = 'device' self._modswitcher.set_enabled(True) 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 = 'device' @listens('appointed_device') def _on_device_changed(self): debug('appointed device changed, script') self._update_modswitcher() @listens('selected_track') def _on_selected_track_changed(self): debug('_on_selected_track_changed') #super(Cntrlr, self)._on_selected_track_changed() #self._drum_group_finder.device_parent = self.song.veiw.selected_track if not len(self.song.view.selected_track.devices): self._update_modswitcher() def restart_monomodular(self): #debug('restart monomodular') self.modhandler.disconnect() with self.component_guard(): self._setup_mod()
class DeviceNavigationComponent(DeviceNavigationComponentBase): __events__ = (u'drum_pad_selection', u'mute_solo_stop_cancel_action_performed') def __init__(self, device_bank_registry=None, banking_info=None, delete_handler=None, track_list_component=None, *a, **k): assert banking_info is not None assert device_bank_registry is not None assert track_list_component is not None self._flattened_chain = FlattenedDeviceChain(collect_devices) self._track_decorator = DecoratorFactory() self._modes = NullModes() self.move_device = None super(DeviceNavigationComponent, self).__init__(item_provider=self._flattened_chain, *a, **k) self._delete_handler = delete_handler self.chain_selection = ChainSelectionComponent(parent=self, is_enabled=False) self.bank_selection = BankSelectionComponent( bank_registry=device_bank_registry, banking_info=banking_info, device_options_provider=self._device_component, is_enabled=False, parent=self) self.move_device = MoveDeviceComponent(parent=self, is_enabled=False) self._last_pressed_button_index = -1 self._selected_on_previous_press = None self._modes = ModesComponent(parent=self) self._modes.add_mode(u'default', [ partial(self.chain_selection.set_parent, None), partial(self.bank_selection.set_device, None) ]) self._modes.add_mode(u'chain_selection', [self.chain_selection]) self._modes.add_mode(u'bank_selection', [self.bank_selection]) self._modes.selected_mode = u'default' self.register_disconnectable(self._flattened_chain) self.__on_items_changed.subject = self self.__on_bank_selection_closed.subject = self.bank_selection self._update_selected_track() self._track_list = track_list_component watcher = self.register_disconnectable( DeviceChainStateWatcher(device_navigation=self)) self.__on_device_item_state_changed.subject = watcher self._update_device() self._update_button_colors() @property def modes(self): return self._modes def _in_device_enabling_mode(self): return self._track_list.selected_mode == u'mute' def _on_select_button_pressed(self, button): device_or_pad = self.items[button.index].item if self._in_device_enabling_mode(): self._toggle_device(device_or_pad) self.notify_mute_solo_stop_cancel_action_performed() else: self._last_pressed_button_index = button.index if not self._delete_handler or not self._delete_handler.is_deleting: self._selected_on_previous_press = device_or_pad if self.selected_object != device_or_pad else None self._select_item(device_or_pad) def _on_select_button_released_immediately(self, button): if not self._in_device_enabling_mode(): self._last_pressed_button_index = -1 device_or_pad = self.items[button.index].item if self._delete_handler and self._delete_handler.is_deleting: self._delete_item(device_or_pad) elif self.selected_object == device_or_pad and device_or_pad != self._selected_on_previous_press: self._on_reselecting_object(device_or_pad) self._selected_on_previous_press = None def _on_select_button_pressed_delayed(self, button): if not self._in_device_enabling_mode(): self._on_pressed_delayed(self.items[button.index].item) def _on_select_button_released(self, button): if button.index == self._last_pressed_button_index: self._modes.selected_mode = u'default' self._last_pressed_button_index = -1 self._end_move_device() @dispatch(Live.DrumPad.DrumPad) def _toggle_device(self, drum_pad): if liveobj_valid(drum_pad): drum_pad.mute = not drum_pad.mute @dispatch(object) def _toggle_device(self, device): if liveobj_valid(device) and device.parameters[0].is_enabled: set_enabled(device, not is_on(device)) @listens(u'state') def __on_device_item_state_changed(self): self._update_button_colors() @listens(u'items') def __on_items_changed(self): new_items = map(lambda x: x.item, self.items) lost_selection_on_empty_pad = new_items and is_drum_pad( new_items[-1] ) and self._flattened_chain.selected_item not in new_items if self._should_select_drum_pad() or lost_selection_on_empty_pad: self._select_item(self._current_drum_pad()) if self.moving: self._show_selected_item() self.notify_drum_pad_selection() def _create_slot(self, index, item, nesting_level): items = self._item_provider.items[self.item_offset:] num_slots = min(self._num_visible_items, len(items)) slot = None if index == 0 and self.can_scroll_left(): slot = IconItemSlot(icon=u'page_left.svg') slot.is_scrolling_indicator = True elif index == num_slots - 1 and self.can_scroll_right(): slot = IconItemSlot(icon=u'page_right.svg') slot.is_scrolling_indicator = True else: slot = ItemSlot(item=item, nesting_level=nesting_level) slot.is_scrolling_indicator = False return slot @listenable_property def moving(self): return self.move_device.is_enabled() @property def device_selection_update_allowed(self): return not self._should_select_drum_pad() def _color_for_button(self, button_index, is_selected): item = self.items[button_index] device_or_pad = item.item is_active = liveobj_valid(device_or_pad) and is_active_element( device_or_pad) chain = find_chain_or_track(device_or_pad) if not is_active: return u'DefaultButton.Off' elif is_selected: return u'ItemNavigation.ItemSelected' elif liveobj_valid(chain): return IndexedColor.from_live_index(chain.color_index, DISPLAY_BUTTON_SHADE_LEVEL) else: return u'ItemNavigation.ItemNotSelected' def _begin_move_device(self, device): if not self.move_device.is_enabled( ) and device.type != Live.Device.DeviceType.instrument: self.move_device.set_device(device) self.move_device.set_enabled(True) self._scroll_overlay.set_enabled(False) self.notify_moving() def _end_move_device(self): if self.move_device and self.move_device.is_enabled(): self.move_device.set_device(None) self.move_device.set_enabled(False) self._scroll_overlay.set_enabled(True) self.notify_moving() def request_drum_pad_selection(self): self._current_track().drum_pad_selected = True def unfold_current_drum_pad(self): self._current_track().drum_pad_selected = False self._current_drum_pad( ).canonical_parent.view.is_showing_chain_devices = True def sync_selection_to_selected_device(self): self._update_item_provider( self.song.view.selected_track.view.selected_device) @property def is_drum_pad_selected(self): return is_drum_pad(self._flattened_chain.selected_item) @property def is_drum_pad_unfolded(self): selection = self._flattened_chain.selected_item assert is_drum_pad(selection) return drum_rack_for_pad(selection).view.is_showing_chain_devices def _current_track(self): return self._track_decorator.decorate( self.song.view.selected_track, additional_properties={u'drum_pad_selected': False}) def _should_select_drum_pad(self): return self._current_track().drum_pad_selected def _current_drum_pad(self): return find_drum_pad(self.items) def _update_selected_track(self): self._selected_track = self.song.view.selected_track selected_track = self._current_track() self.reset_offset() self._flattened_chain.set_device_parent(selected_track) self._device_selection_in_track_changed.subject = selected_track.view self._modes.selected_mode = u'default' self._end_move_device() self._restore_selection(selected_track) def _restore_selection(self, selected_track): to_select = None if self._should_select_drum_pad(): to_select = self._current_drum_pad() if to_select == None: to_select = selected_track.view.selected_device self._select_item(to_select) def back_to_top(self): pass @property def selected_object(self): selected_item = self.item_provider.selected_item return getattr(selected_item, u'proxied_object', selected_item) @dispatch(Live.DrumPad.DrumPad) def _do_select_item(self, pad): self._current_track().drum_pad_selected = True device = self._first_device_on_pad(pad) self._appoint_device(device) def _first_device_on_pad(self, drum_pad): chain = drum_rack_for_pad(drum_pad).view.selected_chain if chain and chain.devices: return first(chain.devices) def _appoint_device(self, device): if self._device_component.device_changed(device): self._device_component.set_device(device) @dispatch(object) def _do_select_item(self, device): self._current_track().drum_pad_selected = False appointed_device = device_to_appoint(device) self._appoint_device(appointed_device) self.song.view.select_device(device, False) self.song.appointed_device = appointed_device @dispatch(Live.DrumPad.DrumPad) def _on_reselecting_object(self, drum_pad): rack = drum_rack_for_pad(drum_pad) self._toggle(rack) if rack.view.is_showing_chain_devices: first_device = self._first_device_on_pad(drum_pad) if first_device: self._select_item(first_device) self.notify_drum_pad_selection() @dispatch(object) def _on_reselecting_object(self, device): if liveobj_valid(device) and device.can_have_chains: if not device.can_have_drum_pads: self._toggle(device) else: self.bank_selection.set_device(device) self._modes.selected_mode = u'bank_selection' @dispatch(Live.DrumPad.DrumPad) def _on_pressed_delayed(self, _): pass @dispatch(object) def _on_pressed_delayed(self, device): self._show_chains(device) self._begin_move_device(device) @dispatch(Live.DrumPad.DrumPad) def _delete_item(self, pad): pass @dispatch(object) def _delete_item(self, device): delete_device(device) def _show_chains(self, device): if device.can_have_chains: self.chain_selection.set_parent(device) self._modes.selected_mode = u'chain_selection' @listens(u'back') def __on_bank_selection_closed(self): self._modes.selected_mode = u'default' def _update_device(self): if not self._should_select_drum_pad( ) and not self._is_drum_rack_selected(): self._modes.selected_mode = u'default' self._update_item_provider(self._device_component.device()) def _is_drum_rack_selected(self): selected_item = self._flattened_chain.selected_item instrument = self._find_top_level_instrument() return liveobj_valid(selected_item) and isinstance( selected_item, Live.RackDevice.RackDevice ) and selected_item.can_have_drum_pads and not liveobj_changed( selected_item, instrument) def _find_top_level_instrument(self): return find_if( lambda device: device.type == Live.Device.DeviceType.instrument, self._current_track().devices) @listens(u'selected_device') def _device_selection_in_track_changed(self): new_selection = self.song.view.selected_track.view.selected_device if self._can_update_device_selection(new_selection): self._modes.selected_mode = u'default' self._update_item_provider(new_selection) def _toggle(self, item): view = item.view if view.is_collapsed: view.is_collapsed = False view.is_showing_chain_devices = True else: view.is_showing_chain_devices = not view.is_showing_chain_devices def _can_update_device_selection(self, new_selection): can_update = liveobj_valid(new_selection) drum_pad_selected_or_requested = self.is_drum_pad_selected or self._should_select_drum_pad( ) if can_update and drum_pad_selected_or_requested: if is_empty_rack(new_selection): can_update = False if can_update and self.is_drum_pad_selected: can_update = not is_first_device_on_pad( new_selection, self._flattened_chain.selected_item) elif not can_update and not drum_pad_selected_or_requested: can_update = True return can_update def _update_item_provider(self, selection): self._flattened_chain.selected_item = selection if not is_drum_pad(selection): self._current_track().drum_pad_selected = False self.notify_drum_pad_selection()
class OhmModes(LividControlSurface): _sysex_id = 2 _alt_sysex_id = 7 _model_name = 'Ohm' _version_check = 'b996' _host_name = 'Ohm' def __init__(self, c_instance): super(OhmModes, self).__init__(c_instance) self._skin = Skin(OhmColors) with self.component_guard(): self._define_sysex() self._setup_controls() self._setup_background() self._setup_m4l_interface() self._setup_translations() self._setup_session_control() self._setup_mixer_control() self._setup_device_control() self._setup_transport_control() self._setup_drumgroup() self._setup_keygroup() self._setup_bassgroup() self._setup_mod() self._setup_modswitcher() self._setup_modes() self._on_device_changed.subject = self._device_provider def _define_sysex(self): #self._send_midi(tuple(switchxfader)) self._reverse_crossfader = SendLividSysexMode(self._livid_settings, call = 'reverse crossfader', message = [1]) def update_display(self): super(OhmModes, self).update_display() #self.strobe() def _initialize_hardware(self): super(OhmModes, self)._initialize_hardware() #self._reverse_crossfader.enter_mode() def _initialize_script(self): super(OhmModes, self)._initialize_script() self._main_modes.selected_mode = 'Mix' self._session.update() self._mixer.update() def _setup_controls(self): is_momentary = True optimized = True resource = PrioritizedResource self._fader = [MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = OHM_FADERS[index], name = 'Fader_' + str(index), num = index, script = self, optimized_send_midi = optimized, resource_type = resource) for index in range(8)] self._button = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = OHM_BUTTONS[index], name = 'Button_' + str(index), script = self, skin = self._skin, optimized_send_midi = optimized, resource_type = resource) for index in range(8)] self._dial = [MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = OHM_DIALS[index], name = 'Encoder_' + str(index), num = index, script = self, optimized_send_midi = optimized, resource_type = resource) for index in range(16)] self._menu = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = OHM_MENU[index], name = 'Menu_' + str(index), script = self, skin = self._skin, optimized_send_midi = optimized, resource_type = resource) for index in range(6)] self._crossfader = MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = CROSSFADER, name = 'Crossfader', script = self, optimized_send_midi = optimized, resource_type = resource) self._livid = MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = LIVID, name = 'Livid_Button', skin = self._skin, script = self, optimized_send_midi = optimized, resource_type = resource) self._shift_l = MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = SHIFT_L, name = 'Page_Button_Left', script = self, skin = self._skin, optimized_send_midi = optimized, resource_type = resource) self._shift_r = MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = SHIFT_R, name = 'Page_Button_Right', script = self, skin = self._skin, optimized_send_midi = optimized, resource_type = resource) self._grid = [[MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = column * 8 + row, name = 'Grid_' + str(column + (row*8)), script = self, skin = self._skin, optimized_send_midi = optimized, resource_type = resource) for column in range(8)] for row in range(8)] self._matrix = ButtonMatrixElement(name = 'Matrix', rows = [[self._grid[row][column] for column in range(8)] for row in range(8)]) self._dial_matrix = ButtonMatrixElement(name = 'DialMatrix', rows = [self._dial[index*4:(index*4)+4] for index in range(4)]) self._menu_matrix = ButtonMatrixElement(name = 'MenuMatrix', rows = [self._menu]) self._fader_matrix = ButtonMatrixElement(name = 'FaderMatrix', rows = [self._fader]) self._button_matrix = ButtonMatrixElement(name = 'ButtonMatrix', rows = [self._button]) self._parameter_controls = ButtonMatrixElement(rows = [self._dial[:4], self._dial[4:8]]) def _setup_background(self): self._background = BackgroundComponent(name = 'Background') self._background.layer = Layer(priority = 3, matrix = self._matrix.submatrix[:,:], livid_button = self._livid, shift_l_button = self._shift_l, shift_r_button = self._shift_r, crossfader = self._crossfader, dial_matrix = self._dial_matrix.submatrix[:,:], menu_matrix = self._menu_matrix.submatrix[:,:], fader_matrix = self._fader_matrix.submatrix[:,:], button_matrix = self._button_matrix.submatrix[:,:]) self._background.set_enabled(False) def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard) self.get_control_names = self._m4l_interface.get_control_names self.get_control = self._m4l_interface.get_control self.grab_control = self._m4l_interface.grab_control self.release_control = self._m4l_interface.release_control def _setup_translations(self): controls = [] for array in self._grid: for button in array: controls.append(button) if FADER_BANKING: controls = controls + self._dial if DIAL_BANKING: controls = controls + self._dial self._translations = TranslationComponent(controls = controls, user_channel_offset = USER_CHANNEL, channel = 8) self._translations.layer = Layer(priority = 5, channel_selector_buttons = self._menu_matrix.submatrix[:,:]) self._translations.set_enabled(False) dj_controls = [self._grid[7][index] for index in range(7)] self._dj_translation = TranslationComponent(controls = dj_controls, channel = 12) def _setup_session_control(self): self._session_ring = SessionRingComponent(num_tracks = 7, num_scenes = 5) self._session_ring.set_enabled(True) self._session_navigation = SessionNavigationComponent(session_ring = self._session_ring) self._session_navigation.scroll_navigation_layer = AddLayerMode(self._session_navigation, Layer(priority = 5, up_button = self._menu[2], down_button = self._menu[5], left_button = self._menu[3], right_button = self._menu[4])) self._session_navigation.page_navigation_layer = AddLayerMode(self._session_navigation, Layer(priority = 5, page_up_button = self._menu[2], page_down_button = self._menu[5], page_left_button = self._menu[3], page_right_button = self._menu[4])) self._session_navigation._vertical_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._vertical_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation.set_enabled(False) self._session = OhmSessionComponent(name = 'Session', session_ring = self._session_ring, auto_name = True) hasattr(self._session, '_enable_skinning') and self._session._enable_skinning() self._session.set_enabled(False) self._session.clip_launch_layer = AddLayerMode(self._session, Layer(priority = 5, clip_launch_buttons = self._matrix.submatrix[:7,:5])) self._session.scene_launch_layer = AddLayerMode(self._session, Layer(priority = 5, scene_launch_buttons = self._matrix.submatrix[7,:5])) self._session_zoom = SessionOverviewComponent(name = 'Session_Overview', session_ring = self._session_ring, enable_skinning = True) self._session_zoom.layer = Layer(priority = 5, button_matrix = self._matrix.submatrix[:7,:5]) self._session_zoom.set_enabled(False) self._session_modes = ModesComponent(name = 'Session_Modes') self._session_modes.add_mode('disabled', [self._session, self._session.clip_launch_layer, self._session.scene_launch_layer, self._session_navigation, self._session_navigation.scroll_navigation_layer]) self._session_modes.add_mode('enabled', [self._session, self._session.scene_launch_layer, self._session_zoom, self._session_navigation, self._session_navigation.page_navigation_layer], behaviour = DefaultedBehaviour()) self._session_modes.layer = Layer(priority = 5, enabled_button = self._grid[7][7]) self._session_modes.selected_mode = 'disabled' self._session_modes.set_enabled(False) def _setup_mixer_control(self): self._mixer = OhmMixerComponent(name = 'Mixer', tracks_provider = self._session_ring, track_assigner = simple_track_assigner, invert_mute_feedback = True, auto_name = True, enable_skinning = True) self._mixer.layer = Layer(priority = 5, volume_controls = self._fader_matrix.submatrix[:7, :], prehear_volume_control = self._dial[15], crossfader_control = self._crossfader) self._mixer.master_strip().layer = Layer(priority = 5, volume_control = self._fader[7], select_button = self._button[7]) self._mixer.mix_layer = AddLayerMode(self._mixer, Layer(priority = 5, mute_buttons = self._matrix.submatrix[:7,5], solo_buttons = self._matrix.submatrix[:7,6], arm_buttons = self._matrix.submatrix[:7,7], send_controls = self._dial_matrix.submatrix[:,:2], pan_controls = self._dial_matrix.submatrix[:7,2:], track_select_buttons = self._button_matrix.submatrix[:7,:],)) self._mixer.dj_layer = AddLayerMode(self._mixer, Layer(priority = 5, mute_buttons = self._matrix.submatrix[:7,5], crossfade_toggles = self._matrix.submatrix[:7,6], end_pan_controls = self._dial_matrix.submatrix[:3,3], eq_gain_controls = self._dial_matrix.submatrix[:,:3], track_select_buttons = self._button_matrix.submatrix[:7,:],)) self._mixer.instrument_layer = AddLayerMode(self._mixer, Layer(priority = 5, instrument_send_controls = self._dial_matrix.submatrix[:,2:], arming_track_select_buttons = self._button_matrix.submatrix[:7,:])) def _setup_device_control(self): self._device = OhmDeviceComponent(script = self, name = 'Device_Component', device_provider = self._device_provider, device_bank_registry = DeviceBankRegistry()) self._device.layer = Layer(priority = 5, parameter_controls = self._parameter_controls ) self._device.set_enabled(False) self._device_navigator = DeviceNavigator(self._device_provider, self._mixer, self, name = 'Device_Navigator', ) self._device_navigator.layer = Layer(priority = 5, prev_button = self._menu[3], next_button = self._menu[4]) self._device_navigator.set_enabled(False) def _setup_transport_control(self): self._transport = OhmTransportComponent() self._transport.name = 'Transport' self._transport.layer = Layer(priority = 5, play_button = self._menu[0], stop_button = self._menu[1]) self._transport.set_enabled(False) def _setup_drumgroup(self): self._drumgroup = MonoDrumGroupComponent(translation_channel = PAGE1_DRUM_CHANNEL, set_pad_translations = self.set_pad_translations) self._drumgroup._on_selected_track_changed.subject = None self._drumgroup.translation_channel = PAGE1_DRUM_CHANNEL self._drumgroup.layer = Layer(priority = 6, matrix = self._matrix.submatrix[:4, :4]) self._drumgroup.set_enabled(False) def _setup_keygroup(self): self._scale_mode = ModesComponent(name = 'ScaleMode') for scale in SCALES: debug('making scale mode:', scale, str(scale)) self._scale_mode.add_mode(str(scale), []) self._scale_mode.layer = Layer(priority = 5, ionian_button = self._grid[7][0], dorian_button = self._grid[7][1], phrygian_button = self._grid[7][2], lydian_button = self._grid[7][3], mixolydian_button = self._grid[7][4], aeolian_button = self._grid[7][5], locrian_button = self._grid[7][6], major_button = self._grid[7][7]) self._scale_mode.selected_mode = 'ionian' self._scale_mode.set_enabled(False) self._on_scale_change.subject = self._scale_mode self._octave_offset_component = ScrollingChannelizedSettingsComponent(name = 'NoteOffset', parent_task_group = self._task_group, value_dict = range(104), default_value_index = 36, default_channel = 0, bank_increment = 12, bank_on_color = 'MonoInstrument.OffsetOnValue', bank_off_color = 'MonoInstrument.OffsetOffValue') self._octave_offset_component.layer = Layer(priority = 5, bank_up_button = self._menu[2], bank_down_button = self._menu[5]) self._on_octave_change.subject = self._octave_offset_component self._keygroup = OhmKeyGroupComponent() self._keygroup._on_selected_track_changed.subject = None self._keygroup.translation_channel = PAGE1_KEYS_CHANNEL self._keygroup.layer = Layer(priority = 6, matrix = self._matrix.submatrix[:, 4:7]) self._keygroup.set_enabled(False) def _setup_bassgroup(self): self._bassgroup = OhmBassGroupComponent() self._bassgroup._on_selected_track_changed.subject = None self._bassgroup.translation_channel = PAGE1_BASS_CHANNEL self._bassgroup.layer = Layer(priority = 6, matrix = self._matrix.submatrix[4:, :4]) self._bassgroup.set_enabled(False) def _setup_mod(self): self.monomodular = get_monomodular(self) self.monomodular.name = 'monomodular_switcher' self.modhandler = OhmModHandler(self) self.modhandler.name = 'ModHandler' self.modhandler.layer = Layer(priority = 5, grid = self._matrix.submatrix[:,:], nav_up_button = self._menu[2], nav_down_button = self._menu[5], nav_left_button = self._menu[3], nav_right_button = self._menu[4], shift_button = self._menu[1], alt_button = self._menu[0], parameter_controls = self._dial_matrix) self.modhandler.legacy_shift_mode = AddLayerMode(self.modhandler, Layer(priority = 6, channel_buttons = self._matrix.submatrix[:, 1], nav_matrix = self._matrix.submatrix[4:8, 2:6])) self.modhandler.shift_mode = AddLayerMode(self.modhandler, Layer(priority = 6, device_selector_matrix = self._matrix.submatrix[:, 0], lock_button = self._livid, key_buttons = self._matrix.submatrix[:, 7])) self.modhandler.set_enabled(False) self.modhandler.set_mod_button(self._livid) def _setup_modswitcher(self): self._modswitcher = ModesComponent(name = 'ModSwitcher') self._modswitcher.add_mode('mod', [self.modhandler, DelayMode(self.modhandler.update, delay = .5)]) self._modswitcher.add_mode('translations', [self._translations]) self._modswitcher.selected_mode = 'translations' self._modswitcher.set_enabled(False) def _setup_modes(self): self._main_modes = ModesComponent(name = 'MainModes') self._main_modes.add_mode('disabled', [self._background]) self._main_modes.add_mode('Mix', [self._session_modes, self._mixer, self._mixer.mix_layer, self._transport]) self._main_modes.add_mode('DJ', [self._session_modes, self._mixer, self._mixer.dj_layer, self._dj_translation, tuple([self._assign_tempo, self._deassign_tempo])], behaviour = DefaultedBehaviour(default_mode = 'Mix')) #tuple([ lambda:self._set_tempo_buttons([self._grid[7][5], self._grid[7][6]]), self._set_tempo_buttons([])])], self._main_modes.add_mode('Instrument', [self._update_keygroup_colors, self._bassgroup, self._keygroup, self._scale_mode, self._octave_offset_component, self._device, self._device_navigator, self._mixer, self._mixer.instrument_layer, self._drumgroup], behaviour = DefaultedBehaviour(default_mode = 'Mix')) self._main_modes.add_mode('Mod', [self._modswitcher, self._device, self._mixer, self._mixer.instrument_layer], behaviour = DefaultedBehaviour(default_mode = 'Mix')) self._main_modes.layer = Layer(priority = 5, Instrument_button = self._shift_l, DJ_button = self._shift_r, Mod_button = self._livid) self._main_modes.selected_mode = 'disabled' self._main_modes.set_enabled(True) def disconnect(self): super(OhmModes, self).disconnect() def strobe(self): if self._backlight_type != 'static': if self._backlight_type is 'pulse': self._backlight = int(math.fabs(self._timer * 16 % 64 - 32) + 32) if self._backlight_type is 'up': self._backlight = int(self._timer * 8 % 64 + 16) if self._backlight_type is 'down': self._backlight = int(math.fabs(int(self._timer * 8 % 64 - 64)) + 16) self._send_midi(tuple([176, 27, int(self._backlight)])) if self._ohm_type != 'static': if self._ohm_type is 'pulse': self._ohm = int(math.fabs(self._timer * 16 % 64 - 32) + 32) if self._ohm_type is 'up': self._ohm = int(self._timer * 8 % 64 + 16) if self._ohm_type is 'down': self._ohm = int(math.fabs(int(self._timer * 8 % 64 - 64)) + 16) self._send_midi(tuple([176, 63, int(self._ohm)])) self._send_midi(tuple([176, 31, int(self._ohm)])) def handle_sysex(self, midi_bytes): debug('sysex: ', str(midi_bytes)) if len(midi_bytes) > 14: if midi_bytes[:6] == tuple([240, 0, 1, 97, 12, 64]): self._register_pad_pressed(midi_bytes[6:14]) elif midi_bytes[:6] == tuple([240, 0, 1, 97, 17, 64]): self._register_pad_pressed(midi_bytes[6:14]) elif midi_bytes[3:11] == tuple([6, 2, 0, 1, 97, 1, 0] + [self._sysex_id]) or midi_bytes[3:11] == tuple([6, 2, 0, 1, 97, 1, 0] + [self._alt_sysex_id]): if not self._connected: #self._connection_routine.kill() self._connected = True self._livid_settings.set_model(midi_bytes[11]) self._initialize_hardware() self.schedule_message(1, self._initialize_script) @listens('device') def _on_device_changed(self): self.schedule_message(1, self._update_modswitcher) #debug('base on_device_changed') self._update_modswitcher() def _on_selected_track_changed(self): super(OhmModes, self)._on_selected_track_changed() if not len(self.song.view.selected_track.devices): self._update_modswitcher() def _update_modswitcher(self): debug('update modswitcher, mod is:', self.modhandler.active_mod()) if self.modhandler.active_mod(): self._modswitcher.selected_mode = 'mod' else: self._modswitcher.selected_mode = 'translations' @listens('selected_mode') def _on_scale_change(self, mode): debug('new scale is:', mode, self._scale_mode.selected_mode) self._keygroup.scale = SCALES.index(self._scale_mode.selected_mode) @listens('value') def _on_octave_change(self, value): self._keygroup.offset = value #stupid hack....4 hours wasted on two buttons is too long, so we're doing this instead def _update_keygroup_colors(self): self._grid[5][7].send_value(2, force = True) self._grid[6][7].send_value(2, force = True) #everything below needs to be consolidated into transport component def _assign_tempo(self): self._grid[5][7].send_value(4, True) self._grid[6][7].send_value(4, True) self._tempo_up_value.subject = self._grid[5][7] self._tempo_down_value.subject = self._grid[6][7] def _deassign_tempo(self): self._tempo_up_value.subject and self._tempo_up_value.subject.turn_off() self._tempo_down_value.subject and self._tempo_down_value.subject.turn_off() self._tempo_up_value.subject = None self._tempo_down_value.subject = None @listens('value') def _tempo_up_value(self, value): if value: self.song.tempo = round(min(self.song.tempo + 1, 999)) @listens('value') def _tempo_down_value(self, value): if value: self.song.tempo = round(max(self.song.tempo - 1, 20))
class KompleteKontrolBase(ControlSurface): mixer_component_class = MixerComponent channel_strip_component_class = ChannelStripComponent is_s_mk2 = False def __init__(self, *a, **k): super(KompleteKontrolBase, self).__init__(*a, **k) with self.component_guard(): self._create_controls() self._create_components() self.__on_main_view_changed.subject = self.application.view self._handshake_response_pending = False self._handshake_task = self._tasks.add(task.run(self._send_handshake)) self._handshake_task.kill() def disconnect(self): self._auto_arm.set_enabled(False) self._send_midi(GOODBYE_MESSAGE) super(KompleteKontrolBase, self).disconnect() def port_settings_changed(self): self.set_components_enabled(False) self._handshake_task.restart() def _send_handshake(self): self._handshake_response_pending = True self._handshake_control.send_value(0, force=True) @listens(u'value') def _on_handshake_response(self, _): self._handshake_task.kill() if self._handshake_response_pending: self._handshake_response_pending = False self.set_components_enabled(True) self.refresh_state() def set_components_enabled(self, enabled): with self.component_guard(): for c in self._components: c.set_enabled(enabled) def _create_controls(self): self._play_button = MultiElement(create_button(16, u'Play_Button'), create_button(17, u'Play_Button_With_Shift')) self._record_button = create_button(18, u'Record_Button') self._count_in_button = create_button(19, u'Count_In_Button') self._stop_button = create_button(20, u'Stop_Button') self._clear_button = create_button(21, u'Clear_Button') self._loop_button = create_button(22, u'Loop_Button') self._metronome_button = create_button(23, u'Metronome_Button') self._tap_tempo_button = create_button(24, u'Tap_Tempo_Button') self._undo_button = create_button(32, u'Undo_Button') self._redo_button = create_button(33, u'Redo_Button') self._quantize_button = create_button(34, u'Quantize_Button') self._automation_button = create_button(35, u'Automation_Button') self._clip_launch_button = create_button(96, u'Clip_Launch_Button') self._track_stop_button = create_button(97, u'Track_Stop_Button') self._jump_encoder = create_encoder(52, u'Jump_Encoder') self._loop_encoder = create_encoder(53, u'Loop_Encoder') self._volume_encoders = ButtonMatrixElement(rows=[[ create_encoder(index + 80, u'Volume_Encoder_{}'.format(index), is_s_mk2=self.is_s_mk2) for index in xrange(NUM_TRACKS) ]], name=u'Volume_Encoders') self._pan_encoders = ButtonMatrixElement(rows=[[ create_encoder(index + 88, u'Pan_Encoder_{}'.format(index), is_s_mk2=self.is_s_mk2) for index in xrange(NUM_TRACKS) ]], name=u'Pan_Encoders') self._track_name_displays = ButtonMatrixElement(rows=[[ create_display_line(sysex.TRACK_NAME_DISPLAY_HEADER, index, u'Track_Name_Display_{}'.format(index), width=33 if self.is_s_mk2 else 11) for index in xrange(NUM_TRACKS) ]], name=u'Track_Name_Displays') self._track_volume_displays = ButtonMatrixElement(rows=[[ create_display_line(sysex.TRACK_VOLUME_DISPLAY_HEADER, index, u'Track_Volume_Display_{}'.format(index), width=12) for index in xrange(NUM_TRACKS) ]], name=u'Track_Volume_Displays') self._track_panning_displays = ButtonMatrixElement(rows=[[ create_display_line(sysex.TRACK_PANNING_DISPLAY_HEADER, index, u'Track_Panning_Display_{}'.format(index), width=12) for index in xrange(NUM_TRACKS) ]], name=u'Track_Panning_Displays') self._track_type_displays = ButtonMatrixElement(rows=[[ create_sysex_element(sysex.TRACK_TYPE_DISPLAY_HEADER, index, u'Track_Type_Display_{}'.format(index)) for index in xrange(NUM_TRACKS) ]], name=u'Track_Type_Displays') self._track_mute_displays = ButtonMatrixElement(rows=[[ create_sysex_element(sysex.TRACK_MUTE_DISPLAY_HEADER, index, u'Track_Mute_Display_{}'.format(index)) for index in xrange(NUM_TRACKS) ]], name=u'Track_Mute_Displays') self._track_solo_displays = ButtonMatrixElement(rows=[[ create_sysex_element(sysex.TRACK_SOLO_DISPLAY_HEADER, index, u'Track_Solo_Display_{}'.format(index)) for index in xrange(NUM_TRACKS) ]], name=u'Track_Solo_Displays') self._track_muted_via_solo_displays = ButtonMatrixElement(rows=[[ create_sysex_element(sysex.TRACK_MUTED_VIA_SOLO_DISPLAY_HEADER, index, u'Track_Muted_via_Solo_Display_{}'.format(index)) for index in xrange(NUM_TRACKS) ]], name=u'Track_Muted_via_Solo_Displays') self._track_selection_displays = ButtonMatrixElement(rows=[[ create_sysex_element(sysex.TRACK_SELECT_DISPLAY_HEADER, index, u'Track_Selection_Display_{}'.format(index)) for index in xrange(NUM_TRACKS) ]], name=u'Track_Selection_Displays') self._focus_follow_control = SysexElement(lambda value: sysex.TRACK_CHANGED_DISPLAY_HEADER + value + (midi.SYSEX_END,), name=u'Focus_Follow_Control') self._handshake_control = create_button(1, u'Handshake_Control') self._handshake_control.reset = nop self._on_handshake_response.subject = self._handshake_control def _create_components(self): self._create_mixer() self._create_transport() self._create_session_recording() self._create_undo_redo() self._create_clip_launch() self._create_clip_launch_background() self._create_detail_clip() self._create_focus_follow() self._create_auto_arm() self._create_view_based_modes() def _create_mixer(self): self._session_ring = SelectionLinkedSessionRingComponent(name=u'Session_Ring', num_tracks=NUM_TRACKS, tracks_to_use=partial(tracks_to_use_from_song, self.song), always_snap_track_offset=True) self._mixer = self.mixer_component_class(name=u'Mixer', tracks_provider=self._session_ring, track_assigner=SimpleTrackAssigner(), channel_strip_component_type=self.channel_strip_component_class, is_enabled=False, layer=self._create_mixer_component_layer()) def _create_mixer_component_layer(self): return Layer(volume_controls=self._volume_encoders, pan_controls=self._pan_encoders, track_name_displays=self._track_name_displays, track_volume_displays=self._track_volume_displays, track_panning_displays=self._track_panning_displays, track_type_displays=self._track_type_displays, track_selection_displays=self._track_selection_displays, track_mute_displays=self._track_mute_displays, track_solo_displays=self._track_solo_displays, track_muted_via_solo_displays=self._track_muted_via_solo_displays) def _create_transport(self): self._transport = TransportComponent(name=u'Transport', is_enabled=False, layer=Layer(play_button=self._play_button, stop_button=self._stop_button, loop_button=self._loop_button, metronome_button=self._metronome_button, tap_tempo_button=self._tap_tempo_button, jump_encoder=self._jump_encoder, loop_start_encoder=self._loop_encoder)) def _create_session_recording(self): self._session_recording = SessionRecordingComponent(name=u'Session_Recording', is_enabled=False, layer=Layer(automation_button=self._automation_button)) def _create_undo_redo(self): self._undo_redo = UndoRedoComponent(name=u'Undo_Redo', is_enabled=False, layer=Layer(undo_button=self._undo_button, redo_button=self._redo_button)) def _create_clip_launch(self): self._clip_launch = ClipLaunchComponent(name=u'Clip_Launch', is_enabled=False, layer=Layer(clip_launch_button=self._clip_launch_button, track_stop_button=self._track_stop_button)) def _create_clip_launch_background(self): self._clip_launch_background = BackgroundComponent(name=u'Background', is_enabled=False, add_nop_listeners=True, layer=Layer(clip_launch_button=self._clip_launch_button, track_stop_button=self._track_stop_button, priority=-1)) def _create_detail_clip(self): self._detail_clip = DetailClipComponent(name=u'Detail_Clip', is_enabled=False, layer=Layer(quantize_notes_button=self._quantize_button, delete_notes_button=self._clear_button)) def _create_focus_follow(self): self._focus_follow = FocusFollowComponent(name=u'Focus_Follow', is_enabled=False, layer=Layer(focus_follow_control=self._focus_follow_control)) def _create_auto_arm(self): self._auto_arm = AutoArmComponent(name=u'Auto_Arm', is_enabled=False) def _create_view_based_modes(self): self._view_based_modes = ModesComponent(is_enabled=False) self._view_based_modes.add_mode(u'session', (EnablingMode(self._clip_launch), AddLayerMode(self._transport, Layer(session_record_button=self._record_button, record_button=self._count_in_button)))) self._view_based_modes.add_mode(u'arrange', AddLayerMode(self._transport, Layer(record_button=self._record_button, session_record_button=self._count_in_button))) self.__on_main_view_changed() @listens(u'is_view_visible', u'Session') def __on_main_view_changed(self): if self.application.view.is_view_visible(u'Session'): self._view_based_modes.selected_mode = u'session' else: self._view_based_modes.selected_mode = u'arrange'
class Launchpad(ControlSurface): u""" Script for Novation's Launchpad Controller """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) is_momentary = True self._suppress_send_midi = False with self.component_guard(): self._skin = make_default_skin() #with inject(skin=const(self._skin)).everywhere(): # self._midimap = MidiMap() self._suggested_input_port = u'Launchpad' self._suggested_output_port = u'Launchpad' self._control_is_with_automap = False self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = u'User_Byte_Button' self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self._wrote_user_byte = False self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143 self._matrix = ButtonMatrixElement() self._matrix.name = u'Button_Matrix' #with inject(skin=const(self._skin)).everywhere(): for row in range(8): button_row = [] for column in range(8): button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, row * 16 + column, skin = self._skin) button.name = str(column) + u'_Clip_' + str(row) + u'_Button' button_row.append(button) self._matrix.add_row(tuple(button_row)) self._top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, skin = self._skin) for index in range(8) ] self._side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index], skin = self._skin) for index in range(8) ] self._top_matrix = ButtonMatrixElement(name = u'Top_Button_Matrix', rows = [self._top_buttons]) self._side_matrix = ButtonMatrixElement(name = u'Side_Button_Matrix', rows = [self._side_buttons]) self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False) self._config_button.add_value_listener(self._config_value) self._top_buttons[0].name = u'Bank_Select_Up_Button' self._top_buttons[1].name = u'Bank_Select_Down_Button' self._top_buttons[2].name = u'Bank_Select_Left_Button' self._top_buttons[3].name = u'Bank_Select_Right_Button' self._top_buttons[4].name = u'Session_Button' self._top_buttons[5].name = u'User1_Button' self._top_buttons[6].name = u'User2_Button' self._top_buttons[7].name = u'Mixer_Button' self._side_buttons[0].name = u'Vol_Button' self._side_buttons[1].name = u'Pan_Button' self._side_buttons[2].name = u'SndA_Button' self._side_buttons[3].name = u'SndB_Button' self._side_buttons[4].name = u'Stop_Button' self._side_buttons[5].name = u'Trk_On_Button' self._side_buttons[6].name = u'Solo_Button' self._side_buttons[7].name = u'Arm_Button' self._create_background() self._create_translations() self._create_session() self._create_mixer() self._create_modes() def _create_background(self): self._background = BackgroundComponent(name = 'Background') self._background.layer = Layer(priority = 5, matrix = self._matrix, side_buttons = self._side_matrix, top_buttons = self._top_matrix) self._background.set_enabled(True) def _create_translations(self): self._translations1 = TranslationComponent(name = 'User1Translation', translated_channel=2, should_enable=True, should_reset=True, is_enabled=False, layer=Layer(matrix = self._matrix, top_buttons = self._top_matrix.submatrix[:4,1], side_buttons = self._side_matrix)) self._translations2 = TranslationComponent(name = 'User2Translation', translated_channel=3, should_enable=True, should_reset=True, is_enabled=False, layer=Layer(matrix = self._matrix, top_buttons = self._top_matrix.submatrix[:4,1], side_buttons = self._side_matrix)) def _create_session(self): self._session_ring = SessionRingComponent(8, 8, name = u'Session_Ring') self._session = SpecialSessionComponent(session_ring = self._session_ring, name = u'Session', is_enabled = False, auto_name = True) self._session_navigation = SessionNavigationComponent(session_ring = self._session_ring, name = u'SessionNavigation', is_enabled = False) self._session_navigation._vertical_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_banking.scroll_up_button.disabled_color = 'Session.NavigationButtonOff' self._session_navigation._vertical_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_banking.scroll_down_button.disabled_color = 'Session.NavigationButtonOff' self._session_navigation._horizontal_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_up_button.disabled_color = 'Session.NavigationButtonOff' self._session_navigation._horizontal_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_down_button.disabled_color = 'Session.NavigationButtonOff' self._session_navigation._vertical_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._vertical_paginator.scroll_up_button.disabled_color = 'Session.PageNavigationButtonOff' self._session_navigation._vertical_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._vertical_paginator.scroll_down_button.disabled_color = 'Session.PageNavigationButtonOff' self._session_navigation._horizontal_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_up_button.disabled_color = 'Session.PageNavigationButtonOff' self._session_navigation._horizontal_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_down_button.disabled_color = 'Session.PageNavigationButtonOff' self._zooming = SessionOverviewComponent(session_ring = self._session_ring, enable_skinning = True, name = u'Session_Zooming', is_enabled = False) self._zooming.layer = Layer(button_matrix = self._matrix) self._session_navigation.nav_layer = AddLayerMode(self._session_navigation, Layer(up_button = self._top_buttons[0], down_button = self._top_buttons[1], left_button = self._top_buttons[2], right_button = self._top_buttons[3])) self._session_navigation.page_layer = AddLayerMode(self._session_navigation, Layer(page_up_button = self._top_buttons[0], page_down_button = self._top_buttons[1], page_left_button = self._top_buttons[2], page_right_button = self._top_buttons[3])) self._session.cliplaunch_layer = AddLayerMode(self._session, Layer(priority = 1, clip_launch_buttons = self._matrix, scene_launch_buttons = self._side_matrix)) self._session.clipstop_layer = AddLayerMode(self._session, Layer(priority = 1, stop_all_clips_button = self._side_buttons[4], stop_track_clip_buttons = self._matrix.submatrix[:, 4:5])) def _create_mixer(self): self._mixer = SpecialMixerComponent(tracks_provider = self._session_ring, auto_name=True, is_enabled=True, invert_mute_feedback=True) self._mixer.name = u'Mixer' self._mixer.master_strip().name = u'Master_Channel_strip' self._mixer.selected_strip().name = u'Selected_Channel_strip' self._sliders = [] self._slider_volume_modes = [] self._slider_pan_modes = [] self._slider_single_modes = [] for column in range(8): self._mixer.channel_strip(column).name = u'Channel_Strip_' + str(column) self._sliders.append(PreciseButtonSliderElement(buttons = tuple([ self._matrix._orig_buttons[7-row][column]for row in range(8) ]))) self._sliders[-1].name = u'Button_Slider_' + str(column) self._slider_matrix = ButtonMatrixElement(name = u'SliderMatrix', rows = [self._sliders]) self._mixer.overview_layer = AddLayerMode(self._mixer, Layer(priority = 1, default_volume_buttons = self._matrix.submatrix[:, :1], default_panning_buttons = self._matrix.submatrix[:, 1:2], default_send1_buttons = self._matrix.submatrix[:, 2:3], default_send2_buttons = self._matrix.submatrix[:, 3:4], mute_buttons = self._matrix.submatrix[:, 5:6], solo_buttons = self._matrix.submatrix[:, 6:7], arm_buttons = self._matrix.submatrix[:, 7:8], unarm_all_button = self._side_buttons[7], unsolo_all_button = self._side_buttons[6], unmute_all_button = self._side_buttons[5])) self._mixer.volume_layer = AddLayerMode(self._mixer, Layer(priority = 1, volume_controls = self._slider_matrix)) self._mixer.pan_layer = AddLayerMode(self._mixer, Layer(priority = 1, pan_controls = self._slider_matrix)) self._mixer.send1_layer = AddLayerMode(self._mixer, Layer(priority = 1, send_controls = self._slider_matrix)) self._mixer.send2_layer = AddLayerMode(self._mixer, Layer(priority = 1, send_controls = self._slider_matrix)) def _create_modes(self): self._session_modes = ModesComponent(name = u'SessionModes') self._session_modes.add_mode(u'Session', [self._session, self._session.cliplaunch_layer, self._session_navigation, self._session_navigation.nav_layer], cycle_mode_button_color = u'MainModes.SelectedOn') self._session_modes.add_mode(u'Zoom', [self._zooming, self._session_navigation, self._session_navigation.page_layer], cycle_mode_button_color = u'MainModes.SelectedPressed') self._session_modes.selected_mode = u'Session' self._session_modes.layer = Layer(priority = 1, cycle_mode_button = self._top_buttons[4]) self._session_modes.set_enabled(False) self._mixer_modes = ModesComponent(name = u'MixerModes') self._mixer_modes.add_mode(u'Overview', [self._session_navigation, self._session_navigation.nav_layer, self._session, self._session.clipstop_layer, self._mixer, self._mixer.overview_layer]) self._mixer_modes.add_mode(u'TrackVolume', [self._session_navigation, self._session_navigation.nav_layer, self._mixer, self._mixer.volume_layer, tuple([self.set_slider_volume_mode, self.set_slider_single_mode])]) self._mixer_modes.add_mode(u'TrackPan', [self._session_navigation, self._session_navigation.nav_layer, self._mixer, self._mixer.pan_layer, tuple([self.set_slider_pan_mode, self.set_slider_single_mode])]) self._mixer_modes.add_mode(u'TrackSend1', [self._session_navigation, self._session_navigation.nav_layer, self._mixer, self._mixer.send1_layer, SetAttributeMode(obj=self._mixer, attribute=u'send_index', value=0), tuple([self.set_slider_send_mode, self.set_slider_single_mode])]) self._mixer_modes.add_mode(u'TrackSend2', [self._session_navigation, self._session_navigation.nav_layer, self._mixer, self._mixer.send2_layer, SetAttributeMode(obj=self._mixer, attribute=u'send_index', value=1), tuple([self.set_slider_send_mode, self.set_slider_single_mode])]) for mode in self._mixer_modes._mode_list: if mode == 'Overview': self._mixer_modes.get_mode_button(mode).mode_selected_color = u'MainModes.SelectedOn' self._mixer_modes.get_mode_button(mode).mode_unselected_color = u'MainModes.SelectedOn' else: self._mixer_modes.get_mode_button(mode).mode_selected_color = u'SubModes.SelectedOn' self._mixer_modes.get_mode_button(mode).mode_unselected_color = u'SubModes.SelectedOff' self._mixer_modes.selected_mode = 'Overview' self._mixer_modes.layer = Layer(priority = 1, Overview_button = self._top_buttons[7], TrackVolume_button = self._side_buttons[0], TrackPan_button = self._side_buttons[1], TrackSend1_button = self._side_buttons[2], TrackSend2_button = self._side_buttons[3]) self._mixer_modes.set_enabled(False) self._selector = ModesComponent(name = u'Selector') self._selector.add_mode(u'disabled', [self._background]) self._selector.add_mode(u'Session', [self._session_modes]) self._selector.add_mode(u'User1', [self._translations1]) self._selector.add_mode(u'User2', [self._translations2]) self._selector.add_mode(u'Mixer', [tuple([self.enable_sliders, self.disable_sliders]), self._mixer_modes]) for mode in self._selector._mode_list: self._selector.get_mode_button(mode).mode_selected_color = u'MainModes.SelectedOn' self._selector.get_mode_button(mode).mode_unselected_color = u'MainModes.SelectedOff' self._selector.layer = Layer(priority = 1, Session_button = self._top_buttons[4], User1_button = self._top_buttons[5], User2_button = self._top_buttons[6], Mixer_button = self._top_buttons[7]) self._selector.set_enabled(True) self._selector.selected_mode = u'disabled' def enable_sliders(self): for slider in self._sliders: slider._disabled = False def disable_sliders(self): for slider in self._sliders: slider._disabled = True def set_slider_single_mode(self): for slider in self._sliders: slider.set_mode(0) def set_slider_volume_mode(self): for slider in self._sliders: slider.set_mode(1) def set_slider_pan_mode(self): for slider in self._sliders: slider.set_mode(2) def set_slider_send_mode(self): for slider in self._sliders: slider.set_mode(1) def disconnect(self): self._suppress_send_midi = True for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.remove_value_listener(self._button_value) self._selector = None self._user_byte_write_button.remove_value_listener(self._user_byte_value) self._config_button.remove_value_listener(self._config_value) super(Launchpad, self).disconnect() self._suppress_send_midi = False self._config_button.send_value(32) self._config_button.send_value(0) self._config_button = None self._user_byte_write_button.send_value(0) self._user_byte_write_button = None def refresh_state(self): super(Launchpad, self).refresh_state() self.schedule_message(5, self._update_hardware) def process_midi_bytes(self, midi_bytes, midi_processor): #def handle_sysex(self, midi_bytes): if len(midi_bytes) == 8: if midi_bytes[1:5] == (0, 32, 41, 6): response = long(midi_bytes[5]) response += long(midi_bytes[6]) << 8 if response == Live.Application.encrypt_challenge2(self._challenge): self._on_handshake_successful() else: super(Launchpad, self).process_midi_bytes(midi_bytes, midi_processor) def _on_handshake_successful(self): debug('Launchpad._on_handshake_successful') self._suppress_send_midi = False self.set_enabled(True) self._selector.selected_mode = 'Session' self._selector.set_enabled(True) debug(self._selector.selected_mode) """ def build_midi_map(self, midi_map_handle): ControlSurface.build_midi_map(self, midi_map_handle) #if self._selector.mode_index == 1: # new_channel = self._selector.channel_for_current_mode() # for note in DRUM_NOTES: # self._translate_message(MIDI_NOTE_TYPE, note, 0, note, new_channel) """ """ def _send_midi(self, midi_bytes, optimized = None): sent_successfully = False if not self._suppress_send_midi: sent_successfully = ControlSurface._send_midi(self, midi_bytes, optimized=optimized) return sent_successfully """ def _update_hardware(self): self._suppress_send_midi = False self._wrote_user_byte = True self._user_byte_write_button.send_value(1) self._suppress_send_midi = True self.set_enabled(False) self._suppress_send_midi = False self._send_challenge() def _send_challenge(self): for index in range(4): challenge_byte = self._challenge >> 8 * index & 127 self._send_midi((176, 17 + index, challenge_byte)) def _user_byte_value(self, value): if not value in range(128): raise AssertionError enabled = self._wrote_user_byte or value == 1 self._control_is_with_automap = not enabled self._suppress_send_midi = self._control_is_with_automap if not self._control_is_with_automap: for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.set_force_next_value() #self._selector.set_mode(0) self._selector.selected_mode = u'Session' self.set_enabled(enabled) self._suppress_send_midi = False else: self._wrote_user_byte = False def _button_value(self, value): debug('_button_value', value, self._selector.selected_mode, self._selector.is_enabled()) #self._top_buttons[0].send_value(127) #assert value in range(128) def _config_value(self, value): assert value in range(128) """
class MonoBlocks(ControlSurface): _rgb = 0 _color_type = 'Push' _timer = 0 _touched = 0 flash_status = False _model_name = 'MonoBlocks' _host_name = 'MonoBlocks' _version_check = 'b996' monomodular = None device_provider_class = ModDeviceProvider def __init__(self, *a, **k): super(MonoBlocks, self).__init__(*a, **k) self.log_message = logger.info self._skin = Skin(MonoBlocksColors) with self.component_guard(): self._setup_monobridge() self._setup_controls() #self._setup_device() self._setup_mod() #self._setup_modes() self._setup_modswitcher() self._on_device_changed.subject = self._device_provider self.schedule_message(1, self._open_log) def _open_log(self): #self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._model_name) + " " + str(self._version_check) + " log opened =>>>>>>>>>>>>>>>>>>>") self.show_message(str(self._model_name) + ' Control Surface Loaded') def _close_log(self): #self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._model_name) + " " + str(self._version_check) + " log closed =>>>>>>>>>>>>>>>>>>>") pass def _setup_controls(self): is_momentary = True optimized = True resource = PrioritizedResource #self._pads_raw = [ ButtonElement(True, MIDI_NOTE_TYPE, 0, identifier, name=u'Pad_{}'.format(identifier), skin=skin) for identifier in xrange(100) ] self._pad = [ MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=BLOCKS_PADS[index], name='Pad_' + str(index), script=self, monobridge=self._monobridge, skin=self._skin, color_map=COLOR_MAP, optimized_send_midi=optimized, resource_type=resource) for index in range(64) ] for button in self._pad: button.set_color_map(tuple(range(128))) self._matrix = ButtonMatrixElement( name='Matrix', rows=[ self._pad[(index * 8):(index * 8) + 8] for index in range(8) ]) #def _setup_device(self): # self._device_selection_follows_track_selection = True # self._device = DeviceComponent(name = 'Device_Component', device_bank_registry = DeviceBankRegistry(), device_provider = self._device_provider) # self._device.set_enabled(True) def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_mod(self): def get_monomodular(host): if isinstance(__builtins__, dict): if not 'monomodular' in list( __builtins__.keys()) or not isinstance( __builtins__['monomodular'], ModRouter): __builtins__['monomodular'] = ModRouter( song=self.song, register_component=self._register_component) else: if not hasattr(__builtins__, 'monomodular') or not isinstance( __builtins__['monomodular'], ModRouter): setattr( __builtins__, 'monomodular', ModRouter(song=self.song, register_component=self._register_component)) monomodular = __builtins__['monomodular'] if not monomodular.has_host(): monomodular.set_host(host) return monomodular self.monomodular = get_monomodular(self) self.monomodular.name = 'monomodular_switcher' with inject(register_component=const(self._register_component), song=const(self.song)).everywhere(): self.modhandler = MonoBlocksModHandler( self ) ## song = self.song, register_component = self._register_component) self.modhandler.name = 'ModHandler' self.modhandler.layer = Layer(priority=6, grid=self._matrix) self.modhandler.alt_shift_layer = AddLayerMode(self.modhandler, Layer()) # Shift_button = self.elements.shift_button, # Alt_button = self.elements.select_button)) self.modhandler.legacy_shift_layer = AddLayerMode( self.modhandler, Layer( priority=7, device_selector_matrix=self._matrix.submatrix[:, :1], channel_buttons=self._matrix.submatrix[:, 1:2], nav_matrix=self._matrix.submatrix[4:8, 2:6], )) self.modhandler.shift_layer = AddLayerMode( self.modhandler, Layer( priority=7, device_selector_matrix=self._matrix.submatrix[:, :1], )) #lock_button = self.elements.master_select_button, #)) self.modhandler.alt_layer = AddLayerMode(self.modhandler, Layer(priority=7, )) #key_buttons = self.elements.select_buttons)) #key_buttons = self.elements.track_state_buttons)) self._modHandle = ModControl(modscript=self, monomodular=self.monomodular, name='ModHandle') self._device_provider.restart_mod() def _setup_modswitcher(self): self._modswitcher = ModesComponent(name='ModSwitcher') self._modswitcher.add_mode('mod', [self.modhandler]) self._modswitcher.selected_mode = 'mod' self._modswitcher.set_enabled(True) def flash(self): if (self.flash_status > 0): for control in self.controls: if isinstance(control, MonoButtonElement): control.flash(self._timer) def update_display(self): super(ControlSurface, self).update_display() self._timer = (self._timer + 1) % 256 self.flash() 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) @listens('device') def _on_device_changed(self): #self.schedule_message(1, self._update_modswitcher) debug('base on_device_changed') #self._update_modswitcher() def _on_selected_track_changed(self): super(MonoBlocks, self)._on_selected_track_changed() if not len(self.song.view.selected_track.devices): self._update_modswitcher() #self.schedule_message(1, self._update_modswitcher) def disconnect(self): super(MonoBlocks, self).disconnect() self._close_log() def restart_monomodular(self): #self.log_message('restart monomodular') self.modhandler.disconnect() with self.component_guard(): self._setup_mod() def process_midi_bytes(self, midi_bytes, midi_processor): """ Finds the right recipient for the MIDI message and translates it into the expected format. The result is forwarded to the midi_processor. """ if midi.is_sysex(midi_bytes): result = self.get_registry_entry_for_sysex_midi_message(midi_bytes) if result is not None: identifier, recipient = result midi_processor(recipient, midi_bytes[len(identifier):-1]) #elif self.received_midi_listener_count() == 0: # logger.warning(u'Got unknown sysex message: ' + midi.pretty_print_bytes(midi_bytes)) else: recipient = self.get_recipient_for_nonsysex_midi_message( midi_bytes) if recipient is not None: midi_processor(recipient, midi.extract_value(midi_bytes))
class Cntrlr(LividControlSurface): __module__ = __name__ __doc__ = " Monomodular controller script for Livid CNTRLR " _sysex_id = 8 _model_name = 'Cntrlr' _host_name = 'Cntrlr' monomodular = None device_provider_class = ModDeviceProvider def __init__(self, *a, **k): super(Cntrlr, self).__init__(*a, **k) self._skin = Skin(CntrlrColors) self._device_selection_follows_track_selection = FOLLOW with self.component_guard(): self._setup_controls() self._define_sysex() self._setup_background() #self._setup_autoarm() self._setup_viewcontrol() self._setup_session_control() self._setup_mixer_control() self._setup_transport_control() #self._setup_device_control() #self._setup_device_selector() #self._setup_session_recording_component() #self._setup_modes() self._setup_m4l_interface() def _initialize_script(self): super(Cntrlr, self)._initialize_script() self._connected = True #self._main_modes.selected_mode = 'MixMode' self._session_ring._update_highlight() self._session_ring.track_offset = 0 if liveobj_valid(self.song.visible_tracks[0]): self.song.view.selected_track = self.song.visible_tracks[0] def _setup_controls(self): is_momentary = True optimized = True resource = PrioritizedResource self._fader = [MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = CNTRLR_FADERS[index], name = 'Fader_' + str(index), num = index, script = self, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(8)] self._dial_left = [MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = CNTRLR_KNOBS_LEFT[index], name = 'Dial_Left_' + str(index), num = CNTRLR_KNOBS_LEFT[index], script = self, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(12)] self._dial_right = [MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = CNTRLR_KNOBS_RIGHT[index], name = 'Dial_Right_' + str(index), num = CNTRLR_KNOBS_RIGHT[index], script = self, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(12)] self._encoder = [CodecEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = CNTRLR_DIALS[index], name = 'Encoder_' + str(index), num = CNTRLR_DIALS[index], script = self, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(12)] self._encoder_button = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = CNTRLR_DIAL_BUTTONS[index], name = 'Encoder_Button_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(12)] self._grid = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = CNTRLR_GRID[index], name = 'Grid_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(16)] self._button = [MonoButtonElement(is_momentary = is_momentary,msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = CNTRLR_BUTTONS[index], name = 'Button_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) 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 _setup_background(self): self._background = BackgroundComponent(name = 'Background') self._background.layer = Layer(priority = 3, matrix = self._matrix.submatrix[:,:], faders = self._fader_matrix.submatrix[:,:], left_knobs = self._knob_left_matrix.submatrix[:,:], right_knobs = self._knob_right_matrix.submatrix[:,:], dials = self._dial_matrix, dial_buttons = self._dial_button_matrix.submatrix[:,:], keys = self._key_matrix.submatrix[:,:]) self._background.set_enabled(True) def _define_sysex(self): #self.encoder_navigation_on = SendLividSysexMode(livid_settings = self._livid_settings, call = 'set_encoder_encosion_mode', message = [13, 0, 0, 0]) pass def _setup_transport_control(self): self._transport = CntrlrTransportComponent(name = 'Transport') self._transport._play_toggle.view_transform = lambda value: 'Transport.PlayOn' if value else 'Transport.PlayOff' self._transport._record_toggle.view_transform = lambda value: 'Transport.RecordOn' if value else 'Transport.RecordOff' self._transport._nudge_up_toggle.view_transform = lambda value: 'Transport.NudgeOn' if value else 'Transport.NudgeOff' self._transport._nudge_down_toggle.view_transform = lambda value: 'Transport.NudgeOn' if value else 'Transport.NudgeOff' self._transport._loop_toggle.view_transform = lambda value: 'Transport.LoopOn' if value else 'Transport.LoopOff' self._transport.layer = Layer(priority = 4, play_button = self._button[28], stop_button = self._button[29], record_button = self._button[30], tap_tempo_button = self._button[31], nudge_up_button = self._button[3], nudge_down_button = self._button[19], loop_button = self._button[23]) self._transport.set_enabled(True) def _setup_autoarm(self): self._auto_arm = CntrlrAutoArmComponent(name='Auto_Arm') #self._auto_arm._update_notification = lambda a: None 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 = FixedLengthSessionRecordingComponent(clip_creator = self._clip_creator, view_controller = ViewControlComponent(), name = 'SessionRecorder') # is_enabled = False) self._recorder.main_layer = AddLayerMode(self._recorder, Layer(priority = 4, record_button = self._button[29])) #self._recorder.shift_layer = AddLayerMode(self._recorder, Layer(priority = 4, automation_button = self._button[29])) self._recorder.set_enabled(False) def _setup_session_control(self): self._session_ring = SessionRingComponent(num_tracks = 4, num_scenes = 4) self._session_ring.set_enabled(True) self._session_navigation = SessionNavigationComponent(name = 'SessionNavigation', session_ring = self._session_ring) self._session_navigation._vertical_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._vertical_paginator.scroll_up_button.disabled_color = 'Session.PageNavigationButtonOff' self._session_navigation._vertical_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._vertical_paginator.scroll_down_button.disabled_color = 'Session.PageNavigationButtonOff' self._session_navigation._horizontal_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_up_button.disabled_color = 'Session.PageNavigationButtonOff' self._session_navigation._horizontal_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_down_button.disabled_color = 'Session.PageNavigationButtonOff' self._session_navigation.layer = Layer(priority = 4, down_button = self._button[14], up_button = self._button[15], left_button = self._button[12], right_button = self._button[13]) self._session_navigation.set_enabled(True) self._session = SessionComponent(session_ring = self._session_ring, auto_name = True) hasattr(self._session, '_enable_skinning') and self._session._enable_skinning() self._session.layer = Layer(priority = 4, clip_launch_buttons = self._matrix.submatrix[:,:]) self._session.set_enabled(True) def _setup_mixer_control(self): self._mixer_session_ring = SessionRingComponent(num_tracks = 4, num_scenes = 4) self._mixer = MonoMixerComponent(name = 'Mixer', tracks_provider = self._mixer_session_ring, track_assigner = simple_track_assigner, invert_mute_feedback = True, auto_name = True, enable_skinning = True) self._mixer.layer = Layer(priority = 4, solo_buttons = self._key_matrix.submatrix[8:11, 0], stop_clip_buttons = self._key_matrix.submatrix[:3, 0], track_select_buttons = self._key_matrix.submatrix[4:8, 0],) for strip in self._mixer._channel_strips: strip._on_select_button_double_clicked = self._toggle_view self._mixer.set_enabled(True) def _toggle_view(self, *a): debug('toggle_view') debug('Clip is visible:', self.application().view.is_view_visible('Detail/Clip')) debug('Device is visible:', self.application().view.is_view_visible('Detail/DeviceChain')) if self.application().view.is_view_visible('Detail/Clip'): self._view_control.show_view('Detail/DeviceChain') else: self._view_control.show_view('Detail/Clip') def _setup_device_control(self): self._device_selection_follows_track_selection = FOLLOW self._device = DeviceComponent(name = 'Device_Component', device_provider = self._device_provider, device_bank_registry = DeviceBankRegistry()) self._device.layer = Layer(priority = 4, parameter_controls = self._dial_matrix.submatrix[:, 1:3],) #self._device.mod_layer = AddLayerMode(self._device, Layer(priority = 4, parameter_controls = self._dial_matrix.submatrix[:, 1:3],)) self._device.main_layer = AddLayerMode(self._device, Layer(priority = 4, parameter_controls = self._dial_matrix.submatrix[:, 1:3], on_off_button = self._encoder_button[4], bank_prev_button = self._encoder_button[6], bank_next_button = self._encoder_button[7],)) #lock_button = self._encoder_button[5], self._device.set_enabled(False) self._device_navigator = DeviceNavigator(self._device_provider, self._mixer, self) self._device_navigator.name = 'Device_Navigator' self._device_navigator.select_dial_layer = AddLayerMode(self._device_navigator, Layer(priority = 6, device_select_dial = self._encoder[0],)) self._device_navigator.main_layer = AddLayerMode(self._device_navigator, Layer(priority = 4, prev_chain_button = self._encoder_button[8], next_chain_button = self._encoder_button[9], exit_button = self._encoder_button[10], enter_button = self._encoder_button[11],)) self._device_navigator.set_enabled(False) def _setup_device_selector(self): self._device_selector = DeviceSelectorComponent(self) self._device_selector.name = 'Device_Selector' #self._device_selector.select_layer = AddLayerMode(self._device_selector, Layer(priority = 6 , matrix = self._matrix.submatrix[:, :])) self._device_selector.select_layer = AddLayerMode(self._device_selector, Layer(priority = 6, matrix = ButtonMatrixElement(rows = [self._grid[:4],self._grid[4:8],self._grid[8:12],self._grid[12:14]]))) self._device_selector.assign_layer = AddLayerMode(self._device_selector, Layer(priority = 7, assign_button = self._grid[14])) self._device_selector.set_enabled(False) def _setup_viewcontrol(self): self._view_control = ViewControlComponent(name='View_Control') #self._view_control.main_layer = AddLayerMode(self._view_control, Layer(priority = 5, # scene_select_dial = self._encoder[2], # track_select_dial = self._encoder[3],)) #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(True) def _setup_modes(self): common = CompoundMode(self._mixer, self._session_ring) main_buttons=CompoundMode(self._mixer.main_buttons_layer, self._transport, self._recorder, self._recorder.main_layer, self._device,) shifted_main_buttons=CompoundMode(self._mixer.solo_buttons_layer, self._recorder, self._recorder.shift_layer, self._session.scene_launch_layer, self._device,) main_faders=CompoundMode(self._mixer.main_faders_layer, self._mixer.master_fader_layer) main_dials=CompoundMode(self._view_control, self._view_control.main_layer, self._device_navigator, self._device_navigator.select_dial_layer, self.encoder_navigation_on) shifted_dials=CompoundMode(self._session_navigation, self._session_navigation.nav_dial_layer, self._device_navigator, self._device_navigator.select_dial_layer, self.encoder_navigation_on) self._modalt_mode = ModesComponent(name = 'ModAltMode') self._modalt_mode.add_mode('disabled', None) self._modalt_mode.add_mode('enabled', [tuple([self._enable_mod_alt, self._disable_mod_alt])], behaviour = CancellableBehaviourWithRelease(), cycle_mode_button_color = 'Mod.AltOn') self._modalt_mode.selected_mode = 'disabled' self._modalt_mode.set_enabled(False) self._modalt_mode.layer = Layer(priority = 4, enabled_button = self._encoder_button[1]) self._modswitcher = ModesComponent(name = 'ModSwitcher') self._modswitcher.add_mode('mod', [self.modhandler, self._modalt_mode, main_faders, self._mixer.main_knobs_layer, self._device, main_dials, DelayMode(self.modhandler.update, delay = .5, parent_task_group = self._task_group)]) self._modswitcher.add_mode('instrument', [self._instrument.shift_button_layer, main_buttons, main_faders, self._mixer.main_knobs_layer, self._device, self._device.main_layer, self._device_navigator, self._device_navigator.main_layer, self._device_navigator.select_dial_layer]) #self._instrument.shift_button_layer, self._optional_translations]) self._modswitcher.selected_mode = 'instrument' self._modswitcher.set_enabled(False) self._instrument._main_modes = ModesComponent(name = 'InstrumentModes') self._instrument._main_modes.add_mode('disabled', [main_buttons, main_dials, self._device.main_layer, self._session, self._session, self._session.clip_launch_layer]) self._instrument._main_modes.add_mode('drumpad', [self._instrument._drumpad.sequencer_layer, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('drumpad_split', [self._instrument._drumpad.split_layer, self._instrument._selected_session, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('drumpad_sequencer', [self._instrument._drumpad.sequencer_layer, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('drumpad_shifted', [self._instrument._drumpad.sequencer_shift_layer, self._instrument.drumpad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('drumpad_split_shifted', [self._instrument._drumpad.split_layer, self._instrument.drumpad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('drumpad_sequencer_shifted', [self._instrument._drumpad.sequencer_shift_layer, self._instrument.drumpad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('keypad', [self._instrument._keypad.sequencer_layer, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('keypad_split', [self._instrument._keypad.split_layer, self._instrument._selected_session, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('keypad_sequencer', [self._instrument._keypad.sequencer_layer, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('keypad_shifted', [self._instrument._keypad.sequencer_shift_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('keypad_split_shifted', [self._instrument._keypad.split_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('keypad_sequencer_shifted', [self._instrument._keypad.sequencer_shift_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('drumpad_session', [self._instrument._drumpad.sequencer_session_layer, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('drumpad_split_session', [self._instrument._drumpad.split_session_layer, self._instrument._selected_session, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('drumpad_sequencer_session', [self._instrument._drumpad.sequencer_session_layer, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('drumpad_shifted_session', [self._instrument._drumpad.sequencer_session_shift_layer, self._instrument.drumpad_shift_layer, main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('drumpad_split_shifted_session', [self._instrument._drumpad.split_session_layer, self._instrument.drumpad_shift_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('drumpad_sequencer_shifted_session', [self._instrument._drumpad.sequencer_session_shift_layer, self._instrument.drumpad_shift_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('keypad_session', [self._instrument._keypad.sequencer_session_layer, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('keypad_split_session', [self._instrument._keypad.split_session_layer, self._instrument._selected_session, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('keypad_sequencer_session', [self._instrument._keypad.sequencer_session_layer, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('keypad_shifted_session', [self._instrument._keypad.sequencer_session_shift_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('keypad_split_shifted_session', [self._instrument._keypad.split_session_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('keypad_sequencer_shifted_session', [self._instrument._keypad.sequencer_session_shift_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('audioloop', [self._instrument.audioloop_layer, main_buttons, self._device.main_layer, main_dials, self._session, DelayMode(self._session.clip_launch_layer, delay = .1)]) self._instrument._main_modes.add_mode('audioloop_shifted', [self._instrument.audioloop_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) #self._instrument._main_modes.add_mode('audioloop_shifted_session', [self._instrument.audioloop_layer, self._session, shifted_main_buttons, main_dials, shifted_dials]) self._instrument.register_component(self._instrument._main_modes) self._instrument._main_modes.selected_mode = 'disabled' self._instrument.set_enabled(True) self._main_modes = ModesComponent(name = 'MainModes') self._main_modes.add_mode('disabled', [self._background]) self._main_modes.add_mode('MixMode', [common, self._instrument, self._instrument.shift_button_layer, self._mixer, main_faders, self._mixer.main_knobs_layer, self._device, self._device.main_layer, self._device_navigator, self._device_navigator.main_layer, self._device_navigator.select_dial_layer]) self._main_modes.add_mode('ModSwitcher', [common, main_faders, main_dials, self._mixer.main_knobs_layer, self._view_control, self._view_control.main_layer, self._device_navigator, self._device_navigator.select_dial_layer, self.encoder_navigation_on, self._modswitcher, DelayMode(self._update_modswitcher, delay = .1)], behaviour = ColoredCancellableBehaviourWithRelease(color = 'ModeButtons.ModSwitcher', off_color = 'ModeButtons.ModSwitcherDisabled')) self._main_modes.add_mode('Translations', [common, main_faders, main_dials, self._mixer.main_knobs_layer, self._translations, DelayMode(self._translations.selector_layer, delay = .1)], behaviour = DefaultedBehaviour(default_mode = 'MixMode', color = 'ModeButtons.Translations', off_color = 'ModeButtons.TranslationsDisabled')) self._main_modes.add_mode('DeviceSelector', [common, self._device_selector, DelayMode(self._device_selector.select_layer, delay = .1), DelayMode(self.modhandler.lock_layer, delay = .1), DelayMode(self._device_selector.assign_layer, delay = .5), main_buttons, main_dials, main_faders, self._mixer.main_knobs_layer, self._device.main_layer, self._device_navigator, self._device_navigator.main_layer, self._device_navigator.select_dial_layer], behaviour = ColoredCancellableBehaviourWithRelease(color = 'ModeButtons.DeviceSelector', off_color = 'ModeButtons.DeviceSelectorDisabled')) self._main_modes.layer = Layer(priority = 4, ModSwitcher_button = self._encoder_button[2], DeviceSelector_button = self._encoder_button[0], Translations_button = self._encoder_button[3]) #, self._main_modes.selected_mode = 'disabled' self._main_modes.set_enabled(True) self._test.subject = self._instrument._main_modes def _setup_modes(self): pass def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent(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') def _get_num_tracks(self): return self.num_tracks # a
class DS1(LividControlSurface): _sysex_id = 16 _model_name = 'DS1' def __init__(self, c_instance): super(DS1, self).__init__(c_instance) self._skin = Skin(DS1Colors) with self.component_guard(): self._define_sysex() self._setup_controls() self._setup_background() self._setup_m4l_interface() self._setup_session_control() self._setup_mixer_control() self._setup_transport_control() self._setup_device_control() self._setup_session_recording_component() self._setup_main_modes() def _initialize_script(self): super(DS1, self)._initialize_script() self._main_modes.set_enabled(True) self._main_modes.selected_mode = 'Main' def _initialize_hardware(self): super(DS1, self)._initialize_hardware() self.local_control_off.enter_mode() self.encoder_absolute_mode.enter_mode() self.encoder_speed_sysex.enter_mode() def _define_sysex(self): self.encoder_speed_sysex = SendLividSysexMode( livid_settings=self._livid_settings, call='set_encoder_mapping', message=ENCODER_SPEED) self.encoder_absolute_mode = SendLividSysexMode( livid_settings=self._livid_settings, call='set_encoder_encosion_mode', message=[2]) self.local_control_off = SendLividSysexMode( livid_settings=self._livid_settings, call='set_local_control', message=[0]) def _setup_controls(self): is_momentary = True optimized = True resource = PrioritizedResource self._fader = [ MonoEncoderElement(mapping_feedback_delay=-1, msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=DS1_FADERS[index], name='Fader_' + str(index), num=index, script=self, optimized_send_midi=optimized, resource_type=resource) for index in range(8) ] self._dial = [[ MonoEncoderElement(mapping_feedback_delay=-1, msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=DS1_DIALS[x][y], name='Dial_' + str(x) + '_' + str(y), num=x + (y * 5), script=self, optimized_send_midi=optimized, resource_type=resource) for x in range(8) ] for y in range(5)] self._side_dial = [ MonoEncoderElement(mapping_feedback_delay=-1, msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=DS1_SIDE_DIALS[x], name='Side_Dial_' + str(x), num=x, script=self, optimized_send_midi=optimized, resource_type=resource) for x in range(4) ] self._encoder = [ MonoEncoderElement(mapping_feedback_delay=-1, msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=DS1_ENCODERS[x], name='Encoder_' + str(x), num=x, script=self, optimized_send_midi=optimized, resource_type=resource) for x in range(4) ] self._encoder_button = [ MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=DS1_ENCODER_BUTTONS[index], name='EncoderButton_' + str(index), script=self, skin=self._skin, optimized_send_midi=optimized, resource_type=resource) for index in range(4) ] self._master_fader = MonoEncoderElement(msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=DS1_MASTER, name='MasterFader', num=0, script=self, optimized_send_midi=optimized, resource_type=resource) self._button = [ MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=DS1_BUTTONS[index], name='Button_' + str(index), script=self, skin=self._skin, optimized_send_midi=optimized, resource_type=resource) for index in range(16) ] self._grid = [[ MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=DS1_GRID[x][y], name='Button_' + str(x) + '_' + str(y), script=self, skin=self._skin, optimized_send_midi=optimized, resource_type=resource) for x in range(3) ] for y in range(3)] self._dummy = [ MonoEncoderElement(msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=120 + x, name='Dummy_Dial_' + str(x), num=x, script=self, optimized_send_midi=optimized, resource_type=resource) for x in range(5) ] self._fader_matrix = ButtonMatrixElement(name='FaderMatrix', rows=[self._fader]) self._top_buttons = ButtonMatrixElement(name='TopButtonMatrix', rows=[self._button[:8]]) self._bottom_buttons = ButtonMatrixElement(name='BottomButtonMatrix', rows=[self._button[8:]]) self._dial_matrix = ButtonMatrixElement(name='DialMatrix', rows=self._dial) self._side_dial_matrix = ButtonMatrixElement(name='SideDialMatrix', rows=[self._side_dial]) self._encoder_matrix = ButtonMatrixElement(name='EncoderMatrix', rows=[self._encoder]) self._encoder_button_matrix = ButtonMatrixElement( name='EncoderButtonMatrix', rows=[self._encoder_button]) self._grid_matrix = ButtonMatrixElement(name='GridMatrix', rows=self._grid) self._selected_parameter_controls = ButtonMatrixElement( name='SelectedParameterControls', rows=[self._dummy + self._encoder[:1] + self._encoder[2:]]) def _setup_background(self): self._background = BackgroundComponent(name='Background') self._background.layer = Layer( priority=0, fader_matrix=self._fader_matrix, top_buttons=self._top_buttons, bottom_buttons=self._bottom_buttons, dial_matrix=self._dial_matrix, side_dial_matrix=self._side_dial_matrix, encoder_button_matrix=self._encoder_button_matrix, grid_matrix=self._grid_matrix) self._background.set_enabled(True) def _setup_autoarm(self): self._auto_arm = AutoArmComponent(name='Auto_Arm') self._auto_arm.can_auto_arm_track = self._can_auto_arm_track def _tracks_to_use(self): return self.song.visible_tracks + self.song.return_tracks def _setup_session_control(self): self._session_ring = SessionRingComponent( num_tracks=8, num_scenes=1, tracks_to_use=self._tracks_to_use) self._session_ring.set_enabled(True) self._session_navigation = DS1SessionNavigationComponent( name='SessionNavigation', session_ring=self._session_ring) self._session_navigation._vertical_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation.layer = Layer( priority=4, track_select_dial=ComboElement(control=self._encoder[1], modifier=[self._encoder_button[1]]), up_button=self._grid[0][1], down_button=self._grid[0][2]) self._session_navigation.set_enabled(False) self._session = DS1SessionComponent(session_ring=self._session_ring, auto_name=True) hasattr(self._session, '_enable_skinning') and self._session._enable_skinning() self._session.layer = Layer( priority=4, scene_launch_buttons=self._grid_matrix.submatrix[1:2, 1:2]) self._session.clips_layer = AddLayerMode( self._session, Layer(priority=4, clip_launch_buttons=self._top_buttons, stop_track_clip_buttons=self._bottom_buttons)) self._session.set_enabled(False) def _setup_mixer_control(self): self._mixer = MonoMixerComponent( name='Mixer', num_returns=2, tracks_provider=self._session_ring, track_assigner=SimpleTrackAssigner(), invert_mute_feedback=True, auto_name=True, enable_skinning=True, channel_strip_component_type=MonoChannelStripComponent) self._mixer.master_strip().set_volume_control(self._master_fader) self._mixer.set_prehear_volume_control(self._side_dial[3]) self._mixer.layer = Layer(volume_controls=self._fader_matrix, track_select_dial=self._encoder[1]) self._strip = [self._mixer.channel_strip(index) for index in range(8)] if KNOBS_ARE_SENDS: for index in range(8): self._strip[index].layer = Layer( priority=4, send_controls=self._dial_matrix.submatrix[index:index + 1, :4], pan_control=self._dial[4][index]) else: for index in range(8): self._strip[index].layer = Layer( priority=4, parameter_controls=self._dial_matrix.submatrix[ index:index + 1, :]) self._mixer.selected_strip().layer = Layer( priority=4, parameter_controls=self._selected_parameter_controls) self._mixer.master_strip().layer = Layer( priority=4, parameter_controls=self._side_dial_matrix.submatrix[:3, :]) self._mixer.main_layer = AddLayerMode( self._mixer, Layer(priority=4, solo_buttons=self._bottom_buttons, mute_buttons=self._top_buttons)) self._mixer.select_layer = AddLayerMode( self._mixer, Layer(priority=4, arm_buttons=self._bottom_buttons, track_select_buttons=self._top_buttons)) self.song.view.selected_track = self._mixer.channel_strip(0)._track self._mixer.set_enabled(False) def _setup_transport_control(self): self._transport = DS1TransportComponent() self._transport.name = 'Transport' self._transport._record_toggle.view_transform = lambda value: 'Transport.RecordOn' if value else 'Transport.RecordOff' self._transport.layer = Layer(priority=4, stop_button=self._grid[1][0], play_button=self._grid[0][0], record_button=self._grid[2][0]) self._transport.set_enabled(True) def _setup_device_control(self): self._device = DeviceComponent( name='Device_Component', device_provider=self._device_provider, device_bank_registry=DeviceBankRegistry()) self._device_navigator = DeviceNavigator(self._device_provider, self._mixer, self) self._device_navigator.name = 'Device_Navigator' def _setup_session_recording_component(self): self._clip_creator = ClipCreator() self._clip_creator.name = 'ClipCreator' self._recorder = SessionRecordingComponent(ViewControlComponent()) self._recorder.set_enabled(True) self._recorder.layer = Layer( priority=4, automation_button=self._grid[1][2], record_button=self._grid[2][1], ) def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent( 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 _setup_translations(self): controls = [] for control in self.controls: controls.append(control) self._translations = TranslationComponent(controls, 10) self._translations.name = 'TranslationComponent' self._translations.set_enabled(False) def _setup_main_modes(self): self._main_modes = ModesComponent(name='MainModes') self._main_modes.add_mode('Main', [ self._mixer, self._mixer.main_layer, self._session, self._session_navigation ], cycle_mode_button_color='ModeButtons.Main') self._main_modes.add_mode('Select', [ self._mixer, self._mixer.select_layer, self._session, self._session_navigation ], cycle_mode_button_color='ModeButtons.Select') self._main_modes.add_mode('Clips', [ self._mixer, self._session, self._session.clips_layer, self._session_navigation ], cycle_mode_button_color='ModeButtons.Clips') self._main_modes.layer = Layer(priority=4, cycle_mode_button=self._grid[2][2]) self._main_modes.selected_mode = 'Main' self._main_modes.set_enabled(False) def _can_auto_arm_track(self, track): routing = track.current_input_routing return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith( 'DS1 Input')
class PushBase(ControlSurface): preferences_key = 'Push' session_component_type = SpecialSessionComponent drum_group_note_editor_skin = 'NoteEditor' note_editor_velocity_range_thresholds = DEFAULT_VELOCITY_RANGE_THRESHOLDS device_component_class = None bank_definitions = None note_editor_class = None def __init__(self, *a, **k): super(PushBase, self).__init__(*a, **k) self.register_slot(self.song.view, self._on_selected_track_changed, 'selected_track') self._device_decorator_factory = self._create_device_decorator_factory() self.register_disconnectable(self._device_decorator_factory) self._double_press_context = DoublePressContext() injecting = self._create_injector() self._push_injector = injecting.everywhere() self._element_injector = inject(element_container=const(None)).everywhere() with self.component_guard(): self._suppress_sysex = False self._skin = self._create_skin() self._clip_creator = ClipCreator() self._note_editor_settings = [] self._notification = None self._user = None with inject(skin=const(self._skin)).everywhere(): self._create_controls() self._element_injector = inject(element_container=const(self.elements)).everywhere() def initialize(self): self._setup_accidental_touch_prevention() self._create_components() self._init_main_modes() self._on_selected_track_changed() self.__on_session_record_changed.subject = self.song self.__on_session_record_changed() self.__on_selected_track_is_frozen_changed.subject = self.song.view self.set_feedback_channels(FEEDBACK_CHANNELS) def disconnect(self): if self._user is not None: with self.component_guard(): self._user.mode = sysex.USER_MODE super(PushBase, self).disconnect() @contextmanager def _component_guard(self): with super(PushBase, self)._component_guard(): with self._push_injector: with self._element_injector: song_view = self.song.view old_selected_track = song_view.selected_track yield if song_view.selected_track != old_selected_track: self._track_selection_changed_by_action() def _create_device_decorator_factory(self): raise NotImplementedError def _create_components(self): self._init_settings() self._init_notification() self._init_message_box() self._init_background() self._init_user() self._init_touch_strip_controller() self._init_accent() self._init_track_frozen() self._init_undo_redo_actions() self._init_duplicate_actions() self._init_delete_actions() self._init_quantize_actions() self._init_session_ring() self._init_fixed_length() self._init_transport_and_recording() self._init_stop_clips_action() self._init_value_components() self._init_track_list() self._init_mixer() self._init_track_mixer() self._init_session() self._init_grid_resolution() self._init_drum_component() self._init_slicing_component() self._init_automation_component() self._init_note_settings_component() self._init_note_editor_settings_component() self._init_step_sequencer() self._init_instrument() self._init_scales() self._init_note_repeat() self._init_matrix_modes() self._init_device() self._init_m4l_interface() def _create_injector(self): return inject(double_press_context=const(self._double_press_context), expect_dialog=const(self.expect_dialog), show_notification=const(self.show_notification), selection=lambda : PushSelection(application=self.application(), device_component=self._device_component, navigation_component=self._device_navigation)) def _create_skin(self): return make_default_skin() def _needs_to_deactivate_session_recording(self): return self._matrix_modes.selected_mode == 'note' and self.song.exclusive_arm def _track_selection_changed_by_action(self): if self._needs_to_deactivate_session_recording(): self._session_recording.deactivate_recording() if self._auto_arm.needs_restore_auto_arm: self._auto_arm.restore_auto_arm() def port_settings_changed(self): self._switch_to_live_mode() def _switch_to_live_mode(self): self._user.mode = sysex.LIVE_MODE self._user.force_send_mode() def _init_settings(self): self._settings = self._create_settings() def _create_settings(self): raise RuntimeError def update(self): self.__on_session_record_changed() self.reset_controlled_track() self.set_feedback_channels(FEEDBACK_CHANNELS) super(PushBase, self).update() def _create_controls(self): raise NotImplementedError def _with_shift(self, button): return ComboElement(button, modifier='shift_button') def _with_firmware_version(self, major_version, minor_version, control_element): raise NotImplementedError def _init_background(self): self._background = BackgroundComponent(is_root=True) self._background.layer = self._create_background_layer() self._matrix_background = BackgroundComponent() self._matrix_background.set_enabled(False) self._matrix_background.layer = Layer(matrix='matrix') self._mod_background = ModifierBackgroundComponent(is_root=True) self._mod_background.layer = Layer(shift_button='shift_button', select_button='select_button', delete_button='delete_button', duplicate_button='duplicate_button', quantize_button='quantize_button') def _create_background_layer(self): return Layer(top_buttons='select_buttons', bottom_buttons='track_state_buttons', scales_button='scale_presets_button', octave_up='octave_up_button', octave_down='octave_down_button', side_buttons='side_buttons', repeat_button='repeat_button', accent_button='accent_button', double_button='double_button', param_controls='global_param_controls', param_touch='global_param_touch_buttons', touch_strip='touch_strip_control', nav_up_button='nav_up_button', nav_down_button='nav_down_button', nav_left_button='nav_left_button', nav_right_button='nav_right_button', aftertouch='aftertouch_control', _notification=self._notification.use_single_line(2), priority=consts.BACKGROUND_PRIORITY) def _init_track_list(self): pass def _can_auto_arm_track(self, track): routing = track.current_input_routing return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith(self.input_target_name_for_auto_arm) def _init_touch_strip_controller(self): strip_controller = TouchStripControllerComponent() strip_controller.set_enabled(False) strip_controller.layer = Layer(touch_strip='touch_strip_control') strip_controller.layer.priority = consts.DIALOG_PRIORITY self._strip_connection = TouchStripEncoderConnection(strip_controller, self.elements.touch_strip_tap, is_root=True) self.elements.tempo_control.set_observer(self._strip_connection) self.elements.swing_control.set_observer(self._strip_connection) self.elements.master_volume_control.set_observer(self._strip_connection) for encoder in self.elements.global_param_controls.nested_control_elements(): encoder.set_observer(self._strip_connection) self._pitch_mod_touch_strip = TouchStripPitchModComponent() self._pitch_mod_touch_strip_layer = Layer(touch_strip='touch_strip_control', touch_strip_indication=self._with_firmware_version(1, 16, ComboElement('touch_strip_control', modifier='select_button')), touch_strip_toggle=self._with_firmware_version(1, 16, ComboElement('touch_strip_tap', modifier='select_button'))) def _create_session_mode(self): raise NotImplementedError def _create_slicing_modes(self): slicing_modes = ModesComponent(name='Slicing_Modes', is_enabled=False) slicing_modes.add_mode('64pads', [AddLayerMode(self._slicing_component, Layer(matrix='matrix')), LayerMode(self._pitch_mod_touch_strip, self._pitch_mod_touch_strip_layer)]) slicing_modes.add_mode('sequencer', [self._slice_step_sequencer, self._note_editor_settings_component, AddLayerMode(self._slicing_component, Layer(matrix=self.elements.matrix.submatrix[:4, 4:8], page_strip='touch_strip_control', scroll_strip=self._with_shift('touch_strip_control')))]) slicing_modes.selected_mode = '64pads' return slicing_modes def _init_matrix_modes(self): self._auto_arm = AutoArmComponent(name='Auto_Arm') self._auto_arm.can_auto_arm_track = self._can_auto_arm_track self._auto_arm.layer = Layer(_notification=self._notification.use_single_line(2)) self._select_playing_clip = SelectPlayingClipComponent(name='Select_Playing_Clip', playing_clip_above_layer=Layer(action_button='nav_up_button'), playing_clip_below_layer=Layer(action_button='nav_down_button')) self._select_playing_clip.layer = Layer(_notification=self._notification.use_single_line(2)) self._percussion_instrument_finder = PercussionInstrumentFinderComponent(device_parent=self.song.view.selected_track) self.__on_percussion_instrument_changed.subject = self._percussion_instrument_finder self._drum_modes = ModesComponent(name='Drum_Modes', is_enabled=False) self._drum_modes.add_mode('sequencer', [self._drum_step_sequencer, self._note_editor_settings_component, AddLayerMode(self._drum_component, Layer(matrix=self.elements.matrix.submatrix[:4, 4:8]))]) self._drum_modes.add_mode('64pads', [AddLayerMode(self._drum_component, Layer(matrix='matrix'))]) self._drum_modes.selected_mode = 'sequencer' self._slicing_modes = self._create_slicing_modes() self._note_modes = ModesComponent(name='Note_Modes') self._note_modes.add_mode('drums', [self._drum_component, self._note_repeat_enabler, self._accent_component, self._drum_modes]) self._note_modes.add_mode('slicing', [self._slicing_component, self._note_repeat_enabler, self._accent_component, self._slicing_modes]) 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._note_repeat_enabler, self._accent_component, self._instrument, self._scales_enabler]) self._note_modes.add_mode('disabled', self._matrix_background) self._note_modes.selected_mode = 'disabled' self._note_modes.set_enabled(False) self._matrix_modes = ModesComponent(name='Matrix_Modes', is_root=True) self._matrix_modes.add_mode('session', self._create_session_mode()) self._matrix_modes.add_mode('note', self._create_note_mode(), behaviour=self._create_note_mode_behaviour()) self._matrix_modes.selected_mode = 'note' self._matrix_modes.layer = Layer(session_button='session_mode_button', note_button='note_mode_button') self.__on_matrix_mode_changed.subject = self._matrix_modes self._matrix_modes.selected_mode = 'note' def _switch_note_mode_layout(self): cyclable_mode = {'instrument': self._instrument, 'drums': self._drum_modes, 'slicing': self._slicing_modes}.get(self._note_modes.selected_mode, None) getattr(cyclable_mode, 'cycle_mode', nop)() def _create_note_mode(self): return [self._percussion_instrument_finder, self._view_control, self._note_modes, self._delete_clip, self._select_playing_clip] def _create_note_mode_behaviour(self): raise NotImplementedError def _init_accent(self): self._accent_component = AccentComponent() self._accent_component.set_full_velocity(self._c_instance.full_velocity) self._accent_component.set_enabled(False) self._accent_component.layer = Layer(cycle_mode_button='accent_button') self.__on_accent_mode_changed.subject = self._accent_component def _create_user_component(self): raise NotImplementedError def _init_user(self): self._user = self._create_user_component() self.__on_hardware_mode_changed.subject = self._user self.__on_before_hardware_mode_sent.subject = self._user self.__on_after_hardware_mode_sent.subject = self._user def _create_session_layer(self): return Layer(clip_launch_buttons='matrix', scene_launch_buttons='side_buttons', duplicate_button='duplicate_button', touch_strip='touch_strip_control') def _set_session_skin(self, session): pass def _create_session(self): session = self.session_component_type(session_ring=self._session_ring, enable_skinning=True, is_enabled=False, auto_name=True, layer=self._create_session_layer()) self._set_session_skin(session) for scene_index in xrange(8): scene = session.scene(scene_index) scene.layer = Layer(select_button='select_button', delete_button='delete_button') scene._do_select_scene = self.on_select_scene for track_index in xrange(8): clip_slot = scene.clip_slot(track_index) clip_slot._do_select_clip = self.on_select_clip_slot clip_slot.layer = Layer(delete_button='delete_button', select_button='select_button', duplicate_button='duplicate_button') session.duplicate_layer = Layer(scene_buttons='side_buttons') return session def on_select_clip_slot(self, clip_slot): """ Called when a clip slot is selected from Push. Override to create specific behaviour. """ pass def on_select_scene(self, scene): """ Called when a scene is selected from Push. Override to create specific behaviour. """ pass def on_select_track(self, track): """ Called when a track is selected from Push's channel strip components. Override to create specific behaviour. """ pass def _create_session_overview(self): return SessionOverviewComponent(session_ring=self._session_ring, name='Session_Overview', enable_skinning=True, is_enabled=False, layer=self._create_session_overview_layer()) def _create_session_overview_layer(self): raise NotImplementedError def _init_session_ring(self): self._session_ring = SessionRingComponent(num_tracks=NUM_TRACKS, num_scenes=NUM_SCENES, tracks_to_use=partial(tracks_to_use_from_song, self.song), is_enabled=True, is_root=True) def _init_session(self): self._session_mode = LazyComponentMode(self._create_session) self._session_overview_mode = LazyComponentMode(self._create_session_overview) self._session_navigation = SessionNavigationComponent(session_ring=self._session_ring, is_enabled=False, layer=self._create_session_navigation_layer()) def _create_session_navigation_layer(self): return Layer(left_button='nav_left_button', right_button='nav_right_button', up_button='nav_up_button', down_button='nav_down_button', page_left_button=self._with_shift('nav_left_button'), page_right_button=self._with_shift('nav_right_button'), page_up_button=MultiElement('octave_up_button', self._with_shift('nav_up_button')), page_down_button=MultiElement('octave_down_button', self._with_shift('nav_down_button'))) def _create_track_modes_layer(self): return Layer(stop_button='global_track_stop_button', mute_button='global_mute_button', solo_button='global_solo_button') def _when_track_is_not_frozen(self, *modes): return TrackFrozenModesComponent(default_mode=[modes], frozen_mode=self._track_frozen_info, is_enabled=False) def _create_device_mode(self): raise NotImplementedError def _create_main_mixer_modes(self): self._main_modes.add_mode('volumes', [self._track_modes, (self._mixer, self._mixer_volume_layer), self._track_note_editor_mode]) self._main_modes.add_mode('pan_sends', [self._track_modes, (self._mixer, self._mixer_pan_send_layer), self._track_note_editor_mode]) self._main_modes.add_mode('track', [self._track_modes, self._track_mixer, (self._mixer, self._mixer_track_layer), self._track_note_editor_mode]) def _create_clip_mode(self): return [self._when_track_is_not_frozen(partial(self._view_control.show_view, 'Detail/Clip'), LazyComponentMode(self._create_clip_control))] def _init_main_modes(self): def configure_note_editor_settings(parameter_provider, mode): for note_editor_setting in self._note_editor_settings: note_editor_setting.component.parameter_provider = parameter_provider note_editor_setting.component.automation_layer = getattr(note_editor_setting, mode + '_automation_layer') self._track_note_editor_mode = partial(configure_note_editor_settings, self._track_parameter_provider, 'track') self._device_note_editor_mode = partial(configure_note_editor_settings, self._device_component, 'device') self._enable_stop_mute_solo_as_modifiers = AddLayerMode(self._mod_background, Layer(stop='global_track_stop_button', mute='global_mute_button', solo='global_solo_button')) self._main_modes = ModesComponent(is_root=True) self._create_main_mixer_modes() self._main_modes.add_mode('clip', self._create_clip_mode()) self._main_modes.add_mode('device', self._create_device_mode(), behaviour=ReenterBehaviour(self._device_navigation.back_to_top)) self._init_browse_mode() self._main_modes.selected_mode = 'device' self._main_modes.layer = self._create_main_modes_layer() def _init_browse_mode(self): raise NotImplementedError def _create_main_modes_layer(self): return Layer(volumes_button='vol_mix_mode_button', pan_sends_button='pan_send_mix_mode_button', track_button='single_track_mix_mode_button', clip_button='clip_mode_button', device_button='device_mode_button', browse_button='browse_mode_button', add_effect_right_button='create_device_button', add_effect_left_button=self._with_shift('create_device_button'), add_instrument_track_button='create_track_button') def _init_track_frozen(self): self._track_frozen_info = InfoComponent(info_text=consts.MessageBoxText.TRACK_FROZEN_INFO, is_enabled=False, layer=self._create_track_frozen_layer()) def _create_track_frozen_layer(self): return Layer() def _init_mixer(self): pass def _init_track_mixer(self): self._track_parameter_provider = self.register_disconnectable(SelectedTrackParameterProvider()) self._track_mixer = DeviceParameterComponent(parameter_provider=self._track_parameter_provider, is_enabled=False, layer=self._create_track_mixer_layer()) def _create_track_mixer_layer(self): return Layer(parameter_controls='fine_grain_param_controls') def _create_device_component(self): return self.device_component_class(device_decorator_factory=self._device_decorator_factory, device_bank_registry=self._device_bank_registry, banking_info=self._banking_info, name='DeviceComponent', is_enabled=True, is_root=True) def _create_device_parameter_component(self): return DeviceParameterComponent(parameter_provider=self._device_component, is_enabled=False, layer=self._create_device_parameter_layer()) def _create_device_parameter_layer(self): return Layer(parameter_controls='fine_grain_param_controls') def _create_device_navigation(self): raise NotImplementedError def _init_device(self): self._device_bank_registry = DeviceBankRegistry() self._banking_info = BankingInfo(self.bank_definitions) self._device_component = self._create_device_component() self._device_parameter_component = self._create_device_parameter_component() self._device_navigation = self._create_device_navigation() def _create_view_control_component(self): return ViewControlComponent(name='View_Control') def _init_fixed_length(self): self._fixed_length_setting = FixedLengthSetting() self._fixed_length_setting.enabled = self.preferences.setdefault('fixed_length_enabled', False) self._fixed_length_setting.selected_index = self.preferences.setdefault('fixed_length_option', DEFAULT_LENGTH_OPTION_INDEX) self.__on_fixed_length_enabled_changed.subject = self._fixed_length_setting self.__on_fixed_length_selected_index_changed.subject = self._fixed_length_setting self._fixed_length_settings_component = FixedLengthSettingComponent(fixed_length_setting=self._fixed_length_setting, is_enabled=False) self._fixed_length = FixedLengthComponent(settings_component=self._fixed_length_settings_component, fixed_length_setting=self._fixed_length_setting) self._fixed_length.layer = Layer(fixed_length_toggle_button='fixed_length_button') def _create_session_recording(self): raise NotImplementedError def _init_transport_and_recording(self): self._view_control = self._create_view_control_component() self._view_control.set_enabled(False) self._view_control.layer = Layer(prev_track_button='nav_left_button', next_track_button='nav_right_button', prev_scene_button=OptionalElement('nav_up_button', self._settings['workflow'], False), next_scene_button=OptionalElement('nav_down_button', self._settings['workflow'], False), prev_scene_list_button=OptionalElement('nav_up_button', self._settings['workflow'], True), next_scene_list_button=OptionalElement('nav_down_button', self._settings['workflow'], True)) self._session_recording = self._create_session_recording() new_button = MultiElement(self.elements.new_button, self.elements.foot_pedal_button.double_press) self._session_recording.layer = Layer(new_button=OptionalElement(new_button, self._settings['workflow'], False), scene_list_new_button=OptionalElement(new_button, self._settings['workflow'], True), record_button='record_button', arrangement_record_button=self._with_shift('record_button'), automation_button='automation_button', new_scene_button=self._with_shift('new_button'), re_enable_automation_button=self._with_shift('automation_button'), delete_automation_button=ComboElement('automation_button', 'delete_button'), foot_switch_button=self.elements.foot_pedal_button.single_press, _uses_foot_pedal='foot_pedal_button') self._transport = TransportComponent(name='Transport', is_root=True) self._transport.layer = Layer(play_button='play_button', stop_button=self._with_shift('play_button'), tap_tempo_button='tap_tempo_button', metronome_button='metronome_button') def _create_clip_control(self): return ClipControlComponent(loop_layer=self._create_clip_loop_layer(), audio_layer=self._create_clip_audio_layer(), clip_name_layer=self._create_clip_name_layer(), name='Clip_Control', is_enabled=False) def _create_clip_loop_layer(self): return Layer(encoders=self.elements.global_param_controls.submatrix[:4, :], shift_button='shift_button') def _create_clip_audio_layer(self): return Layer(warp_mode_encoder='parameter_controls_raw[4]', transpose_encoder='parameter_controls_raw[5]', detune_encoder='parameter_controls_raw[6]', gain_encoder='parameter_controls_raw[7]', shift_button='shift_button') def _create_clip_name_layer(self): return Layer() def _init_grid_resolution(self): self._grid_resolution = self.register_disconnectable(GridResolution()) def _init_note_settings_component(self): raise NotImplementedError def _init_automation_component(self): self._automation_component = AutomationComponent() def _init_note_editor_settings_component(self): self._note_editor_settings_component = NoteEditorSettingsComponent(note_settings_component=self._note_settings_component, automation_component=self._automation_component, initial_encoder_layer=Layer(initial_encoders='global_param_controls', priority=consts.MOMENTARY_DIALOG_PRIORITY), encoder_layer=Layer(encoders='global_param_controls', priority=consts.MOMENTARY_DIALOG_PRIORITY)) self._note_editor_settings_component.mode_selector_layer = self._create_note_editor_mode_selector_layer() self._note_editor_settings.append(NamedTuple(component=self._note_editor_settings_component, track_automation_layer=self._create_note_editor_track_automation_layer(), device_automation_layer=self._create_note_editor_track_automation_layer())) def _create_note_editor_mode_selector_layer(self): return Layer(select_buttons='select_buttons', state_buttons='track_state_buttons', priority=consts.MOMENTARY_DIALOG_PRIORITY) def _create_note_editor_track_automation_layer(self): return Layer(priority=consts.MOMENTARY_DIALOG_PRIORITY) def _create_note_editor_device_automation_layer(self): return Layer(priority=consts.MOMENTARY_DIALOG_PRIORITY) def _create_instrument_layer(self): return Layer(playhead='playhead_element', mute_button='global_mute_button', quantization_buttons='side_buttons', loop_selector_matrix=self.elements.double_press_matrix.submatrix[:, 0], short_loop_selector_matrix=self.elements.double_press_event_matrix.submatrix[:, 0], note_editor_matrices=ButtonMatrixElement([[ self.elements.matrix.submatrix[:, 7 - row] for row in xrange(7) ]])) def _init_instrument(self): self._note_layout = NoteLayout(song=self.song, preferences=self.preferences) instrument_basic_layer = Layer(octave_strip=self._with_shift('touch_strip_control'), octave_up_button='octave_up_button', octave_down_button='octave_down_button', scale_up_button=self._with_shift('octave_up_button'), scale_down_button=self._with_shift('octave_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_layout=self._note_layout, note_editor_settings=self._note_editor_settings_component, note_editor_class=self.note_editor_class, velocity_range_thresholds=self.note_editor_velocity_range_thresholds, layer=self._create_instrument_layer(), instrument_play_layer=instrument_basic_layer + Layer(matrix='matrix', aftertouch_control='aftertouch_control', delete_button='delete_button'), instrument_sequence_layer=instrument_basic_layer + Layer(note_strip='touch_strip_control'), pitch_mod_touch_strip_mode=LayerMode(self._pitch_mod_touch_strip, self._pitch_mod_touch_strip_layer)) self.__on_note_editor_layout_changed.subject = self._instrument def _create_scales_enabler(self): raise NotImplementedError def _init_scales(self): self._scales_enabler = self._create_scales_enabler() def _create_step_sequencer_layer(self): return Layer(playhead='playhead_element', button_matrix=self.elements.matrix.submatrix[:8, :4], loop_selector_matrix=self.elements.double_press_matrix.submatrix[4:8, 4:8], short_loop_selector_matrix=self.elements.double_press_event_matrix.submatrix[4:8, 4:8], quantization_buttons='side_buttons', solo_button='global_solo_button', select_button='select_button', delete_button='delete_button', shift_button='shift_button', mute_button='global_mute_button') def _init_step_sequencer(self): drum_note_editor = self.note_editor_class(clip_creator=self._clip_creator, grid_resolution=self._grid_resolution, skin_base_key=self.drum_group_note_editor_skin, velocity_range_thresholds=self.note_editor_velocity_range_thresholds) self._note_editor_settings_component.add_editor(drum_note_editor) self._drum_step_sequencer = StepSeqComponent(self._clip_creator, self._skin, name='Drum_Step_Sequencer', grid_resolution=self._grid_resolution, note_editor_component=drum_note_editor, instrument_component=self._drum_component) self._drum_step_sequencer.set_enabled(False) self._drum_step_sequencer.layer = self._create_step_sequencer_layer() self._audio_loop = LoopSelectorComponent(follow_detail_clip=True, measure_length=1.0, name='Loop_Selector') self._audio_loop.set_enabled(False) self._audio_loop.layer = Layer(loop_selector_matrix='matrix') slice_note_editor = self.note_editor_class(clip_creator=self._clip_creator, grid_resolution=self._grid_resolution, skin_base_key=self.drum_group_note_editor_skin, velocity_range_thresholds=self.note_editor_velocity_range_thresholds) self._note_editor_settings_component.add_editor(slice_note_editor) self._slice_step_sequencer = StepSeqComponent(self._clip_creator, self._skin, name='Slice_Step_Sequencer', grid_resolution=self._grid_resolution, note_editor_component=slice_note_editor, instrument_component=self._slicing_component, is_enabled=False) self._slice_step_sequencer.layer = Layer(playhead='playhead_element', button_matrix=self.elements.matrix.submatrix[:8, :4], loop_selector_matrix=self.elements.double_press_matrix.submatrix[4:8, 4:8], short_loop_selector_matrix=self.elements.double_press_event_matrix.submatrix[4:8, 4:8], quantization_buttons='side_buttons', select_button='select_button') def _drum_pad_notification_formatter(self): return lambda x: adjust_string(x, 8) def _create_drum_component(self): raise NotImplementedError def _init_drum_component(self): self._drum_component = self._create_drum_component() self._drum_component.layer = Layer(page_strip='touch_strip_control', scroll_strip=self._with_shift('touch_strip_control'), solo_button='global_solo_button', select_button='select_button', delete_button='delete_button', scroll_page_up_button='octave_up_button', scroll_page_down_button='octave_down_button', quantize_button='quantize_button', duplicate_button='duplicate_button', mute_button='global_mute_button', scroll_up_button=self._with_shift('octave_up_button'), scroll_down_button=self._with_shift('octave_down_button')) def _init_slicing_component(self): self._slicing_component = SlicedSimplerComponent(is_enabled=False) self._slicing_component.layer = Layer(scroll_page_up_button='octave_up_button', scroll_page_down_button='octave_down_button', scroll_up_button=self._with_shift('octave_up_button'), scroll_down_button=self._with_shift('octave_down_button'), delete_button='delete_button', select_button='select_button') 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 = self._create_note_repeat_layer() self._note_repeat_enabler = EnablingModesComponent(name='Note_Repeat_Enabler', component=self._note_repeat, enabled_color='DefaultButton.Alert', disabled_color='DefaultButton.On') self._note_repeat_enabler.set_enabled(False) self._note_repeat_enabler.layer = Layer(cycle_mode_button='repeat_button') def _create_note_repeat_layer(self): return Layer(aftertouch_control='aftertouch_control', select_buttons='side_buttons', priority=consts.DIALOG_PRIORITY) def _init_notification(self): self._notification = self._create_notification_component() def _create_notification_component(self): raise NotImplementedError def _create_message_box_background_layer(self): return BackgroundLayer('select_buttons', 'track_state_buttons', 'scale_presets_button', 'octave_up_button', 'octave_down_button', 'side_buttons', 'repeat_button', 'accent_button', 'global_param_controls', 'global_param_touch_buttons', 'touch_strip_control', 'touch_strip_tap', 'matrix', 'nav_up_button', 'nav_down_button', 'nav_left_button', 'nav_right_button', 'shift_button', 'select_button', 'delete_button', 'duplicate_button', 'double_button', 'quantize_button', 'play_button', 'new_button', 'automation_button', 'tap_tempo_button', 'metronome_button', 'fixed_length_button', 'record_button', 'undo_button', 'tempo_control', 'swing_control', 'master_volume_control', 'global_param_controls', 'vol_mix_mode_button', 'pan_send_mix_mode_button', 'single_track_mix_mode_button', 'clip_mode_button', 'device_mode_button', 'browse_mode_button', 'user_button', 'master_select_button', 'create_device_button', 'create_track_button', 'global_track_stop_button', 'global_mute_button', 'global_solo_button', 'note_mode_button', 'session_mode_button', priority=consts.MESSAGE_BOX_PRIORITY) def _create_message_box_layer(self): raise RuntimeError def _init_message_box(self): self._dialog = DialogComponent(is_enabled=True, is_root=True) self._dialog.message_box_layer = (self._create_message_box_background_layer(), self._create_message_box_layer()) def _for_non_frozen_tracks(self, component, **k): """ Wrap component into a mode that will only enable it when the track is not frozen """ TrackFrozenModesComponent(default_mode=component, frozen_mode=self._track_frozen_info, **k) return component def _init_undo_redo_actions(self): self._undo_redo = UndoRedoComponent(name='Undo_Redo', is_root=True) self._undo_redo.layer = Layer(undo_button='undo_button', redo_button=self._with_shift('undo_button')) def _init_stop_clips_action(self): pass def _create_capture_and_insert_scene_component(self): return CaptureAndInsertSceneComponent(name='Capture_And_Insert_Scene', is_root=True) def _init_duplicate_actions(self): capture_element = ChoosingElement(self._settings['workflow'], 'duplicate_button', self._with_shift('duplicate_button')) self._capture_and_insert_scene = self._create_capture_and_insert_scene_component() self._capture_and_insert_scene.set_enabled(True) self._capture_and_insert_scene.layer = Layer(action_button=capture_element) duplicate_element = OptionalElement('duplicate_button', self._settings['workflow'], False) self._duplicate_detail_clip = DuplicateDetailClipComponent(name='Duplicate_Detail_Clip', is_root=True) self._duplicate_detail_clip.set_enabled(True) self._duplicate_detail_clip.layer = Layer(action_button=duplicate_element) self._duplicate_loop = self._for_non_frozen_tracks(DuplicateLoopComponent(name='Duplicate_Loop', layer=Layer(action_button='double_button'), is_enabled=False), is_root=True) def _init_delete_actions(self): self._delete_component = DeleteComponent(name='Deleter', is_root=True) self._delete_component.layer = Layer(delete_button='delete_button') self._delete_default_component = DeleteAndReturnToDefaultComponent(name='DeleteAndDefault', is_root=True) self._delete_default_component.layer = Layer(delete_button='delete_button') self._delete_clip = DeleteSelectedClipComponent(name='Selected_Clip_Deleter', is_root=True) self._delete_clip.layer = Layer(action_button='delete_button') self._delete_scene = DeleteSelectedSceneComponent(name='Selected_Scene_Deleter', is_root=True) self._delete_scene.layer = Layer(action_button=self._with_shift('delete_button')) def _init_quantize_actions(self): raise NotImplementedError def _init_value_components(self): self._swing_amount = ValueComponent('swing_amount', self.song, display_label='Swing Amount:', display_format='%d%%', model_transform=lambda x: clamp(x / 200.0, 0.0, 0.5), view_transform=lambda x: x * 200.0, encoder_factor=100.0, encoder_touch_delay=TEMPO_SWING_TOUCH_DELAY, is_root=True) self._swing_amount.layer = Layer(encoder='swing_control') self._tempo = ValueComponent('tempo', self.song, display_label='Tempo:', display_format='%0.2f BPM', encoder_factor=128.0, encoder_touch_delay=TEMPO_SWING_TOUCH_DELAY, is_root=True) self._tempo.layer = Layer(encoder='tempo_control', shift_button='shift_button') self._master_vol = ParameterValueComponent(self.song.master_track.mixer_device.volume, display_label='Master Volume:', display_seg_start=3, name='Master_Volume_Display', is_root=True) self._master_vol.layer = Layer(encoder='master_volume_control') self._master_cue_vol = ParameterValueComponent(self.song.master_track.mixer_device.cue_volume, display_label='Cue Volume:', display_seg_start=3, name='Cue_Volume_Display', is_root=True) self._master_cue_vol.layer = Layer(encoder=self._with_shift('master_volume_control')) def _init_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard, priority=consts.M4L_PRIORITY, is_root=True) self.get_control_names = self._m4l_interface.get_control_names self.get_control = self._m4l_interface.get_control self.grab_control = self._m4l_interface.grab_control self.release_control = self._m4l_interface.release_control @listens('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) @listens('selected_track.is_frozen') def __on_selected_track_is_frozen_changed(self): self._select_note_mode() def _on_selected_track_changed(self): self.reset_controlled_track() self._select_note_mode() self._note_repeat_enabler.selected_mode = 'disabled' def _send_midi(self, midi_event_bytes, optimized = True): if not self._suppress_sysex or not midi.is_sysex(midi_event_bytes): return super(PushBase, self)._send_midi(midi_event_bytes, optimized) def _update_full_velocity(self, accent_is_active): self._drum_step_sequencer.full_velocity = accent_is_active self._instrument.full_velocity = accent_is_active def _update_playhead_color(self, color): self._instrument.playhead_color = color self._drum_step_sequencer.playhead_color = color @listens('session_record') def __on_session_record_changed(self): status = self.song.session_record self._update_playhead_color('PlayheadRecord' if status else 'Playhead') feedback_color = int(to_midi_value(self._skin['Instrument.FeedbackRecord']) if status else to_midi_value(self._skin['Instrument.Feedback'])) self._c_instance.set_feedback_velocity(feedback_color) @listens('selected_mode') def __on_accent_mode_changed(self, mode_name): accent_is_active = mode_name == 'enabled' self._update_full_velocity(accent_is_active) @listens('enabled') def __on_fixed_length_enabled_changed(self, enabled): self.preferences['fixed_length_enabled'] = enabled @listens('selected_index') def __on_fixed_length_selected_index_changed(self, index): self.preferences['fixed_length_option'] = index @listens('before_mode_sent') def __on_before_hardware_mode_sent(self, mode): self._suppress_sysex = False @listens('after_mode_sent') def __on_after_hardware_mode_sent(self, mode): if mode == sysex.USER_MODE: self._suppress_sysex = True @listens('mode') def __on_hardware_mode_changed(self, mode): if mode == sysex.USER_MODE: self._suppress_sysex = True self._update_auto_arm() @listens('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(self._user.mode == sysex.LIVE_MODE and (selected_mode or self._matrix_modes.selected_mode) == 'note') @listens('instrument') def __on_percussion_instrument_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, sliced_simpler = self._percussion_instruments_for_track(track) self._drum_component.set_drum_group_device(drum_device) self._slicing_component.set_simpler(sliced_simpler) 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' elif sliced_simpler: self._note_modes.selected_mode = 'slicing' else: self._note_modes.selected_mode = 'instrument' self.reset_controlled_track() def _percussion_instruments_for_track(self, track): self._percussion_instrument_finder.device_parent = track drum_device = self._percussion_instrument_finder.drum_group sliced_simpler = self._percussion_instrument_finder.sliced_simpler return (drum_device, sliced_simpler) def _setup_accidental_touch_prevention(self): self._accidental_touch_prevention_layer = BackgroundLayer('tempo_control_tap', 'swing_control_tap', 'master_volume_control_tap', priority=consts.MOMENTARY_DIALOG_PRIORITY) self.__on_param_encoder_touched.replace_subjects(self.elements.global_param_touch_buttons_raw) @listens_group('value') def __on_param_encoder_touched(self, value, encoder): """ When using the parameter encoders, other encoders around it are often accidentally touched and will take over the screen. By stealing the touch buttons from the encoders, we ensure they are not triggered while using any of the parameter encoders. """ if any(imap(lambda e: e.is_pressed(), self.elements.global_param_touch_buttons_raw)): self._accidental_touch_prevention_layer.grab(self) else: self._accidental_touch_prevention_layer.release(self) def get_matrix_button(self, column, row): return self.elements.matrix_rows_raw[7 - row][column] def expect_dialog(self, message): self.schedule_message(1, partial(self._dialog.expect_dialog, message)) def show_notification(self, message, blink_text = None, notification_time = None): return self._notification.show_notification(message, blink_text, notification_time) def process_midi_bytes(self, midi_bytes, midi_processor): if not midi.is_sysex(midi_bytes): recipient = self.get_recipient_for_nonsysex_midi_message(midi_bytes) if isinstance(recipient, ButtonElement) and midi.extract_value(midi_bytes) != 0 and self._notification is not None: self._notification.hide_notification() super(PushBase, self).process_midi_bytes(midi_bytes, midi_processor)
class MonoPedal(ControlSurface): def __init__(self, *a, **k): self.log_message = logger.warning super(MonoPedal, self).__init__(*a, **k) self._monomod_version = 'b996' 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) # logger.info('initializing debug...') # debug = initialize_debug() #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(is_momentary=True, msg_type=MIDI_CC_TYPE, channel=0, identifier=PEDAL_DEFS[index], name='Pedal_' + str(index), script=self)) self._pedal[index]._report = False self._pedal[7] = LoopPedalExpressionElement( script=self, msg_type=MIDI_CC_TYPE, channel=0, identifier=1, map_mode=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, is_momentary=True, msg_type=MIDI_NOTE_TYPE, channel=0, identifier=index + 13, name='LED_' + str(index), script=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 AumPush2(Push2): device_component_class = AumPush2DeviceComponent device_provider_class = ModDeviceProvider def __init__(self, c_instance, model): self._monomod_version = 'b996' self._cntrlr_version = 'b996' self._host_name = 'AumPush2' self._color_type = 'Push' self._auto_arm_calls = 0 self.log_message = logger.warning super(AumPush2, self).__init__(c_instance, model) with self.component_guard(): self._hack_stuff() #self._on_selected_track_changed.subject = self.song.view #self._on_main_mode_changed.subject = self._main_modes self.log_message('<<<<<<<<<<<<<<<<<<<<<<<< AumPush2 ' + str(self._monomod_version) + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>') def _create_components(self): self._remove_pedal() super(AumPush2, self)._create_components() #no idea why this is messing up the stock colors? def _create_skin(self): return self.register_disconnectable(make_default_skin()) def _setup_mod(self): def get_monomodular(host): if isinstance(__builtins__, dict): if not 'monomodular' in __builtins__.keys() or not isinstance(__builtins__['monomodular'], ModRouter): __builtins__['monomodular'] = ModRouter(song = self.song, register_component = self._register_component) else: if not hasattr(__builtins__, 'monomodular') or not isinstance(__builtins__['monomodular'], ModRouter): setattr(__builtins__, 'monomodular', ModRouter(song = self.song, register_component = self._register_component)) monomodular = __builtins__['monomodular'] if not monomodular.has_host(): monomodular.set_host(host) return monomodular self.monomodular = get_monomodular(self) self.monomodular.name = 'monomodular_switcher' with inject(register_component = const(self._register_component), song = const(self.song)).everywhere(): self.modhandler = PushModHandler(self) ## song = self.song, register_component = self._register_component) #debug('mod task group:', self.modhandler.parent_task_group) self.modhandler.name = 'ModHandler' self.modhandler.layer = Layer( priority = 6, lock_button = self.elements.note_mode_button, grid = self.elements.matrix, shift_button = self.elements.shift_button, alt_button = self.elements.select_button, nav_up_button = self.elements.octave_up_button, nav_down_button = self.elements.octave_down_button, nav_left_button = self.elements.in_button, nav_right_button = self.elements.out_button, key_buttons = self.elements.side_buttons, ) #self.modhandler.layer.priority = 0 self.modhandler.legacy_shift_layer = AddLayerMode( self.modhandler, Layer(priority = 7, device_selector_matrix = self.elements.matrix.submatrix[:, :1], channel_buttons = self.elements.matrix.submatrix[:, 1:2], nav_matrix = self.elements.matrix.submatrix[4:8, 2:6], )) self.modhandler.shift_layer = AddLayerMode( self.modhandler, Layer( priority = 7, device_selector_matrix = self.elements.matrix.submatrix[:, :1], )) #lock_button = self.elements.master_select_button, #)) self.modhandler.alt_layer = AddLayerMode( self.modhandler, Layer( priority = 7, )) #key_buttons = self.elements.select_buttons)) #key_buttons = self.elements.track_state_buttons)) self._device_provider.restart_mod() def _init_matrix_modes(self): super(AumPush2, self)._init_matrix_modes() #self._setup_monoinstrument() self._setup_mod() self._note_modes.add_mode('mod', [self.modhandler]) self._note_modes.add_mode('looperhack', [self._audio_loop]) def _create_device_component(self): return self.device_component_class(script = self, device_decorator_factory=self._device_decorator_factory, device_bank_registry=self._device_bank_registry, banking_info=self._banking_info, name='DeviceComponent', is_enabled=True, is_root=True) """ def _create_main_mixer_modes(self): self._mixer_control = MixerControlComponent(name='Global_Mix_Component', view_model=self._model.mixerView, tracks_provider=self._session_ring, is_enabled=False, layer=Layer(controls='fine_grain_param_controls', volume_button='track_state_buttons_raw[0]', panning_button='track_state_buttons_raw[1]', send_slot_one_button='track_state_buttons_raw[2]', send_slot_two_button='track_state_buttons_raw[3]', send_slot_three_button='track_state_buttons_raw[4]', send_slot_four_button='track_state_buttons_raw[5]', send_slot_five_button='track_state_buttons_raw[6]', cycle_sends_button='track_state_buttons_raw[7]')) self._model.mixerView.realtimeMeterData = self._mixer_control.real_time_meter_handlers track_mixer_control = TrollMixerControlComponent(script = self, name='Track_Mix_Component', is_enabled=False, tracks_provider=self._session_ring, layer=Layer(controls='fine_grain_param_controls', scroll_left_button='track_state_buttons_raw[6]', scroll_right_button='track_state_buttons_raw[7]')) self._track_mixer_control = track_mixer_control self._model.mixerView.trackControlView = track_mixer_control self._mix_modes = ModesComponent(is_enabled=False) self._mix_modes.add_mode('global', self._mixer_control) self._mix_modes.add_mode('track', track_mixer_control) self._mix_modes.selected_mode = 'global' self._model.mixerSelectView = self._mixer_control self._model.trackMixerSelectView = track_mixer_control class MixModeBehaviour(ReenterBehaviour): def press_immediate(behaviour_self, component, mode): if self._is_on_master() and self._mix_modes.selected_mode != 'track': self._mix_modes.selected_mode = 'track' super(MixModeBehaviour, behaviour_self).press_immediate(component, mode) def on_reenter(behaviour_self): if not self._is_on_master(): self._mix_modes.cycle_mode() self._main_modes.add_mode('mix', [self._mix_modes, tuple([self._check_track_mixer_entry, self._check_track_mixer_exit]), SetAttributeMode(obj=self._note_editor_settings_component, attribute='parameter_provider', value=self._track_parameter_provider)], behaviour=MixModeBehaviour()) """ def _create_main_mixer_modes(self): self._mixer_control = MixerControlComponent(name='Global_Mix_Component', view_model=self._model.mixerView, tracks_provider=self._session_ring, is_enabled=False, layer=Layer(controls='fine_grain_param_controls', volume_button='track_state_buttons_raw[0]', panning_button='track_state_buttons_raw[1]', send_slot_one_button='track_state_buttons_raw[2]', send_slot_two_button='track_state_buttons_raw[3]', send_slot_three_button='track_state_buttons_raw[4]', send_slot_four_button='track_state_buttons_raw[5]', send_slot_five_button='track_state_buttons_raw[6]', cycle_sends_button='track_state_buttons_raw[7]')) self._model.mixerView.realtimeMeterData = self._mixer_control.real_time_meter_handlers track_mixer_control = TrollMixerControlComponent(script = self, name='Track_Mix_Component', is_enabled=False, tracks_provider=self._session_ring, layer=Layer(controls='fine_grain_param_controls', scroll_left_button='track_state_buttons_raw[6]', scroll_right_button='track_state_buttons_raw[7]')) self._track_mixer_control = track_mixer_control #track_mixer_control = TrackMixerControlComponent(name='Track_Mix_Component', is_enabled=False, tracks_provider=self._session_ring, layer=Layer(controls='fine_grain_param_controls', scroll_left_button='track_state_buttons_raw[6]', scroll_right_button='track_state_buttons_raw[7]')) routing_control = RoutingControlComponent(is_enabled=False, layer=Layer(monitor_state_encoder='parameter_controls_raw[0]')) track_mix_or_routing_chooser = TrackOrRoutingControlChooserComponent(tracks_provider=self._session_ring, track_mixer_component=track_mixer_control, routing_control_component=routing_control, is_enabled=False, layer=Layer(mix_button='track_state_buttons_raw[0]', routing_button='track_state_buttons_raw[1]')) self._model.mixerView.trackControlView = track_mix_or_routing_chooser self._mix_modes = ModesComponent(is_enabled=False) self._mix_modes.add_mode('global', self._mixer_control) self._mix_modes.add_mode('track', track_mix_or_routing_chooser) self._mix_modes.selected_mode = 'global' self._model.mixerSelectView = self._mixer_control self._model.trackMixerSelectView = track_mixer_control class MixModeBehaviour(ReenterBehaviour): def press_immediate(behaviour_self, component, mode): if self._is_on_master() and self._mix_modes.selected_mode != 'track': self._mix_modes.selected_mode = 'track' super(MixModeBehaviour, behaviour_self).press_immediate(component, mode) def on_reenter(behaviour_self): if not self._is_on_master(): self._mix_modes.cycle_mode() self._main_modes.add_mode('mix', [self._mix_modes, SetAttributeMode(obj=self._note_editor_settings_component, attribute='parameter_provider', value=self._track_parameter_provider)], behaviour=MixModeBehaviour()) def _with_select(self, button): return ComboElement(button, [self.elements.select_button]) def _hack_stuff(self): self._crossfader_strip = TouchStripControllerComponent() self._crossfader_strip.layer = Layer(touch_strip = self.elements.touch_strip_control) self._crossfader_strip.set_enabled(False) self._device_selector = DeviceSelectorComponent(self) self._device_selector._off_value = 64 self._device_selector.layer = Layer(priority = 9, matrix = self.elements.matrix.submatrix[:, :4]) self._device_selector.set_enabled(False) self._send_reset = AumPushResetSendsComponent(self) self._send_reset.layer = Layer(priority = 9, send_a_button = self._with_select(self.elements.track_state_buttons_raw[4]), send_b_button = self._with_select(self.elements.track_state_buttons_raw[5]), send_c_button = self._with_select(self.elements.track_state_buttons_raw[6]), send_d_button = self._with_select(self.elements.track_state_buttons_raw[7])) self._send_reset.set_enabled(False) static_modes = CompoundMode(tuple([self._grab_crossfader, self._release_crossfader]), self._crossfader_strip, self._device_selector, self._send_reset) self._troll_modes = ModesComponent() self._troll_modes.add_mode('disabled', [], cycle_mode_button_color = 'DefaultButton.Off') self._troll_modes.add_mode('enabled', [static_modes, tuple([self._grab_track_mode, self._release_track_mode, ])], cycle_mode_button_color = 'DefaultButton.Alert') self._troll_modes.layer = Layer(priority = 6, cycle_mode_button = 'master_select_button') self._troll_modes.selected_mode = 'disabled' #self.schedule_message(5, self._remove_pedal) @listens('selected_mode') def _on_main_mode_changed(self, mode): debug('main_mode selected mode is now:', mode) #if self._troll_modes.selected_mode is 'enabled' and not mode is 'device': # self._troll_modes.selected_mode = 'disabled' def _init_main_modes(self): super(AumPush2, self)._init_main_modes() self._on_main_mode_changed.subject = self._main_modes def _grab_track_mode(self): debug('grab device mode') """self._main_modes.pop_unselected_modes() if not self._main_modes.selected_mode is 'device': self._main_modes.push_mode('device') self._device_component._update_parameters()""" self._track_mixer_control._mode_on_troll_entrance = self._mix_modes.selected_mode self._track_mixer_control._main_offset = self._track_mixer_control.scroll_offset self._track_mixer_control._scroll_offset = self._track_mixer_control._troll_offset if self._main_modes.selected_mode is 'mix': self._check_track_mixer_entry() def _release_track_mode(self): debug('release device mode') """if self._troll_modes.selected_mode is 'enabled': self._troll_modes.selected_mode = 'disabled' if len(self._main_modes.active_modes) > 1: self._main_modes.pop_mode('device') self._device_component._update_parameters()""" self._track_mixer_control._troll_offset = self._track_mixer_control.scroll_offset self._track_mixer_control._scroll_offset = self._track_mixer_control._main_offset if self._main_modes.selected_mode is 'mix': self._mix_modes.selected_mode = self._track_mixer_control._mode_on_troll_entrance if self._track_mixer_control._mode_on_troll_entrance is 'track': self._track_mixer_control.notify_scroll_offset() self._track_mixer_control.update() def _check_track_mixer_entry(self): debug('_check_track_mixer_entry') if self._troll_modes.selected_mode is 'enabled': if not self._mix_modes.selected_mode is 'track': self._mix_modes.push_mode('track') self._track_mixer_control.notify_scroll_offset() self._track_mixer_control.update() def _check_track_mixer_exit(self): debug('_check_track_mixer_exit') def _disable_troll(self): #self._troll_modes.selected_mode = 'disabled' debug('disable troll') def _init_mute_solo_stop(self): super(AumPush2, self)._init_mute_solo_stop() self._master_selector.layer = Layer(toggle_button=self._with_select('master_select_button')) def _grab_crossfader(self): self._crossfader_strip.set_parameter(self.song.master_track.mixer_device.crossfader) def _release_crossfader(self): self._crossfader_strip.set_parameter(None) def _remove_pedal(self): #self.real_foot_pedal_button = self.elements.foot_pedal_button self.elements.foot_pedal_button = DoublePressElement(create_button(127, name = 'Foot_Pedal', skin = self._skin, is_rgb=True)) for control in self.controls: if isinstance(control, ConfigurableButtonElement) and control._original_identifier is 69: self.log_message('found control: ' + str(control)) self.controls.remove(control) break self.request_rebuild_midi_map() """ @listens('device') def _on_device_changed(self): debug('_on_device_changed') #self.schedule_message(1, self._select_note_mode) #self._select_note_mode() @listens('selected_track') def _on_selected_track_changed(self): #if self._troll_modes.selected_mode is 'enabled': # self._device_component._update_parameters() pass """ def _select_note_mode(self, mod_device = None): track = self.song.view.selected_track drum_device, sliced_simpler = self._percussion_instruments_for_track(track) self._drum_component.set_drum_group_device(drum_device) self._slicing_component.set_simpler(sliced_simpler) debug('select_note_mode: ', self.modhandler.is_locked(), self.modhandler.active_mod(), len(track.devices)) if not (self._note_modes.selected_mode is 'mod' and self.modhandler.is_locked()): 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 self.modhandler.active_mod(): self._note_modes.selected_mode = 'mod' elif track and track.has_audio_input: self._note_modes.selected_mode = 'looperhack' elif drum_device: self._note_modes.selected_mode = 'drums' elif sliced_simpler: self._note_modes.selected_mode = 'slicing' else: self._note_modes.selected_mode = 'instrument' self.reset_controlled_track() def disconnect(self): self.log_message('<<<<<<<<<<<<<<<<<<<<<<<< AumPush2 ' + str(self._monomod_version) + ' log closed >>>>>>>>>>>>>>>>>>>>>>>>') super(AumPush2, self).disconnect() def _can_auto_arm_track(self, track): routing = track.current_input_routing return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith('AumPush2')
class OhmModes(LividControlSurface): _sysex_id = 2 _alt_sysex_id = 7 _model_name = 'Ohm' _version_check = 'b996' _host_name = 'Ohm' device_provider_class = ModDeviceProvider def __init__(self, c_instance): super(OhmModes, self).__init__(c_instance) self._skin = Skin(OhmColors) with self.component_guard(): self._define_sysex() self._setup_controls() self._setup_background() self._setup_m4l_interface() self._setup_translations() self._setup_session_control() self._setup_mixer_control() self._setup_device_control() self._setup_transport_control() self._setup_drumgroup() self._setup_keygroup() self._setup_bassgroup() self._setup_mod() self._setup_modswitcher() self._setup_modes() self._on_device_changed.subject = self._device_provider def _define_sysex(self): #self._send_midi(tuple(switchxfader)) self._reverse_crossfader = SendLividSysexMode( self._livid_settings, call='reverse crossfader', message=[1]) def update_display(self): super(OhmModes, self).update_display() #self.strobe() def _initialize_hardware(self): super(OhmModes, self)._initialize_hardware() #self._reverse_crossfader.enter_mode() def _initialize_script(self): super(OhmModes, self)._initialize_script() self._main_modes.selected_mode = 'Mix' self._session.update() self._mixer.update() def _setup_controls(self): is_momentary = True optimized = True resource = PrioritizedResource self._fader = [ MonoEncoderElement(msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=OHM_FADERS[index], name='Fader_' + str(index), num=index, script=self, optimized_send_midi=optimized, resource_type=resource) for index in range(8) ] self._button = [ MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=OHM_BUTTONS[index], name='Button_' + str(index), script=self, skin=self._skin, optimized_send_midi=optimized, resource_type=resource) for index in range(8) ] self._dial = [ MonoEncoderElement(msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=OHM_DIALS[index], name='Encoder_' + str(index), num=index, script=self, optimized_send_midi=optimized, resource_type=resource) for index in range(16) ] self._menu = [ MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=OHM_MENU[index], name='Menu_' + str(index), script=self, skin=self._skin, optimized_send_midi=optimized, resource_type=resource) for index in range(6) ] self._crossfader = MonoEncoderElement(msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=CROSSFADER, name='Crossfader', script=self, optimized_send_midi=optimized, resource_type=resource) self._livid = MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=LIVID, name='Livid_Button', skin=self._skin, script=self, optimized_send_midi=optimized, resource_type=resource) self._shift_l = MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=SHIFT_L, name='Page_Button_Left', script=self, skin=self._skin, optimized_send_midi=optimized, resource_type=resource) self._shift_r = MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=SHIFT_R, name='Page_Button_Right', script=self, skin=self._skin, optimized_send_midi=optimized, resource_type=resource) self._grid = [[ MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=column * 8 + row, name='Grid_' + str(column + (row * 8)), script=self, skin=self._skin, optimized_send_midi=optimized, resource_type=resource) for column in range(8) ] for row in range(8)] self._matrix = ButtonMatrixElement( name='Matrix', rows=[[self._grid[row][column] for column in range(8)] for row in range(8)]) self._dial_matrix = ButtonMatrixElement( name='DialMatrix', rows=[self._dial[index * 4:(index * 4) + 4] for index in range(4)]) self._menu_matrix = ButtonMatrixElement(name='MenuMatrix', rows=[self._menu]) self._fader_matrix = ButtonMatrixElement(name='FaderMatrix', rows=[self._fader]) self._button_matrix = ButtonMatrixElement(name='ButtonMatrix', rows=[self._button]) self._parameter_controls = ButtonMatrixElement( rows=[self._dial[:4], self._dial[4:8]]) def _setup_background(self): self._background = BackgroundComponent(name='Background') self._background.layer = Layer( priority=3, matrix=self._matrix.submatrix[:, :], livid_button=self._livid, shift_l_button=self._shift_l, shift_r_button=self._shift_r, crossfader=self._crossfader, dial_matrix=self._dial_matrix.submatrix[:, :], menu_matrix=self._menu_matrix.submatrix[:, :], fader_matrix=self._fader_matrix.submatrix[:, :], button_matrix=self._button_matrix.submatrix[:, :]) self._background.set_enabled(False) def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent( controls=self.controls, component_guard=self.component_guard) self.get_control_names = self._m4l_interface.get_control_names self.get_control = self._m4l_interface.get_control self.grab_control = self._m4l_interface.grab_control self.release_control = self._m4l_interface.release_control def _setup_translations(self): controls = [] for array in self._grid: for button in array: controls.append(button) if FADER_BANKING: controls = controls + self._dial if DIAL_BANKING: controls = controls + self._dial self._translations = TranslationComponent( controls=controls, user_channel_offset=USER_CHANNEL, channel=8) self._translations.layer = Layer( priority=5, channel_selector_buttons=self._menu_matrix.submatrix[:, :]) self._translations.set_enabled(False) dj_controls = [self._grid[7][index] for index in range(7)] self._dj_translation = TranslationComponent(controls=dj_controls, channel=12) def _setup_session_control(self): self._session_ring = SessionRingComponent(num_tracks=7, num_scenes=5) self._session_ring.set_enabled(True) self._session_navigation = SessionNavigationComponent( session_ring=self._session_ring) self._session_navigation.scroll_navigation_layer = AddLayerMode( self._session_navigation, Layer(priority=5, up_button=self._menu[2], down_button=self._menu[5], left_button=self._menu[3], right_button=self._menu[4])) self._session_navigation.page_navigation_layer = AddLayerMode( self._session_navigation, Layer(priority=5, page_up_button=self._menu[2], page_down_button=self._menu[5], page_left_button=self._menu[3], page_right_button=self._menu[4])) self._session_navigation._vertical_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._vertical_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation.set_enabled(False) self._session = OhmSessionComponent(name='Session', session_ring=self._session_ring, auto_name=True) hasattr(self._session, '_enable_skinning') and self._session._enable_skinning() self._session.set_enabled(False) self._session.clip_launch_layer = AddLayerMode( self._session, Layer(priority=5, clip_launch_buttons=self._matrix.submatrix[:7, :5])) self._session.scene_launch_layer = AddLayerMode( self._session, Layer(priority=5, scene_launch_buttons=self._matrix.submatrix[7, :5])) self._session_zoom = SessionOverviewComponent( name='Session_Overview', session_ring=self._session_ring, enable_skinning=True) self._session_zoom.layer = Layer( priority=5, button_matrix=self._matrix.submatrix[:7, :5]) self._session_zoom.set_enabled(False) self._session_modes = ModesComponent(name='Session_Modes') self._session_modes.add_mode('disabled', [ self._session, self._session.clip_launch_layer, self._session.scene_launch_layer, self._session_navigation, self._session_navigation.scroll_navigation_layer ]) self._session_modes.add_mode('enabled', [ self._session, self._session.scene_launch_layer, self._session_zoom, self._session_navigation, self._session_navigation.page_navigation_layer ], behaviour=DefaultedBehaviour()) self._session_modes.layer = Layer(priority=5, enabled_button=self._grid[7][7]) self._session_modes.selected_mode = 'disabled' self._session_modes.set_enabled(False) def _setup_mixer_control(self): self._mixer = OhmMixerComponent(name='Mixer', tracks_provider=self._session_ring, track_assigner=simple_track_assigner, invert_mute_feedback=True, auto_name=True, enable_skinning=True) self._mixer.layer = Layer( priority=5, volume_controls=self._fader_matrix.submatrix[:7, :], prehear_volume_control=self._dial[15], crossfader_control=self._crossfader) self._mixer.master_strip().layer = Layer(priority=5, volume_control=self._fader[7], select_button=self._button[7]) self._mixer.mix_layer = AddLayerMode( self._mixer, Layer( priority=5, mute_buttons=self._matrix.submatrix[:7, 5], solo_buttons=self._matrix.submatrix[:7, 6], arm_buttons=self._matrix.submatrix[:7, 7], send_controls=self._dial_matrix.submatrix[:, :2], pan_controls=self._dial_matrix.submatrix[:7, 2:], track_select_buttons=self._button_matrix.submatrix[:7, :], )) self._mixer.dj_layer = AddLayerMode( self._mixer, Layer( priority=5, mute_buttons=self._matrix.submatrix[:7, 5], crossfade_toggles=self._matrix.submatrix[:7, 6], end_pan_controls=self._dial_matrix.submatrix[:3, 3], eq_gain_controls=self._dial_matrix.submatrix[:, :3], track_select_buttons=self._button_matrix.submatrix[:7, :], )) self._mixer.instrument_layer = AddLayerMode( self._mixer, Layer(priority=5, instrument_send_controls=self._dial_matrix.submatrix[:, 2:], arming_track_select_buttons=self._button_matrix. submatrix[:7, :])) def _setup_device_control(self): self._device = OhmDeviceComponent( script=self, name='Device_Component', device_provider=self._device_provider, device_bank_registry=DeviceBankRegistry()) self._device.layer = Layer(priority=5, parameter_controls=self._parameter_controls) self._device.set_enabled(False) self._device_navigator = DeviceNavigator( self._device_provider, self._mixer, self, name='Device_Navigator', ) self._device_navigator.layer = Layer(priority=5, prev_button=self._menu[3], next_button=self._menu[4]) self._device_navigator.set_enabled(False) def _setup_transport_control(self): self._transport = OhmTransportComponent() self._transport.name = 'Transport' self._transport.layer = Layer(priority=5, play_button=self._menu[0], stop_button=self._menu[1]) self._transport.set_enabled(False) def _setup_drumgroup(self): self._drumgroup = MonoDrumGroupComponent( translation_channel=PAGE1_DRUM_CHANNEL, set_pad_translations=self.set_pad_translations) self._drumgroup._on_selected_track_changed.subject = None self._drumgroup.translation_channel = PAGE1_DRUM_CHANNEL self._drumgroup.layer = Layer(priority=6, matrix=self._matrix.submatrix[:4, :4]) self._drumgroup.set_enabled(False) def _setup_keygroup(self): self._scale_mode = ModesComponent(name='ScaleMode') for scale in SCALES: debug('making scale mode:', scale, str(scale)) self._scale_mode.add_mode(str(scale), []) self._scale_mode.layer = Layer(priority=5, ionian_button=self._grid[7][0], dorian_button=self._grid[7][1], phrygian_button=self._grid[7][2], lydian_button=self._grid[7][3], mixolydian_button=self._grid[7][4], aeolian_button=self._grid[7][5], locrian_button=self._grid[7][6], major_button=self._grid[7][7]) self._scale_mode.selected_mode = 'ionian' self._scale_mode.set_enabled(False) self._on_scale_change.subject = self._scale_mode self._octave_offset_component = ScrollingChannelizedSettingsComponent( name='NoteOffset', parent_task_group=self._task_group, value_dict=range(104), default_value_index=36, default_channel=0, bank_increment=12, bank_on_color='MonoInstrument.OffsetOnValue', bank_off_color='MonoInstrument.OffsetOffValue') self._octave_offset_component.layer = Layer( priority=5, bank_up_button=self._menu[2], bank_down_button=self._menu[5]) self._on_octave_change.subject = self._octave_offset_component self._keygroup = OhmKeyGroupComponent() self._keygroup._on_selected_track_changed.subject = None self._keygroup.translation_channel = PAGE1_KEYS_CHANNEL self._keygroup.layer = Layer(priority=6, matrix=self._matrix.submatrix[:, 4:7]) self._keygroup.set_enabled(False) def _setup_bassgroup(self): self._bassgroup = OhmBassGroupComponent() self._bassgroup._on_selected_track_changed.subject = None self._bassgroup.translation_channel = PAGE1_BASS_CHANNEL self._bassgroup.layer = Layer(priority=6, matrix=self._matrix.submatrix[4:, :4]) self._bassgroup.set_enabled(False) def _setup_mod(self): self.monomodular = get_monomodular(self) self.monomodular.name = 'monomodular_switcher' self.modhandler = OhmModHandler(script=self, device_provider=self._device_provider) self.modhandler.name = 'ModHandler' self.modhandler.layer = Layer( priority=5, grid=self._matrix.submatrix[:, :], nav_up_button=self._menu[2], nav_down_button=self._menu[5], nav_left_button=self._menu[3], nav_right_button=self._menu[4], shift_button=self._menu[1], alt_button=self._menu[0], ) #parameter_controls = self._dial_matrix) self.modhandler.legacy_shift_mode = AddLayerMode( self.modhandler, Layer(priority=6, channel_buttons=self._matrix.submatrix[:, 1], nav_matrix=self._matrix.submatrix[4:8, 2:6])) self.modhandler.shift_mode = AddLayerMode( self.modhandler, Layer(priority=6, device_selector_matrix=self._matrix.submatrix[:, 0], lock_button=self._livid, key_buttons=self._matrix.submatrix[:, 7])) self.modhandler.set_enabled(False) self.modhandler.set_mod_button(self._livid) def _setup_modswitcher(self): self._modswitcher = ModesComponent(name='ModSwitcher') self._modswitcher.add_mode('mod', [ self.modhandler, self._device, DelayMode(self.modhandler.update, delay=.5) ]) self._modswitcher.add_mode('translations', [self._translations]) self._modswitcher.selected_mode = 'translations' self._modswitcher.set_enabled(False) def _setup_modes(self): self._main_modes = ModesComponent(name='MainModes') self._main_modes.add_mode('disabled', [self._background]) self._main_modes.add_mode('Mix', [ self._session_modes, self._mixer, self._mixer.mix_layer, self._transport ]) self._main_modes.add_mode( 'DJ', [ self._session_modes, self._mixer, self._mixer.dj_layer, self._dj_translation, tuple([self._assign_tempo, self._deassign_tempo]) ], behaviour=DefaultedBehaviour(default_mode='Mix')) #tuple([ lambda:self._set_tempo_buttons([self._grid[7][5], self._grid[7][6]]), self._set_tempo_buttons([])])], self._main_modes.add_mode( 'Instrument', [ self._update_keygroup_colors, self._bassgroup, self._keygroup, self._scale_mode, self._octave_offset_component, self._device, self._device_navigator, self._mixer, self._mixer.instrument_layer, self._drumgroup ], behaviour=DefaultedBehaviour(default_mode='Mix')) self._main_modes.add_mode( 'Mod', [ self._modswitcher, self._device, self._mixer, self._mixer.instrument_layer ], behaviour=DefaultedBehaviour(default_mode='Mix')) self._main_modes.layer = Layer(priority=5, Instrument_button=self._shift_l, DJ_button=self._shift_r, Mod_button=self._livid) self._main_modes.selected_mode = 'disabled' self._main_modes.set_enabled(True) def disconnect(self): super(OhmModes, self).disconnect() def strobe(self): if self._backlight_type != 'static': if self._backlight_type is 'pulse': self._backlight = int( math.fabs(self._timer * 16 % 64 - 32) + 32) if self._backlight_type is 'up': self._backlight = int(self._timer * 8 % 64 + 16) if self._backlight_type is 'down': self._backlight = int( math.fabs(int(self._timer * 8 % 64 - 64)) + 16) self._send_midi(tuple([176, 27, int(self._backlight)])) if self._ohm_type != 'static': if self._ohm_type is 'pulse': self._ohm = int(math.fabs(self._timer * 16 % 64 - 32) + 32) if self._ohm_type is 'up': self._ohm = int(self._timer * 8 % 64 + 16) if self._ohm_type is 'down': self._ohm = int(math.fabs(int(self._timer * 8 % 64 - 64)) + 16) self._send_midi(tuple([176, 63, int(self._ohm)])) self._send_midi(tuple([176, 31, int(self._ohm)])) def handle_sysex(self, midi_bytes): debug('sysex: ', str(midi_bytes)) if len(midi_bytes) > 14: if midi_bytes[:6] == tuple([240, 0, 1, 97, 12, 64]): self._register_pad_pressed(midi_bytes[6:14]) elif midi_bytes[:6] == tuple([240, 0, 1, 97, 17, 64]): self._register_pad_pressed(midi_bytes[6:14]) elif midi_bytes[3:11] == tuple( [6, 2, 0, 1, 97, 1, 0] + [self._sysex_id]) or midi_bytes[3:11] == tuple( [6, 2, 0, 1, 97, 1, 0] + [self._alt_sysex_id]): if not self._connected: #self._connection_routine.kill() self._connected = True self._livid_settings.set_model(midi_bytes[11]) self._initialize_hardware() self.schedule_message(1, self._initialize_script) @listens('device') def _on_device_changed(self): self.schedule_message(1, self._update_modswitcher) #debug('base on_device_changed') self._update_modswitcher() def _on_selected_track_changed(self): super(OhmModes, self)._on_selected_track_changed() if not len(self.song.view.selected_track.devices): self._update_modswitcher() def _update_modswitcher(self): debug('update modswitcher, mod is:', self.modhandler.active_mod()) if self.modhandler.active_mod(): self._modswitcher.selected_mode = 'mod' else: self._modswitcher.selected_mode = 'translations' @listens('selected_mode') def _on_scale_change(self, mode): debug('new scale is:', mode, self._scale_mode.selected_mode) self._keygroup.scale = SCALES.index(self._scale_mode.selected_mode) @listens('value') def _on_octave_change(self, value): self._keygroup.offset = value #stupid hack....4 hours wasted on two buttons is too long, so we're doing this instead def _update_keygroup_colors(self): self._grid[5][7].send_value(2, force=True) self._grid[6][7].send_value(2, force=True) #everything below needs to be consolidated into transport component def _assign_tempo(self): self._grid[5][7].send_value(4, True) self._grid[6][7].send_value(4, True) self._tempo_up_value.subject = self._grid[5][7] self._tempo_down_value.subject = self._grid[6][7] def _deassign_tempo(self): self._tempo_up_value.subject and self._tempo_up_value.subject.turn_off( ) self._tempo_down_value.subject and self._tempo_down_value.subject.turn_off( ) self._tempo_up_value.subject = None self._tempo_down_value.subject = None @listens('value') def _tempo_up_value(self, value): if value: self.song.tempo = round(min(self.song.tempo + 1, 999)) @listens('value') def _tempo_down_value(self, value): if value: self.song.tempo = round(max(self.song.tempo - 1, 20))
class Push2(IdentifiableControlSurface, PushBase): session_component_type = SessionComponent drum_group_note_editor_skin = 'DrumGroupNoteEditor' input_target_name_for_auto_arm = 'Push2 Input' RESEND_MODEL_DATA_TIMEOUT = 5.0 def __init__(self, c_instance = None, model = None, *a, **k): raise model is not None or AssertionError self._model = model self._double_click_context = DoubleClickContext() self._real_time_mapper = c_instance.real_time_mapper self._device_decorator_factory = DeviceDecoratorFactory() self._clip_decorator_factory = ClipDecoratorFactory() self._real_time_data_list = [] super(Push2, self).__init__(c_instance=c_instance, product_id_bytes=sysex.IDENTITY_RESPONSE_PRODUCT_ID_BYTES, *a, **k) self._board_revision = 0 self._firmware_version = FirmwareVersion(0, 0, 0) self._real_time_client = RealTimeClientModel() self._connected = False self._identified = False self._initialized = False self.register_disconnectable(model) self.register_disconnectable(self._device_decorator_factory) with self.component_guard(): self._model.realTimeClient = self._real_time_client self._real_time_client.clientId = self._real_time_mapper.client_id logger.info('Push 2 script loaded') def initialize(self): if not self._initialized: self._initialized = True self._init_hardware_settings() self._init_pad_curve() self._hardware_settings.fade_in_led_brightness(self._setup_settings.hardware.led_brightness) self._pad_curve_sender.send() self._send_color_palette() super(Push2, self).initialize() self.__on_selected_track_frozen_changed.subject = self.song.view self.__on_selected_track_frozen_changed() self._switch_to_live_mode() self._user.defer_sysex_sending = True self.update() if self._firmware_update.provided_version > self._firmware_version and self._board_revision > 0 and self._identified: self._firmware_update.start() def _try_initialize(self): if self._connected and self._identified: self.initialize() def on_process_state_changed(self, state): StateEnum = MidiRemoteScript.Push2ProcessState self._connected = state == StateEnum.connected if state == StateEnum.died: self._c_instance.launch_external_process() if state == StateEnum.connected: with self.component_guard(): self._try_initialize() self._model.commit_changes(send_all=True) def on_user_data_arrived(self, message): if self._initialized: data = json.loads(message) self._process_qml_errors(data) self._firmware_update.process_firmware_response(data) def _process_qml_errors(self, data): qmlerrors = [ entry['description'] for entry in data if entry['type'] == 'qmlerror' ] if qmlerrors: raise QmlError('\n'.join(qmlerrors)) def disconnect(self): self.__on_before_push_mode_sent.subject = None super(Push2, self).disconnect() self.__dict__.clear() logger.info('Push 2 script unloaded') def register_real_time_data(self, real_time_data): self._real_time_data_list.append(real_time_data) def _commit_real_time_data_changes(self): for d in self._real_time_data_list: d.update_attachment() def _create_skin(self): return self.register_disconnectable(make_default_skin()) def _create_injector(self): return inject(double_press_context=const(self._double_press_context), double_click_context=const(self._double_click_context), expect_dialog=const(self.expect_dialog), show_notification=const(self.show_notification), commit_model_changes=const(self._model.commit_changes), register_real_time_data=const(self.register_real_time_data), selection=lambda : PushSelection(application=self.application(), device_component=self._device_component, navigation_component=self._device_navigation)) def _create_components(self): self._init_dialog_modes() super(Push2, self)._create_components() self._init_browser() self._init_session_ring_selection_linking() self._init_setup_component() self._init_firmware_update() self._init_convert_enabler() @contextmanager def _component_guard(self): with super(Push2, self)._component_guard(): with inject(real_time_mapper=const(self._c_instance.real_time_mapper)).everywhere(): yield self._commit_real_time_data_changes() self._model.commit_changes() def _create_notification_component(self): notification = NotificationComponent(is_root=True) self._model.notificationView = notification return notification def _create_background_layer(self): return super(Push2, self)._create_background_layer() + Layer(mix_button='mix_button', page_left_button='page_left_button', page_right_button='page_right_button', mute_button='global_mute_button', solo_button='global_solo_button', track_stop_button='global_track_stop_button', convert_button='convert_button', layout_button='layout_button', setup_button='setup_button') def _create_message_box_background_layer(self): return super(Push2, self)._create_message_box_background_layer() + BackgroundLayer('mix_button', 'page_left_button', 'page_right_button', 'convert_button', 'layout_button', 'setup_button') def _create_message_box_layer(self): return Layer(cancel_button='track_state_buttons_raw[0]', priority=consts.MESSAGE_BOX_PRIORITY) def _init_message_box(self): super(Push2, self)._init_message_box() self._model.liveDialogView = self._dialog._message_box def _create_mixer(self): return MixerComponent(is_root=True, tracks_provider=self._session_ring, solo_layer=Layer(solo_buttons='select_buttons'), mute_layer=Layer(mute_buttons='select_buttons')) def _create_convert(self): convert = ConvertComponent(decorator_factory=self._device_decorator_factory, name='Convert', tracks_provider=self._session_ring, is_enabled=False, layer=make_dialog_layer(action_buttons='select_buttons', cancel_button='track_state_buttons_raw[0]')) self.__on_convert_closed.subject = convert self._model.convertView = convert return convert def _init_note_settings_component(self): self._note_settings_component = NoteSettingsComponent(grid_resolution=self._grid_resolution, is_enabled=False, layer=Layer(full_velocity_button='accent_button', priority=consts.MOMENTARY_DIALOG_PRIORITY)) self._model.noteSettingsView = self._note_settings_component def _init_note_editor_settings_component(self): super(Push2, self)._init_note_editor_settings_component() self._model.stepSettingsView = self._note_editor_settings_component.step_settings def _init_automation_component(self): self._automation_component = AutomationComponent() self._model.stepAutomationSettingsView = self._automation_component def _init_convert_enabler(self): self._convert_enabler = ConvertEnabler(is_root=True, is_enabled=True, enter_dialog_mode=self._enter_dialog_mode, exit_dialog_mode=self._exit_dialog_mode) self._convert_enabler.layer = Layer(convert_toggle_button='convert_button') @listens('cancel') def __on_convert_closed(self): self._dialog_modes.selected_mode = None def _init_main_modes(self): super(Push2, self)._init_main_modes() self._main_modes.add_mode('user', [self._user_mode_ui_blocker]) self._model.modeState = self.register_disconnectable(ModeCollector(main_modes=self._main_modes, mix_modes=self._mix_modes, global_mix_modes=self._mixer_control, device_modes=self._device_navigation.modes)) self.__on_main_mode_button_value.replace_subjects([self.elements.vol_mix_mode_button, self.elements.pan_send_mix_mode_button, self.elements.single_track_mix_mode_button, self.elements.clip_mode_button, self.elements.device_mode_button, self.elements.browse_mode_button, self.elements.create_device_button, self.elements.create_track_button]) @listens_group('value') def __on_main_mode_button_value(self, value, sender): if not value: self._exit_modal_modes() def _exit_modal_modes(self): self._dialog_modes.selected_mode = None self._setup_enabler.selected_mode = 'disabled' def _create_capture_and_insert_scene_component(self): return CaptureAndInsertSceneComponent(name='Capture_And_Insert_Scene', decorator_factory=self._clip_decorator_factory, is_root=True) def _init_stop_clips_action(self): stop_clips_buttons = ButtonMatrixElement(rows=[wrap_button('select_buttons_raw', 'global_track_stop_button')]) self._stop_clips = StopClipComponent(session_ring=self._session_ring, name='Stop_Clip', is_root=True) self._stop_clips.layer = Layer(stop_all_clips_button=self._with_shift('global_track_stop_button'), stop_selected_track_clip_button='global_track_stop_button', stop_track_clips_buttons=stop_clips_buttons) def _init_mixer(self): self._mixer = self._create_mixer() self._mixer.add_mode('stop', self._stop_clips) self._mixer.stop_button.mode_unselected_color = 'DefaultButton.On' self._mixer.layer = Layer(solo_track_button='global_solo_button', mute_track_button='global_mute_button', stop_button='global_track_stop_button') self._mixer_solo_layer = self._create_mixer_solo_layer() self._mixer_mute_layer = self._create_mixer_mute_layer() self._mixer.master_strip().name = 'Master_Channel_strip' self._master_selector = MasterTrackComponent(tracks_provider=self._session_ring, is_enabled=False, layer=Layer(toggle_button='master_select_button')) self._master_selector.set_enabled(True) self._model.mixerButtonState = self._mixer.mixer_button_state self._mixer.set_enabled(True) def _create_instrument_layer(self): return super(Push2, self)._create_instrument_layer() + Layer(prev_loop_page_button='page_left_button', next_loop_page_button='page_right_button') def _create_step_sequencer_layer(self): return super(Push2, self)._create_step_sequencer_layer() + Layer(prev_loop_page_button='page_left_button', next_loop_page_button='page_right_button') def _create_session(self): session = super(Push2, self)._create_session() for scene_ix in xrange(8): scene = session.scene(scene_ix) for track_ix in xrange(8): clip_slot = scene.clip_slot(track_ix) clip_slot.set_decorator_factory(self._clip_decorator_factory) return session def _create_session_navigation_layer(self): return Layer(left_button='nav_left_button', right_button='nav_right_button', up_button='nav_up_button', down_button='nav_down_button', page_left_button='page_left_button', page_right_button='page_right_button', page_up_button='octave_up_button', page_down_button='octave_down_button') def on_select_clip_slot(self, clip_slot): self.show_notification('Clip Selected: ' + select_clip_and_get_name_from_slot(clip_slot, self.song)) def on_select_scene(self, scene): self.show_notification('Scene Selected: ' + select_scene_and_get_name(scene, self.song)) def _create_session_mode(self): session_modes = ModesComponent(is_enabled=False) session_modes.add_mode('session', self._session_mode) session_modes.add_mode('overview', self._session_overview_mode) session_modes.layer = Layer(cycle_mode_button='layout_button') session_modes.selected_mode = 'session' return [session_modes, self._session_navigation] def _create_session_overview_layer(self): return Layer(button_matrix='matrix') def _create_drum_component(self): return DrumGroupComponent(name='Drum_Group', is_enabled=False, notification_formatter=self._drum_pad_notification_formatter(), tracks_provider=self._session_ring, device_decorator_factory=self._device_decorator_factory, quantizer=self._quantize) def _create_device_mode(self): self._drum_pad_parameter_component = DrumPadParameterComponent(view_model=self._model, is_enabled=False, layer=Layer(choke_encoder='parameter_controls_raw[0]')) self._device_or_pad_parameter_chooser = ModesComponent() self._device_or_pad_parameter_chooser.add_mode('device', [make_freeze_aware(self._device_parameter_component, self._device_parameter_component.layer), self._device_view]) self._device_or_pad_parameter_chooser.add_mode('drum_pad', [make_freeze_aware(self._drum_pad_parameter_component, self._drum_pad_parameter_component.layer)]) self._device_or_pad_parameter_chooser.selected_mode = 'device' return [partial(self._view_control.show_view, 'Detail/DeviceChain'), self._device_or_pad_parameter_chooser, make_freeze_aware(self._device_enabling, self._device_enabling.layer), self._setup_freeze_aware_device_navigation(), self._device_note_editor_mode, SetAttributeMode(obj=self._note_editor_settings_component, attribute='parameter_provider', value=self._device_component)] def _setup_freeze_aware_device_navigation(self): def create_layer_setter(layer_name, layer): return SetAttributeMode(obj=self._device_navigation, attribute=layer_name, value=layer) return make_freeze_aware(self._device_navigation, self._device_navigation.layer, default_mode_extras=[create_layer_setter('scroll_right_layer', Layer(button=self.elements.track_state_buttons_raw[-1])), create_layer_setter('scroll_left_layer', Layer(button=self.elements.track_state_buttons_raw[0]))], frozen_mode_extras=[lambda : setattr(self._device_navigation.modes, 'selected_mode', 'default'), create_layer_setter('scroll_right_layer', Layer()), create_layer_setter('scroll_left_layer', Layer())]) @listens('drum_pad_selection') def __on_drum_pad_selection_changed(self): if self._device_navigation.is_drum_pad_selected: show_pad_parameters = self._device_navigation.is_drum_pad_unfolded new_mode = 'drum_pad' if show_pad_parameters else 'device' selected_pad = show_pad_parameters and self._device_navigation.item_provider.selected_item self._drum_pad_parameter_component.drum_pad = selected_pad self._device_or_pad_parameter_chooser.selected_mode = new_mode self._automation_component.set_drum_pad_selected(self._device_navigation.is_drum_pad_selected) def _init_browser(self): class BrowserMode(LazyComponentMode, Disconnectable): def __init__(self, model = None, *a, **k): raise model is not None or AssertionError super(BrowserMode, self).__init__(*a, **k) self._model = model def enter_mode(self): self._model.browserView = self.component self._model.browserData = self.component super(BrowserMode, self).enter_mode() def disconnect(self): super(BrowserMode, self).disconnect() self._model = None self._browser_mode = BrowserMode(self._model, self._create_browser) self._new_track_browser_mode = BrowserMode(self._model, self._create_new_track_browser) self.register_disconnectable(self._browser_mode) self.register_disconnectable(self._new_track_browser_mode) def _init_browse_mode(self): class BrowserModeBehaviour(ModeButtonBehaviour): def press_immediate(self, component, mode): if mode == component.selected_mode: component.selected_mode = component.active_modes[0] else: component.push_mode(mode) browser = Live.Application.get_application().browser def clear_hotswap_target(): browser.hotswap_target = None def select_filter_type_for_track(): has_midi_support = self.song.view.selected_track.has_midi_input browser.filter_type = Live.Browser.FilterType.midi_track_devices if has_midi_support else Live.Browser.FilterType.audio_effect_hotswap def select_filter_type_for_hotswapping(): if liveobj_valid(browser.hotswap_target): browser.filter_type = Live.Browser.FilterType.disabled else: select_filter_type_for_track() self._main_modes.add_mode('browse', [BrowserHotswapMode(application=self.application()), select_filter_type_for_hotswapping, self._browser_mode], behaviour=BrowserModeBehaviour()) self._main_modes.add_mode('add_device', [clear_hotswap_target, select_filter_type_for_track, self._browser_mode], behaviour=BrowserModeBehaviour()) self._main_modes.add_mode('add_track', [clear_hotswap_target, self._new_track_browser_mode], behaviour=BrowserModeBehaviour()) def _create_browser_layer(self): return Layer(up_button='nav_up_button', down_button='nav_down_button', right_button='nav_right_button', left_button='nav_left_button', back_button='track_state_buttons_raw[-2]', open_button='track_state_buttons_raw[-1]', load_button='select_buttons_raw[-1]', scroll_encoders=self.elements.global_param_controls.submatrix[:-1, :], scroll_focused_encoder='parameter_controls_raw[-1]', close_button='track_state_buttons_raw[0]', prehear_button='track_state_buttons_raw[1]') def _create_browser(self): browser = BrowserComponent(name='Browser', is_enabled=False, preferences=self.preferences, layer=self._create_browser_layer()) self._on_browser_loaded.add_subject(browser) self._on_browser_closed.add_subject(browser) return browser def _create_new_track_browser(self): browser = NewTrackBrowserComponent(name='NewTrackBrowser', is_enabled=False, preferences=self.preferences, layer=self._create_browser_layer()) self._on_browser_loaded.add_subject(browser) self._on_browser_closed.add_subject(browser) return browser @listens_group('loaded') def _on_browser_loaded(self, sender): browser = Live.Application.get_application().browser if browser.hotswap_target is None: self._main_modes.selected_mode = 'device' drum_rack = find_drum_group_device(self.song.view.selected_track) if drum_rack and is_empty_rack(drum_rack): self._device_navigation.request_drum_pad_selection() if drum_rack and self._device_navigation.is_drum_pad_selected and not self._device_navigation.is_drum_pad_unfolded: self._device_navigation.unfold_current_drum_pad() @listens_group('close') def _on_browser_closed(self, sender): if self._main_modes.selected_mode == 'add_track': self._main_modes.selected_mode = self._main_modes.active_modes[0] else: self._main_modes.selected_mode = 'device' def _is_on_master(self): return self.song.view.selected_track == self.song.master_track def _determine_mix_mode(self): selected_mode = self._main_modes.selected_mode mix_mode = self._mix_modes.selected_mode if selected_mode == 'mix': if self._is_on_master(): if mix_mode == 'global': self._mix_modes.push_mode('track') elif mix_mode == 'track' and 'global' in self._mix_modes.active_modes: self._mix_modes.pop_mode('track') def _on_selected_track_changed(self): if self._initialized: super(Push2, self)._on_selected_track_changed() self._close_browse_mode() self._determine_mix_mode() def _close_browse_mode(self): selected_mode = self._main_modes.selected_mode if selected_mode in ('browse', 'add_device', 'add_track'): self._main_modes.pop_mode(selected_mode) @listens('selected_track.is_frozen') def __on_selected_track_frozen_changed(self): frozen = self.song.view.selected_track.is_frozen self._main_modes.browse_button.enabled = self._main_modes.add_track_button.enabled = self._main_modes.add_device_button.enabled = not frozen self._close_browse_mode() def _create_device_component(self): return DeviceComponent(device_decorator_factory=self._device_decorator_factory, device_bank_registry=self._device_bank_registry, banking_info=BankingInfo(bank_definitions=BANK_DEFINITIONS), name='DeviceComponent', is_enabled=True, is_root=True) def _create_device_parameter_component(self): return DeviceParameterComponent(parameter_provider=self._device_component, is_enabled=False, layer=Layer(parameter_controls='fine_grain_param_controls')) def _create_device_navigation(self): self._chain_selection = ChainSelectionComponent(is_enabled=False, layer=Layer(select_buttons='select_buttons')) self._chain_selection.scroll_left_layer = Layer(button='select_buttons_raw[0]') self._chain_selection.scroll_right_layer = Layer(button='select_buttons_raw[-1]') self._bank_selection = BankSelectionComponent(bank_registry=self._device_bank_registry, banking_info=BankingInfo(bank_definitions=BANK_DEFINITIONS), device_options_provider=self._device_component, is_enabled=False, layer=Layer(option_buttons='track_state_buttons', select_buttons='select_buttons', priority=consts.DIALOG_PRIORITY)) self._bank_selection.scroll_left_layer = Layer(button='select_buttons_raw[0]', priority=consts.DIALOG_PRIORITY) self._bank_selection.scroll_right_layer = Layer(button='select_buttons_raw[-1]', priority=consts.DIALOG_PRIORITY) move_device = MoveDeviceComponent(is_enabled=False, layer=Layer(move_encoders='global_param_controls')) device_navigation = DeviceNavigationComponent(name='DeviceNavigation', device_bank_registry=self._device_bank_registry, device_component=self._device_component, delete_handler=self._delete_component, chain_selection=self._chain_selection, bank_selection=self._bank_selection, move_device=move_device, track_selection=self._track_list_component, is_enabled=False, layer=Layer(select_buttons='track_state_buttons')) device_navigation.scroll_left_layer = Layer(button='track_state_buttons_raw[0]') device_navigation.scroll_right_layer = Layer(button='track_state_buttons_raw[-1]') self._device_enabling = DeviceEnablingComponent(device_navigation=device_navigation, is_enabled=False, layer=Layer(toggle_buttons=ButtonMatrixElement(rows=[wrap_button('track_state_buttons_raw', 'global_mute_button')]))) self.__on_drum_pad_selection_changed.subject = device_navigation self._device_component.allow_update_callback = lambda : device_navigation.device_selection_update_allowed return device_navigation def _init_device(self): super(Push2, self)._init_device() self._device_view = DeviceViewComponent(name='DeviceView', device_component=self._device_component, view_model=self._model, is_enabled=False) self._model.devicelistView = self._device_navigation self._model.chainListView = self._chain_selection self._model.parameterBankListView = self._bank_selection self._model.editModeOptionsView = self._bank_selection.options def _drum_pad_notification_formatter(self): return None def _create_view_control_component(self): return ViewControlComponent(name='View_Control', tracks_provider=self._session_ring) def _create_session_recording(self): return SessionRecordingComponent(fixed_length_setting=self._fixed_length_setting, clip_creator=self._clip_creator, view_controller=self._view_control, name='Session_Recording', is_root=True) def _init_session_ring(self): self._session_ring = SessionRingTrackProvider(num_tracks=NUM_TRACKS, num_scenes=NUM_SCENES, tracks_to_use=partial(tracks_to_use_from_song, self.song), is_enabled=True, is_root=True) def _init_session_ring_selection_linking(self): self._sessionring_link = self.register_disconnectable(SessionRingSelectionLinking(session_ring=self._session_ring, selection_changed_notifier=self._view_control)) def _init_track_list(self): track_delete_buttons = ButtonMatrixElement(rows=[wrap_button('select_buttons_raw', 'delete_button')]) track_duplicate_buttons = ButtonMatrixElement(rows=[wrap_button('select_buttons_raw', 'duplicate_button')]) track_arm_buttons = ButtonMatrixElement(rows=[wrap_button('select_buttons_raw', 'record_button')]) self._track_list_component = MixerTrackListComponent(tracks_provider=self._session_ring, trigger_recording_on_release_callback=self._session_recording.set_trigger_recording_on_release, is_enabled=False, layer=Layer(select_buttons='select_buttons', delete_buttons=track_delete_buttons, duplicate_buttons=track_duplicate_buttons, arm_buttons=track_arm_buttons)) self._model.tracklistView = self._track_list_component def _create_main_mixer_modes(self): self._mixer_control = MixerControlComponent(name='Global_Mix_Component', view_model=self._model.mixerView, tracks_provider=self._session_ring, is_enabled=False, layer=Layer(controls='fine_grain_param_controls', volume_button='track_state_buttons_raw[0]', panning_button='track_state_buttons_raw[1]', send_slot_one_button='track_state_buttons_raw[2]', send_slot_two_button='track_state_buttons_raw[3]', send_slot_three_button='track_state_buttons_raw[4]', send_slot_four_button='track_state_buttons_raw[5]', send_slot_five_button='track_state_buttons_raw[6]', cycle_sends_button='track_state_buttons_raw[7]')) self._model.mixerView.realtimeMeterData = self._mixer_control.real_time_meter_handlers track_mixer_control = TrackMixerControlComponent(name='Track_Mix_Component', is_enabled=False, tracks_provider=self._session_ring, layer=Layer(controls='fine_grain_param_controls', scroll_left_button='track_state_buttons_raw[6]', scroll_right_button='track_state_buttons_raw[7]')) self._model.mixerView.trackControlView = track_mixer_control self._mix_modes = ModesComponent(is_enabled=False) self._mix_modes.add_mode('global', self._mixer_control) self._mix_modes.add_mode('track', track_mixer_control) self._mix_modes.selected_mode = 'global' self._model.mixerSelectView = self._mixer_control self._model.trackMixerSelectView = track_mixer_control class MixModeBehaviour(ReenterBehaviour): def press_immediate(behaviour_self, component, mode): if self._is_on_master() and self._mix_modes.selected_mode != 'track': self._mix_modes.selected_mode = 'track' super(MixModeBehaviour, behaviour_self).press_immediate(component, mode) def on_reenter(behaviour_self): if not self._is_on_master(): self._mix_modes.cycle_mode() self._main_modes.add_mode('mix', [self._mix_modes, SetAttributeMode(obj=self._note_editor_settings_component, attribute='parameter_provider', value=self._track_parameter_provider), self._track_list_component], behaviour=MixModeBehaviour()) def _init_dialog_modes(self): self._dialog_modes = ModesComponent(is_root=True) self._dialog_modes.add_mode('convert', LazyComponentMode(self._create_convert)) self.__dialog_mode_button_value.replace_subjects([self.elements.scale_presets_button, self.elements.convert_button]) @listens_group('value') def __dialog_mode_button_value(self, value, sender): if not value: self._setup_enabler.selected_mode = 'disabled' def _enter_dialog_mode(self, mode_name): self._dialog_modes.selected_mode = None if self._dialog_modes.selected_mode == mode_name else mode_name def _exit_dialog_mode(self, mode_name): if self._dialog_modes.selected_mode == mode_name: self._dialog_modes.selected_mode = None def _create_scales(self): root_note_buttons = ButtonMatrixElement(rows=[self.elements.track_state_buttons_raw[1:-1], self.elements.select_buttons_raw[1:-1]]) scales = ScalesComponent(note_layout=self._note_layout, is_enabled=False, layer=make_dialog_layer(root_note_buttons=root_note_buttons, in_key_toggle_button='select_buttons_raw[0]', fixed_toggle_button='select_buttons_raw[-1]', scale_encoders=self.elements.global_param_controls.submatrix[1:-1, :], close_button='track_state_buttons_raw[0]')) self.__on_scales_closed.subject = scales self._model.scalesView = scales return scales def _init_scales(self): self._dialog_modes.add_mode('scales', self._create_scales()) super(Push2, self)._init_scales() def _create_scales_enabler(self): return ScalesEnabler(enter_dialog_mode=self._enter_dialog_mode, exit_dialog_mode=self._exit_dialog_mode, is_enabled=False, is_root=True, layer=Layer(toggle_button='scale_presets_button')) @listens('close') def __on_scales_closed(self): self._dialog_modes.selected_mode = None def _create_clip_mode(self): base_loop_layer = Layer(shift_button='shift_button', loop_button='track_state_buttons_raw[1]', zoom_encoder='fine_grain_param_controls_raw[0]', encoders=self.elements.global_param_controls.submatrix[1:4, :]) self._loop_controller = LoopSettingsControllerComponent(is_enabled=False) self._model.loopSettingsView = self._loop_controller audio_clip_layer = Layer(warp_mode_encoder='parameter_controls_raw[5]', transpose_encoder='parameter_controls_raw[6]', detune_encoder=self._with_shift('parameter_controls_raw[6]'), gain_encoder='parameter_controls_raw[7]', shift_button='shift_button') audio_clip_controller = AudioClipSettingsControllerComponent(is_enabled=False) self._model.audioClipSettingsView = audio_clip_controller clip_control_mode_selector = ModesComponent(is_enabled=False) clip_control_mode_selector.add_mode('midi', [make_freeze_aware(self._loop_controller, base_loop_layer + Layer(encoders=self.elements.global_param_controls.submatrix[:3, :]))]) clip_control_mode_selector.add_mode('audio', [make_freeze_aware(self._loop_controller, base_loop_layer + Layer(encoders=self.elements.global_param_controls.submatrix[1:4, :])), make_freeze_aware(audio_clip_controller, audio_clip_layer)]) clip_control_mode_selector.add_mode('no_clip', []) clip_control_mode_selector.selected_mode = 'no_clip' clip_control = ClipControlComponent(loop_controller=self._loop_controller, audio_clip_controller=audio_clip_controller, mode_selector=clip_control_mode_selector, decorator_factory=self._clip_decorator_factory, is_enabled=False) self._model.clipView = clip_control return [clip_control_mode_selector, make_freeze_aware(self._loop_controller, base_loop_layer), make_freeze_aware(audio_clip_controller, audio_clip_layer), clip_control, self._track_list_component] def _init_quantize_actions(self): self._quantize_settings = QuantizationSettingsComponent(name='Quantization_Settings', is_enabled=False, layer=make_dialog_layer(swing_amount_encoder='parameter_controls_raw[0]', quantize_to_encoder='parameter_controls_raw[1]', quantize_amount_encoder='parameter_controls_raw[2]', record_quantization_encoder='parameter_controls_raw[4]', record_quantization_toggle_button='track_state_buttons_raw[4]', priority=consts.MOMENTARY_DIALOG_PRIORITY)) self._model.quantizeSettingsView = self._quantize_settings self._quantize = self._for_non_frozen_tracks(QuantizationComponent(name='Selected_Clip_Quantize', settings=self._quantize_settings, is_enabled=False, layer=Layer(action_button='quantize_button')), is_root=True) def _init_fixed_length(self): super(Push2, self)._init_fixed_length() self._fixed_length_settings_component.layer = make_dialog_layer(length_option_buttons='select_buttons', fixed_length_toggle_button='track_state_buttons_raw[0]', priority=consts.MOMENTARY_DIALOG_PRIORITY) self._model.fixedLengthSelectorView = self._fixed_length_settings_component self._model.fixedLengthSettings = self._fixed_length_setting def _init_value_components(self): super(Push2, self)._init_value_components() self._model.importantGlobals.swing = self._swing_amount.display self._model.importantGlobals.tempo = self._tempo.display self._model.importantGlobals.masterVolume = self._master_vol.display self._model.importantGlobals.cueVolume = self._master_cue_vol.display def _create_main_modes_layer(self): return Layer(mix_button='mix_button', clip_button='clip_mode_button', device_button='device_mode_button', browse_button='browse_mode_button', add_device_button='create_device_button', add_track_button='create_track_button') def _should_send_palette(self): return self._firmware_version <= FirmwareVersion(0, 5, 28) def _send_color_palette(self): if self._should_send_palette(): with self.component_guard(): palette_entry = SysexElement(sysex.make_rgb_palette_entry_message) finalize_palette = SysexElement(sysex.make_reapply_palette_message) for index, hex_color, white_balance in COLOR_TABLE: palette_entry.send_value(index, hex_color, white_balance) finalize_palette.send_value() def _init_pad_curve(self): self._pad_curve_sender = PadVelocityCurveSender(curve_sysex_element=SysexElement(sysex.make_pad_velocity_curve_message), threshold_sysex_element=SysexElement(sysex.make_pad_threshold_message), settings=self._setup_settings.pad_settings, chunk_size=sysex.PAD_VELOCITY_CURVE_CHUNK_SIZE) def _create_user_component(self): self._user_mode_ui_blocker = Component(is_enabled=False, layer=self._create_message_box_background_layer()) sysex_control = SysexElement(send_message_generator=sysex.make_mode_switch_messsage, sysex_identifier=sysex.make_message_identifier(sysex.MODE_SWITCH_MESSAGE_ID)) user = UserComponent(value_control=sysex_control, is_enabled=True, is_root=True) user.layer = Layer(user_mode_toggle_button='user_button', priority=consts.USER_BUTTON_PRIORITY) self.__on_before_push_mode_sent.subject = user self.__on_after_push_mode_sent.subject = user return user @listens('before_mode_sent') def __on_before_push_mode_sent(self, mode): if mode == sysex.USER_MODE and self._main_modes.selected_mode != 'user': self._main_modes.push_mode('user') @listens('after_mode_sent') def __on_after_push_mode_sent(self, mode): if mode == sysex.LIVE_MODE and self._main_modes.selected_mode == 'user': self._main_modes.pop_mode('user') self._user.defer_sysex_sending = mode == sysex.LIVE_MODE def _create_settings(self): return create_settings(preferences=self.preferences) def _init_hardware_settings(self): self._setup_settings = self.register_disconnectable(Settings(preferences=self.preferences)) self._hardware_settings = HardwareSettingsComponent(led_brightness_element=SysexElement(sysex.make_led_brightness_message), display_brightness_element=SysexElement(sysex.make_display_brightness_message), settings=self._setup_settings.hardware) def _init_setup_component(self): self._setup_settings.general.workflow = 'scene' if self._settings['workflow'].value else 'clip' self.__on_workflow_setting_changed.subject = self._setup_settings.general setup = SetupComponent(name='Setup', settings=self._setup_settings, pad_curve_sender=self._pad_curve_sender, in_developer_mode=self._c_instance.in_developer_mode, is_enabled=False, layer=make_dialog_layer(category_radio_buttons='select_buttons', priority=consts.SETUP_DIALOG_PRIORITY)) setup.general.layer = Layer(workflow_encoder='parameter_controls_raw[0]', display_brightness_encoder='parameter_controls_raw[1]', led_brightness_encoder='parameter_controls_raw[2]', priority=consts.SETUP_DIALOG_PRIORITY) setup.pad_settings.layer = Layer(sensitivity_encoder='parameter_controls_raw[4]', gain_encoder='parameter_controls_raw[5]', dynamics_encoder='parameter_controls_raw[6]', priority=consts.SETUP_DIALOG_PRIORITY) setup.display_debug.layer = Layer(show_row_spaces_button='track_state_buttons_raw[0]', show_row_margins_button='track_state_buttons_raw[1]', show_row_middle_button='track_state_buttons_raw[2]', show_button_spaces_button='track_state_buttons_raw[3]', show_unlit_button_button='track_state_buttons_raw[4]', show_lit_button_button='track_state_buttons_raw[5]', priority=consts.SETUP_DIALOG_PRIORITY) setup.profiling.layer = Layer(show_qml_stats_button='track_state_buttons_raw[0]', show_usb_stats_button='track_state_buttons_raw[1]', show_realtime_ipc_stats_button='track_state_buttons_raw[2]', priority=consts.SETUP_DIALOG_PRIORITY) self._model.setupView = setup self._setup_enabler = EnablingModesComponent(component=setup, enabled_color='DefaultButton.On', disabled_color='DefaultButton.On') self._setup_enabler.layer = Layer(cycle_mode_button='setup_button') def _init_firmware_update(self): self._firmware_update = FirmwareUpdateComponent(layer=self._create_message_box_background_layer()) self._model.firmwareUpdate = self._firmware_update @listens('workflow') def __on_workflow_setting_changed(self, value): self._settings['workflow'].value = value == 'scene' def _create_note_mode(self): class NoteLayoutSwitcher(Component): cycle_button = ButtonControl() def __init__(self, switch_note_mode_layout = None, *a, **k): raise switch_note_mode_layout is not None or AssertionError super(NoteLayoutSwitcher, self).__init__(*a, **k) self._switch_note_mode_layout = switch_note_mode_layout @cycle_button.pressed def cycle_button(self, button): self._switch_note_mode_layout() note_layout_switcher = NoteLayoutSwitcher(switch_note_mode_layout=self._switch_note_mode_layout, is_enabled=False, layer=Layer(cycle_button='layout_button')) return super(Push2, self)._create_note_mode() + [note_layout_switcher] def _create_note_mode_behaviour(self): return self._auto_arm.auto_arm_restore_behaviour() def _create_controls(self): class Deleter(object): @property def is_deleting(_): return self._delete_default_component.is_deleting def delete_clip_envelope(_, param): return self._delete_default_component.delete_clip_envelope(param) self.elements = Elements(deleter=Deleter(), undo_handler=self.song, playhead=self._c_instance.playhead, model=self._model) self.__on_param_encoder_touched.replace_subjects(self.elements.global_param_touch_buttons_raw) self._update_encoder_model() def _update_full_velocity(self, accent_is_active): super(Push2, self)._update_full_velocity(accent_is_active) self._slice_step_sequencer.full_velocity = accent_is_active def _update_playhead_color(self, color): super(Push2, self)._update_playhead_color(color) self._slice_step_sequencer.playhead_color = color @listens_group('value') def __on_param_encoder_touched(self, value, encoder): self._update_encoder_model() def _update_encoder_model(self): self._model.controls.encoders = [ NamedTuple(__id__='encoder_%i' % i, touched=e.is_pressed()) for i, e in enumerate(self.elements.global_param_touch_buttons_raw) ] def _with_firmware_version(self, major_version, minor_version, control_element): """ We consider all features to be available for Push 2 """ return control_element def _send_hardware_settings(self): self._hardware_settings.send() self._pad_curve_sender.send() self._send_color_palette() def port_settings_changed(self): super(Push2, self).port_settings_changed() if self._initialized: self._send_hardware_settings() self.update() def on_identified(self, response_bytes): try: major, minor, build, sn, board_revision = sysex.extract_identity_response_info(response_bytes) self._model.firmwareInfo.major = major self._model.firmwareInfo.minor = minor self._model.firmwareInfo.build = build self._model.firmwareInfo.serialNumber = sn logger.info('Push 2 identified') logger.info('Firmware %i.%i Build %i' % (major, minor, build)) logger.info('Serial number %i' % sn) logger.info('Board Revision %i' % board_revision) self._firmware_version = FirmwareVersion(major, minor, build) self._board_revision = board_revision self._identified = True self._try_initialize() except IndexError: logger.warning("Couldn't identify Push 2 unit") def update(self): if self._initialized: super(Push2, self).update() def request_zoom(self, zoom_factor): mode = self._main_modes.selected_mode if mode == 'device': self._device_component.request_zoom(zoom_factor) elif mode == 'clip': self._loop_controller.request_zoom(zoom_factor)
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.shift_button.set_control_element(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) @listens('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) @listens('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 Cntrlr(BaseCntrlr): def __init__(self, *a, **k): super(Cntrlr, self).__init__(*a, **k) self._skin = Skin(CntrlrColors) for button in self._grid: button._skin = self._skin def _open_log(self): self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) + " for Georg Oswald " + str(self._version_check) + " log opened =>>>>>>>>>>>>>>>>>>>") self.show_message(str(self._host_name) + ' Control Surface Loaded') def _setup_transport_control(self): super(Cntrlr, self)._setup_transport_control() self._transport._overdub_toggle.view_transform = lambda value: 'Transport.OverdubOn' if value else 'Transport.OverdubOff' self._transport.layer = Layer(priority = 4, play_button = self._button[24]) self._transport.overdub_layer = AddLayerMode(self._transport, Layer(priority = 4, overdub_button = self._button[25])) def _setup_session_control(self): super(Cntrlr, self)._setup_session_control() self._session_navigation.nav_layer = AddLayerMode(self._session_navigation, Layer(priority = 4, page_down_button = self._button[22], page_up_button = self._button[23], page_left_button = self._button[20], page_right_button = self._button[21])) self._session.stop_clips_layer = AddLayerMode(self._session, Layer(priority = 4, stop_all_clips_button = self._button[29],)) def _setup_session_recording_component(self): super(Cntrlr, self)._setup_session_recording_component() self._recorder.main_layer = AddLayerMode(self._recorder, Layer(priority = 4)) self._recorder.shift_layer = AddLayerMode(self._recorder, Layer(priority = 4, automation_button = self._button[25])) def _setup_mixer_control(self): super(Cntrlr, self)._setup_mixer_control() mute_buttons = ButtonMatrixElement(name = 'mute_buttons', rows = [self._button[:4] + self._button[12:16]]) select_buttons = ButtonMatrixElement(name = 'select_buttons', rows = [self._button[16:20] + self._button[28:32]]) self._G_session_ring = SessionRingComponent(num_tracks = 8, num_scenes = 4) self._G_session_ring.set_enabled(False) self._G_mixer = MonoMixerComponent(name = 'Mixer', num_returns = 4,tracks_provider = self._G_session_ring, track_assigner = simple_track_assigner, invert_mute_feedback = True, auto_name = True, enable_skinning = True) if FREE_ENCODER_IS_CROSSFADER: self._mixer.layer = Layer(priority = 4, crossfader_control = self._encoder[1]) #self._G_mixer.select_dial_layer = AddLayerMode(self._G_mixer, Layer(priority = 5, # track_select_dial = self._encoder[3],)) self._G_mixer.main_faders_layer = AddLayerMode(self._G_mixer, Layer(priority = 4, volume_controls = self._fader_matrix.submatrix[:8, :],)) self._G_mixer.main_buttons_layer = AddLayerMode(self._G_mixer, Layer(priority = 4, mute_buttons = mute_buttons, arming_track_select_buttons = select_buttons, solo_buttons = self._key_matrix.submatrix[4:12, :1],)) self._G_mixer.shifted_buttons_layer = AddLayerMode(self._G_mixer, Layer(priority = 4, mute_buttons = mute_buttons,)) self._G_mixer.solo_buttons_layer = AddLayerMode(self._G_mixer, Layer(priority = 4, solo_buttons = self._key_matrix.submatrix[4:12, :1],)) self._G_mixer.mute_buttons_layer = AddLayerMode(self._G_mixer, Layer(priority = 4, mute_buttons = mute_buttons,)) self._G_mixer.stop_layer = AddLayerMode(self._G_mixer, Layer(priority = 4, stop_clip_buttons = self._key_matrix.submatrix[8:12, 1:],)) self._G_mixer.main_knobs_layer = AddLayerMode(self._G_mixer, Layer(priority = 4)) self._G_mixer.master_fader_layer = AddLayerMode(self._G_mixer.master_strip(), Layer(priority = 4,)) self._G_mixer.instrument_buttons_layer = AddLayerMode(self._G_mixer, Layer(priority = 4, mute_buttons = mute_buttons, track_select_buttons = select_buttons,)) self._G_mixer.set_enabled(False) def _setup_device_control(self): super(Cntrlr, self)._setup_device_control() self._device_navigator.main_layer = AddLayerMode(self._device_navigator, Layer(priority = 4, prev_button = self._encoder_button[8], next_button = self._encoder_button[9], exit_button = self._encoder_button[10], enter_button = self._encoder_button[11],)) 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._drum_group_finder = PercussionInstrumentFinder(device_parent=self.song.view.selected_track) self._instrument = CntrlrMonoInstrumentComponent(name = 'InstrumentComponent', is_enabled = True, script = self, skin = self._skin, grid_resolution = self._grid_resolution, drum_group_finder = self._drum_group_finder, parent_task_group = self._task_group, settings = DEFAULT_INSTRUMENT_SETTINGS, device_provider = self._device_provider) self._instrument.shift_button_layer = AddLayerMode(self._instrument, Layer(priority = 5, session_mode_button = self._button[26], shift_mode_button = self._button[27])) self._instrument.audioloop_layer = AddLayerMode(self._instrument, Layer(priority = 5)) self._instrument.keypad_shift_layer = AddLayerMode(self._instrument, Layer(priority = 5, scale_up_button = self._button[31], scale_down_button = self._button[30], 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],)) self._instrument.drumpad_shift_layer = AddLayerMode(self._instrument, Layer(priority = 5, scale_up_button = self._button[31], scale_down_button = self._button[30], 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],)) self._instrument._keypad.sequencer_layer = LayerMode(self._instrument._keypad, Layer(priority = 5, playhead = self._playhead_element, keypad_matrix = self._matrix.submatrix[:,:],)) self._instrument._keypad.split_layer = LayerMode(self._instrument._keypad, Layer(priority = 5, keypad_matrix = self._matrix.submatrix[:,:],)) self._instrument._keypad.sequencer_shift_layer = LayerMode(self._instrument._keypad, Layer(priority = 5, keypad_matrix = self._matrix.submatrix[:,:], loop_selector_matrix = self._key_matrix.submatrix[4:8, 0], quantization_buttons = self._key_matrix.submatrix[:7, 1], follow_button = self._button[23])) self._instrument._keypad.sequencer_session_layer = LayerMode(self._instrument._keypad, Layer(priority = 5, playhead = self._playhead_element,)) self._instrument._keypad.split_session_layer = LayerMode(self._instrument._keypad, Layer(priority = 5, split_matrix = self._key_matrix.submatrix[:16,:1])) self._instrument._keypad.sequencer_session_shift_layer = LayerMode(self._instrument._keypad, Layer(priority = 5, loop_selector_matrix = self._key_matrix.submatrix[4:8, :1], quantization_buttons = self._key_matrix.submatrix[:7, 1:], follow_button = self._button[23])) self._instrument._drumpad.sequencer_layer = LayerMode(self._instrument._drumpad, Layer(priority = 5, playhead = self._playhead_element, drumpad_matrix = self._matrix.submatrix[:,:],)) self._instrument._drumpad.split_layer = LayerMode(self._instrument._drumpad, Layer(priority = 5, drumpad_matrix = self._matrix.submatrix[:,:], split_matrix = self._key_matrix.submatrix[:16,:1])) self._instrument._drumpad.sequencer_shift_layer = LayerMode(self._instrument._drumpad, Layer(priority = 5, drumpad_matrix = self._matrix.submatrix[:,:], loop_selector_matrix = self._key_matrix.submatrix[4:8, :1], quantization_buttons = self._key_matrix.submatrix[:7, 1:], follow_button = self._button[23])) self._instrument._drumpad.sequencer_session_layer = LayerMode(self._instrument._drumpad, Layer(priority = 5, playhead = self._playhead_element,)) self._instrument._drumpad.split_session_layer = LayerMode(self._instrument._drumpad, Layer(priority = 5, split_matrix = self._key_matrix.submatrix[:16,:1])) self._instrument._drumpad.sequencer_session_shift_layer = LayerMode(self._instrument._drumpad, Layer(priority = 5, loop_selector_matrix = self._key_matrix.submatrix[4:8, :1], quantization_buttons = self._key_matrix.submatrix[:7, 1:], follow_button = self._button[23])) #self._instrument.set_session_mode_button(self._button[30]) def _setup_modes(self): common = CompoundMode(self._mixer, self._session_ring) main_buttons=CompoundMode(self._G_mixer.main_buttons_layer, self._session_navigation, self._session_navigation.nav_layer, self._transport, self._transport.overdub_layer, self._recorder, self._recorder.main_layer, self._device) shifted_main_buttons=CompoundMode(self._G_mixer.shifted_buttons_layer, self._recorder, self._recorder.shift_layer, self._session, self._session.scene_launch_layer, self._session.stop_clips_layer, self._transport, self._device) main_faders=CompoundMode(self._G_mixer.main_faders_layer, self._G_mixer.master_fader_layer) main_dials=CompoundMode(self._view_control, self._view_control.main_layer, self._device_navigator, self._device_navigator.select_dial_layer, self.encoder_navigation_on) shifted_dials=CompoundMode(self._session_navigation, self._session_navigation.nav_dial_layer, self._device_navigator, self._device_navigator.select_dial_layer, self.encoder_navigation_on) self._modalt_mode = ModesComponent(name = 'ModAltMode') self._modalt_mode.add_mode('disabled', None) self._modalt_mode.add_mode('enabled', [tuple([self._enable_mod_alt, self._disable_mod_alt])], behaviour = CancellableBehaviourWithRelease(), cycle_mode_button_color = 'Mod.AltOn') self._modalt_mode.selected_mode = 'disabled' self._modalt_mode.set_enabled(False) self._modalt_mode.layer = Layer(priority = 4, enabled_button = self._encoder_button[1]) self._modswitcher = ModesComponent(name = 'ModSwitcher') self._modswitcher.add_mode('mod', [self.modhandler, self._modalt_mode, main_faders, self._G_mixer.main_knobs_layer, self._device, self._device_navigator.main_layer, main_dials, DelayMode(self.modhandler.update, delay = .5, parent_task_group = self._task_group)]) self._modswitcher.add_mode('instrument', [self._instrument.shift_button_layer, main_buttons, main_faders, self._G_mixer.main_knobs_layer, self._device, self._device_navigator.main_layer]) #self._instrument.shift_button_layer, self._optional_translations]) self._modswitcher.selected_mode = 'instrument' self._modswitcher.set_enabled(False) self._instrument._main_modes = ModesComponent(name = 'InstrumentModes') self._instrument._main_modes.add_mode('disabled', [main_buttons, main_dials, self._device.main_layer, self._session, self._session, self._session.clip_launch_layer]) self._instrument._main_modes.add_mode('drumpad', [self._instrument._drumpad.sequencer_layer, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('drumpad_split', [self._instrument._drumpad.split_layer, self._instrument._selected_session, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('drumpad_sequencer', [self._instrument._drumpad.sequencer_layer, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('drumpad_shifted', [self._instrument._drumpad.sequencer_shift_layer, self._instrument.drumpad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('drumpad_split_shifted', [self._instrument._drumpad.split_layer, self._instrument.drumpad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('drumpad_sequencer_shifted', [self._instrument._drumpad.sequencer_shift_layer, self._instrument.drumpad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('keypad', [self._instrument._keypad.sequencer_layer, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('keypad_split', [self._instrument._keypad.split_layer, self._instrument._selected_session, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('keypad_sequencer', [self._instrument._keypad.sequencer_layer, main_buttons, self._device.main_layer, main_dials]) self._instrument._main_modes.add_mode('keypad_shifted', [self._instrument._keypad.sequencer_shift_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('keypad_split_shifted', [self._instrument._keypad.split_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('keypad_sequencer_shifted', [self._instrument._keypad.sequencer_shift_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, shifted_dials]) self._instrument._main_modes.add_mode('drumpad_session', [self._instrument._drumpad.sequencer_session_layer, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('drumpad_split_session', [self._instrument._drumpad.split_session_layer, self._instrument._selected_session, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('drumpad_sequencer_session', [self._instrument._drumpad.sequencer_session_layer, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('drumpad_shifted_session', [self._instrument._drumpad.sequencer_session_shift_layer, self._instrument.drumpad_shift_layer, main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('drumpad_split_shifted_session', [self._instrument._drumpad.split_session_layer, self._instrument.drumpad_shift_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('drumpad_sequencer_shifted_session', [self._instrument._drumpad.sequencer_session_shift_layer, self._instrument.drumpad_shift_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('keypad_session', [self._instrument._keypad.sequencer_session_layer, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('keypad_split_session', [self._instrument._keypad.split_session_layer, self._instrument._selected_session, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('keypad_sequencer_session', [self._instrument._keypad.sequencer_session_layer, main_buttons, self._device.main_layer, self._session, DelayMode(self._session.clip_launch_layer, delay = .1), main_dials]) self._instrument._main_modes.add_mode('keypad_shifted_session', [self._instrument._keypad.sequencer_session_shift_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('keypad_split_shifted_session', [self._instrument._keypad.split_session_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('keypad_sequencer_shifted_session', [self._instrument._keypad.sequencer_session_shift_layer, self._instrument.keypad_shift_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) self._instrument._main_modes.add_mode('audioloop', [self._instrument.audioloop_layer, main_buttons, self._device.main_layer, main_dials, self._session, DelayMode(self._session.clip_launch_layer, delay = .1)]) self._instrument._main_modes.add_mode('audioloop_shifted', [self._instrument.audioloop_layer, shifted_main_buttons, self._device.main_layer, self._session_zoom, shifted_dials]) #self._instrument._main_modes.add_mode('audioloop_shifted_session', [self._instrument.audioloop_layer, self._session, shifted_main_buttons, main_dials, shifted_dials]) self._instrument.register_component(self._instrument._main_modes) self._instrument._main_modes.selected_mode = 'disabled' self._instrument.set_enabled(True) self._main_modes = ModesComponent(name = 'MainModes') self._main_modes.add_mode('disabled', [self._background]) self._main_modes.add_mode('MixMode', [common, self._instrument, self._instrument.shift_button_layer, self._G_mixer, main_faders, self._G_mixer.main_knobs_layer, self._device, self._device.main_layer, self._device_navigator, self._device_navigator.main_layer, self._device_navigator.select_dial_layer]) self._main_modes.add_mode('ModSwitcher', [common, main_faders, main_dials, self._G_mixer.main_knobs_layer, self._view_control, self._view_control.main_layer, self._device_navigator, self._device_navigator.select_dial_layer, self.encoder_navigation_on, self._modswitcher, DelayMode(self._update_modswitcher, delay = .1)], behaviour = ColoredCancellableBehaviourWithRelease(color = 'ModeButtons.ModSwitcher', off_color = 'ModeButtons.ModSwitcherDisabled')) self._main_modes.add_mode('Translations', [common, main_faders, main_dials, self._G_mixer.main_knobs_layer, self._translations, DelayMode(self._translations.selector_layer, delay = .1)], behaviour = DefaultedBehaviour(default_mode = 'MixMode', color = 'ModeButtons.Translations', off_color = 'ModeButtons.TranslationsDisabled')) self._main_modes.add_mode('DeviceSelector', [common, self._device_selector, DelayMode(self._device_selector.select_layer, delay = .1), DelayMode(self.modhandler.lock_layer, delay = .1), DelayMode(self._device_selector.assign_layer, delay = .5), main_buttons, main_dials, main_faders, self._G_mixer.main_knobs_layer, self._device.main_layer, self._device_navigator, self._device_navigator.main_layer, self._device_navigator.select_dial_layer], behaviour = ColoredCancellableBehaviourWithRelease(color = 'ModeButtons.DeviceSelector', off_color = 'ModeButtons.DeviceSelectorDisabled')) self._main_modes.layer = Layer(priority = 4, ModSwitcher_button = self._encoder_button[2], DeviceSelector_button = self._encoder_button[0], Translations_button = self._encoder_button[3]) #, self._main_modes.selected_mode = 'disabled' self._main_modes.set_enabled(True) self._test.subject = self._instrument._main_modes #a
class NoteEditorSettingsComponent(ModesComponent): initial_encoders = control_list(EncoderControl) encoders = control_list(EncoderControl) def __init__(self, note_settings_component_class=None, automation_component_class=None, grid_resolution=None, initial_encoder_layer=None, encoder_layer=None, *a, **k): super(NoteEditorSettingsComponent, self).__init__(*a, **k) assert encoder_layer assert note_settings_component_class is not None assert automation_component_class is not None self.settings = note_settings_component_class( grid_resolution=grid_resolution, parent=self, is_enabled=False) self.automation = automation_component_class(parent=self, is_enabled=False) self._mode_selector = ModeSelector(parent=self, is_enabled=False) self._visible_detail_view = u'Detail/DeviceChain' self._show_settings_task = self._tasks.add( task.sequence(task.wait(defaults.MOMENTARY_DELAY), task.run(self._show_settings))).kill() self._update_infos_task = self._tasks.add( task.run(self._update_note_infos)).kill() self._settings_modes = ModesComponent(parent=self) self._settings_modes.set_enabled(False) self._settings_modes.add_mode(u'automation', [ self.automation, self._mode_selector, partial(self._set_envelope_view_visible, True), partial(show_clip_view, self.application) ]) self._settings_modes.add_mode(u'note_settings', [ self.settings, self._update_note_infos, self._mode_selector, partial(self._set_envelope_view_visible, False), partial(show_clip_view, self.application) ]) self._settings_modes.selected_mode = u'note_settings' self.__on_selected_setting_mode_changed.subject = self._settings_modes self.add_mode(u'disabled', []) self.add_mode(u'about_to_show', [ AddLayerMode(self, initial_encoder_layer), (self._show_settings_task.restart, self._show_settings_task.kill) ]) self.add_mode(u'enabled', [ DetailViewRestorerMode(self.application), AddLayerMode(self, encoder_layer), self._settings_modes ]) self.selected_mode = u'disabled' self._editors = [] self._on_detail_clip_changed.subject = self.song.view self._on_selected_track_changed.subject = self.song.view self.__on_full_velocity_changed.subject = self.settings self.__on_setting_changed.subject = self.settings automation_layer = forward_property(u'automation')(u'layer') mode_selector_layer = forward_property(u'_mode_selector')(u'layer') selected_setting = forward_property(u'_settings_modes')(u'selected_mode') @property def step_settings(self): return self._settings_modes @property def editors(self): return self._editors @listenable_property def is_touched(self): return any( imap( lambda e: e and e.is_touched, ifilter(lambda e: self._can_notify_is_touched(e), self.encoders))) def _is_step_held(self): return len(self._active_note_regions()) > 0 def add_editor(self, editor): assert editor != None self._editors.append(editor) self._on_active_note_regions_changed.add_subject(editor) self._on_notes_changed.replace_subjects(self._editors) self.__on_modify_all_notes_changed.add_subject(editor) def set_encoders(self, encoders): self.encoders.set_control_element(encoders) self.settings.set_encoder_controls(encoders) self.automation.set_parameter_controls(encoders) @property def parameter_provider(self): self.automation.parameter_provider @parameter_provider.setter def parameter_provider(self, value): self.automation.parameter_provider = value @listens(u'selected_mode') def __on_selected_setting_mode_changed(self, mode): if mode == u'automation': self.automation.selected_time = self._active_note_regions() def update_view_state_based_on_selected_setting(self, setting): if self.selected_mode == u'enabled' and self.is_touched or setting is None: self._set_settings_view_enabled(False) elif self._is_step_held(): if self.selected_setting == u'automation' and self.automation.can_automate_parameters or self.selected_setting == u'note_settings': self._show_settings() @listens(u'full_velocity') def __on_full_velocity_changed(self): for editor in self._editors: editor.set_full_velocity() @listens(u'setting_changed') def __on_setting_changed(self, index, value): for editor in self._editors: self._modify_note_property_offset(editor, index, value) def _modify_note_property_offset(self, editor, index, value): if index == 1: editor.set_nudge_offset(value) elif index == 2: editor.set_length_offset(value) elif index == 3: editor.set_velocity_offset(value) def _set_envelope_view_visible(self, visible): clip = self.song.view.detail_clip if liveobj_valid(clip): if visible: clip.view.show_envelope() else: clip.view.hide_envelope() def _set_settings_view_enabled(self, should_show_view): really_show_view = should_show_view and self.automation.can_automate_parameters if self.selected_setting == u'automation' else should_show_view if really_show_view: if self.selected_mode == u'disabled': self.selected_mode = u'about_to_show' else: self._hide_settings() def _active_note_regions(self): all_active_regions = imap(lambda e: e.active_note_regions, self._editors) return list(set(chain.from_iterable(all_active_regions))) @listens_group(u'active_note_regions') def _on_active_note_regions_changed(self, _): if self.is_enabled(): all_steps = self._active_note_regions() self.automation.selected_time = all_steps self._update_note_infos() self._set_settings_view_enabled( len(all_steps) > 0 and self.selected_setting != None or self.is_touched) @listens_group(u'modify_all_notes') def __on_modify_all_notes_changed(self, editor): self.selected_mode = u'about_to_show' if editor.modify_all_notes_enabled else u'disabled' @listens_group(u'notes_changed') def _on_notes_changed(self, editor): self._update_infos_task.restart() @listens(u'detail_clip') def _on_detail_clip_changed(self): self.automation.clip = self.song.view.detail_clip if self.is_enabled( ) else None @listens(u'selected_track') def _on_selected_track_changed(self): self.selected_mode = u'disabled' @initial_encoders.touched def initial_encoders(self, encoder): if self.selected_mode == u'about_to_show': self._show_settings() @initial_encoders.value def initial_encoders(self, encoder, value): if self.selected_mode == u'about_to_show': self._show_settings() @encoders.touched def encoders(self, encoder): if self._can_notify_is_touched(encoder): self.notify_is_touched() @encoders.released def encoders(self, encoder): if not self.is_touched and not self._is_step_held( ) and not self._is_edit_all_notes_active(): self._hide_settings() if self._can_notify_is_touched(encoder): self.notify_is_touched() @encoders.value def encoders(self, encoder, value): self._notify_modification() def _can_notify_is_touched(self, encoder): if self.is_enabled(): return self._settings_modes.selected_mode != u'note_settings' or encoder.index >= self.encoders.control_count - self.settings.number_of_settings return False def _is_edit_all_notes_active(self): return find_if(lambda e: e.modify_all_notes_enabled, self._editors) != None def _notify_modification(self): for editor in self._editors: editor.notify_modification() def _update_note_infos(self): if self.settings.is_enabled(): def min_max((l_min, l_max), (r_min, r_max)): return (min(l_min, r_min), max(l_max, r_max)) all_min_max_attributes = filter( None, imap(lambda e: e.get_min_max_note_values(), self._editors)) min_max_values = [ (99999, -99999) ] * 4 if len(all_min_max_attributes) > 0 else None for min_max_attribute in all_min_max_attributes: for i, attribute in enumerate(min_max_attribute): min_max_values[i] = min_max(min_max_values[i], attribute) for i in xrange(4): self.settings.set_min_max( i, min_max_values[i] if min_max_values else None) self.settings.set_info_message( u'Tweak to add note' if not self._is_edit_all_notes_active() and not min_max_values else u'')
class Codec(LividControlSurface): _sysex_id = 4 _model_name = 'Code' _host_name = 'Codec' _version_check = 'b996' monomodular = None def __init__(self, c_instance, *a, **k): self.log_message = logger.warning super(Codec, self).__init__(c_instance, *a, **k) self._locked = False self._shift_button = None self._device_selection_follows_track_selection=FOLLOW self._leds_last = 0 self._shift_latching = LatchingShiftedBehaviour if SHIFT_LATCHING else ShiftedBehaviour self._skin = Skin(CodecColors) with self.component_guard(): self._define_sysex() self._setup_controls() self._setup_background() self._setup_mixer_controls() self._setup_device_navigator() self._setup_device_controls() self._setup_special_device_control() self._setup_device_chooser() self._setup_device_selector() self._setup_send_reset() self._setup_default_buttons() self._setup_shift_modes() self._setup_mod() self._setup_modswitcher() self._setup_modes() self._setup_m4l_interface() self._background.set_enabled(True) def _initialize_hardware(self): super(Codec, self)._initialize_hardware() def _initialize_script(self): super(Codec, self)._initialize_script() self._on_device_changed.subject = self._device_provider self._main_modes.set_enabled(True) self._main_modes.selected_mode = 'mix' def _define_sysex(self): self.fast_encoder_sysex = SendLividSysexMode(livid_settings = self._livid_settings, call = 'set_encoder_speed', message = FAST_ENCODER_MSG) self.normal_encoder_sysex = SendLividSysexMode(livid_settings = self._livid_settings, call = 'set_encoder_speed', message = NORMAL_ENCODER_MSG) self.slow_encoder_sysex = SendLividSysexMode(livid_settings = self._livid_settings, call = 'set_encoder_speed', message = SLOW_ENCODER_MSG) def _setup_controls(self): is_momentary = True optimized = False resource = PrioritizedResource self._livid = DoublePressElement(MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = LIVID, name = 'Livid_Button', script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge)) self._dial = [[CodecEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = CODE_DIALS[row][column], name = 'Dial_' + str(column) + '_' + str(row), num = (column + (row*8)), script = self, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for row in range(4)] for column in range(8)] self._button = [[MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = CODE_BUTTONS[row][column], name = 'Button_' + str(column) + '_' + str(row), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for row in range(4)] for column in range(8)] self._column_button = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = CODE_COLUMN_BUTTONS[index], name = 'Column_Button_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(8)] self._row_button = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = CODE_ROW_BUTTONS[index], name = 'Row_Button_' + str(index), script = self, skin = self._skin, color_map = COLOR_MAP, optimized_send_midi = optimized, resource_type = resource, monobridge = self._monobridge) for index in range(4)] self._code_keys = ButtonMatrixElement(name = 'Code_Keys', rows = [self._column_button]) self._code_buttons = ButtonMatrixElement(name = 'Code_Buttons', rows = [self._row_button]) self._encoder_matrix = ButtonMatrixElement(name = 'Encoder_Matrix', rows = [[self._dial[column][row] for column in range(8)] for row in range(4)]) self._button_matrix = ButtonMatrixElement(name = 'Button_Matrix', rows = [[self._button[column][row] for column in range(8)] for row in range(4)]) def _setup_background(self): self._background = BackgroundComponent() self._background.layer = Layer(priority = 3, matrix = self._button_matrix, encoders = self._encoder_matrix, livid = self._livid, buttons = self._code_buttons, keys = self._code_keys) self._background.set_enabled(False) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' self._transport.set_enabled(False) def _setup_mixer_controls(self): self._session_ring = SessionRingComponent(name = 'Session_Ring', num_tracks = 8, num_scenes = 0) self._session_navigation = SessionNavigationComponent(name = 'Session_Navigation', session_ring = self._session_ring) self._session_navigation.layer = Layer(priority = 4, left_button = self._button[6][0], right_button = self._button[7][0]) self._session_navigation.set_enabled(False) #self._session = SessionComponent(name = 'Session', session_ring = self._session_ring) self._mixer = CodecMixerComponent(num_returns = 4, name = 'Mixer', tracks_provider = self._session_ring, invert_mute_feedback = True, auto_name = True) self._mixer._mix_layer = AddLayerMode(self._mixer, Layer(priority = 4, volume_controls = self._encoder_matrix.submatrix[:8,3], pan_controls = self._encoder_matrix.submatrix[:8,2], send_controls = self._encoder_matrix.submatrix[:8, :2], )) self._mixer._solo_mute_layer = AddLayerMode(self._mixer, Layer(priority = 4, solo_buttons = self._button_matrix.submatrix[:8,2], mute_buttons = self._button_matrix.submatrix[:8,3], )) self._mixer._select_layer = AddLayerMode(self._mixer, Layer(priority = 4, track_select_buttons = self._code_keys)) self._mixer._sends_layer = AddLayerMode(self._mixer, Layer(priority = 4, send_controls = self._encoder_matrix.submatrix[:, :])) self._mixer.set_enabled(False) def _setup_device_navigator(self): self._device_navigator = DeviceNavigator(self._device_provider, self._mixer, self) self._device_navigator._dev1_layer = AddLayerMode(self._device_navigator, Layer(priority = 4, prev_button = self._button[4][0], next_button = self._button[5][0], prev_chain_button = self._button[6][0], next_chain_button = self._button[7][0])) self._device_navigator._dev2_layer = AddLayerMode(self._device_navigator, Layer(priority = 4, prev_button = self._button[4][1], next_button = self._button[5][1], prev_chain_button = self._button[6][1], next_chain_button = self._button[7][1])) self._device_navigator._dev3_layer = AddLayerMode(self._device_navigator, Layer(priority = 4, prev_button = self._button[4][2], next_button = self._button[5][2], prev_chain_button = self._button[6][2], next_chain_button = self._button[7][2])) self._device_navigator._dev4_layer = AddLayerMode(self._device_navigator, Layer(priority = 4, prev_button = self._button[4][3], next_button = self._button[5][3], prev_chain_button = self._button[6][3], next_chain_button = self._button[7][3])) self._device_navigator.set_enabled(False) def _setup_device_controls(self): self._device = [None for index in range(4)] for index in range(4): self._device[index] = CodecDeviceComponent(self, index+1, device_bank_registry = DeviceBankRegistry()) self._device[index].name = 'CodecDevice_Component_' + str(index+1) self._device[index].layer = Layer(priority = 4, parameter_controls = self._encoder_matrix.submatrix[:, index], on_off_button = self._button[1][index], bank_prev_button = self._button[2][index], bank_next_button = self._button[3][index], ) self._device[index]._nav_layer = AddLayerMode(self._device[index], Layer(priority = 4, nav_prev_button = self._button[6][index], nav_next_button = self._button[7][index],)) self._device[index].set_enabled(False) def _setup_special_device_control(self): self._special_device = SpecialCodecDeviceComponent(self, device_bank_registry = DeviceBankRegistry(), device_provider = self._device_provider) self._special_device.name = 'SpecialCodecDeviceComponent' self._is_active_device = True self._special_device.layer = Layer(priority = 4, parameter_controls = self._encoder_matrix.submatrix[:,:], on_off_button = self._button[1][0], bank_prev_button = self._button[4][0], bank_next_button = self._button[5][0], ) self._special_device.set_enabled(False) def _setup_device_chooser(self): self._selected_device = self._device[0] self._last_selected_device = self._device[0] self._selected_device_modes = ModesComponent() self._selected_device_modes.add_mode('disabled', [None]) self._selected_device_modes.add_mode('device_0', [self._device_navigator._dev1_layer], behaviour = DefaultedBehaviour()) self._selected_device_modes.add_mode('device_1', [self._device_navigator._dev2_layer], behaviour = DefaultedBehaviour()) self._selected_device_modes.add_mode('device_2', [self._device_navigator._dev3_layer], behaviour = DefaultedBehaviour()) self._selected_device_modes.add_mode('device_3', [self._device_navigator._dev4_layer], behaviour = DefaultedBehaviour()) self._selected_device_modes.layer = Layer(priority = 4, device_0_button = self._button[0][0], device_1_button = self._button[0][1], device_2_button = self._button[0][2], device_3_button = self._button[0][3]) self._selected_device_modes.selected_mode = 'device_0' self._selected_device_modes.set_enabled(False) self._on_device_selector_mode_changed.subject = self._selected_device_modes def _setup_device_selector(self): self._device_selector = DeviceSelectorComponent(self) self._device_selector.name = 'Device_Selector' self._device_selector.layer = Layer(priority = 4, matrix = self._code_keys) self._device_selector.set_enabled(False) def _setup_send_reset(self): self._send_reset = CodecResetSendsComponent(self) self._send_reset.set_enabled(False) #self._send_reset.set_buttons(self._button) def _setup_default_buttons(self): self._value_default = ParameterDefaultComponent(script = self, dials = self._dial) self._value_default.layer = Layer(priority = 3, matrix = self._button_matrix) self._value_default.set_enabled(False) def _setup_shift_modes(self): self._main_shift_modes = ModesComponent(name = 'MainShiftModes') self._main_shift_modes.add_mode('disabled', [self.normal_encoder_sysex], cycle_mode_button_color = 'DefaultButton.Off') self._main_shift_modes.add_mode('enabled', [self.slow_encoder_sysex], cycle_mode_button_color = 'DefaultButton.On') #, self._value_default self._main_shift_modes.layer = Layer(priority = 4, cycle_mode_button = self._livid) self._main_shift_modes.set_enabled(False) self._main_shift_modes.selected_mode = 'disabled' self._mod_shift_modes = ModesComponent(name = 'ModShiftModes') self._mod_shift_modes.layer = Layer(priority = 4, cycle_mode_button = self._livid) self._mod_shift_modes.set_enabled(False) def _setup_mod(self): self.monomodular = get_monomodular(self) self.monomodular.name = 'monomodular_switcher' self.modhandler = CodecModHandler(script = self, device_provider = self._device_provider) self.modhandler.name = 'ModHandler' self.modhandler.layer = Layer(priority = 4, code_grid = self._button_matrix.submatrix[:,:], code_encoder_grid = self._encoder_matrix.submatrix[:,:]) self.modhandler.set_enabled(False) self.modhandler.code_buttons_layer = AddLayerMode(self.modhandler, Layer(priority = 5, code_buttons = self._code_buttons)) self.modhandler.keys_layer = AddLayerMode(self.modhandler, Layer(priority = 5, key_buttons = self._code_keys)) self.modhandler.code_keys_layer = AddLayerMode(self.modhandler, Layer(priority = 5, code_keys = self._code_buttons)) self.modhandler.alt_layer = AddLayerMode(self.modhandler, Layer(priority = 4, lock_button = self._livid)) def _setup_modswitcher(self): self._modswitcher = ModesComponent(name = 'ModSwitcher') self._modswitcher.add_mode('mod', [self.modhandler, self._mod_shift_modes]) self._modswitcher.add_mode('special_device', [self._special_device, self._mixer, self._mixer._select_layer, self._main_shift_modes]) self._modswitcher.selected_mode = 'special_device' self._modswitcher.set_enabled(False) self._mod_shift_modes.add_mode('disabled', [self.modhandler.keys_layer], cycle_mode_button_color = 'Mod.ShiftOff') self._mod_shift_modes.add_mode('enabled', [self.modhandler.code_keys_layer, self.modhandler.code_buttons_layer, tuple([self._send_mod_shift, self._release_mod_shift])], cycle_mode_button_color = 'Mod.ShiftOn') self._mod_shift_modes.selected_mode = 'disabled' def _setup_modes(self): self._main_modes = ModesComponent(name = 'MainModes') self._main_modes.add_mode('disabled', []) self._main_modes.add_mode('mix_shifted', [self._mixer, self._mixer._mix_layer, self._mixer._solo_mute_layer, self._device_selector, self._background], groups = ['shifted'], behaviour = self._shift_latching(color = 'Mode.Main')) self._main_modes.add_mode('mix', [self._mixer, self._mixer._mix_layer, self._mixer._select_layer, self._mixer._solo_mute_layer, self._session_navigation, self._background, self._main_shift_modes], behaviour = self._shift_latching(color = 'Mode.Main')) self._main_modes.add_mode('sends_shifted', [self._mixer, self._mixer._sends_layer, self._mixer._select_layer, self._device_selector, self._background], groups = ['shifted'], behaviour = self._shift_latching(color = 'Mode.Main')) self._main_modes.add_mode('sends', [self._mixer, self._mixer._sends_layer, self._mixer._select_layer, self._background, self._main_shift_modes], behaviour = self._shift_latching(color = 'Mode.Main')) self._main_modes.add_mode('device_shifted', [self._selected_device_modes, self._device_selector, self._device[0], self._device[1], self._device[2], self._device[3], self._device_selector, self._background], groups = ['shifted'], behaviour = self._shift_latching(color = 'Mode.Main')) self._main_modes.add_mode('device', [self._mixer, self._mixer._select_layer, self._selected_device_modes, self._device[0], self._device[1], self._device[2], self._device[3], self._background, self._mixer._select_layer, self._main_shift_modes], behaviour = self._shift_latching(color = 'Mode.Main')) self._main_modes.add_mode('special_device_shifted', [self._modswitcher, self._device_selector, self._background], groups = ['shifted'], behaviour = self._shift_latching(color = 'Mode.Main')) self._main_modes.add_mode('special_device', [self._modswitcher, self._background], behaviour = self._shift_latching(color = 'Mode.Main')) #self._main_modes.add_mode('select', [self.normal_encoder_sysex], behaviour = DelayedExcludingMomentaryBehaviour(excluded_groups = ['shifted'])) self._main_modes.layer = Layer(priority = 4, mix_button = self._row_button[0], sends_button = self._row_button[1], device_button = self._row_button[2], special_device_button = self._row_button[3], ) self._main_modes.selected_mode = 'disabled' self._main_modes.set_enabled(False) def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard) self.get_control_names = self._m4l_interface.get_control_names self.get_control = self._m4l_interface.get_control self.grab_control = self._m4l_interface.grab_control self.release_control = self._m4l_interface.release_control @listens('selected_mode') def _on_device_selector_mode_changed(self, mode): if mode == 'disabled': for device in self._device: device.set_dynamic_device_provider(None) elif mode in DEVICE_COMPONENTS: active_device = self._device[DEVICE_COMPONENTS.index(self._selected_device_modes.selected_mode)] for device in self._device: if device is active_device: device.set_dynamic_device_provider(self._device_provider) else: device.set_dynamic_device_provider(None) if active_device.find_track(active_device._get_device()) == self.song.view.selected_track: active_device.display_device() @listens('device') def _on_device_changed(self): self._on_device_name_changed.subject = self._device_provider.device self.schedule_message(1, self._update_modswitcher) @listens('name') def _on_device_name_changed(self): for device in self._device: device.scan_all() def _on_selected_track_changed(self): super(Codec, self)._on_selected_track_changed() #self.schedule_message(1, self._update_modswitcher) if not len(self.song.view.selected_track.devices): 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 = 'special_device' """general functionality""" def disconnect(self): self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Codec log closed >>>>>>>>>>>>>>>>>>>>>>>>>') super(Codec, self).disconnect() def update_display(self): super(Codec, self).update_display() self.modhandler.send_ring_leds() def restart_monomodular(self): #self.log_message('restart monomodular') self.modhandler.disconnect() with self.component_guard(): self._setup_mod() def _send_mod_shift(self): self.modhandler._shift_value(1) def _release_mod_shift(self): self.modhandler._shift_value(0)
class Push(PushBase): input_target_name_for_auto_arm = 'Push Input' device_component_class = DeviceComponent device_provider_class = DeviceProvider selected_track_parameter_provider_class = SelectedTrackParameterProvider bank_definitions = BANK_DEFINITIONS note_editor_class = NoteEditorComponent sliced_simpler_class = SlicedSimplerComponent quantization_settings_class = QuantizationSettingsComponent note_settings_component_class = NoteSettingsComponent automation_component_class = AutomationComponent def __init__(self, *a, **k): (super(Push, self).__init__)(*a, **k) with self.component_guard(): self.initialize() logger.info('Push script loaded') self._send_midi(sysex.WELCOME_MESSAGE) def disconnect(self): super(Push, self).disconnect() logger.info('Push script unloaded') self._send_midi(sysex.GOOD_BYE_MESSAGE) def port_settings_changed(self): super(Push, self).port_settings_changed() self._start_handshake_task.restart() def on_select_clip_slot(self, clip_slot): self._selector.on_select_clip(clip_slot) def on_select_scene(self, scene): self._selector.on_select_scene(scene) def on_select_track(self, track): self._selector.on_select_track(track) def _create_components(self): self._init_handshake() self._init_selector() super(Push, self)._create_components() self._init_browser() self._init_track_modes() def _create_settings(self): settings = create_settings(preferences=(self.preferences)) self._Push__on_pad_curve.subject = settings['curve'] self._Push__on_pad_threshold.subject = settings['threshold'] self._Push__on_aftertouch_threshold.subject = settings[ 'aftertouch_threshold'] self._Push__on_aftertouch_mode.subject = settings['aftertouch_mode'] return settings def _create_device_decorator_factory(self): return DeviceDecoratorFactory() def _init_settings(self): super(Push, self)._init_settings() self._init_global_pad_parameters() self._update_pad_params() def _init_selector(self): self._selector = SelectComponent(name='Selector') self._selector.layer = Layer(select_button='select_button') self._selector.selection_display_layer = Layer( display_line='display_line3', priority=(consts.DIALOG_PRIORITY)) def _init_handshake(self): dongle_message, dongle = make_dongle_message( sysex.DONGLE_ENQUIRY_PREFIX) identity_control = create_sysex_element(sysex.IDENTITY_PREFIX, sysex.IDENTITY_ENQUIRY) dongle_control = create_sysex_element(sysex.DONGLE_PREFIX, dongle_message) presentation_control = create_sysex_element( sysex.DONGLE_PREFIX, sysex.make_presentation_message(self.application)) self._handshake = HandshakeComponent( identity_control=identity_control, dongle_control=dongle_control, presentation_control=presentation_control, dongle=dongle) self._on_handshake_success.subject = self._handshake self._on_handshake_failure.subject = self._handshake self._start_handshake_task = self._tasks.add( task.sequence(task.wait(HANDSHAKE_DELAY), task.run(self._start_handshake))) self._start_handshake_task.kill() def _init_user(self): super(Push, self)._init_user() self._on_push_hardware_mode_changed.subject = self._user self._update_pad_params() def _with_firmware_version(self, major_version, minor_version, control_element): return MinimumFirmwareVersionElement(major_version, minor_version, control_element, self._handshake) def _start_handshake(self): self._start_handshake_task.kill() self.elements.playhead_element.proxied_object = self._c_instance.playhead self.elements.velocity_levels_element.proxied_object = self._c_instance.velocity_levels self.elements.full_velocity_element.proxied_object = self._c_instance.full_velocity self._note_repeat_enabler.set_note_repeat(self._c_instance.note_repeat) for control in self.controls: receive_value_backup = getattr(control, '_receive_value_backup', nop) if receive_value_backup != nop: control.receive_value = receive_value_backup send_midi_backup = getattr(control, '_send_midi_backup', nop) if send_midi_backup != nop: control.send_midi = send_midi_backup self._handshake._start_handshake() self.update() @listens('success') def _on_handshake_success(self): logger.info('Handshake succeded with firmware version %.2f!' % self._handshake.firmware_version) self.update() self._c_instance.set_firmware_version(self._handshake.firmware_version) if self._handshake.has_version_requirements(1, 16): self._user.settings = self._settings else: settings = copy(self._settings) del settings['aftertouch_threshold'] self._user.settings = settings self._Push__on_aftertouch_mode(self._settings['aftertouch_mode'].value) @listens('failure') def _on_handshake_failure(self, bootloader_mode): logger.error('Handshake failed, performing harakiri!') if bootloader_mode: self._c_instance.set_firmware_version(0.0) self._c_instance.playhead.enabled = False self.elements.playhead_element.proxied_object = NullPlayhead() self._c_instance.velocity_levels.enabled = False self.elements.velocity_levels_element.proxied_object = NullVelocityLevels( ) self._c_instance.full_velocity.enabled = False self.elements.full_velocity_element.proxied_object = NullFullVelocity() self._note_repeat_enabler.set_note_repeat(None) for control in self.controls: receive_value_backup = getattr(control, 'receive_value', nop) send_midi_backup = getattr(control, 'send_midi', nop) try: control.receive_value = nop if receive_value_backup != nop: control._receive_value_backup = receive_value_backup control.send_midi = nop if send_midi_backup != nop: control._send_midi_backup = send_midi_backup except AttributeError: pass @listens('mode') def _on_push_hardware_mode_changed(self, mode): if mode == LIVE_MODE: if self._start_handshake_task.is_running: self._start_handshake() elif self._handshake.handshake_succeeded: self.update() def _create_background_layer(self): return super(Push, self)._create_background_layer() + Layer( display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', in_button='in_button', out_button='out_button', pad_parameters=(self._pad_parameter_control)) def _create_message_box_background_layer(self): return super(Push, self)._create_message_box_background_layer( ) + BackgroundLayer( 'in_button', 'out_button', priority=(consts.MESSAGE_BOX_PRIORITY)) def _create_track_frozen_layer(self): return Layer(display='display_line2', _notification=(self._notification.use_full_display(1))) def _create_notification_component(self): return NotificationComponent(display_lines='display_lines', is_enabled=True) def _create_message_box_layer(self): return Layer(display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', cancel_button='select_buttons_raw[-1]', priority=(consts.MESSAGE_BOX_PRIORITY)) def _create_clip_mode(self): return [self._track_modes, (self._mixer, self._mixer_layer)] + super( Push, self)._create_clip_mode() def _create_clip_loop_layer(self): return super(Push, self)._create_clip_loop_layer() + Layer( name_display=(self.elements.display_line1.subdisplay[:36]), value_display=(self.elements.display_line2.subdisplay[:36])) def _create_clip_audio_layer(self): return super(Push, self)._create_clip_audio_layer() + Layer( name_display=(self.elements.display_line1.subdisplay[36:]), value_display=(self.elements.display_line2.subdisplay[36:])) def _create_clip_name_layer(self): return super(Push, self)._create_clip_name_layer() + Layer( display='display_line3') def _init_track_modes(self): self._track_modes = ModesComponent(name='Track_Modes') self._track_modes.set_enabled(False) self._track_modes.add_mode( 'stop', AddLayerMode(self._stop_clips, self._stop_track_clips_layer)) self._track_modes.add_mode( 'solo', AddLayerMode(self._mixer, self._mixer_solo_layer)) self._track_modes.add_mode( 'mute', AddLayerMode(self._mixer, self._mixer_mute_layer)) self._track_modes.layer = self._create_track_modes_layer() self._track_modes.selected_mode = 'mute' def _browser_back_to_top(self): self._browser_mode.component.back_to_top() def _browser_reset_load_memory(self): self._browser_mode.component.reset_load_memory() def _init_browser(self): self._browser_mode = BrowserMode(self._create_browser, self._scales_enabler) self._browser_hotswap_mode = MultiEntryMode( BrowserHotswapMode(application=(self.application))) self._on_browse_mode_changed.subject = self.application.view def _create_main_mixer_modes(self): self._main_modes.add_mode('volumes', [ self._track_modes, (self._mixer, self._mixer_volume_layer), self._track_note_editor_mode ]) self._main_modes.add_mode('pan_sends', [ self._track_modes, (self._mixer, self._mixer_pan_send_layer), self._track_note_editor_mode ]) self._main_modes.add_mode('track', [ self._track_modes, self._track_mixer, (self._mixer, self._mixer_track_layer), self._track_note_editor_mode ]) def _init_browse_mode(self): self._main_modes.add_mode( 'browse', [ self._when_track_is_not_frozen( self._enable_stop_mute_solo_as_modifiers, partial(self._view_control.show_view, 'Browser'), self._browser_back_to_top, self._browser_hotswap_mode, self._browser_mode, self._browser_reset_load_memory) ], groups=['add_effect', 'add_track', 'browse'], behaviour=(mixin(DynamicBehaviourMixin, CancellableBehaviour)( lambda: not self._browser_hotswap_mode._mode.can_hotswap( ) and 'add_effect_left'))) self._main_modes.add_mode( 'add_effect_right', [ self._when_track_is_not_frozen( self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyEnablingMode(self._create_create_device_right)) ], behaviour=(mixin(ExcludingBehaviourMixin, CancellableBehaviour)(['add_track', 'browse'])), groups=['add_effect']) self._main_modes.add_mode( 'add_effect_left', [ self._when_track_is_not_frozen( self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyEnablingMode(self._create_create_device_left)) ], behaviour=(mixin(ExcludingBehaviourMixin, CancellableBehaviour)(['add_track', 'browse'])), groups=['add_effect']) self._main_modes.add_mode( 'add_instrument_track', [ self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyEnablingMode(self._create_create_instrument_track) ], behaviour=mixin(ExcludingBehaviourMixin, AlternativeBehaviour)( excluded_groups=['browse', 'add_effect'], alternative_mode='add_default_track'), groups=['add_track']) self._main_modes.add_mode('add_default_track', [ self._enable_stop_mute_solo_as_modifiers, self._browser_back_to_top, LazyEnablingMode(self._create_create_default_track) ], groups=['add_track']) self._main_modes.add_effect_right_button.mode_unselected_color = self._main_modes.add_effect_left_button.mode_unselected_color = self._main_modes.add_instrument_track_button.mode_unselected_color = 'DefaultButton.On' @listens('browse_mode') def _on_browse_mode_changed(self): if self.application.browser.hotswap_target or ( self._main_modes.selected_mode == 'browse' or self._browser_hotswap_mode.is_entered): self._main_modes.selected_mode = 'device' def _create_browser(self): state_buttons = self.elements.track_state_buttons.submatrix[:7, :] browser = BrowserComponent( name='Browser', is_enabled=False, layer=Layer( encoder_controls='global_param_controls', display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', enter_button='in_button', exit_button='out_button', select_buttons='select_buttons', state_buttons=state_buttons, shift_button=(WithPriority(consts.SHARED_PRIORITY, 'shift_button')), prehear_button='track_state_buttons_raw[7]', _notification=(self._notification.use_full_display(2))), make_browser_model=make_browser_model, preferences=(self.preferences)) return browser def _create_create_device_right(self): return CreateDeviceComponent( name='Create_Device_Right', browser_component=(self._browser_mode.component), browser_mode=(self._browser_mode), browser_hotswap_mode=(self._browser_hotswap_mode), insert_left=False, is_enabled=False) def _create_create_device_left(self): return CreateDeviceComponent( name='Create_Device_Right', browser_component=(self._browser_mode.component), browser_mode=(self._browser_mode), browser_hotswap_mode=(self._browser_hotswap_mode), insert_left=True, is_enabled=False) def _create_create_default_track(self): create_default_track = CreateDefaultTrackComponent( name='Create_Default_Track', is_enabled=False) create_default_track.options.layer = Layer( display_line='display_line4', label_display_line='display_line3', blank_display_line2='display_line2', blank_display_line1='display_line1', select_buttons='select_buttons', state_buttons='track_state_buttons', priority=(consts.DIALOG_PRIORITY)) return create_default_track def _create_create_instrument_track(self): return CreateInstrumentTrackComponent( name='Create_Instrument_Track', browser_component=(self._browser_mode.component), browser_mode=(self._browser_mode), browser_hotswap_mode=(self._browser_hotswap_mode), is_enabled=False) def _create_device_mode(self): return [ self._when_track_is_not_frozen( self._enable_stop_mute_solo_as_modifiers, partial(self._view_control.show_view, 'Detail/DeviceChain'), self._device_parameter_component, self._device_navigation, self._device_note_editor_mode) ] def _create_scales(self): scales = InstrumentScalesComponent( note_layout=(self._note_layout), is_enabled=False, name='Scales', layer=( BackgroundLayer('display_line1', 'display_line2', priority=(consts.DIALOG_PRIORITY)), Layer( scale_line1=(self.elements.display_line1.subdisplay[:18]), scale_line2=(self.elements.display_line2.subdisplay[:18]), scale_line3=(self.elements.display_line3.subdisplay[:9]), scale_line4=(self.elements.display_line4.subdisplay[:9]), top_display_line=( self.elements.display_line3.subdisplay[9:]), bottom_display_line=( self.elements.display_line4.subdisplay[9:]), top_buttons='select_buttons', bottom_buttons='track_state_buttons', encoder_controls='global_param_controls', _notification=(self._notification.use_single_line( 0, get_slice[18:], align_right)), priority=(consts.DIALOG_PRIORITY)), Layer(presets_toggle_button='shift_button'))) scales.presets_layer = ( BackgroundLayer('track_state_buttons', 'global_param_controls', 'display_line1', 'display_line2', priority=(consts.DIALOG_PRIORITY)), Layer(top_display_line='display_line3', bottom_display_line='display_line4', top_buttons='select_buttons', _notification=(self._notification.use_single_line(0)), priority=(consts.DIALOG_PRIORITY))) return scales def _create_scales_enabler(self): return EnablingModesComponent( component=(self._create_scales()), enabled_color='DefaultButton.On', is_enabled=False, layer=Layer(cycle_mode_button='scale_presets_button')) def _create_drum_component(self): return DrumGroupComponent(name='Drum_Group', is_enabled=False, quantizer=(self._quantize), selector=(self._selector)) def _create_note_settings_component_layer(self): return Layer(top_display_line='display_line1', bottom_display_line='display_line2', info_display_line='display_line3', clear_display_line='display_line4', full_velocity_button='accent_button', priority=(consts.MOMENTARY_DIALOG_PRIORITY)) def _create_note_editor_track_automation_layer(self): return super( Push, self)._create_note_editor_track_automation_layer() + Layer( name_display_line='display_line1', graphic_display_line='display_line2', value_display_line='display_line3', priority=(consts.MOMENTARY_DIALOG_PRIORITY)) def _create_note_editor_device_automation_layer(self): return super( Push, self)._create_note_editor_device_automation_layer() + Layer( name_display_line='display_line1', value_display_line='display_line2', graphic_display_line='display_line3', priority=(consts.MOMENTARY_DIALOG_PRIORITY)) def _init_stop_clips_action(self): self._stop_clips = StopClipComponent(session_ring=(self._session_ring), name='Stop_Clip') self._stop_clips.layer = Layer(stop_all_clips_button=( self._with_shift('global_track_stop_button'))) self._stop_track_clips_layer = Layer( stop_track_clips_buttons='track_state_buttons') def _init_quantize_actions(self): self._quantize = self._for_non_frozen_tracks( QuantizationComponent( name='Selected_Clip_Quantize', settings_class=(self.quantization_settings_class), is_enabled=False, layer=Layer(action_button='quantize_button'))) self._quantize.settings.layer = ( BackgroundLayer('global_param_controls', 'select_buttons', 'track_state_buttons', priority=(consts.MOMENTARY_DIALOG_PRIORITY)), Layer( swing_amount_encoder='parameter_controls_raw[0]', quantize_to_encoder='parameter_controls_raw[1]', quantize_amount_encoder='parameter_controls_raw[2]', record_quantization_encoder='parameter_controls_raw[7]', record_quantization_toggle_button='track_state_buttons_raw[7]', display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', priority=(consts.MOMENTARY_DIALOG_PRIORITY))) def _init_fixed_length(self): super(Push, self)._init_fixed_length() self._fixed_length.settings_component.layer = ( BackgroundLayer( (self.elements.track_state_buttons.submatrix[:7, :]), 'display_line1', 'display_line2', priority=(consts.MOMENTARY_DIALOG_PRIORITY)), Layer(length_option_buttons='select_buttons', label_display_line='display_line3', option_display_line='display_line4', legato_launch_toggle_button='track_state_buttons_raw[7]', _notification=(self._notification.use_single_line(1)), priority=(consts.MOMENTARY_DIALOG_PRIORITY))) def _create_note_repeat_layer(self): return super(Push, self)._create_note_repeat_layer() + Layer( pad_parameters=(self._pad_parameter_control), priority=(consts.DIALOG_PRIORITY)) def _create_user_component(self): sysex_control = create_sysex_element(sysex.MODE_CHANGE) user = UserComponent(value_control=sysex_control) user.layer = Layer(action_button='user_button') user.settings_layer = Layer(display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', encoders='global_param_controls') user.settings_layer.priority = consts.DIALOG_PRIORITY return user def _init_value_components(self): super(Push, self)._init_value_components() self._swing_amount.display.layer = ( BackgroundLayer('display_line4', priority=(consts.DIALOG_PRIORITY)), Layer(label_display='display_line1', value_display='display_line3', graphic_display='display_line2', priority=(consts.DIALOG_PRIORITY))) self._tempo.display.layer = (BackgroundLayer( 'display_line3', 'display_line4', priority=(consts.DIALOG_PRIORITY)), Layer(label_display='display_line1', value_display='display_line2', priority=(consts.DIALOG_PRIORITY))) self._master_vol.display.layer = ( BackgroundLayer('display_line4', priority=(consts.DIALOG_PRIORITY)), Layer(label_display='display_line1', value_display='display_line3', graphic_display='display_line2', priority=(consts.DIALOG_PRIORITY))) self._master_cue_vol.display.layer = ( BackgroundLayer('display_line4', priority=(consts.DIALOG_PRIORITY)), Layer(label_display='display_line1', value_display='display_line3', graphic_display='display_line2', priority=(consts.DIALOG_PRIORITY))) def _create_note_mode(self): return super(Push, self)._create_note_mode() + [ self._percussion_instrument_finder, self._global_pad_parameters ] def _instantiate_session(self): return SpecialSessionComponent( session_ring=(self._session_ring), is_enabled=False, auto_name=True, fixed_length_recording=(self._create_fixed_length_recording()), layer=(self._create_session_layer())) def _create_session_mode(self): return [ self._session_overview_mode, self._session_mode, self._session_navigation ] def _create_session_overview_layer(self): return Layer(button_matrix='shifted_matrix') def _set_session_skin(self, session): session.set_rgb_mode(LIVE_COLORS_TO_MIDI_VALUES, RGB_COLOR_TABLE, clip_slots_only=True) def _on_selected_track_changed(self): super(Push, self)._on_selected_track_changed() self._main_modes.pop_groups(['add_effect']) def _init_main_modes(self): super(Push, self)._init_main_modes() self._Push__on_main_mode_button_value.replace_subjects([ self.elements.vol_mix_mode_button, self.elements.pan_send_mix_mode_button, self.elements.single_track_mix_mode_button, self.elements.clip_mode_button, self.elements.device_mode_button, self.elements.browse_mode_button ]) def _create_mixer_layer(self): return Layer(track_select_buttons='select_buttons', track_names_display='display_line4') def _create_mixer_solo_layer(self): return Layer(solo_buttons='track_state_buttons') def _create_mixer_mute_layer(self): return Layer(mute_buttons='track_state_buttons') def _create_mixer_pan_send_layer(self): return Layer(track_select_buttons='select_buttons', pan_send_toggle='pan_send_mix_mode_button', pan_send_controls='fine_grain_param_controls', track_names_display='display_line4', pan_send_names_display='display_line1', pan_send_graphics_display='display_line2', selected_track_name_display='display_line3', pan_send_values_display=(ComboElement( 'display_line3', 'any_touch_button'))) def _create_mixer_volume_layer(self): return Layer(track_select_buttons='select_buttons', volume_controls='fine_grain_param_controls', track_names_display='display_line4', volume_names_display='display_line1', volume_graphics_display='display_line2', selected_track_name_display='display_line3', volume_values_display=(ComboElement( 'display_line3', 'any_touch_button'))) def _create_mixer_track_layer(self): return Layer(track_select_buttons='select_buttons', selected_track_name_display='display_line3', track_names_display='display_line4') def _init_mixer(self): self._mixer = SpecialMixerComponent( tracks_provider=(self._session_ring)) self._mixer.set_enabled(False) self._mixer.name = 'Mixer' self._mixer_layer = self._create_mixer_layer() self._mixer_pan_send_layer = self._create_mixer_pan_send_layer() self._mixer_volume_layer = self._create_mixer_volume_layer() self._mixer_track_layer = self._create_mixer_track_layer() self._mixer_solo_layer = self._create_mixer_solo_layer() self._mixer_mute_layer = self._create_mixer_mute_layer() for track in range(self.elements.matrix.width()): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) strip.set_invert_mute_feedback(True) strip.set_delete_handler(self._delete_component) strip._do_select_track = self.on_select_track strip.layer = Layer(shift_button='shift_button', duplicate_button='duplicate_button', selector_button='select_button') self._mixer.selected_strip().name = 'Selected_Channel_strip' self._mixer.master_strip().name = 'Master_Channel_strip' self._mixer.master_strip()._do_select_track = self.on_select_track self._mixer.master_strip().layer = Layer( select_button='master_select_button', selector_button='select_button') self._mixer.set_enabled(True) def _create_track_mixer_layer(self): return super(Push, self)._create_track_mixer_layer() + Layer( name_display_line='display_line1', graphic_display_line='display_line2', value_display_line=(ComboElement('display_line3', 'any_touch_button'))) def _create_device_parameter_layer(self): return super(Push, self)._create_device_parameter_layer() + Layer( name_display_line='display_line1', value_display_line='display_line2', graphic_display_line=(ComboElement('display_line3', 'any_touch_button'))) def _create_device_navigation(self): return DeviceNavigationComponent( device_bank_registry=(self._device_bank_registry), banking_info=(self._banking_info), is_enabled=False, session_ring=(self._session_ring), layer=Layer(enter_button='in_button', exit_button='out_button', select_buttons='select_buttons', state_buttons='track_state_buttons', display_line='display_line4', _notification=(self._notification.use_single_line(2))), info_layer=Layer( display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', _notification=(self._notification.use_full_display(2))), delete_handler=(self._delete_component)) def _init_device(self): super(Push, self)._init_device() self._device_component.layer = Layer(shift_button='shift_button') @listens_group('value') def __on_main_mode_button_value(self, value, sender): if not value: self._scales_enabler.selected_mode = 'disabled' def _create_controls(self): self._create_pad_sensitivity_update() push_ref = weakref.ref(self) class Deleter(object): @property def is_deleting(_): if push_ref(): return push_ref()._delete_default_component.is_deleting raise RuntimeError( 'Attempting to check if Push is deleting when the Push instance is dead' ) def delete_clip_envelope(_, param): if push_ref(): return push_ref( )._delete_default_component.delete_clip_envelope(param) raise RuntimeError( 'Attempting to delete clip envelope when Push instance is dead' ) self.elements = Elements( deleter=(Deleter()), undo_handler=UndoStepHandler(song=(self.song)), pad_sensitivity_update=(self._pad_sensitivity_update), playhead=(self._c_instance.playhead), velocity_levels=(self._c_instance.velocity_levels), full_velocity=(self._c_instance.full_velocity)) def _create_pad_sensitivity_update(self): all_pad_sysex_control = create_sysex_element( sysex.ALL_PADS_SENSITIVITY_PREFIX) pad_sysex_control = create_sysex_element(sysex.PAD_SENSITIVITY_PREFIX) sensitivity_sender = pad_parameter_sender(all_pad_sysex_control, pad_sysex_control) self._pad_sensitivity_update = PadUpdateComponent( all_pads=(list(range(64))), parameter_sender=sensitivity_sender, default_profile=action_pad_sensitivity, update_delay=TIMER_DELAY) def _init_global_pad_parameters(self): self._pad_parameter_control = self._with_firmware_version( 1, 16, create_sysex_element( (sysex.PAD_PARAMETER_PREFIX), default_value=(sysex.make_pad_parameter_message()))) aftertouch_threshold = self._settings['aftertouch_threshold'].value self._global_pad_parameters = GlobalPadParameters( aftertouch_threshold=aftertouch_threshold, is_enabled=False, layer=Layer(pad_parameter=(self._pad_parameter_control))) @listens('value') def __on_pad_curve(self, _value): self._update_pad_params() @listens('value') def __on_pad_threshold(self, value): self._user.set_settings_info_text( '' if value >= CRITICAL_THRESHOLD_LIMIT else consts.MessageBoxText. STUCK_PAD_WARNING) self._update_pad_params() @listens('value') def __on_aftertouch_threshold(self, value): self._global_pad_parameters.aftertouch_threshold = value @listens('value') def __on_aftertouch_mode(self, value): mode = 'mono' if value else 'polyphonic' self._instrument.instrument.set_aftertouch_mode(mode) self._selected_note_instrument.set_aftertouch_mode(mode) def _update_pad_params(self): new_pad_parameters = make_pad_parameters( self._settings['curve'].value, self._settings['threshold'].value) self._pad_sensitivity_update.set_profile('instrument', new_pad_parameters) self._pad_sensitivity_update.set_profile('drums', new_pad_parameters) self._pad_sensitivity_update.set_profile('loop', action_pad_sensitivity) def _update_calibration(self): self._send_midi(sysex.CALIBRATION_SET) def update(self): self._update_calibration() super(Push, self).update()
class DS1(LividControlSurface): _sysex_id = 16 _model_name = 'DS1' def __init__(self, c_instance): super(DS1, self).__init__(c_instance) self._skin = Skin(DS1Colors) with self.component_guard(): self._define_sysex() self._setup_controls() self._setup_background() self._setup_m4l_interface() self._setup_session_control() self._setup_mixer_control() self._setup_transport_control() self._setup_device_control() self._setup_session_recording_component() self._setup_main_modes() def _initialize_script(self): super(DS1, self)._initialize_script() self._main_modes.set_enabled(True) self._main_modes.selected_mode = 'Main' def _initialize_hardware(self): super(DS1, self)._initialize_hardware() self.local_control_off.enter_mode() self.encoder_absolute_mode.enter_mode() self.encoder_speed_sysex.enter_mode() def _define_sysex(self): self.encoder_speed_sysex = SendLividSysexMode(livid_settings = self._livid_settings, call = 'set_encoder_mapping', message = ENCODER_SPEED) self.encoder_absolute_mode = SendLividSysexMode(livid_settings = self._livid_settings, call = 'set_encoder_encosion_mode', message = [2]) self.local_control_off = SendLividSysexMode(livid_settings = self._livid_settings, call = 'set_local_control', message = [0]) def _setup_controls(self): is_momentary = True optimized = True resource = PrioritizedResource self._fader = [MonoEncoderElement(mapping_feedback_delay = -1, msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = DS1_FADERS[index], name = 'Fader_' + str(index), num = index, script = self, optimized_send_midi = optimized, resource_type = resource) for index in range(8)] self._dial = [[MonoEncoderElement(mapping_feedback_delay = -1, msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = DS1_DIALS[x][y], name = 'Dial_' + str(x) + '_' + str(y), num = x + (y*5), script = self, optimized_send_midi = optimized, resource_type = resource) for x in range(8)] for y in range(5)] self._side_dial = [MonoEncoderElement(mapping_feedback_delay = -1, msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = DS1_SIDE_DIALS[x], name = 'Side_Dial_' + str(x), num = x, script = self, optimized_send_midi = optimized, resource_type = resource) for x in range(4)] self._encoder = [MonoEncoderElement(mapping_feedback_delay = -1, msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = DS1_ENCODERS[x], name = 'Encoder_' + str(x), num = x, script = self, optimized_send_midi = optimized, resource_type = resource) for x in range(4)] self._encoder_button = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = DS1_ENCODER_BUTTONS[index], name = 'EncoderButton_' + str(index), script = self, skin = self._skin, optimized_send_midi = optimized, resource_type = resource) for index in range(4)] self._master_fader = MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = DS1_MASTER, name = 'MasterFader', num = 0, script = self, optimized_send_midi = optimized, resource_type = resource) self._button = [MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = DS1_BUTTONS[index], name = 'Button_' + str(index), script = self, skin = self._skin, optimized_send_midi = optimized, resource_type = resource) for index in range(16)] self._grid = [[MonoButtonElement(is_momentary = is_momentary, msg_type = MIDI_NOTE_TYPE, channel = CHANNEL, identifier = DS1_GRID[x][y], name = 'Button_' + str(x) + '_' + str(y), script = self, skin = self._skin, optimized_send_midi = optimized, resource_type = resource) for x in range(3)] for y in range(3)] self._dummy = [MonoEncoderElement(msg_type = MIDI_CC_TYPE, channel = CHANNEL, identifier = 120+x, name = 'Dummy_Dial_' + str(x), num = x, script = self, optimized_send_midi = optimized, resource_type = resource) for x in range(5)] self._fader_matrix = ButtonMatrixElement(name = 'FaderMatrix', rows = [self._fader]) self._top_buttons = ButtonMatrixElement(name = 'TopButtonMatrix', rows = [self._button[:8]]) self._bottom_buttons = ButtonMatrixElement(name = 'BottomButtonMatrix', rows = [self._button[8:]]) self._dial_matrix = ButtonMatrixElement(name = 'DialMatrix', rows = self._dial) self._side_dial_matrix = ButtonMatrixElement(name = 'SideDialMatrix', rows = [self._side_dial]) self._encoder_matrix = ButtonMatrixElement(name = 'EncoderMatrix', rows = [self._encoder]) self._encoder_button_matrix = ButtonMatrixElement(name = 'EncoderButtonMatrix', rows = [self._encoder_button]) self._grid_matrix = ButtonMatrixElement(name = 'GridMatrix', rows = self._grid) self._selected_parameter_controls = ButtonMatrixElement(name = 'SelectedParameterControls', rows = [self._dummy + self._encoder[:1] + self._encoder[2:]]) def _setup_background(self): self._background = BackgroundComponent(name = 'Background') self._background.layer = Layer(priority = 0, fader_matrix = self._fader_matrix, top_buttons = self._top_buttons, bottom_buttons = self._bottom_buttons, dial_matrix = self._dial_matrix, side_dial_matrix = self._side_dial_matrix, encoder_button_matrix = self._encoder_button_matrix, grid_matrix = self._grid_matrix) self._background.set_enabled(True) def _setup_autoarm(self): self._auto_arm = AutoArmComponent(name='Auto_Arm') self._auto_arm.can_auto_arm_track = self._can_auto_arm_track def _tracks_to_use(self): return self.song.visible_tracks + self.song.return_tracks def _setup_session_control(self): self._session_ring = SessionRingComponent(num_tracks = 8, num_scenes = 1, tracks_to_use = self._tracks_to_use) self._session_ring.set_enabled(True) self._session_navigation = DS1SessionNavigationComponent(name = 'SessionNavigation', session_ring = self._session_ring) self._session_navigation._vertical_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation.layer = Layer(priority = 4, track_select_dial = ComboElement(control = self._encoder[1], modifier = [self._encoder_button[1]] ), up_button = self._grid[0][1], down_button = self._grid[0][2]) self._session_navigation.set_enabled(False) self._session = DS1SessionComponent(session_ring = self._session_ring, auto_name = True) hasattr(self._session, '_enable_skinning') and self._session._enable_skinning() self._session.layer = Layer(priority = 4, scene_launch_buttons = self._grid_matrix.submatrix[1:2, 1:2]) self._session.clips_layer = AddLayerMode(self._session, Layer(priority = 4, clip_launch_buttons = self._top_buttons, stop_track_clip_buttons = self._bottom_buttons)) self._session.set_enabled(False) def _setup_mixer_control(self): self._mixer = MonoMixerComponent(name = 'Mixer', num_returns = 2, tracks_provider = self._session_ring, track_assigner = simple_track_assigner, invert_mute_feedback = True, auto_name = True, enable_skinning = True) self._mixer.master_strip().set_volume_control(self._master_fader) self._mixer.set_prehear_volume_control(self._side_dial[3]) self._mixer.layer = Layer(volume_controls = self._fader_matrix, track_select_dial = self._encoder[1]) self._strip = [self._mixer.channel_strip(index) for index in range(8)] for index in range(8): self._strip[index].layer = Layer(priority = 4, parameter_controls = self._dial_matrix.submatrix[index:index+1, :]) self._mixer.selected_strip().layer = Layer(priority = 4, parameter_controls = self._selected_parameter_controls) self._mixer.master_strip().layer = Layer(priority = 4, parameter_controls = self._side_dial_matrix.submatrix[:3, :]) self._mixer.main_layer = AddLayerMode(self._mixer, Layer(priority = 4, solo_buttons = self._bottom_buttons, mute_buttons = self._top_buttons)) self._mixer.select_layer = AddLayerMode(self._mixer, Layer(priority = 4, arm_buttons = self._bottom_buttons, track_select_buttons = self._top_buttons)) self.song.view.selected_track = self._mixer.channel_strip(0)._track self._mixer.set_enabled(False) def _setup_transport_control(self): self._transport = DS1TransportComponent() self._transport.name = 'Transport' self._transport._record_toggle.view_transform = lambda value: 'Transport.RecordOn' if value else 'Transport.RecordOff' self._transport.layer = Layer(priority = 4, stop_button = self._grid[1][0], play_button = self._grid[0][0], record_button = self._grid[2][0]) self._transport.set_enabled(True) def _setup_device_control(self): self._device = DeviceComponent(name = 'Device_Component', device_provider = self._device_provider, device_bank_registry = DeviceBankRegistry()) self._device_navigator = DeviceNavigator(self._device_provider, self._mixer, self) self._device_navigator.name = 'Device_Navigator' def _setup_session_recording_component(self): self._clip_creator = ClipCreator() self._clip_creator.name = 'ClipCreator' self._recorder = SessionRecordingComponent(ViewControlComponent()) self._recorder.set_enabled(True) self._recorder.layer = Layer(priority = 4, automation_button = self._grid[1][2], record_button = self._grid[2][1],) def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent(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 _setup_translations(self): controls = [] for control in self.controls: controls.append(control) self._translations = TranslationComponent(controls, 10) self._translations.name = 'TranslationComponent' self._translations.set_enabled(False) def _setup_main_modes(self): self._main_modes = ModesComponent(name = 'MainModes') self._main_modes.add_mode('Main', [self._mixer, self._mixer.main_layer, self._session, self._session_navigation], cycle_mode_button_color = 'ModeButtons.Main') self._main_modes.add_mode('Select', [self._mixer, self._mixer.select_layer, self._session, self._session_navigation], cycle_mode_button_color = 'ModeButtons.Select') self._main_modes.add_mode('Clips', [self._mixer, self._session, self._session.clips_layer, self._session_navigation], cycle_mode_button_color = 'ModeButtons.Clips') self._main_modes.layer = Layer(priority = 4, cycle_mode_button = self._grid[2][2]) self._main_modes.selected_mode = 'Main' self._main_modes.set_enabled(False) def _can_auto_arm_track(self, track): routing = track.current_input_routing return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith('DS1 Input') #self._main_modes.selected_mode in ['Sends', 'Device'] and # a
class Minim(LividControlSurface): _sysex_id = 18 _model_name = 'Minim' def __init__(self, c_instance, *a, **k): super(Minim, self).__init__(c_instance, *a, **k) self._shift_latching = LatchingShiftedBehaviour if SHIFT_LATCHING else ShiftedBehaviour self._skin = Skin(MinimColors) with self.component_guard(): self._define_sysex() self._setup_monobridge() self._setup_controls() self._setup_background() self._setup_autoarm() self._setup_viewcontrol() self._setup_session() self._setup_mixer() self._setup_transport() self._setup_recorder() self._setup_instrument() self._setup_modes() self._setup_m4l_interface() self.log_message( '<<<<<<<<<<<<<<<<<<<<<<<<< Minim log opened >>>>>>>>>>>>>>>>>>>>>>>>>' ) self.show_message('Minim Control Surface Loaded') self._background.set_enabled(True) def _check_connection(self): if not self._connected: debug(self._model_name, '_check_connection') self._livid_settings.new_query_surface() #self._connection_routine.restart() self.schedule_message(5, self._check_connection) def _initialize_hardware(self): debug('sending local control off') self.local_control_off.enter_mode() def _initialize_script(self): self._on_device_changed.subject = self._device_provider self._main_modes.set_enabled(True) self._main_modes.selected_mode = 'session' self._session_ring._update_highlight() self.refresh_state() def _setup_controls(self): is_momentary = True optimized = False resource = PrioritizedResource self._fader = MonoEncoderElement(msg_type=MIDI_CC_TYPE, channel=CHANNEL, identifier=MINIM_SLIDER, name='Fader', script=self, mapping_feedback_delay=-1, optimized_send_midi=optimized, resource_type=resource) self._pad = [[ MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=MINIM_PADS[row][column], name='Pad_' + str(column) + '_' + str(row), script=self, skin=self._skin, color_map=COLOR_MAP, optimized_send_midi=optimized, resource_type=resource) for column in range(4) ] for row in range(2)] self._button = [[ MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=MINIM_BUTTONS[row][column], name='Button_' + str(column) + '_' + str(row), script=self, skin=self._skin, color_map=COLOR_MAP, optimized_send_midi=optimized, resource_type=resource) for column in range(4) ] for row in range(2)] self._side_button = [ MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=MINIM_SIDE_BUTTONS[index], name='Side_Button_' + str(index), script=self, skin=self._skin, color_map=COLOR_MAP, optimized_send_midi=optimized, resource_type=resource) for index in range(5) ] self._top_button = [ MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=MINIM_TOP_BUTTONS[index], name='Top_Button_' + str(index), script=self, skin=self._skin, color_map=COLOR_MAP, optimized_send_midi=optimized, resource_type=resource) for index in range(2) ] self._bottom_button = MonoButtonElement(is_momentary=is_momentary, msg_type=MIDI_NOTE_TYPE, channel=CHANNEL, identifier=MINIM_BOTTOM_BUTTON, name='Bottom_Button', script=self, skin=self._skin, color_map=COLOR_MAP, optimized_send_midi=optimized, resource_type=resource) self._matrix = ButtonMatrixElement(name='Pad_Matrix', rows=[ self._button[:][0], self._pad[:][0], self._pad[:][1], self._button[:][1] ]) self._side_button_matrix = ButtonMatrixElement( name='Side_Button_Matrix', rows=[self._side_button]) self._top_button_matrix = ButtonMatrixElement(name='Button_Matrix', rows=[self._top_button]) def _setup_background(self): self._background = BackgroundComponent() self._background.layer = Layer( priority=3, matrix=self._matrix.submatrix[:, :], side_buttons=self._side_button_matrix, top_buttons=self._top_button_matrix.submatrix[:, :], bottom_button=self._bottom_button) self._background.set_enabled(False) def _define_sysex(self): self._livid_settings = LividSettings(model=18, control_surface=self) self.local_control_off = SendLividSysexMode( livid_settings=self._livid_settings, call='set_local_control', message=[42, 42]) def _setup_autoarm(self): self._auto_arm = AutoArmComponent(name='Auto_Arm') self._auto_arm.can_auto_arm_track = self._can_auto_arm_track self._auto_arm._update_notification = lambda: None def _setup_viewcontrol(self): self._viewcontrol = ViewControlComponent() self._viewcontrol.layer = Layer(priority=4, prev_track_button=self._top_button[0], next_track_button=self._top_button[1]) self._viewcontrol.set_enabled(False) def _setup_transport(self): self._transport = TransportComponent(name='Transport') self._transport.layer = Layer( priority=4, play_button=self._side_button[0] ) #, overdub_button = self._side_button[1]) self._transport.set_enabled(False) def _setup_mixer(self): self._mixer = MonoMixerComponent( name='Mixer', tracks_provider=self._session_ring, track_assigner=SimpleTrackAssigner(), invert_mute_feedback=True, auto_name=True, enable_skinning=True, channel_strip_component_type=MonoChannelStripComponent) self._mixer._selected_strip.layer = Layer(priority=4, volume_control=self._fader) self._mixer.solo_mute_record_stop_layer = AddLayerMode( self._mixer, Layer( priority=4, mute_buttons=self._matrix.submatrix[:, 0], solo_buttons=self._matrix.submatrix[:, 1], arm_buttons=self._matrix.submatrix[:, 2], )) self._mixer.select_layer = AddLayerMode( self._mixer, Layer(priority=4, arming_track_select_buttons=self._matrix.submatrix[:, 3])) self._mixer.mute_layer = AddLayerMode( self._mixer, Layer(priority=4, mute_buttons=self._matrix.submatrix[:, 3])) def _setup_session(self): self._session_ring = SessionRingComponent(name='Session_Ring', num_tracks=4, num_scenes=4) self._session = SessionComponent(name='Session', session_ring=self._session_ring, auto_name=True) self._session.cliplaunch_layer = AddLayerMode( self._session, Layer(priority=4, clip_launch_buttons=self._matrix.submatrix[:, :])) self._session.stop_layer = AddLayerMode( self._session, Layer(priority=4, stop_track_clip_buttons=self._matrix.submatrix[:, 3])) self._session_navigation = SessionNavigationComponent( name='Session_Navigation', session_ring=self._session_ring) self._session_navigation._horizontal_layer = AddLayerMode( self._session_navigation, Layer(priority=4, left_button=self._top_button[0], right_button=self._top_button[1])) self._session_navigation._vertical_layer = AddLayerMode( self._session_navigation, Layer(priority=4, up_button=self._top_button[0], down_button=self._top_button[1])) self._session_navigation.set_enabled(False) def _setup_recorder(self): self._recorder = SessionRecordingComponent( view_controller=self._viewcontrol) self._recorder.layer = Layer(priority=4, new_button=self._side_button[2], record_button=self._side_button[1]) self._recorder.set_enabled(False) def _setup_instrument(self): self._grid_resolution = GridResolution() self._c_instance.playhead.enabled = True self._playhead_element = PlayheadElement(self._c_instance.playhead) self._drum_group_finder = PercussionInstrumentFinder( device_parent=self.song.view.selected_track) self._instrument = MinimMonoInstrumentComponent( name='InstrumentComponent', script=self, skin=self._skin, drum_group_finder=self._drum_group_finder, grid_resolution=self._grid_resolution, settings=DEFAULT_INSTRUMENT_SETTINGS, device_provider=self._device_provider, parent_task_group=self._task_group) self._instrument._drumpad._drumgroup._button_coordinates_to_pad_index = lambda first_note, coordinates: coordinates[ 1] + (abs(coordinates[0] - 1) * 4) + first_note self._instrument._drumpad._drumgroup.create_translation_entry = lambda button: ( button.coordinate[1], button.coordinate[ 0] + 2, button.identifier, button.channel) self._instrument.layer = Layer(priority=6, shift_button=self._side_button[3]) self._instrument.keypad_options_layer = AddLayerMode( self._instrument, Layer( priority=6, scale_up_button=self._button[0][3], scale_down_button=self._button[0][2], offset_up_button=self._button[0][1], offset_down_button=self._button[0][0], )) #vertical_offset_up_button = self._top_button[1], #vertical_offset_down_button = self._top_button[0])) self._instrument.drumpad_options_layer = AddLayerMode( self._instrument, Layer( priority=6, scale_up_button=self._button[0][3], scale_down_button=self._button[0][2], drum_offset_up_button=self._button[0][1], drum_offset_down_button=self._button[0][0], )) self._instrument._keypad.main_layer = LayerMode( self._instrument._keypad, Layer(priority=6, keypad_matrix=self._matrix.submatrix[:, 1:3])) self._instrument._keypad.select_layer = LayerMode( self._instrument._keypad, Layer(priority=6, keypad_select_matrix=self._matrix.submatrix[:, 1:3])) self._instrument._drumpad.main_layer = LayerMode( self._instrument._drumpad, Layer(priority=6, drumpad_matrix=self._matrix.submatrix[:, 1:3])) self._instrument._drumpad.select_layer = LayerMode( self._instrument._drumpad, Layer(priority=6, drumpad_select_matrix=self._matrix.submatrix[:, 1:3])) self._instrument._main_modes = ModesComponent(name='InstrumentModes') self._instrument._main_modes.add_mode('disabled', []) self._instrument._main_modes.add_mode('drumpad', [ self._instrument._drumpad, self._instrument._drumpad.main_layer, self._instrument.drumpad_options_layer ]) self._instrument._main_modes.add_mode('drumpad_shifted', [ self._instrument._drumpad, self._instrument._drumpad.select_layer, self._instrument.drumpad_options_layer ]) self._instrument._main_modes.add_mode('keypad', [ self._instrument._keypad, self._instrument._keypad.main_layer, self._instrument.keypad_options_layer ]) self._instrument._main_modes.add_mode('keypad_shifted', [ self._instrument._keypad, self._instrument._keypad.select_layer, self._instrument.keypad_options_layer ]) #self._instrument.register_component(self._instrument._main_modes) self._instrument.set_enabled(False) #self._instrument.audioloop_layer = LayerMode(self._instrument, Layer(priority = 6, loop_selector_matrix = self._base_grid)) def _setup_modes(self): self._main_modes = ModesComponent(name='MainModes') self._main_modes.add_mode('disabled', []) self._main_modes.add_mode( 'session_shifted', [ self._recorder, self._mixer, self._mixer.solo_mute_record_stop_layer, self._session, self._session.stop_layer, self._session_navigation, self._session_navigation._vertical_layer, self._transport ], groups=['shifted'], behaviour=self._shift_latching(color='Mode.Session')) self._main_modes.add_mode( 'session', [ self._recorder, self._mixer, self._session, self._session.cliplaunch_layer, self._session_navigation, self._session_navigation._horizontal_layer, self._transport ], behaviour=self._shift_latching(color='Mode.Session')) self._main_modes.add_mode( 'instrument_shifted', [ self._recorder, self._mixer, self._mixer.mute_layer, self._viewcontrol, self._instrument, self._transport ], groups=['shifted'], behaviour=self._shift_latching(color='Mode.Instrument')) self._main_modes.add_mode( 'instrument', [ self._recorder, self._mixer, self._mixer.select_layer, self._viewcontrol, self._instrument, self._transport ], behaviour=self._shift_latching(color='Mode.Instrument')) self._main_modes.layer = Layer(priority=6, session_button=self._side_button[4], instrument_button=self._side_button[3]) self._main_modes.set_enabled(False) self._main_modes.selected_mode = 'disabled' def _can_auto_arm_track(self, track): routing = track.current_input_routing return routing == 'Ext: All Ins' or routing == 'All Ins' or routing.startswith( 'Livid Minim Input') def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent( controls=self.controls, component_guard=self.component_guard) self.get_control_names = self._m4l_interface.get_control_names self.get_control = self._m4l_interface.get_control self.grab_control = self._m4l_interface.grab_control self.release_control = self._m4l_interface.release_control @listens('device') def _on_device_changed(self): pass def disconnect(self): self.log_message( '<<<<<<<<<<<<<<<<<<<<<<<<< Minim log closed >>>>>>>>>>>>>>>>>>>>>>>>>' ) super(Minim, self).disconnect() def handle_sysex(self, midi_bytes): #debug('sysex: ', str(midi_bytes)) #debug('matching:', midi_bytes[1:5], 'to', tuple([0, 1, 97] + [self._sysex_id])) if len(midi_bytes) == 9 and midi_bytes[1:5] == tuple([0, 1, 97] + [self._sysex_id]): if not self._connected: #debug('connecting from sysex...') self._connected = True self._initialize_hardware() self._initialize_script()
class 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.shift_button.set_control_element(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) @listens('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) @listens('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 OhmModesRay(OhmModes): _sysex_id = 2 _alt_sysex_id = 7 _model_name = 'Ohm' _version_check = 'b996' _host_name = 'Ohm' device_provider_class = ModDeviceProvider def __init__(self, c_instance): super(OhmModes, self).__init__(c_instance) self._skin = Skin(OhmColors) with self.component_guard(): self._define_sysex() self._setup_controls() self._setup_background() self._setup_m4l_interface() #self._setup_translations() self._setup_session_control() self._setup_mixer_control() #self._setup_device_control() #self._setup_transport_control() #self._setup_drumgroup() #self._setup_keygroup() #self._setup_bassgroup() #self._setup_mod() #self._setup_modswitcher() self._setup_modes() #self._on_device_changed.subject = self._device_provider def _setup_session_control(self): self._session_ring = SessionRingComponent(num_tracks=7, num_scenes=7) self._session_ring.set_enabled(True) self._session_navigation = SessionNavigationComponent( session_ring=self._session_ring) self._session_navigation.scroll_navigation_layer = AddLayerMode( self._session_navigation, Layer(priority=5, up_button=self._menu[1], down_button=self._menu[4], left_button=self._menu[3], right_button=self._menu[5])) self._session_navigation.page_navigation_layer = AddLayerMode( self._session_navigation, Layer(priority=5, page_up_button=self._menu[2], page_down_button=self._menu[5], page_left_button=self._menu[3], page_right_button=self._menu[4])) self._session_navigation._vertical_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_up_button.color = 'Session.NavigationButtonOn' self._session_navigation._horizontal_banking.scroll_down_button.color = 'Session.NavigationButtonOn' self._session_navigation._vertical_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._vertical_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_up_button.color = 'Session.PageNavigationButtonOn' self._session_navigation._horizontal_paginator.scroll_down_button.color = 'Session.PageNavigationButtonOn' self._session_navigation.set_enabled(False) self._session = SpecialOhmSessionComponent( name='Session', session_ring=self._session_ring, auto_name=True) self._session.set_enabled(False) self._session.clip_launch_layer = AddLayerMode( self._session, Layer(priority=5, clip_launch_buttons=self._matrix.submatrix[:7, :7])) self._session.scene_launch_layer = AddLayerMode( self._session, Layer(priority=5, scene_launch_buttons=self._matrix.submatrix[7, :7])) self._session.stop_clips_layer = AddLayerMode( self._session, Layer(priority=5, stop_track_clip_buttons=self._matrix.submatrix[:7, 7], stop_all_clips_button=self._grid[7][7])) """self._session_zoom = SessionOverviewComponent(name = 'Session_Overview', session_ring = self._session_ring, enable_skinning = True) self._session_zoom.layer = Layer(priority = 5, button_matrix = self._matrix.submatrix[:7,:7]) self._session_zoom.set_enabled(False) self._session_modes = ModesComponent(name = 'Session_Modes') self._session_modes.add_mode('disabled', [self._session, self._session.clip_launch_layer, self._session.scene_launch_layer, self._session_navigation, self._session_navigation.scroll_navigation_layer]) self._session_modes.add_mode('enabled', [self._session, self._session.scene_launch_layer, self._session_zoom, self._session_navigation, self._session_navigation.page_navigation_layer], behaviour = DefaultedBehaviour()) self._session_modes.layer = Layer(priority = 5, enabled_button = self._grid[7][7]) self._session_modes.selected_mode = 'disabled' self._session_modes.set_enabled(False)""" def _setup_mixer_control(self): self._mixer = OhmMixerComponent(name='Mixer', tracks_provider=self._session_ring, track_assigner=simple_track_assigner, invert_mute_feedback=True, auto_name=True, enable_skinning=True) #self._mixer.layer = Layer(priority = 5, volume_controls = self._fader_matrix.submatrix[:7, :], prehear_volume_control = self._dial[15], crossfader_control = self._crossfader) self._mixer.layer = Layer( priority=5, solo_buttons=self._button_matrix.submatrix[:7, :]) """self._mixer.master_strip().layer = Layer(priority = 5, volume_control = self._fader[7], select_button = self._button[7]) self._mixer.mix_layer = AddLayerMode(self._mixer, Layer(priority = 5, mute_buttons = self._matrix.submatrix[:7,5], solo_buttons = self._matrix.submatrix[:7,6], arm_buttons = self._matrix.submatrix[:7,7], send_controls = self._dial_matrix.submatrix[:,:2], pan_controls = self._dial_matrix.submatrix[:7,2:], track_select_buttons = self._button_matrix.submatrix[:7,:],)) self._mixer.dj_layer = AddLayerMode(self._mixer, Layer(priority = 5, mute_buttons = self._matrix.submatrix[:7,5], crossfade_toggles = self._matrix.submatrix[:7,6], end_pan_controls = self._dial_matrix.submatrix[:3,3], eq_gain_controls = self._dial_matrix.submatrix[:,:3], track_select_buttons = self._button_matrix.submatrix[:7,:],)) self._mixer.instrument_layer = AddLayerMode(self._mixer, Layer(priority = 5, instrument_send_controls = self._dial_matrix.submatrix[:,2:], arming_track_select_buttons = self._button_matrix.submatrix[:7,:])) """ def _setup_modes(self): self._main_modes = ModesComponent(name='MainModes') self._main_modes.add_mode('disabled', [self._background]) self._main_modes.add_mode('Mix', [ self._mixer, self._session, self._session.stop_clips_layer, self._session.clip_launch_layer, self._session.scene_launch_layer, self._session_navigation, self._session_navigation.scroll_navigation_layer ]) self._main_modes.selected_mode = 'disabled' self._main_modes.set_enabled(True)