def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) self._device_selection_follows_track_selection = True self._suggested_input_port = 'Impulse' self._suggested_output_port = 'Impulse' self._has_sliders = True self._current_midi_map = None self._display_reset_delay = -1 self._shift_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 39) self._preview_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 41) self._master_slider = SliderElement(MIDI_CC_TYPE, 0, 8) self._shift_button.name = 'Shift_Button' self._master_slider.name = 'Master_Volume_Control' self._master_slider.add_value_listener(self._slider_value, identify_sender=True) self._preview_button.add_value_listener(self._preview_value) self._setup_mixer() self._setup_session() self._setup_transport() self._setup_device() self._setup_name_display() device_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1, 10) mixer_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1, 9) device_button.name = 'Encoder_Device_Mode' mixer_button.name = 'Encoder_Mixer_Mode' self._encoder_modes = EncoderModeSelector(self._device_component, self._mixer, self._next_bank_button, self._prev_bank_button, self._encoders) self._encoder_modes.set_device_mixer_buttons(device_button, mixer_button) self._string_to_display = None for component in self.components: component.set_enabled(False)
def _setup_global_control(self): is_momentary = True self._global_bank_buttons = [] self._global_param_controls = [] for index in range(8): ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 56 + index) ringed_encoder = RingedEncoderElement(MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute) ringed_encoder.name = 'Track_Control_' + str(index) ringed_encoder.set_feedback_delay(-1) ring_button.name = ringed_encoder.name + '_Ring_Mode_Button' ringed_encoder.set_ring_mode_button(ring_button) self._global_param_controls.append(ringed_encoder) self._global_bank_buttons = [] global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button') for index in range(4): self._global_bank_buttons.append(ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87 + index))#(not is_momentary, MIDI_NOTE_TYPE, 0, 87 + index)) self._global_bank_buttons[-1].name = global_bank_labels[index] self._encoder_modes = EncoderMixerModeSelectorComponent(self._mixer) self._encoder_modes.name = 'Track_Control_Modes' #self._encoder_modes.set_modes_buttons(self._global_bank_buttons) # set in ShiftableEncoderSelectorComponent self._encoder_modes.set_controls(tuple(self._global_param_controls)) #self._encoder_device_modes = EncoderDeviceModeSelectorComponent(self._mixer, self._device) #new self._encoder_device_modes = EncoderDeviceComponent(self._mixer, self._device, self) self._encoder_device_modes.name = 'Alt_Device_Control_Modes' #new self._encoder_eq_modes = EncoderEQComponent(self._mixer, self)#EncoderEQModeSelectorComponent(self._mixer) #new self._encoder_eq_modes.name = 'EQ_Control_Modes' #new global_translation_selector = ChannelTranslationSelector() #translate track encoders to channels 1 through 4, based on button selection (pan = 1, send A = 2, send B = 3, send C = 4) global_translation_selector.name = 'Global_Translations' global_translation_selector.set_controls_to_translate(tuple(self._global_param_controls)) global_translation_selector.set_mode_buttons(tuple(self._global_bank_buttons)) encoder_user_modes = EncoderUserModesComponent(self, self._encoder_modes, tuple(self._global_param_controls), tuple(self._global_bank_buttons), self._mixer, self._device, self._encoder_device_modes, self._encoder_eq_modes) #self._mixer, tuple(sliders)) #added encoder_user_modes.name = 'Encoder_User_Modes' #added self._encoder_shift_modes = ShiftableEncoderSelectorComponent(self, tuple(self._global_bank_buttons), encoder_user_modes, self._encoder_modes, self._encoder_eq_modes, self._encoder_device_modes) #tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, slider_modes, matrix_modes) #, self._send_introduction_message) #also added self for _parent self._encoder_shift_modes.name = 'Encoder_Shift_Modes' self._encoder_shift_modes.set_mode_toggle(self._shift_button)
def _setup_global_control(self): is_momentary = True global_bank_buttons = [] global_param_controls = [] for index in range(8): ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 56 + index) ringed_encoder = RingedEncoderElement(MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute) ringed_encoder.name = "Track_Control_" + str(index) ring_button.name = ringed_encoder.name + "_Ring_Mode_Button" ringed_encoder.set_ring_mode_button(ring_button) global_param_controls.append(ringed_encoder) global_bank_buttons = [] global_bank_labels = ("Pan_Button", "Send_A_Button", "Send_B_Button", "Send_C_Button") for index in range(4): global_bank_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87 + index)) global_bank_buttons[-1].name = global_bank_labels[index] encoder_modes = EncModeSelectorComponent(self._mixer) encoder_modes.name = "Track_Control_Modes" encoder_modes.set_modes_buttons(global_bank_buttons) encoder_modes.set_controls(tuple(global_param_controls)) global_translation_selector = ChannelTranslationSelector() global_translation_selector.name = "Global_Translations" global_translation_selector.set_controls_to_translate(tuple(global_param_controls)) global_translation_selector.set_mode_buttons(tuple(global_bank_buttons))
def _setup_custom_components(self): is_momentary = True master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) self._master_select_button = master_select_button master_select_button.name = 'Master_Select_Button' select_buttons = [] self._select_buttons = [] arm_buttons = [] sliders = [] for track in range(8): select_buttons.append(FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51, self)) self._select_buttons.append(select_buttons[track]) arm_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) if track is 7: self._user3 = arm_buttons[track] sliders.append(MonoEncoderElement2(MIDI_CC_TYPE, track, 7, Live.MidiMap.MapMode.absolute, 'Slider_' + str(track), track, self)) #sliders.append(MonoEncoderElement2(MIDI_CC_TYPE, track, 7)) select_buttons[-1].name = str(track) + '_Select_Button' arm_buttons[-1].name = str(track) + '_Arm_Button' #sliders[-1].name = str(track) + '_Volume_Control' transport = TransportComponent() transport.name = 'Transport' slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) slider_modes.name = 'Slider_Modes' self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message, self) self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button)
def set_touch_mode(self, touchchannel): self.touch_mode = True nr_dev_ctrl = len(self._parameter_controls) for ctrl in self._parameter_controls: touch_button = ButtonElement(False, MIDI_CC_TYPE, touchchannel, ctrl.message_identifier()) self.del_touch_buttons.append(touch_button) touch_button.add_value_listener(self._clear_param, True)
def _setup_mixer(self): mute_solo_flip_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 34) self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 37) self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 38) self._strip_buttons = [] mute_solo_flip_button.name = 'Mute_Solo_Flip_Button' self._next_nav_button.name = 'Next_Track_Button' self._prev_nav_button.name = 'Prev_Track_Button' self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button) self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.master_strip().set_volume_control(self._master_slider) self._sliders = [] for index in range(8): strip = self._mixer.channel_strip(index) strip.name = 'Channel_Strip_' + str(index) strip.set_invert_mute_feedback(True) self._sliders.append(SliderElement(MIDI_CC_TYPE, 0, index)) self._sliders[-1].name = str(index) + '_Volume_Control' self._sliders[-1].set_feedback_delay(-1) self._sliders[-1].add_value_listener(self._slider_value, identify_sender=True) strip.set_volume_control(self._sliders[-1]) self._strip_buttons.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + index)) self._strip_buttons[-1].name = str(index) + '_Mute_Button' self._strip_buttons[-1].add_value_listener(self._mixer_button_value, identify_sender=True) self._mixer.master_strip().set_mute_button(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 17)) self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)
def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._solo_buttons = [] for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, self) self._solo_buttons.append(solo_button) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) master_volume_control.name = 'Master_Volume_Control' prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_prehear_volume_control(prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control)
def _setup_mixer(self): self._selected_mute_solo_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 12) mute_solo_flip_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 57) self._strip_buttons = [] self._selected_mute_solo_button.name = "Selected_Mute_Button" mute_solo_flip_button.name = "Mute_Solo_Flip_Button" self._selected_mute_solo_button.add_value_listener(self._mixer_button_value, identify_sender=True) self._mixer = ShiftableMixerComponent(8) self._mixer.name = "Mixer" self._mixer.set_shift_button(self._shift_button) self._mixer.set_selected_mute_solo_button(self._selected_mute_solo_button) self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button) self._mixer.selected_strip().name = "Selected_Channel_Strip" self._mixer.master_strip().name = "Master_Channel_Strip" self._mixer.master_strip().set_volume_control(self._master_slider) self._sliders = [] for index in range(8): strip = self._mixer.channel_strip(index) strip.name = "Channel_Strip_" + str(index) strip.set_invert_mute_feedback(True) self._sliders.append(SliderElement(MIDI_CC_TYPE, 15, 33 + index)) self._sliders[-1].name = str(index) + "_Volume_Control" self._sliders[-1].set_feedback_delay(-1) self._sliders[-1].add_value_listener(self._slider_value, identify_sender=True) strip.set_volume_control(self._sliders[-1]) self._strip_buttons.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 49 + index)) self._strip_buttons[-1].name = str(index) + "_Mute_Button" self._strip_buttons[-1].add_value_listener(self._mixer_button_value, identify_sender=True) self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._monomod_version = 'b994' self.hosts = [] self._host_name = 'BlockPad' self._color_type = 'Monochrome' self._timer = 0 is_momentary = True self._suggested_input_port = 'block (Controls)' self._suggested_output_port = 'block (Controls)' self._wrote_user_byte = False matrix = ButtonMatrixElement() for row in range(8): button_row = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((column * 8) + row), 'Button_'+str(column)+'_'+str(row), self) for column in range(8) ] matrix.add_row(tuple(button_row)) knobs = [ EncoderElement(MIDI_CC_TYPE, 0, KNOB_CC[index], Live.MidiMap.MapMode.absolute) for index in range(8) ] sliders = [ EncoderElement(MIDI_CC_TYPE, 0, SLIDER_CC[index], Live.MidiMap.MapMode.absolute) for index in range(2) ] self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0) self._config_button.add_value_listener(self._config_value) top_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, TOP_NOTES[index], 'Top_Button'+str(index), self) for index in range(8) ] side_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index], 'Side_Button'+str(index), self) for index in range(8) ] self._setup_monobridge() self._setup_monomod() self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, tuple(knobs), tuple(sliders), self) self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self.set_enabled(True) self.log_message("--------------= BlockPad log opened =--------------") #Create entry in log file self.refresh_state()
def _setup_mixer_control(self): is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant num_tracks = 7 # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent(num_tracks, 0) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track mixer.selected_strip().set_mute_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 64)) #mixer.selected_strip().set_solo_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 44)) mixer.selected_strip().set_arm_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 72)) track_select_notes = [65, 73, 66, 74, 67, 75, 68, 76] #more note numbers need to be added if num_scenes is increased slider_select_notes = [23, 22, 15, 14, 5, 7, 6, 4] pan_select_notes = [21, 20, 13, 12, 3, 1, 0, 2] master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 4) master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 76) prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 26, Live.MidiMap.MapMode.absolute) crossfader = SliderElement(MIDI_CC_TYPE, 0, 24) for index in range(num_tracks): mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, track_select_notes[index])) mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL, slider_select_notes[index])) mixer.channel_strip(index).set_pan_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, pan_select_notes[index], Live.MidiMap.MapMode.absolute)) crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' master_select_button.name = 'Master_Select_Button' prehear_control.name = 'Prehear_Volume_Control' mixer.set_crossfader_control(crossfader) mixer.set_prehear_volume_control(prehear_control) mixer.master_strip().set_volume_control(master_volume_control) mixer.master_strip().set_select_button(master_select_button)
def send_value(self, value, force_send=False ): if value in self.blink_colors: self.blinking = value else: self.blinking = False if value is not None: ButtonElement.send_value(self, value, force_send)
def __init__(self, identifier): ButtonElement.__init__( self, momentary=True, msg_type=MIDI_NOTE_TYPE, channel=self.channel, identifier=identifier)
def _setup_global_control(self): is_momentary = True self._global_bank_buttons = [] self._global_param_controls = [] for index in range(8): ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 56 + index) ringed_encoder = RingedEncoderElement(MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute) ringed_encoder.name = 'Track_Control_' + str(index) ringed_encoder.set_feedback_delay(-1) ring_button.name = ringed_encoder.name + '_Ring_Mode_Button' ringed_encoder.set_ring_mode_button(ring_button) self._global_param_controls.append(ringed_encoder) self._global_bank_buttons = [] global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button') for index in range(4): self._global_bank_buttons.append(ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87 + index)) self._global_bank_buttons[-1].name = global_bank_labels[index] self._encoder_modes = EncModeSelectorComponent(self._mixer) self._encoder_modes.name = 'Track_Control_Modes' self._encoder_modes.set_controls(tuple(self._global_param_controls)) self._encoder_device_modes = EncoderDeviceComponent(self._mixer, self._device, self) self._encoder_device_modes.name = 'Alt_Device_Control_Modes' self._encoder_eq_modes = EncoderEQComponent(self._mixer, self) self._encoder_eq_modes.name = 'EQ_Control_Modes' global_translation_selector = ChannelTranslationSelector() global_translation_selector.name = 'Global_Translations' global_translation_selector.set_controls_to_translate(tuple(self._global_param_controls)) global_translation_selector.set_mode_buttons(tuple(self._global_bank_buttons)) encoder_user_modes = EncoderUserModesComponent(self, self._encoder_modes, tuple(self._global_param_controls), tuple(self._global_bank_buttons), self._mixer, self._device, self._encoder_device_modes, self._encoder_eq_modes) encoder_user_modes.name = 'Encoder_User_Modes' self._encoder_shift_modes = ShiftableEncoderSelectorComponent(self, tuple(self._global_bank_buttons), encoder_user_modes, self._encoder_modes, self._encoder_eq_modes, self._encoder_device_modes) self._encoder_shift_modes.name = 'Encoder_Shift_Modes' self._encoder_shift_modes.set_mode_toggle(self._shift_button)
def receive_value(self, value): self._is_notifying = True ButtonElement.receive_value(self, value) self._is_notifying = False for listener in self._pending_listeners: self.add_value_listener(listener[0], listener[1]) self._pending_listeners = []
def make_pad_button(pad_mode, pad_no, name): if pad_mode is PAD_MODE_CC: button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, PADS_CHANNEL, PADS_CC_START + pad_no) else: button = ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, PADS_CHANNEL, PADS_NOTES_START + pad_no) button.name = name return button
def button(notenr, name=None, color=None): if color is None: rv = ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, notenr) else: rv = ColorButton(True, MIDI_NOTE_TYPE, CHANNEL, notenr, color) if name: rv.name = name return rv
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._suppress_send_midi = True self._suppress_session_highlight = True is_momentary = True self._suggested_input_port = 'Launchpad' self._suggested_output_port = 'Launchpad' self._control_is_with_automap = False self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = 'User_Byte_Button' self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self._wrote_user_byte = False self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143 matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' for row in range(8): button_row = [] for column in range(8): button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, row * 16 + column) button.name = str(column) + '_Clip_' + str(row) + '_Button' button_row.append(button) matrix.add_row(tuple(button_row)) self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False) self._config_button.add_value_listener(self._config_value) top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index) for index in range(8) ] side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index]) for index in range(8) ] top_buttons[0].name = 'Bank_Select_Up_Button' top_buttons[1].name = 'Bank_Select_Down_Button' top_buttons[2].name = 'Bank_Select_Left_Button' top_buttons[3].name = 'Bank_Select_Right_Button' top_buttons[4].name = 'Session_Button' top_buttons[5].name = 'User1_Button' top_buttons[6].name = 'User2_Button' top_buttons[7].name = 'Mixer_Button' side_buttons[0].name = 'Vol_Button' side_buttons[1].name = 'Pan_Button' side_buttons[2].name = 'SndA_Button' side_buttons[3].name = 'SndB_Button' side_buttons[4].name = 'Stop_Button' side_buttons[5].name = 'Trk_On_Button' side_buttons[6].name = 'Solo_Button' side_buttons[7].name = 'Arm_Button' self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self) self._selector.name = 'Main_Modes' self._do_combine() for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.add_value_listener(self._button_value) self.set_highlighting_session_component(self._selector.session_component()) self._suppress_session_highlight = False #self.set_suppress_rebuild_requests(False) self.log_message("LaunchPad95 Loaded !")
def _setup_session_control(self): is_momentary = True self._shift_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98, 'Shift_Button', self) right_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96, 'Right_Button', self) self._right_button = right_button left_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97, 'Left_Button', self) self._left_button = left_button up_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94, 'Up_Button', self) self._up_button = up_button down_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95, 'Down_Button', self) self._down_button = down_button self._session = PedaledSessionComponent(8, 5) self._session.name = 'Session_Control' self._session.set_track_bank_buttons(right_button, left_button) self._session.set_scene_bank_buttons(down_button, up_button) matrix = ButtonMatrixElement() self._matrix = matrix # added a matrix.name = 'Button_Matrix' scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82)) for index in range(5) ] track_stop_buttons = [ AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52, 'Track_' + str(index) + '_Stop_Button', self) for index in range(8) ] self._track_stop_buttons = track_stop_buttons # added a for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_'+ str(index) + '_Launch_Button' stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) stop_all_button.name = 'Stop_All_Clips_Button' self._session.set_stop_all_clips_button(stop_all_button) self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session.set_stop_track_clip_value(2) for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53), str(track_index) + '_Clip_' + str(scene_index) + '_Button', self) #button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(5) clip_slot.set_started_value(1) clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) matrix.add_row(tuple(button_row)) self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = SessionZoomingComponent(self._session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button) self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5)
def _setup_device_and_transport_control(self): is_momentary = True device_bank_buttons = [] device_param_controls = [] bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Metronome_Button') for index in range(8): device_bank_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 58 + index)) device_bank_buttons[-1].name = bank_button_labels[index] ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 24 + index) ringed_encoder = MonoRingedEncoderElement(MIDI_CC_TYPE, 0, 16 + index, Live.MidiMap.MapMode.absolute, index, self) ringed_encoder.set_ring_mode_button(ring_mode_button) ringed_encoder.name = 'Device_Control_' + str(index) ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button' device_param_controls.append(ringed_encoder) device = ShiftableDeviceComponent() device.name = 'Device_Component' device.set_bank_buttons(tuple(device_bank_buttons)) device.set_shift_button(self._shift_button) device.set_parameter_controls(tuple(device_param_controls)) device.set_on_off_button(device_bank_buttons[1]) self.set_device_component(device) self._device = device detail_view_toggler = DetailViewCntrlComponent() detail_view_toggler.name = 'Detail_View_Control' detail_view_toggler.set_shift_button(self._shift_button) detail_view_toggler.set_device_clip_toggle_button(device_bank_buttons[0]) detail_view_toggler.set_detail_toggle_button(device_bank_buttons[4]) detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3]) transport = ShiftableTransportComponent() transport.name = 'Transport' self._transport = transport play_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 91) stop_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 92) record_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 93) nudge_up_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 100, 'Nudge_Up_Button', self) self._nudge_up_button = nudge_up_button nudge_down_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 101, 'Nudge_Down_Button', self) self._nudge_down_button = nudge_down_button tap_tempo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99) play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' record_button.name = 'Record_Button' #nudge_up_button.name = 'Nudge_Up_Button' #nudge_down_button.name = 'Nudge_Down_Button' tap_tempo_button.name = 'Tap_Tempo_Button' transport.set_shift_button(self._shift_button) transport.set_play_button(play_button) transport.set_stop_button(stop_button) transport.set_record_button(record_button) transport.set_nudge_buttons(nudge_up_button, nudge_down_button) transport.set_tap_tempo_button(tap_tempo_button) transport.set_quant_toggle_button(device_bank_buttons[5]) transport.set_overdub_button(device_bank_buttons[6]) transport.set_metronome_button(device_bank_buttons[7]) bank_button_translator = ShiftTranslatorComponent() bank_button_translator.set_controls_to_translate(tuple(device_bank_buttons)) bank_button_translator.set_shift_button(self._shift_button)
def send_value(self, value, force_send=False ): self.current_color = value if value > 0 and value is not self.off_color: self.blinking = True else: self.blinking = False if value is not None: #super(FlashingButtonElement, self).send_value(value, force_send) ButtonElement.send_value(self, value, force_send)
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self.set_suppress_rebuild_requests(True) self._suppress_send_midi = True self._suppress_session_highlight = True is_momentary = True self._suggested_input_port = "Launchpad" self._suggested_output_port = "Launchpad" self._control_is_with_automap = False self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = "User_Byte_Button" self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self._wrote_user_byte = False self._challenge = (Live.Application.get_random_int(0, 400000000) & 2139062143) matrix = ButtonMatrixElement() matrix.name = "Button_Matrix" for row in range(8): button_row = [] for column in range(8): button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((row * 16) + column)) button.name = (((str(column) + "_Clip_") + str(row)) + "_Button") button_row.append(button) matrix.add_row(tuple(button_row)) self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0) self._config_button.add_value_listener(self._config_value) top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, (104 + index)) for index in range(8) ] side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index]) for index in range(8) ] top_buttons[0].name = "Bank_Select_Up_Button" top_buttons[1].name = "Bank_Select_Down_Button" top_buttons[2].name = "Bank_Select_Left_Button" top_buttons[3].name = "Bank_Select_Right_Button" top_buttons[4].name = "Session_Button" top_buttons[5].name = "User1_Button" top_buttons[6].name = "User2_Button" top_buttons[7].name = "Mixer_Button" side_buttons[0].name = "Vol_Button" side_buttons[1].name = "Pan_Button" side_buttons[2].name = "SndA_Button" side_buttons[3].name = "SndB_Button" side_buttons[4].name = "Stop_Button" side_buttons[5].name = "Trk_On_Button" side_buttons[6].name = "Solo_Button" side_buttons[7].name = "Arm_Button" self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self) self._selector.name = "Main_Modes" for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.add_value_listener(self._button_value) self._suppress_session_highlight = False self.set_suppress_rebuild_requests(False) self.log_message("LaunchPad85 Loaded !")
def _setup_device(self): self._encoders = [] for offset in range(8): self._encoders.append( PeekableEncoderElement( MIDI_CC_TYPE, 15, 17 + offset, Live.MidiMap.MapMode.relative_smooth_two_compliment ) ) self._encoders[-1].set_feedback_delay(-1) self._encoders[-1].add_value_listener(self._encoder_value, identify_sender=True) self._encoders[-1].name = "Device_Control_" + str(offset) prev_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 14) next_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 15) prev_bank_button.name = "Device_Bank_Down_Button" next_bank_button.name = "Device_Bank_Up_Button" device = BestBankDeviceComponent() device.name = "Device_Component" self.set_device_component(device) device.set_parameter_controls(tuple(self._encoders)) device.set_bank_nav_buttons(prev_bank_button, next_bank_button) self._device_bank_buttons = (prev_bank_button, next_bank_button) prev_bank_button.add_value_listener(self._device_bank_value) next_bank_button.add_value_listener(self._device_bank_value) self._inst_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 109) self._inst_button.name = "Inst_Button" self._inst_button.add_value_listener(self._inst_value) self._device_navigation = DetailViewCntrlComponent() self._device_navigation.name = "Device_Navigation_Component"
def __init__(self, is_momentary, msg_type, channel, identifier, blink_on = False, blink_colors = []): ButtonElement.__init__(self, is_momentary, msg_type, channel, identifier) self.blink_on = blink_on self.blink_colors = set(blink_colors) self.blinking = False
def _init_session_component(self, global_channel, num_tracks, num_scenes): self._session_component = SessionComponent(num_tracks, num_scenes) self._session_selected_scene = self._session_component.selected_scene() stop_buttons = [] for i in range(num_tracks): stopper = ButtonElement(True, MIDI_CC_TYPE, global_channel, (3, 6, 9)[i]) stopper.name = 'Clip_Stop_Button' stop_buttons = stop_buttons + [stopper] clip_start_button = ButtonElement(True, MIDI_CC_TYPE, global_channel, (2, 5, 8)[i]) clip_start_button.name = 'Clip_Start_Button' self._session_selected_scene.clip_slot(i).set_launch_button(clip_start_button)
def __init__(self, is_momentary, msg_type, channel, identifier, send_channel = None, identifier_send_offset = 0, send_msg_type = None): ButtonElement.__init__(self, is_momentary, msg_type, channel, identifier) self._send_channel = send_channel self._send_msg_type = send_msg_type self._identifier_send_offset = identifier_send_offset self._on_value = AMB_FULL self._off_value = LED_OFF self._is_enabled = True self._is_notifying = False self._force_next_value = False self._pending_listeners = []
def __init__(self, is_momentary, msg_type, channel, identifier, name, cs): ButtonElement.__init__(self, is_momentary, msg_type, channel, identifier) self._last_pressed = 0 self._flash_state = 0 self._color = 0 self._on_value = 127 self._off_value = 0 self._is_enabled = True self._is_notifying = False self._force_next_value = False self.name = name self._script = cs self._report_value = True
def __init__(self, is_momentary, msg_type, channel, identifier, name, cs): ButtonElement.__init__(self, is_momentary, msg_type, channel, identifier) self._flash_state = 0 self._on_value = 127 self._off_value = 0 self._is_enabled = True self._is_notifying = False self._force_next_value = False #self._pending_listeners = [] self.name = name self._parameter = None self._script = cs self._report_value
def install_connections( self ): # this override has to be here so that translation will happen when buttons are disabled if self._is_enabled: ButtonElement.install_connections(self) elif (self._msg_channel != self._original_channel) or (self._msg_identifier != self._original_identifier): self._install_translation( self._msg_type, self._original_identifier, self._original_channel, self._msg_identifier, self._msg_channel, )
def mf_disable_bank_buttons(self): # Workaround for not sending values to track when pressing bank buttons self.padm0 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 0) self.padm1 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 1) self.padm2 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 2) self.padm3 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 3) self.padm0.add_value_listener(self.bank_buttons_dummy, identify_sender=True) self.padm1.add_value_listener(self.bank_buttons_dummy, identify_sender=True) self.padm2.add_value_listener(self.bank_buttons_dummy, identify_sender=True) self.padm3.add_value_listener(self.bank_buttons_dummy, identify_sender=True)
def __init__(self, is_momentary, msg_type, channel, identifier, name, cs): ButtonElement.__init__(self, is_momentary, msg_type, channel, identifier) #assert (MonoButtonElement._original_forwarding_callback != None) self._last_pressed = 0 self._flash_state = 0 self._color = 0 self._on_value = 127 self._off_value = 0 self._is_enabled = True self._is_notifying = False self._force_next_value = False self.name = name self._script = cs self._report_value = False self._last_sent_value = -1
def _setup_mixer_control(self): is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant num_tracks = 7 # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent( num_tracks, 0) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset( 0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track mixer.selected_strip().set_mute_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 64)) #mixer.selected_strip().set_solo_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 44)) mixer.selected_strip().set_arm_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 72)) track_select_notes = [ 65, 73, 66, 74, 67, 75, 68, 76 ] #more note numbers need to be added if num_scenes is increased slider_select_notes = [23, 22, 15, 14, 5, 7, 6, 4] pan_select_notes = [21, 20, 13, 12, 3, 1, 0, 2] master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 4) master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 76) prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 26, Live.MidiMap.MapMode.absolute) crossfader = SliderElement(MIDI_CC_TYPE, 0, 24) for index in range(num_tracks): mixer.channel_strip(index).set_select_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, track_select_notes[index])) mixer.channel_strip(index).set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, slider_select_notes[index])) mixer.channel_strip(index).set_pan_control( EncoderElement(MIDI_CC_TYPE, CHANNEL, pan_select_notes[index], Live.MidiMap.MapMode.absolute)) crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' master_select_button.name = 'Master_Select_Button' prehear_control.name = 'Prehear_Volume_Control' mixer.set_crossfader_control(crossfader) mixer.set_prehear_volume_control(prehear_control) mixer.master_strip().set_volume_control(master_volume_control) mixer.master_strip().set_select_button(master_select_button)
def _setup_mixer(self): mute_solo_flip_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 34) self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 37) self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 38) self._strip_buttons = [] mute_solo_flip_button.name = 'Mute_Solo_Flip_Button' self._next_nav_button.name = 'Next_Track_Button' self._prev_nav_button.name = 'Prev_Track_Button' self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button) self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.master_strip().set_volume_control(self._master_slider) self._sliders = [] for index in range(8): strip = self._mixer.channel_strip(index) strip.name = 'Channel_Strip_' + str(index) strip.set_invert_mute_feedback(True) self._sliders.append(SliderElement(MIDI_CC_TYPE, 0, index)) self._sliders[-1].name = str(index) + '_Volume_Control' self._sliders[-1].set_feedback_delay(-1) self._sliders[-1].add_value_listener(self._slider_value, identify_sender=True) strip.set_volume_control(self._sliders[-1]) self._strip_buttons.append( ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + index)) self._strip_buttons[-1].name = str(index) + '_Mute_Button' self._strip_buttons[-1].add_value_listener( self._mixer_button_value, identify_sender=True) self._mixer.master_strip().set_mute_button( ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 17)) self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) self._device_selection_follows_track_selection = True self._suggested_input_port = 'Launchkey InControl' self._suggested_output_port = 'Launchkey InControl' self._has_sliders = True self._current_midi_map = None self._master_slider = make_slider(7, 'Master_Volume_Control') self._modes_buttons = [] for index in range(3): button = ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, 0, 13 + index) self._modes_buttons.append(button) self._modes_buttons[-1].add_value_listener( self._dummy_listener) self._setup_mixer() self._setup_session() self._setup_transport() self._setup_device() for component in self.components: component.set_enabled(False)
def _set_modifiers_buttons(self): is_momentary = True self._shift_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, shift_mod) self._alt_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, alt_mod) self._ctrl_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, ctrl_mod) if (self._shift_button != None): self._shift_button.add_value_listener(self._shift_value) if (self._alt_button != None): self._alt_button.add_value_listener(self._alt_value) if (self._ctrl_button != None): self._ctrl_button.add_value_listener(self._ctrl_value) # INIT NORMAL MODE self._manage_modes(0)
def __init__(self, *a, **k): super(AudioClipEditComponent, self).__init__(*a, **k) self._loop_start_slider = SliderElement(MIDI_CC_TYPE, 2, 60) self._action_loop_start.subject = self._loop_start_slider self._loop_end_slider = SliderElement(MIDI_CC_TYPE, 2, 61) self._action_loop_end.subject = self._loop_end_slider self._mark_start_slider = SliderElement(MIDI_CC_TYPE, 2, 62) self._action_mark_start.subject = self._mark_start_slider self._mark_end_slider = SliderElement(MIDI_CC_TYPE, 2, 63) self._action_mark_end.subject = self._mark_end_slider self._pitch_c_slider = SliderElement(MIDI_CC_TYPE, 2, 64) self._pitch_f_slider = SliderElement(MIDI_CC_TYPE, 2, 65) self._gain_slider = SliderElement(MIDI_CC_TYPE, 2, 66) self._action_pitch_c.subject = self._pitch_c_slider self._action_pitch_f.subject = self._pitch_f_slider self._action_gain.subject = self._gain_slider self._loop_inc_slider = SliderElement(MIDI_CC_TYPE, 2, 67) self._action_loop_inc.subject = self._loop_inc_slider self._loop_move_button = ButtonElement(False, MIDI_CC_TYPE, 2, 74) self._action_mv_loop.subject = self._loop_move_button self._loop_set_button = ButtonElement(False, MIDI_CC_TYPE, 2, 70) self._action_loop_toggle.subject = self._loop_set_button self._warp_set_button = ButtonElement(False, MIDI_CC_TYPE, 2, 71) self._action_warp_toggle.subject = self._warp_set_button self._zoom_scroll_button = ButtonElement(False, MIDI_CC_TYPE, 2, 73) self._action_scroll_mode.subject = self._zoom_scroll_button self.selected_clip_slot = None self.inc_index = 4 self.loop_inc = INC_STEPS[self.inc_index] self.start_inc = INC_STEPS[self.inc_index] self.mv_loop = False self._on_pitch_c_changed.subject = None self._on_pitch_f_changed.subject = None self._on_gain_changed.subject = None self._scroll_mode = False self.update_selected_clip() return
def _setup_transport_control(self): is_momentary = True """ Instantiate a Transport Component """ transport = TransportComponent() """ Buttons declaration """ button_play = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_play_button) button_stop = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_stop_button) button_record = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_record_button) button_loop = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_loop_button) button_seek_ffwd = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_seek_ffwd) button_seek_rwd = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_seek_rwd) """ Buttons association """ transport.set_play_button(button_play) transport.set_stop_button(button_stop) transport.set_record_button(button_record) transport.set_loop_button(button_loop) transport.set_seek_buttons(button_seek_ffwd, button_seek_rwd)
def set_touch_mode(self, touchchannel): self.touch_mode = True id_vol = self._volume_control.message_identifier() id_pan = self._pan_control.message_identifier() id_send = None for send in self._send_controls: if send: id_send = send.message_identifier() self.clear_vol_button = ButtonElement(False, MIDI_CC_TYPE, touchchannel, id_vol) self.clear_vol_button.add_value_listener(self._do_clear_vol) self.clear_pan_button = ButtonElement(False, MIDI_CC_TYPE, touchchannel, id_pan) self.clear_pan_button.add_value_listener(self._do_clear_pan) self.clear_send_button = ButtonElement(False, MIDI_CC_TYPE, touchchannel, id_send) self.clear_send_button.add_value_listener(self._do_clear_send) for send in self._send_controls: if send: self.send_control = send return
def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(NUM_TRACKS) self._mixer.set_serato_interface(self._serato_interface) self._mixer.master_strip().set_serato_interface(self._serato_interface) self._track_arm_buttons = [] self._track_solo_buttons = [] self._track_mute_buttons = [] self._track_select_buttons = [] self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for track in range(NUM_TRACKS): strip = self._mixer.channel_strip(track) strip.set_serato_interface(self._serato_interface) self._track_arm_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_solo_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_mute_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_select_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) strip.set_arm_button(self._track_arm_buttons[-1]) strip.set_solo_button(self._track_solo_buttons[-1]) strip.set_mute_button(self._track_mute_buttons[-1]) strip.set_select_button(self._track_select_buttons[-1]) strip.set_shift_button(self._shift_button)
def _setup_mixer(self): self._selected_mute_solo_button = ButtonElement( IS_MOMENTARY, MIDI_CC_TYPE, 15, 12) mute_solo_flip_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 57) self._strip_buttons = [] self._selected_mute_solo_button.name = u'Selected_Mute_Button' mute_solo_flip_button.name = u'Mute_Solo_Flip_Button' self._selected_mute_solo_button.add_value_listener( self._mixer_button_value, identify_sender=True) self._mixer = ShiftableMixerComponent(8) self._mixer.name = u'Mixer' self._mixer.set_shift_button(self._shift_button) self._mixer.set_selected_mute_solo_button( self._selected_mute_solo_button) self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button) self._mixer.selected_strip().name = u'Selected_Channel_Strip' self._mixer.master_strip().name = u'Master_Channel_Strip' self._mixer.master_strip().set_volume_control(self._master_slider) self._sliders = [] for index in range(8): strip = self._mixer.channel_strip(index) strip.name = u'Channel_Strip_' + str(index) strip.set_invert_mute_feedback(True) self._sliders.append(SliderElement(MIDI_CC_TYPE, 15, 33 + index)) self._sliders[-1].name = str(index) + u'_Volume_Control' self._sliders[-1].set_feedback_delay(-1) self._sliders[-1].add_value_listener(self._slider_value, identify_sender=True) strip.set_volume_control(self._sliders[-1]) self._strip_buttons.append( ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 49 + index)) self._strip_buttons[-1].name = str(index) + u'_Mute_Button' self._strip_buttons[-1].add_value_listener( self._mixer_button_value, identify_sender=True) self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)
def __init__(self, button_index, monochrome=False, *a, **k): super(PadMode, self).__init__(button_index, *a, **k) self._note_display_mode = ND_KEYBOARD1 self.current_scale_index = 0 self._scale = None self._base_note = 0 self._octave = 0.55 self.current_scale_index = 0 self._in_edit_mode = False self._editmode = None self._is_monochrome = monochrome self._color_edit_assign = monochrome and self.assign_edit_mono or self.assign_edit_color self.assign_transpose(SCALES[self.current_scale_index]) is_momentary = True self.octave_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 120) self.octave_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 121) self.base_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 124) self.base_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 125) self.scale_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 118) self.scale_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 119) self._adjust_scale.subject = SliderElement(MIDI_CC_TYPE, 2, 116) self._adjust_octav.subject = SliderElement(MIDI_CC_TYPE, 2, 115) self._adjust_basem.subject = SliderElement(MIDI_CC_TYPE, 2, 117) self._do_oct_down.subject = self.octave_down_button self._do_oct_up.subject = self.octave_up_button self._do_base_down.subject = self.base_down_button self._do_base_up.subject = self.base_up_button self._do_scale_down.subject = self.scale_down_button self._do_scale_up.subject = self.scale_up_button self._seg_display = None return
def make_button(identifier, channel, name): return ButtonElement(True, MIDI_CC_TYPE, channel, identifier, name=name)
class Maschine(ControlSurface): """Basic Control Script for All Maschine Modell Mikro, Mikro Mk2, Mk1, Mk2, Studio""" __module__ = __name__ def __init__(self, c_instance): super(Maschine, self).__init__(c_instance) with self.component_guard(): register_sender(self) self._diplay_cache = ['', '', '', ''] self._suppress_send_midi = True is_momentary = True self._c_ref = c_instance self.display_task = DisplayTask() self._challenge = Live.Application.get_random_int( 0, 400000000) & 2139062143 self._active = False self._midi_pause_count = 0 self.blink_state = 0 self.send_slider_index = 0 self.nav_index = 0 self.arm_selected_track = False self.undo_state = 0 self.redo_state = 0 self._set_suppress_rebuild_requests(True) self._modeselect = ModeSelector(self.is_monochrome()) self._device = self._set_up_device_control() self._set_up_session(self._modeselect) self._set_up_mixer() self._setup_transport() self._set_global_buttons() self._editsection = EditSection() self._editsection.connect_session(self._session) self._editsection.set_mode_selector(self._modeselect) self._session.set_mode(self._modeselect._clip_mode) self._audio_clip_editor = AudioClipEditComponent() self._note_repeater = NoteRepeatComponent(c_instance.note_repeat) self._midi_edit = MidiEditSection() self._init_settings() self._init_maschine() self.set_highlighting_session_component(self._session) self.set_pad_translations(PAD_TRANSLATIONS) self._on_selected_track_changed() self.set_up_function_buttons() self.show_message(str('')) self.request_rebuild_midi_map() self._set_suppress_rebuild_requests(False) self._active = True self._display_device_param = False self.set_feedback_channels(FEEDBACK_CHANNELS) self._final_init() self._suppress_send_midi = False self.apply_preferences() self.init_text_display() self._on_appointed_device_changed.subject = self.song() def _init_maschine(self): pass def _final_init(self): pass def create_pad_button(self, scene_index, track_index, color_source): pass def create_gated_button(self, identifier, hue): pass def apply_preferences(self): pref_dict = self._pref_dict if 'step_advance' in pref_dict: self._session.set_step_advance(pref_dict['step_advance']) if 'solo_exclusive' in pref_dict: self._modeselect.set_solo_exclusive(pref_dict['solo_exclusive']) else: self._modeselect.set_solo_exclusive(True) if 'arm_exclusive' in pref_dict: self._modeselect.set_arm_exclusive(pref_dict['arm_exclusive']) else: self._modeselect.set_arm_exclusive(True) if 'quantize_val' in pref_dict: self._editsection.quantize = pref_dict['quantize_val'] else: self._editsection.quantize = 5 if 'initial_cliplen' in pref_dict: self._editsection.initial_clip_len = pref_dict['initial_cliplen'] else: self._editsection.initial_clip_len = 4.0 if 'auto_arm_sel_track' in pref_dict: self.arm_selected_track = pref_dict['auto_arm_sel_track'] else: self.arm_selected_track = False if 'note_color_mode' in pref_dict: self._modeselect._pad_mode._note_display_mode = pref_dict[ 'note_color_mode'] else: self._modeselect._pad_mode._note_display_mode = ND_KEYBOARD1 self._pref_dict[ 'note_color_mode'] = self._modeselect._pad_mode._note_display_mode self.set_sel_arm_button.send_value( self.arm_selected_track and 127 or 0, True) self._note_repeater.recall_values(self._pref_dict) def store_preferences(self): self._pref_dict['step_advance'] = self._session.get_step_advance() self._pref_dict['solo_exclusive'] = self._modeselect.is_solo_exclusive( ) self._pref_dict['arm_exclusive'] = self._modeselect.is_arm_exclusive() self._pref_dict['quantize_val'] = self._editsection.quantize self._pref_dict['initial_cliplen'] = self._editsection.initial_clip_len self._pref_dict['auto_arm_sel_track'] = self.arm_selected_track self._pref_dict[ 'note_color_mode'] = self._modeselect._pad_mode._note_display_mode self._note_repeater.store_values(self._pref_dict) def _init_settings(self): from pickle import loads, dumps from encodings import ascii nop(ascii) preferences = self._c_instance.preferences(self.preferences_name()) self._pref_dict = {} try: self._pref_dict = loads(str(preferences)) except Exception: pass pref_dict = self._pref_dict preferences.set_serializer(lambda: dumps(pref_dict)) def preferences_name(self): return 'Maschine' def _pre_serialize(self): from pickle import dumps from encodings import ascii nop(ascii) preferences = self._c_instance.preferences('Maschine') self.store_preferences() dump = dumps(self._pref_dict) preferences.set_serializer(lambda: dump) def toggle_nav_mode(self): self._session.switch_step_advance() self.show_message(' View Navigation in steps of ' + str(self._session.get_step_advance())) def _set_up_session(self, mode_selector): is_momentary = True self._session = MaschineSessionComponent() self._session.set_color_manager(mode_selector.get_color_manager()) self.nav_buttons = (self.create_gated_button(92, COLOR_HUE_NAV), self.create_gated_button(81, COLOR_HUE_NAV), self.create_gated_button(93, COLOR_HUE_NAV), self.create_gated_button(91, COLOR_HUE_NAV)) self._session.set_scene_bank_buttons(self.nav_buttons[0], self.nav_buttons[1]) self._session.set_track_bank_buttons(self.nav_buttons[2], self.nav_buttons[3]) track_stop_buttons = [ StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, index + STOP_CC_OFF) for index in range(4) ] self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._matrix = [] self._bmatrix = ButtonMatrixElement() for scene_index in range(4): button_row = [] for track_index in range(4): button = self.create_pad_button(scene_index, track_index, mode_selector) button_row.append(button) self._matrix.append(tuple(button_row)) self._bmatrix.add_row(tuple(button_row)) self._session.set_matrix(self._matrix) for button, (track_index, scene_index) in self._bmatrix.iterbuttons(): if button: scene = self._session.scene(scene_index) clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(button) clip_slot.set_triggered_to_play_value(1) clip_slot.set_triggered_to_record_value(1) clip_slot.set_started_value(1) clip_slot.set_recording_value(1) clip_slot.set_stopped_value(1) self._session._link() def _set_up_mixer(self): is_momentary = True self._mixer = MaschineMixerComponent(8) self.send_sliders = [] for track in range(8): self.send_sliders.append( SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, SEND_CC_OFF + track)) for track in range(8): strip = self._mixer.channel_strip(track) strip.set_arm_button( StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, ARM_CC_OFF + track)) strip.set_solo_button( StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SOLO_CC_OFF + track)) strip.set_mute_button( StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, MUTE_CC_OFF + track)) strip.set_volume_control( SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, LEVEL_CC_OFF + track)) strip.set_pan_control( SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, PAN_CC_OFF + track)) strip.set_select_button( StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SELECT_CC_OFF + track)) st = tuple([self.send_sliders[track]]) strip.set_send_controls(st) self.send_slider_toggle_button = StateButton(False, MIDI_CC_TYPE, 0, 90) self._do_toggle_send.subject = self.send_slider_toggle_button self._session.set_mixer(self._mixer) def _set_global_buttons(self): is_momentary = True self._undo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 85) self._do_undo.subject = self._undo_button self._redo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 87) self._do_redo.subject = self._redo_button self._stop_all_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 111) self._do_stop_all.subject = self._stop_all_button self._toggle_detail_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 121) self._action_toogle_detail_view.subject = self._toggle_detail_button self._fire_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 9) self._do_fire_button.subject = self._fire_button self._g_clear_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 106) self._hold_clear_action.subject = self._g_clear_button self._g_duplicate_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 107) self._hold_duplicate_action.subject = self._g_duplicate_button self.track_left_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 120) self.track_right_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 121) self.set_sel_arm_button = StateButton(is_momentary, MIDI_CC_TYPE, 2, 56) self._reenable_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 120) self._do_auto_reenable.subject = self._reenable_button self._on_change_reenabled.subject = self.song() self._on_change_reenabled() self._a_trk_left.subject = self.track_left_button self._a_trk_right.subject = self.track_right_button self._a_sel_arm.subject = self.set_sel_arm_button def _set_up_device_control(self): is_momentary = True device = MaschineDeviceComponent() param_controls = [] for index in range(8): param_controls.append( SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_CC_OFF + index)) device.set_parameter_controls(tuple(param_controls)) self.device_control = param_controls device.set_on_off_button( StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF)) device.set_bank_nav_buttons( StateButton(is_momentary, MIDI_CC_TYPE, 3, 104), ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 105)) self._device_nav_button_left = StateButton(is_momentary, MIDI_CC_TYPE, 3, 106) self._device_nav_button_right = StateButton(is_momentary, MIDI_CC_TYPE, 3, 107) self._navigate_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 127) self._nav_value_left.subject = self._device_nav_button_left self._nav_value_right.subject = self._device_nav_button_right self._do_focus_navigate.subject = self._navigate_button self.set_device_component(device) return device def _setup_transport(self): is_momentary = True transport = TransportComponent() studiotransport = MaschineTransport() playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108) stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110) recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109) overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107) metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104) eventRecButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 98) playButton.name = 'Play' stopButton.name = 'Stop' recordButton.name = 'Record' overdubButton.name = 'Overdub' metrononmeButton.name = 'Metronome' transport.set_play_button(playButton) transport.set_stop_button(stopButton) transport.set_record_button(recordButton) transport.set_overdub_button(overdubButton) transport.set_metronome_button(metrononmeButton) studiotransport.set_session_auto_button(eventRecButton) studiotransport.set_arrangement_overdub_button( StateButton(is_momentary, MIDI_CC_TYPE, 0, 106)) studiotransport.set_back_arrange_button( StateButton(is_momentary, MIDI_CC_TYPE, 0, 105)) transport.set_nudge_buttons( StateButton(is_momentary, MIDI_CC_TYPE, 1, 51), StateButton(is_momentary, MIDI_CC_TYPE, 1, 50)) punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52) punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53) punchinbutton.name = 'Punch In' punchoutbutton.name = 'Punch Out' transport.set_punch_buttons(punchinbutton, punchoutbutton) transport.set_loop_button( StateButton(is_momentary, MIDI_CC_TYPE, 1, 54)) self.song_follow_button = ButtonElement(True, MIDI_CC_TYPE, 2, 98) self._do_song_follow.subject = self.song_follow_button self._song_follow_changed.subject = self.song().view self._song_follow_changed() self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59) self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58) transport.set_seek_buttons(self.transp_ff_button, self.transp_rw_button) self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 105) self.xfadeKnob.connect_to( self.song().master_track.mixer_device.crossfader) self.master_knob = SliderElement(MIDI_CC_TYPE, 0, 99) self.master_knob.connect_to( self.song().master_track.mixer_device.volume) self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88) self._do_tap_tempo.subject = self.tap_button self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 55) self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56) self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57) self._do_toggle_cue.subject = self.cue_add_delete_button self._do_toggle_prev_cue.subject = self.cue_prev_button self._do_toggle_next_cue.subject = self.cue_next_button def set_up_function_buttons(self): is_momentary = True self.keycolor_mod_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 73) self._do_key_color.subject = self.keycolor_mod_button self._update_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 86) self._do_update_display.subject = self._update_button @subject_slot('appointed_device') def _on_appointed_device_changed(self): self._modeselect._device_changed() def _update_hardware(self): self._session.update() self._modeselect.refresh() self.update_undo_redo(True) def refresh_state(self): ControlSurface.refresh_state(self) self._update_hardware() def _send_midi(self, midi_bytes, **keys): self._c_ref.send_midi(midi_bytes) return True def init_text_display(self): if USE_DISPLAY: self._modeselect._pad_mode.update_text_display() def _on_selected_track_changed(self): super(Maschine, self)._on_selected_track_changed() self.set_controlled_track(self.song().view.selected_track) self._on_devices_changed.subject = self.song().view.selected_track @subject_slot('devices') def _on_devices_changed(self): pass def update(self): self.set_feedback_channels(FEEDBACK_CHANNELS) super(Maschine, self).update() def is_monochrome(self): return False def _deassign_matrix(self): for scene_index in range(4): scene = self._session.scene(scene_index) for track_index in range(4): clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(None) return def update_display(self): with self.component_guard(): with self._is_sending_scheduled_messages(): self._task_group.update(0.1) self._modeselect.notify(self.blink_state) self.blink_state = (self.blink_state + 1) % 4 self.display_task.tick() self.update_undo_redo(False) def update_undo_redo(self, force=False): if force: self.undo_state = self.song().can_undo self.redo_state = self.song().can_redo if self.song().can_undo != self.undo_state: self.undo_state = self.song().can_undo self._undo_button.send_value(self.undo_state == 1 and 127 or 0) if self.song().can_redo != self.redo_state: self.redo_state = self.song().can_redo self._redo_button.send_value(self.redo_state == 1 and 127 or 0) def adjust_loop_start(self, delta): loopval = self.song().loop_start self.song().loop_start = min(self.song().song_length, max(0, loopval + delta)) def adjust_loop_length(self, delta): loopval = self.song().loop_length self.song().loop_length = min(self.song().song_length, max(abs(delta), loopval + delta)) def _do_armsolo_mode(self, value): pass @subject_slot('value') def _do_fire_button(self, value): assert self._fire_button != None assert value in range(128) if value != 0: if self.isShiftDown(): self.song().tap_tempo() else: clip_slot = self.song().view.highlighted_clip_slot if clip_slot: clip_slot.fire() return @subject_slot('value') def _do_undo(self, value): if value != 0: if self.use_layered_buttons() and self.isShiftDown(): if self.song().can_redo == 1: self.song().redo() self.show_message(str('REDO')) elif self.song().can_undo == 1: self.song().undo() self.show_message(str('UNDO')) @subject_slot('value') def _do_redo(self, value): if value != 0: if self.song().can_redo == 1: self.song().redo() self.show_message(str('REDO')) @subject_slot('value') def _do_stop_all(self, value): if value != 0: if self.use_layered_buttons() and self.isShiftDown(): self.song().stop_all_clips(0) else: self.song().stop_all_clips(1) def isShiftDown(self): return self._editsection.isShiftdown() def modifiers(self): return self._editsection.modifiers() def use_layered_buttons(self): return False def _handle_base_note(self, diff): self._modeselect._pad_mode.inc_base_note(diff) def _handle_octave(self, diff): self._modeselect._pad_mode.inc_octave(diff) octave_val = self._modeselect._pad_mode def _handle_scale(self, diff): self._modeselect._pad_mode.inc_scale(diff) @subject_slot('value') def _do_update_display(self, value): if value != 0: self.refresh_state() @subject_slot('value') def _do_key_color(self, value): assert value in range(128) if value != 0: self._modeselect._pad_mode.step_key_color_mode() @subject_slot('value') def _do_tap_tempo(self, value): assert value in range(128) if value != 0: self.song().tap_tempo() @subject_slot('value') def _do_toggle_cue(self, value): assert value in range(128) if value != 0: self.song().set_or_delete_cue() @subject_slot('value') def _do_toggle_prev_cue(self, value): assert value in range(128) if value != 0: self.song().jump_to_prev_cue() @subject_slot('value') def _do_toggle_next_cue(self, value): assert value in range(128) if value != 0: self.song().jump_to_next_cue() @subject_slot('value') def _do_toggle_send(self, value): assert value in range(128) if self.isShiftDown(): if value != 0: self.refresh_state() self.show_message('Refresh Display') else: nr_of_tracks = len(self.song().return_tracks) if value == 0 or nr_of_tracks < 1: return prev = self.send_slider_index self.send_slider_index += 1 if self.send_slider_index >= nr_of_tracks: self.send_slider_index = 0 self.show_message(' Set Send ' + str(SENDS[self.send_slider_index])) self.timed_message( 2, ' Set Send ' + str(SENDS[self.send_slider_index])) if prev != self.send_slider_index: for track in range(8): strip = self._mixer.channel_strip(track) slider_list = [] for index in range(self.send_slider_index + 1): if index < self.send_slider_index - 1: slider_list.append(None) else: slider_list.append(self.send_sliders[track]) strip.set_send_controls(tuple(slider_list)) return @subject_slot('value') def _a_trk_left(self, value): assert value in range(128) if value != 0: if self.application().view.is_view_visible('Session'): direction = Live.Application.Application.View.NavDirection.left self.application().view.scroll_view(direction, 'Session', True) track = self.song().view.selected_track self.timed_message(2, 'T:' + track.name, False) if self.arm_selected_track and track.can_be_armed: arm_exclusive(self.song(), track) @subject_slot('value') def _a_trk_right(self, value): assert value in range(128) if value != 0: if self.application().view.is_view_visible('Session'): direction = Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Session', True) track = self.song().view.selected_track self.timed_message(2, 'T:' + track.name, False) if self.arm_selected_track and track.can_be_armed: arm_exclusive(self.song(), track) @subject_slot('value') def _a_sel_arm(self, value): if value != 0: if self.arm_selected_track: self.arm_selected_track = False self.set_sel_arm_button.send_value(0, True) else: self.arm_selected_track = True self.set_sel_arm_button.send_value(127, True) @subject_slot('value') def _nav_value_left(self, value): assert self._device_nav_button_left != None assert value in range(128) modifier_pressed = True if value != 0: if not self.application().view.is_view_visible( 'Detail') or not self.application().view.is_view_visible( 'Detail/DeviceChain'): self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: direction = Live.Application.Application.View.NavDirection.left self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed) return @subject_slot('value') def _nav_value_right(self, value): assert self._device_nav_button_right != None assert value in range(128) if value != 0: modifier_pressed = True if not self.application().view.is_view_visible( 'Detail') or not self.application().view.is_view_visible( 'Detail/DeviceChain'): self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: direction = Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed) return @subject_slot('value') def _do_focus_navigate(self, value): assert self._navigate_button != None assert value in range(128) if value != 0: self.nav_index = (self.nav_index + 1) % len(VIEWS_ALL) self.application().view.focus_view(VIEWS_ALL[self.nav_index]) self.show_message('Focus on : ' + str(VIEWS_ALL[self.nav_index])) return def focus_clip_detail(self): self.application().view.focus_view('Detail/Clip') @subject_slot('follow_song') def _song_follow_changed(self): view = self.song().view if view.follow_song: self.song_follow_button.send_value(1, True) else: self.song_follow_button.send_value(0, True) @subject_slot('value') def _do_song_follow(self, value): if value != 0: view = self.song().view if view.follow_song: view.follow_song = False self.song_follow_button.send_value(0, True) else: view.follow_song = True self.song_follow_button.send_value(1, True) @subject_slot('value') def _hold_duplicate_action(self, value): if value != 0: pass @subject_slot('value') def _hold_clear_action(self, value): if value != 0: self._mixer.enter_clear_mode() self._device_component.enter_clear_mode() else: self._mixer.exit_clear_mode() self._device_component.exit_clear_mode() @subject_slot('value') def _action_toogle_main_view(self, value): if value != 0: appv = self.application().view if appv.is_view_visible('Arranger'): appv.show_view('Session') else: appv.show_view('Arranger') @subject_slot('value') def _action_toogle_detail_view(self, value): if value != 0: appv = self.application().view if self.isShiftDown(): if appv.is_view_visible('Arranger'): appv.show_view('Session') else: appv.show_view('Arranger') elif appv.is_view_visible('Detail/Clip'): appv.show_view('Detail/DeviceChain') else: appv.show_view('Detail/Clip') @subject_slot('re_enable_automation_enabled') def _on_change_reenabled(self): if self.song().re_enable_automation_enabled: self._reenable_button.turn_on() else: self._reenable_button.turn_off() @subject_slot('value') def _do_auto_reenable(self, value): if value != 0: self.song().re_enable_automation() def to_color_edit_mode(self, active): pass def clear_display_all(self): self.send_to_display('', 0) self.send_to_display('', 1) self.send_to_display('', 2) self.send_to_display('', 3) def clear_display(self, grid): self.send_to_display('', grid) def timed_message(self, grid, text, hold=False): if USE_DISPLAY == False: self.show_message(text) else: self.display_task.set_func(self.clear_display, grid) self.send_to_display(text, grid) if hold: self.display_task.hold() self.display_task.start() def timed_message_release(self): self.display_task.release() def update_bank_display(self): if USE_DISPLAY: name, bank = self._device._current_bank_details() if self._display_device_param: prms = len(bank) d1 = '' for i in range(4): parm = bank[i] if parm: name = parm.name d1 += name[:6] + (i < 3 and '|' or '') else: d1 += ' ' + (i < 3 and '|' or '') self.send_to_display(d1, 2) d1 = '' for i in range(4): parm = bank[i + 4] if parm: name = parm.name d1 += name[:6] + (i < 3 and '|' or '') else: d1 += ' ' + (i < 3 and '|' or '') self.send_to_display(d1, 4) else: self.timed_message(2, 'Bank: ' + name) def display_parameters(self, paramlist): if USE_DISPLAY == False: return def send_to_display(self, text, grid=0): if USE_DISPLAY == False: return if self._diplay_cache[grid] == text: return self._diplay_cache[grid] = text if len(text) > 28: text = text[:27] msgsysex = [240, 0, 0, 102, 23, 18, min(grid, 3) * 28] filled = text.ljust(28) for c in filled: msgsysex.append(ord(c)) msgsysex.append(247) self._send_midi(tuple(msgsysex)) def cleanup(self): pass def disconnect(self): self._pre_serialize() self.clear_display_all() for button, (track_index, scene_index) in self._bmatrix.iterbuttons(): if button: button.send_color_direct(PColor.OFF[0]) time.sleep(0.2) self._active = False self._suppress_send_midi = True super(Maschine, self).disconnect() return
def _setup_device_and_transport_control(self): is_momentary = True device_param_controls = [] for index in range(8): device_param_controls.append( EncoderElement(MIDI_CC_TYPE, 15, 62 - index, Live.MidiMap.MapMode.absolute)) device = SpecialDeviceComponent() device.set_bank_nav_buttons( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 107), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 106)) device.set_parameter_controls(tuple(device_param_controls)) self.set_device_component(device) transport = SpecialTransportComponent() transport.set_play_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 20)) transport.set_stop_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 21)) transport.set_record_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 22)) transport.set_seek_buttons( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 24), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 25)) transport.set_tap_tempo_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 94)) transport.set_undo_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 23)) transport.set_redo_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 27)) transport.set_bts_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 26))
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self.c_instance = c_instance self.retries_count = 0 self.device_connected = False self.clip_color_callbacks = {} self.slot_callbacks = {} self.text_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x03) self.text_end_sequence = (0xf7, ) self.enable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x02, 0xf7) self.disable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x00, 0xf7) self.id_sequence = (0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7) self.text_color_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x04) self.log('INITIALIZING') self.app = Live.Application.get_application() #maj = self.app.get_major_version() #min = self.app.get_minor_version() #bug = self.app.get_bugfix_version() #self.show_message(str(1) + "." + str(0) + "." + str(9)) self.show_message("Version " + VERSION) # reseting text self.write_text(' ') # reset display clips self.reset_display_clips() # getting browser visible state self.session_browser_visible = self.app.view.is_view_visible("Browser") # getting browser visible state self.arrange_browser_visible = self.app.view.is_view_visible("Browser") # getting session view visible state self.session_visible = self.app.view.is_view_visible("Session") # getting arrange view visible state self.arrange_visible = self.app.view.is_view_visible("Arranger") # getting detail view visible state self.detail_visible = self.app.view.is_view_visible("Detail") # getting back to arranger state self.back_to_arranger_state = self.song().back_to_arranger # initializing channel strip to null self._channel_strip = None # initializing transport component self._transport = TransportComponent() # initializing mixer component self._mixer = MixerComponent(NUM_TRACKS, 2) # initializing session component self._session = SessionComponent(NUM_TRACKS, NUM_ROWS) self._session.add_offset_listener(self.session_offset_changed) # configuring operation mode selector buttons self._operation_mode_buttons = ButtonElement( True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_1_BUTTON), ButtonElement( True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_2_BUTTON), ButtonElement( True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_3_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_4_BUTTON), # initializing operation mode selector self._operation_mode_selector = OP1ModeSelectorComponent( self, self._transport, self._mixer, self._session) # setting operation mode selector buttons self._operation_mode_selector.set_mode_buttons( self._operation_mode_buttons) # adding value listener for operation mode index self._operation_mode_selector.add_mode_index_listener( self.mode_index_changed) # setting global transport assignments self._transport.set_record_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_REC_BUTTON)) self._transport.set_play_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_PLAY_BUTTON)) self._transport.set_stop_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_STOP_BUTTON)) self._transport.set_metronome_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_METRONOME_BUTTON)) self._transport.set_tap_tempo_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_HELP_BUTTON)) self._transport.set_punch_buttons( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS1_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS2_BUTTON)) self._transport.set_loop_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS3_BUTTON)) self._transport.set_overdub_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS4_BUTTON)) # setting global session assignments self._session.set_scene_bank_buttons( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_COM), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MICRO)) # setting misc listeners self.browser_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 15) self.browser_toggle_button.add_value_listener( self.browser_toggle_button_callback) self.mainview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 16) self.mainview_toggle_button.add_value_listener( self.mainview_toggle_button_callback) self.detailview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 17) self.detailview_toggle_button.add_value_listener( self.detailview_toggle_button_callback) self.clear_track_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 25) self.clear_track_button.add_value_listener( self.clear_track_button_callback) self.back_to_arranger_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 26) self.back_to_arranger_button.add_value_listener( self.back_to_arranger_button_callback) # adding value listener for selected track change self.song().view.add_selected_track_listener( self.selected_track_changed) # adding value listener for selected scene change self.song().view.add_selected_scene_listener( self.selected_scene_changed) # setting assignments for currently selected track self.selected_track_changed() # setting assignments for currently selected scene self.selected_scene_changed()
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): is_momentary = True self.set_pad_translations(PAD_TRANSLATIONS) self._suggested_input_port = 'HyperControl' self._suggested_output_port = 'HyperControl' self._display_on_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 15, 79) self._waiting_for_first_response = True mixer1 = DisplayingMixerComponent(0) mixer1.set_select_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 111), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 110)) mixer1.set_mute_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 12)) mixer1.set_solo_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 13)) mixer2 = NotifyingMixerComponent(8) mixer2.set_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 15), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 14)) mixer2.master_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, 15, 41)) for index in range(8): mixer2.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, 15, 33 + index)) device = PageableDeviceComponent(device_selection_follows_track_selection=True) self.set_device_component(device) ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 115) rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 114) loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 113) transport = TransportComponent() transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 116)) transport.set_play_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 117)) transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 118)) session = SessionComponent(0, 0) transport_view_modes = TransportViewModeSelector(transport, session, ffwd_button, rwd_button, loop_button) select_button_modes = SelectButtonModeSelector(mixer2, tuple([ ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 49 + offset) for offset in range(8) ])) select_button_modes.set_mode_toggle(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 57)) self._mixer_encoder_modes = EncoderMixerModeSelector(mixer2) encoders = [] for offset in range(8): encoders.append(PeekableEncoderElement(MIDI_CC_TYPE, 15, 17 + offset, Live.MidiMap.MapMode.relative_smooth_two_compliment)) encoders[-1].set_feedback_delay(-1) mixer_or_device = MixerOrDeviceModeSelector(self._mixer_encoder_modes, device, tuple(encoders), tuple([ ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 74 + offset) for offset in range(4) ])) mixer_or_device.set_mode_toggle(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 109)) mixer_or_device.set_peek_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 78)) self._track_display = PhysicalDisplayElement(8, 1) self._track_display.set_clear_all_message(SYSEX_START + (16, 247)) self._track_display.set_message_parts(SYSEX_START + (17, 1, 0, 0), (247,)) self._track_display.segment(0).set_data_source(mixer1.selected_strip().track_name_data_source()) device_display = PhysicalDisplayElement(8, 1) device_display.set_message_parts(SYSEX_START + (17, 1, 0, 10), (247,)) parameter_display = PhysicalDisplayElement(16, 1) parameter_display.set_message_parts(SYSEX_START + (17, 2, 0, 0), (247,)) select_button_modes.set_mode_display(parameter_display) mixer1.set_display(parameter_display) mixer2.set_bank_display(parameter_display) page_displays = [] for index in range(4): page_displays.append(PhysicalDisplayElement(5, 1)) page_displays[-1].set_message_parts(SYSEX_START + (17, 4, index, 0), (247,)) encoder_display = PhysicalDisplayElement(80, 8) encoder_display.set_message_parts(SYSEX_START + (17, 3), (247,)) for index in range(8): pos_id = tuple() if index != 0: pos_id += (0,) if index > 3: pos_id += (index % 4, 13) else: pos_id += (index % 4, 0) encoder_display.segment(index).set_position_identifier(pos_id) mixer_or_device.set_displays(encoder_display, parameter_display, device_display, tuple(page_displays)) for component in self.components: component.set_enabled(False)
def _init_mixer_component(self, volume_controls, trackarm_controls, mixer_options, global_channel, volume_map_mode): if volume_controls != None and trackarm_controls != None: num_strips = max(len(volume_controls), len(trackarm_controls)) send_info = [] momentary_buttons = False mixer = SpecialMixerComponent(num_strips) mixer.name = 'Mixer' mixer.master_strip().name = 'Master_Channel_Strip' mixer.selected_strip().name = 'Selected_Channel_Strip' if mixer_options != None: if 'MASTERVOLUME' in mixer_options.keys() and mixer_options['MASTERVOLUME'] in range(128): encoder = EncoderElement(MIDI_CC_TYPE, global_channel, mixer_options['MASTERVOLUME'], volume_map_mode) encoder.name = 'Master_Volume_Control' mixer.master_strip().set_volume_control(encoder) if 'NUMSENDS' in mixer_options.keys() and mixer_options['NUMSENDS'] > 0: for send in range(mixer_options['NUMSENDS']): key = 'SEND' + str(send + 1) raise key in mixer_options.keys() or AssertionError send_info.append(mixer_options[key]) momentary_buttons = 'NOTOGGLE' in mixer_options.keys() next_bank_button = None prev_bank_button = None if 'NEXTBANK' in mixer_options.keys() and mixer_options['NEXTBANK'] in range(128): next_bank_button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, mixer_options['NEXTBANK']) next_bank_button.name = 'Mixer_Next_Bank_Button' if 'PREVBANK' in mixer_options.keys() and mixer_options['PREVBANK'] in range(128): prev_bank_button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, mixer_options['PREVBANK']) prev_bank_button.name = 'Mixer_Previous_Bank_Button' mixer.set_bank_buttons(next_bank_button, prev_bank_button) for track in range(num_strips): strip = mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) if track in range(len(volume_controls)): channel = global_channel cc = volume_controls[track] if isinstance(volume_controls[track], (tuple, list)): cc = volume_controls[track][0] if volume_controls[track][1] in range(16): channel = volume_controls[track][1] if cc in range(128) and channel in range(16): encoder = EncoderElement(MIDI_CC_TYPE, channel, cc, volume_map_mode) encoder.name = str(track) + '_Volume_Control' strip.set_volume_control(encoder) if track in range(len(trackarm_controls)) and trackarm_controls[track] in range(128): button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, trackarm_controls[track]) button.name = str(track) + '_Arm_Button' strip.set_arm_button(button) send_controls = [] for send in send_info: encoder = None if track in range(len(send)): channel = global_channel cc = send[track] if isinstance(send[track], (tuple, list)): cc = send[track][0] if send[track][1] in range(16): channel = send[track][1] if cc in range(128) and channel in range(16): encoder = EncoderElement(MIDI_CC_TYPE, channel, cc, volume_map_mode) encoder.name = str(track) + '_Send_' + str(list(send_info).index(send)) + '_Control' send_controls.append(encoder) strip.set_send_controls(tuple(send_controls))
def create_button(identifier, name): button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, GLOBAL_CHANNEL, identifier) button.name = name return button
def __init__(self, modeselector, editsection, *a, **k): super(KnobSection, self).__init__(*a, **k) self._modesel = modeselector self._editsection = editsection self._modesel.connect_main_knob(self) is_momentary = True self.main_knob = SliderElement(MIDI_CC_TYPE, 1, 85) self.push_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 87) self.volume_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 110) self.swing_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 111) self.tempo_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 112) self.xfade_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 116) self._mode_button = self.canonical_parent.create_gated_button(80, KSM_HUES[0]) self._color_edit_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 113) self._set_inicliplen_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 122) self._set_quantize_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 126) self.do_main.subject = self.main_knob self.do_main_push.subject = self.push_button self._do_volume.subject = self.volume_button self._do_swing.subject = self.swing_button self._do_tempo.subject = self.tempo_button self._do_xfade.subject = self.xfade_button self._do_toggle_mode.subject = self._mode_button self._do_color_button.subject = self._color_edit_button self._do_mikr_cliplen.subject = self._set_inicliplen_button self._do_mikr_quantize.subject = self._set_quantize_button self._do_dedicated_rec_quantize.subject = SliderElement(MIDI_CC_TYPE, 2, 112) self._do_dedicated_clip_quantize.subject = SliderElement(MIDI_CC_TYPE, 2, 113) self._radio_buttons = ( self.volume_button, self.swing_button, self.tempo_button, self.xfade_button, self._color_edit_button) self._do_button_left.subject = ButtonElement(is_momentary, MIDI_CC_TYPE, 2, 120) self._do_button_right.subject = ButtonElement(is_momentary, MIDI_CC_TYPE, 2, 121) self.volume_button.send_value(0, True) self._mode_button.set_color(KSM_HUES[0]) self.knob_action = self._scroll_action self._prev_mode = None self._prev_action = None return
class KnobSection(CompoundComponent): _wheel_overide = None _mode = KSM_SCROLL _push_down = False scrub_mode = True alt_mode = False def __init__(self, modeselector, editsection, *a, **k): super(KnobSection, self).__init__(*a, **k) self._modesel = modeselector self._editsection = editsection self._modesel.connect_main_knob(self) is_momentary = True self.main_knob = SliderElement(MIDI_CC_TYPE, 1, 85) self.push_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 87) self.volume_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 110) self.swing_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 111) self.tempo_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 112) self.xfade_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 116) self._mode_button = self.canonical_parent.create_gated_button(80, KSM_HUES[0]) self._color_edit_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 113) self._set_inicliplen_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 122) self._set_quantize_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 126) self.do_main.subject = self.main_knob self.do_main_push.subject = self.push_button self._do_volume.subject = self.volume_button self._do_swing.subject = self.swing_button self._do_tempo.subject = self.tempo_button self._do_xfade.subject = self.xfade_button self._do_toggle_mode.subject = self._mode_button self._do_color_button.subject = self._color_edit_button self._do_mikr_cliplen.subject = self._set_inicliplen_button self._do_mikr_quantize.subject = self._set_quantize_button self._do_dedicated_rec_quantize.subject = SliderElement(MIDI_CC_TYPE, 2, 112) self._do_dedicated_clip_quantize.subject = SliderElement(MIDI_CC_TYPE, 2, 113) self._radio_buttons = ( self.volume_button, self.swing_button, self.tempo_button, self.xfade_button, self._color_edit_button) self._do_button_left.subject = ButtonElement(is_momentary, MIDI_CC_TYPE, 2, 120) self._do_button_right.subject = ButtonElement(is_momentary, MIDI_CC_TYPE, 2, 121) self.volume_button.send_value(0, True) self._mode_button.set_color(KSM_HUES[0]) self.knob_action = self._scroll_action self._prev_mode = None self._prev_action = None return def do_message(self, msg, statusbarmsg=None): if statusbarmsg == None: self.canonical_parent.show_message(msg) else: self.canonical_parent.show_message(statusbarmsg) self.canonical_parent.timed_message(2, msg) return def use_scrub_mode(self): return self.scrub_mode def set_scrub_mode(self, value): self.scrub_mode = value self.scrub_mode_button.send_value(value and 127 or 0) def set_override(self, overide_callback): if self._wheel_overide != overide_callback: self._wheel_overide = overide_callback self.volume_button.send_value(0, True) self.swing_button.send_value(0, True) self.tempo_button.send_value(0, True) self._mode_button.switch_off() self._mode = None return def reset_overide(self): if self._wheel_overide: self._wheel_overide = None return def _scroll_action(self, value): inc = value == 1 and 1 or -1 self._modesel.navigate(inc, self._push_down, self._editsection.isShiftdown()) def _do_channel_slider(self, value): song = self.song() if self._editsection.isShiftdown(): dir = value == 127 and Live.Application.Application.View.NavDirection.left or Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(dir, 'Detail/DeviceChain', True) else: if self._push_down: dir = value == 127 and -1 or 1 scenes = song.scenes scene = song.view.selected_scene sindex = list(scenes).index(scene) sel_scene = sindex + dir if sel_scene >= 0 and sel_scene < len(scenes): song.view.selected_scene = scenes[sel_scene] else: direction = value == 127 and Live.Application.Application.View.NavDirection.left or Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Session', True) if self.canonical_parent.arm_selected_track: arm_exclusive(song) def _do_transport(self, value): diff = value == 127 and -1 or 1 jump = 4.0 if self._push_down: if self._editsection.isShiftdown(): jump = 0.25 else: jump = 1.0 else: if self._editsection.isShiftdown(): jump = 0.5 if self.scrub_mode: self.song().scrub_by(jump * diff) else: self.song().jump_by(jump * diff) @subject_slot('value') def do_main(self, value): if self._wheel_overide: self._wheel_overide(value == 1 and 1 or -1, self._editsection.isShiftdown(), self._push_down) else: if self.knob_action: self.knob_action(value) def _disable_radio_button(self): for button in self._radio_buttons: button.send_value(0, True) def enter_toggle_mode(self, mode=None): self.reset_overide() self.switch_pad_wheel_edit(False) self.alt_mode = False if self._mode < KSM_SCROLL or mode != None: if mode == None: self.switch_pad_wheel_edit(False) self._mode = KSM_SCROLL else: self._mode = mode self._disable_radio_button() else: modeval = self._mode + 1 if modeval > KSM_TRANSPORT: modeval = KSM_SCROLL self._mode = modeval if self._mode == KSM_SCROLL: self.knob_action = self._scroll_action self.do_message('Main Knob -> Navigate') else: if self._mode == KSM_SELECT: self.knob_action = self._do_channel_slider self.do_message('Main Knob -> Select') else: if self._mode == KSM_TRANSPORT: self.knob_action = self._do_transport self.do_message('Main Knob -> Transport') self._mode_button.set_color(KSM_HUES[self._mode - KSM_SCROLL]) return @subject_slot('value') def _do_toggle_mode(self, value): if value > 0: if self._editsection.isShiftdown(): self.canonical_parent.toggle_nav_mode() else: self.enter_toggle_mode() def _scroll_xfade(self, value): diff = value == 127 and -1 or 1 if self._wheel_overide: self._wheel_overide(diff, self._editsection.isShiftdown(), self._push_down) else: self.chg_xfade(diff) def _scroll_volume(self, value): diff = value == 127 and -1 or 1 if self._wheel_overide: self._wheel_overide(diff, self._editsection.isShiftdown(), self._push_down) else: if self._editsection.isShiftdown(): self.chg_cue(diff) else: self.chg_volume(diff) def _scroll_tempo(self, value): diff = value == 127 and -1 or 1 if self._wheel_overide: self._wheel_overide(diff, self._editsection.isShiftdown(), self._push_down) else: if self._push_down: self.chg_tempo(diff * 0.1) else: if self._editsection.isShiftdown(): self.chg_tempo(diff * 0.01) else: self.chg_tempo(diff) def _scroll_req_quantize(self, value): diff = value == 127 and -1 or 1 if self._wheel_overide: self._wheel_overide(diff, self._editsection.isShiftdown(), self._push_down) else: song = self.song() if self._editsection.isShiftdown(): quant = song.clip_trigger_quantization song.clip_trigger_quantization = max(0, min(13, quant + diff)) self.do_message('Clip Quantize ' + CLIQ_DESCR[song.clip_trigger_quantization]) else: rec_quant = song.midi_recording_quantization index = QUANT_CONST.index(rec_quant) + diff if index >= 0 and index < len(QUANT_CONST): song.midi_recording_quantization = QUANT_CONST[index] self.do_message(QUANT_DESCR[index]) @subject_slot('value') def do_main_push(self, value): if value != 0: self.alt_mode = not self.alt_mode self._push_down = value != 0 self._modesel.handle_push(value != 0) def switch_pad_wheel_edit(self, activate): if activate: self._color_edit_button.send_value(1, True) self._editsection.set_color_edit(True) else: self._color_edit_button.send_value(0, True) self._editsection.set_color_edit(False) def invoke_color_mode(self, active): if active and self._mode != KSM_EDIT: self._prev_mode = self._mode self._to_mode(KSM_EDIT) else: if not active and self._prev_mode != None: self.switch_pad_wheel_edit(False) self._to_mode(self._prev_mode) self._prev_mode = None return @subject_slot('value') def _do_color_button(self, value, force=False): if value > 0: if self._mode != KSM_EDIT: self._prev_mode = self._mode self.reset_overide() self._to_mode(KSM_EDIT) elif self._prev_mode != None: self.switch_pad_wheel_edit(False) self._to_mode(self._prev_mode) self._prev_mode = None return def _to_mode(self, mode): button = None if mode == KSM_VOLUME: button = self.volume_button self.knob_action = self._scroll_volume self.switch_pad_wheel_edit(False) else: if mode == KSM_SWING: button = self.swing_button self.knob_action = self._scroll_req_quantize self.switch_pad_wheel_edit(False) else: if mode == KSM_TEMPO: button = self.tempo_button self.knob_action = self._scroll_tempo self.switch_pad_wheel_edit(False) else: if mode == KSM_XFADE: button = self.xfade_button self.knob_action = self._scroll_xfade self.switch_pad_wheel_edit(False) else: if mode == KSM_EDIT: self._editsection.set_color_edit(True) else: self.enter_toggle_mode(mode) self._mode = mode for rbutton in self._radio_buttons: if rbutton != button: rbutton.send_value(0) if button: self._mode_button.switch_off() button.send_value(127, True) return def _edit_color(self, value): diff = value == 127 and -1 or 1 if self._wheel_overide: self._wheel_overide(diff, self._editsection.isShiftdown(), self._push_down) else: self._editsection.edit_colors(diff) @subject_slot('value') def _do_button_left(self, value): if value != 0: self._modesel.navigate(-1, self._editsection.isShiftdown(), False) @subject_slot('value') def _do_button_right(self, value): if value != 0: self._modesel.navigate(1, self._editsection.isShiftdown(), False) @subject_slot('value') def _do_mikr_cliplen(self, value): if value == 0: self.knob_action = self._prev_action else: self._prev_action = self.knob_action self.knob_action = self._modify_init_cliplen @subject_slot('value') def _do_mikr_quantize(self, value): if value == 0: self.knob_action = self._prev_action else: self._prev_action = self.knob_action self.knob_action = self._modify_quant_grid def _modify_init_cliplen(self, value): if self._push_down: self._editsection.mod_new_initlen(value == 1 and 1 or -1) else: self._editsection.mod_new_initlen(value == 1 and 4 or -4) def _modify_quant_grid(self, value): self._editsection.mod_quant_size(value == 1 and 1 or -1) @subject_slot('value') def _do_xfade(self, value): if value > 0 and self._mode != KSM_XFADE: self.reset_overide() self._to_mode(KSM_XFADE) @subject_slot('value') def _do_volume(self, value): if value > 0 and self._mode != KSM_VOLUME: self.reset_overide() self._to_mode(KSM_VOLUME) @subject_slot('value') def _do_swing(self, value): if value > 0 and self._mode != KSM_SWING: self.reset_overide() self._to_mode(KSM_SWING) @subject_slot('value') def _do_tempo(self, value): if value > 0 and self._mode != KSM_TEMPO: self.reset_overide() self._to_mode(KSM_TEMPO) @subject_slot('value') def _do_dedicated_clip_quantize(self, value): diff = value == 127 and -1 or 1 song = self.song() quant = song.clip_trigger_quantization song.clip_trigger_quantization = max(0, min(13, quant + diff)) self.do_message('Clip Quantize ' + CLIQ_DESCR[song.clip_trigger_quantization]) @subject_slot('value') def _do_dedicated_rec_quantize(self, value): diff = value == 127 and -1 or 1 song = self.song() rec_quant = song.midi_recording_quantization index = QUANT_CONST.index(rec_quant) + diff if index >= 0 and index < len(QUANT_CONST): song.midi_recording_quantization = QUANT_CONST[index] self.do_message('Rec Quantize: ' + QUANT_STRING[index]) def chg_tempo(self, diff): self.song().tempo = max(20, min(999, self.song().tempo + diff)) self.canonical_parent.timed_message(2, 'Tempo: ' + str(round(self.song().tempo, 2))) def chg_volume(self, diff): if self._push_down: self.song().master_track.mixer_device.volume.value = calc_new_parm(self.song().master_track.mixer_device.volume, diff) else: repeat(self.song().master_track.mixer_device.volume, diff) def chg_xfade(self, diff): if self._push_down: self.song().master_track.mixer_device.crossfader.value = calc_new_parm(self.song().master_track.mixer_device.crossfader, diff) else: repeat(self.song().master_track.mixer_device.crossfader, diff) def chg_cue(self, diff): if self._push_down: self.song().master_track.mixer_device.cue_volume.value = calc_new_parm(self.song().master_track.mixer_device.cue_volume, diff) else: repeat(self.song().master_track.mixer_device.cue_volume, diff) def update(self): pass def refresh(self): pass
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._device_selection_follows_track_selection = True with self.component_guard(): self._suppress_send_midi = True self._suppress_session_highlight = True self._control_is_with_automap = False is_momentary = True self._suggested_input_port = 'Akai MPK26' self._suggested_output_port = 'Akai MPK26' self.log("BEFORE mixer") self._setup_mixer_control() self._setup_device_control() # self.clipcontrol(8) self.log("AFTER MIXER") """SESSION ViEW""" global session session = SessionComponent(GRIDSIZE[0],GRIDSIZE[1]) session.name = 'Session_Control' matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' up_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, UP_BUTTON) down_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, DOWN_BUTTON) left_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, LEFT_BUTTON) right_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, RIGHT_BUTTON) session.set_scene_bank_buttons(down_button, up_button) session.set_track_bank_buttons(right_button, left_button) # session_zoom = SessionZoomingComponent(session) # session_zoom.set_nav_buttons(up_button,down_button,left_button,right_button) session_stop_buttons = [] self.log("SETTING UP GRID") for row in xrange(GRIDSIZE[1]): button_row = [] self.log("CZ ROW") self.log(str(row)) scene = session.scene(row) scene.name = 'Scene_' + str(row) scene.set_launch_button(ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, SCENE_BUTTONS[row])) scene.set_triggered_value(2) for column in xrange(GRIDSIZE[0]): self.log("CZ COLUMN") self.log(str(column)) button = ConfigurableButtonElement(True, MIDI_NOTE_TYPE, CHANNEL_MIXER, LAUNCH_BUTTONS[row][column]) button.name = str(column) + '_Clip_' + str(row) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_' + str(row) clip_slot.set_launch_button(button) matrix.add_row(tuple(button_row)) for column in xrange(GRIDSIZE[0]): session_stop_buttons.append((ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL_MIXER, TRACK_STOPS[column]))) self._suppress_session_highlight = False self._suppress_send_midi = False self.set_highlighting_session_component(session) session.set_stop_track_clip_buttons(tuple(session_stop_buttons)) session.set_mixer(mixer)
def _setup_mixer_control(self): num_tracks = GRIDSIZE[0] # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent(num_tracks) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track master = mixer.master_strip() master.set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_USER, MASTER_VOLUME)) mixer.set_prehear_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_USER, PREHEAR)) for index in xrange(GRIDSIZE[0]): mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, MIX_FADERS[index])) # mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_INST, MIX_FADERS[index])) mixer.channel_strip(index).set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, PAN_CONTROLS[index])) mixer.channel_strip(index).set_arm_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, ARM_BUTTONS[index])) #sets the record arm button mixer.channel_strip(index).set_solo_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, SOLO_BUTTONS[index])) mixer.channel_strip(index).set_mute_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, MUTE_BUTTONS[index])) mixer.channel_strip(index).set_select_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, TRACK_SELECTS[index])) mixer.channel_strip(index).set_send_controls([SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][0]), SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][1]), SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][2]), SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][3])]) """TRANSPORT CONTROLS""" stop_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL_MIXER, STOP_BUTTON) play_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL_MIXER, PLAY_BUTTON) record_button = ButtonElement(False,MIDI_CC_TYPE,CHANNEL_MIXER,RECORD_BUTTON) overdub_button = ButtonElement(False,MIDI_CC_TYPE,CHANNEL_MIXER,OVERDUB_BUTTON) transport = TransportComponent() transport.TEMPO_TOP = 188 transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_overdub_button(overdub_button) transport.set_record_button(record_button) transport.set_seek_buttons(ButtonElement(False,MIDI_CC_TYPE,0,SEEK_LEFT),ButtonElement(False,MIDI_CC_TYPE,0,SEEK_RIGHT)) transport.set_tempo_control(SliderElement(MIDI_CC_TYPE, CHANNEL_USER, TEMPO)) transport.set_metronome_button(ButtonElement(False,MIDI_CC_TYPE,CHANNEL_USER, METRONOME)) transport.set_tap_tempo_button(ButtonElement(False,MIDI_CC_TYPE,CHANNEL_USER,TAP_TEMPO))
def _init_device_component(self, device_controls, bank_controls, global_channel, macro_map_mode): is_momentary = True if device_controls: device = DeviceComponent() device.name = 'Device_Component' if bank_controls: next_button = None prev_button = None if 'NEXTBANK' in bank_controls.keys() and bank_controls['NEXTBANK'] in range(128): next_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, bank_controls['NEXTBANK']) next_button.name = 'Device_Next_Bank_Button' if 'PREVBANK' in bank_controls.keys() and bank_controls['PREVBANK'] in range(128): prev_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, bank_controls['PREVBANK']) prev_button.name = 'Device_Previous_Bank_Button' device.set_bank_nav_buttons(prev_button, next_button) if 'TOGGLELOCK' in bank_controls.keys() and bank_controls['TOGGLELOCK'] in range(128): lock_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, bank_controls['TOGGLELOCK']) lock_button.name = 'Device_Lock_Button' device.set_lock_button(lock_button) bank_buttons = [] for index in range(8): key = 'BANK' + str(index + 1) if key in bank_controls.keys(): control_info = bank_controls[key] channel = global_channel cc = -1 if isinstance(control_info, (tuple, list)): cc = control_info[0] if control_info[1] in range(16): channel = control_info[1] else: cc = control_info if cc in range(128) and channel in range(16): button = ButtonElement(is_momentary, MIDI_CC_TYPE, channel, cc) button.name = 'Device_Bank_' + str(index) + '_Button' bank_buttons.append(button) if len(bank_buttons) > 0: device.set_bank_buttons(tuple(bank_buttons)) parameter_encoders = [] for control_info in device_controls: channel = global_channel cc = -1 if isinstance(control_info, (tuple, list)): cc = control_info[0] if control_info[1] in range(16): channel = control_info[1] else: cc = control_info if cc in range(128) and channel in range(16): encoder = EncoderElement(MIDI_CC_TYPE, channel, cc, macro_map_mode) encoder.name = 'Device_Parameter_' + str(list(device_controls).index(control_info)) + '_Control' parameter_encoders.append(encoder) if len(parameter_encoders) > 0: device.set_parameter_controls(tuple(parameter_encoders)) self.set_device_component(device)
def _init_transport_component(self, transport_controls, global_channel): is_momentary = True if transport_controls: transport = TransportComponent() transport.name = 'Transport' if 'STOP' in transport_controls.keys() and transport_controls['STOP'] in range(128): stop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['STOP']) stop_button.name = 'Stop_Button' transport.set_stop_button(stop_button) if 'PLAY' in transport_controls.keys() and transport_controls['PLAY'] in range(128): play_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['PLAY']) play_button.name = 'Play_Button' transport.set_play_button(play_button) if 'REC' in transport_controls.keys() and transport_controls['REC'] in range(128): rec_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['REC']) rec_button.name = 'Record_Button' transport.set_record_button(rec_button) if 'LOOP' in transport_controls.keys() and transport_controls['LOOP'] in range(128): loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['LOOP']) loop_button.name = 'Loop_Button' transport.set_loop_button(loop_button) ffwd_button = None rwd_button = None momentary_seek = 'NORELEASE' not in transport_controls.keys() if 'FFWD' in transport_controls.keys() and transport_controls['FFWD'] in range(128): ffwd_button = ButtonElement(momentary_seek, MIDI_CC_TYPE, global_channel, transport_controls['FFWD']) ffwd_button.name = 'FFwd_Button' if 'RWD' in transport_controls.keys() and transport_controls['RWD'] in range(128): rwd_button = ButtonElement(momentary_seek, MIDI_CC_TYPE, global_channel, transport_controls['RWD']) rwd_button.name = 'Rwd_Button' transport.set_seek_buttons(ffwd_button, rwd_button)
def _load_MIDI_map(self): is_momentary = True # SCENELAUNCH Buttons for scene_id in range(MATRIX_DEPTH): if (SCENELAUNCH[scene_id] == -1): button = None else: button = ButtonElement(is_momentary, SCENELAUNCH_TYPE[scene_id], SCENELAUNCH_CH[scene_id], SCENELAUNCH[scene_id]) button.name = u'Scene_' + str(scene_id) self._note_map_scenes.append(button) # BUTTON_VECTOR Buttons for button_id in range(NUMBER_BUTTONS): if (BUTTON_VECTOR[button_id] == -1): button = None else: if (button_id == 0): button = ButtonElement(False, BUTTON_VECTOR_TYPE[button_id], BUTTON_VECTOR_CH[button_id], BUTTON_VECTOR[button_id]) else: button = ButtonElement(is_momentary, BUTTON_VECTOR_TYPE[button_id], BUTTON_VECTOR_CH[button_id], BUTTON_VECTOR[button_id]) button.name = u'Global_Button_' + str(button_id) self._note_map_buttons.append(button) # SLIDER_VECTOR Sliders for slider_id in range(NUMBER_SLIDERS): if (SLIDER_VECTOR[slider_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, SLIDER_VECTOR_CH[slider_id], SLIDER_VECTOR[slider_id]) control.name = u'Global_Slider_' + str(slider_id) self._ctrl_map_sliders.append(control) # TRACKSTOP Buttons for track_id in range(TRACK_NUMBER): if (TRACKSTOP[track_id] == -1): button = None else: button = ButtonElement(is_momentary, TRACKSTOP_TYPE[track_id], TRACKSTOP_CH[track_id], TRACKSTOP[track_id]) button.name = u'Trk_Stop_Button_' + str(track_id) self._note_map_trk_stop_buttons.append(button) # TRACKSEL Buttons for track_id in range(TRACK_NUMBER): if (TRACKSEL[track_id] == -1): button = None else: button = ButtonElement(is_momentary, TRACKSEL_TYPE[track_id], TRACKSEL_CH[track_id], TRACKSEL[track_id]) button.name = u'Trk_Sel_Button_' + str(track_id) self._note_map_trk_sel_buttons.append(button) # TRACKMUTE Buttons for track_id in range(TRACK_NUMBER): if (TRACKMUTE[track_id] == -1): button = None else: button = ButtonElement(False, TRACKMUTE_TYPE[track_id], TRACKMUTE_CH[track_id], TRACKMUTE[track_id]) button.name = u'Trk_Mute_Button_' + str(track_id) self._note_map_trk_mute_buttons.append(button) # TRACKSOLO Buttons for track_id in range(TRACK_NUMBER): if (TRACKSOLO[track_id] == -1): button = None else: button = ButtonElement(is_momentary, TRACKSOLO_TYPE[track_id], TRACKSOLO_CH[track_id], TRACKSOLO[track_id]) button.name = u'Trk_Solo_Button_' + str(track_id) self._note_map_trk_solo_buttons.append(button) # TRACKREC Buttons for track_id in range(TRACK_NUMBER): if (TRACKREC[track_id] == -1): button = None else: button = ButtonElement(False, TRACKREC_TYPE[track_id], TRACKREC_CH[track_id], TRACKREC[track_id]) button.name = u'Trk_Rec_Button_' + str(track_id) self._note_map_trk_rec_buttons.append(button) # TRACKVOL Sliders for track_id in range(TRACK_NUMBER): if (TRACKVOL[track_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, TRACKVOL_CH[track_id], TRACKVOL[track_id]) control.name = u'Trk_Vol_Slider_' + str(track_id) self._ctrl_map_trk_volume.append(control) # TRACKPAN Sliders for track_id in range(TRACK_NUMBER): if (TRACKPAN[track_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, TRACKPAN_CH[track_id], TRACKPAN[track_id]) control.name = u'Trk_Pan_Slider_' + str(track_id) self._ctrl_map_trk_pan.append(control) # TRACKSENDA Sliders for track_id in range(TRACK_NUMBER): if (TRACKSENDA[track_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, TRACKSENDA_CH[track_id], TRACKSENDA[track_id]) control.name = u'Trk_SendA_Slider_' + str(track_id) self._ctrl_map_senda.append(control) # TRACKSENDB Sliders for track_id in range(TRACK_NUMBER): if (TRACKSENDB[track_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, TRACKSENDB_CH[track_id], TRACKSENDB[track_id]) control.name = u'Trk_SendB_Slider_' + str(track_id) self._ctrl_map_sendb.append(control) # TRACKSENDC Sliders for track_id in range(TRACK_NUMBER): if (TRACKSENDC[track_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, TRACKSENDC_CH[track_id], TRACKSENDC[track_id]) control.name = u'Trk_SendC_Slider_' + str(track_id) self._ctrl_map_sendc.append(control) # DEVICEBANK Buttons for bank_id in range(BANKS_NUMBER): if (DEVICEBANK[bank_id] == -1): button = None else: button = ButtonElement(is_momentary, DEVICEBANK_TYPE[bank_id], DEVICEBANK_CH[bank_id], DEVICEBANK[bank_id]) button.name = u'Bank_Button_' + str(bank_id) self._note_map_bank_buttons.append(button) # PARAMCONTROL Sliders for param_id in range(PARAMS_NUMBER): if (PARAMCONTROL[param_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, PARAMCONTROL_CH[param_id], PARAMCONTROL[param_id]) control.name = u'Slider_Param_' + str(param_id) self._ctrl_map_parameter.append(control)
class AxiomPro(ControlSurface): """ Script for the M-Audio Axiom Pro """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): is_momentary = True self.set_pad_translations(PAD_TRANSLATIONS) self._suggested_input_port = 'HyperControl' self._suggested_output_port = 'HyperControl' self._display_on_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 15, 79) self._waiting_for_first_response = True mixer1 = DisplayingMixerComponent(0) mixer1.set_select_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 111), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 110)) mixer1.set_mute_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 12)) mixer1.set_solo_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 13)) mixer2 = NotifyingMixerComponent(8) mixer2.set_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 15), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 14)) mixer2.master_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, 15, 41)) for index in range(8): mixer2.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, 15, 33 + index)) device = PageableDeviceComponent(device_selection_follows_track_selection=True) self.set_device_component(device) ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 115) rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 114) loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 113) transport = TransportComponent() transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 116)) transport.set_play_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 117)) transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 118)) session = SessionComponent(0, 0) transport_view_modes = TransportViewModeSelector(transport, session, ffwd_button, rwd_button, loop_button) select_button_modes = SelectButtonModeSelector(mixer2, tuple([ ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 49 + offset) for offset in range(8) ])) select_button_modes.set_mode_toggle(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 57)) self._mixer_encoder_modes = EncoderMixerModeSelector(mixer2) encoders = [] for offset in range(8): encoders.append(PeekableEncoderElement(MIDI_CC_TYPE, 15, 17 + offset, Live.MidiMap.MapMode.relative_smooth_two_compliment)) encoders[-1].set_feedback_delay(-1) mixer_or_device = MixerOrDeviceModeSelector(self._mixer_encoder_modes, device, tuple(encoders), tuple([ ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 74 + offset) for offset in range(4) ])) mixer_or_device.set_mode_toggle(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 109)) mixer_or_device.set_peek_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 78)) self._track_display = PhysicalDisplayElement(8, 1) self._track_display.set_clear_all_message(SYSEX_START + (16, 247)) self._track_display.set_message_parts(SYSEX_START + (17, 1, 0, 0), (247,)) self._track_display.segment(0).set_data_source(mixer1.selected_strip().track_name_data_source()) device_display = PhysicalDisplayElement(8, 1) device_display.set_message_parts(SYSEX_START + (17, 1, 0, 10), (247,)) parameter_display = PhysicalDisplayElement(16, 1) parameter_display.set_message_parts(SYSEX_START + (17, 2, 0, 0), (247,)) select_button_modes.set_mode_display(parameter_display) mixer1.set_display(parameter_display) mixer2.set_bank_display(parameter_display) page_displays = [] for index in range(4): page_displays.append(PhysicalDisplayElement(5, 1)) page_displays[-1].set_message_parts(SYSEX_START + (17, 4, index, 0), (247,)) encoder_display = PhysicalDisplayElement(80, 8) encoder_display.set_message_parts(SYSEX_START + (17, 3), (247,)) for index in range(8): pos_id = tuple() if index != 0: pos_id += (0,) if index > 3: pos_id += (index % 4, 13) else: pos_id += (index % 4, 0) encoder_display.segment(index).set_position_identifier(pos_id) mixer_or_device.set_displays(encoder_display, parameter_display, device_display, tuple(page_displays)) for component in self.components: component.set_enabled(False) def refresh_state(self): ControlSurface.refresh_state(self) self._waiting_for_first_response = True self.schedule_message(10, self._send_midi, SYSEX_START + (32, 46, 247)) def handle_sysex(self, midi_bytes): if midi_bytes[0:-2] == SYSEX_START + (32,): msg_id_byte = midi_bytes[-2] is_setup_response = msg_id_byte in (46, 38) has_sliders = msg_id_byte == 46 if is_setup_response: if self._waiting_for_first_response: self._waiting_for_first_response = False self._display_on_button.send_value(0) for component in self.components: component.set_enabled(True) self._display_on_button.send_value(127) self._send_midi(SYSEX_START + (16, 247)) self._send_midi(SYSEX_START + (17, 3, 0, 1, 65, 98, 108, 101, 116, 111, 110, 32, 76, 105, 118, 101, 32, 67, 111, 110, 116, 114, 111, 108, 32, 0, 1, 4, 83, 117, 114, 102, 97, 99, 101, 32, 118, 49, 46, 48, 46, 48, 46, 247)) self._mixer_encoder_modes.set_show_volume_page(not has_sliders) for display in self._displays: display.set_block_messages(False) self.schedule_message(25, self._refresh_displays) elif msg_id_byte == 43: self._send_midi(SYSEX_START + (16, 247)) for display in self._displays: if display is self._track_display: display.update() else: display.set_block_messages(True) def disconnect(self): ControlSurface.disconnect(self) self._send_midi(SYSEX_START + (32, 0, 247)) self._send_midi(SYSEX_START + (16, 247)) self._send_midi(SYSEX_START + (17, 3, 0, 4, 65, 98, 108, 101, 116, 111, 110, 32, 76, 105, 118, 101, 32, 67, 111, 110, 116, 114, 111, 108, 32, 0, 1, 4, 83, 117, 114, 102, 97, 99, 101, 32, 67, 108, 111, 115, 101, 100, 46, 247))
class Launchpad(ControlSurface): _active_instances = [] def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) live = Live.Application.get_application() self._live_major_version = live.get_major_version() self._live_minor_version = live.get_minor_version() self._live_bugfix_version = live.get_bugfix_version() self._selector = None #needed because update hardware is called. self._mk2_rgb = False with self.component_guard(): self._suppress_send_midi = True self._suppress_session_highlight = True self._suggested_input_port = ("Launchpad", "Launchpad Mini", "Launchpad S", "Launchpad MK2") self._suggested_output_port = ("Launchpad", "Launchpad Mini", "Launchpad S", "Launchpad MK2") self._control_is_with_automap = False self._user_byte_write_button = None self._config_button = None self._wrote_user_byte = False self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143 self._init_done = False # caller will send challenge and we will continue as challenge is received. def init(self): #skip init if already done. if self._init_done: return self._init_done = True # second part of the __init__ after model has been identified using its challenge response if self._mk2_rgb: from SkinMK2 import make_skin self._skin = make_skin() self._side_notes = (89, 79, 69, 59, 49, 39, 29, 19) #self._drum_notes = (20, 30, 31, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126) self._drum_notes = (20, 30, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126) else: from SkinMK1 import make_skin self._skin = make_skin() self._side_notes = (8, 24, 40, 56, 72, 88, 104, 120) self._drum_notes = (41, 42, 43, 44, 45, 46, 47, 57, 58, 59, 60, 61, 62, 63, 73, 74, 75, 76, 77, 78, 79, 89, 90, 91, 92, 93, 94, 95, 105, 106, 107) with self.component_guard(): is_momentary = True self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False) self._config_button.add_value_listener(self._config_value) self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = 'User_Byte_Button' self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' for row in range(8): button_row = [] for column in range(8): if self._mk2_rgb: # for mk2 buttons are assigned "top to bottom" midi_note = (81 - (10 * row)) + column else: midi_note = row * 16 + column button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, midi_note, skin = self._skin, control_surface = self) button.name = str(column) + '_Clip_' + str(row) + '_Button' button_row.append(button) matrix.add_row(tuple(button_row)) top_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, skin = self._skin) for index in range(8)] side_buttons = [ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, self._side_notes[index], skin = self._skin) for index in range(8)] top_buttons[0].name = 'Bank_Select_Up_Button' top_buttons[1].name = 'Bank_Select_Down_Button' top_buttons[2].name = 'Bank_Select_Left_Button' top_buttons[3].name = 'Bank_Select_Right_Button' top_buttons[4].name = 'Session_Button' top_buttons[5].name = 'User1_Button' top_buttons[6].name = 'User2_Button' top_buttons[7].name = 'Mixer_Button' side_buttons[0].name = 'Vol_Button' side_buttons[1].name = 'Pan_Button' side_buttons[2].name = 'SndA_Button' side_buttons[3].name = 'SndB_Button' side_buttons[4].name = 'Stop_Button' side_buttons[5].name = 'Trk_On_Button' side_buttons[6].name = 'Solo_Button' side_buttons[7].name = 'Arm_Button' self._osd = M4LInterface() self._osd.name = "OSD" self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self._osd, self) self._selector.name = 'Main_Modes' self._do_combine() for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.add_value_listener(self._button_value) self.set_highlighting_session_component(self._selector.session_component()) self._suppress_session_highlight = False # due to our 2 stage init, we need to rebuild midi map self.request_rebuild_midi_map() # and request update self._selector.update() if self._mk2_rgb: self.log_message("LaunchPad95 (mk2) Loaded !") else: self.log_message("LaunchPad95 Loaded !") 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._do_uncombine() if self._selector != None: self._user_byte_write_button.remove_value_listener(self._user_byte_value) self._config_button.remove_value_listener(self._config_value) ControlSurface.disconnect(self) self._suppress_send_midi = False if self._mk2_rgb: # launchpad mk2 needs disconnect string sent self._send_midi((240, 0, 32, 41, 2, 24, 64, 247)) if self._config_button != None: 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 _combine_active_instances(): support_devices = False for instance in Launchpad._active_instances: support_devices |= (instance._device_component != None) offset = 0 for instance in Launchpad._active_instances: instance._activate_combination_mode(offset, support_devices) offset += instance._selector._session.width() _combine_active_instances = staticmethod(_combine_active_instances) def _activate_combination_mode(self, track_offset, support_devices): if(Settings.STEPSEQ__LINK_WITH_SESSION): self._selector._stepseq.link_with_step_offset(track_offset) if(Settings.SESSION__LINK): self._selector._session.link_with_track_offset(track_offset) def _do_combine(self): if (DO_COMBINE and (self not in Launchpad._active_instances)): Launchpad._active_instances.append(self) Launchpad._combine_active_instances() def _do_uncombine(self): if self in Launchpad._active_instances: Launchpad._active_instances.remove(self) if(Settings.SESSION__LINK): self._selector._session.unlink() if(Settings.STEPSEQ__LINK_WITH_SESSION): self._selector._stepseq.unlink() Launchpad._combine_active_instances() def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(5, self._update_hardware) def handle_sysex(self, midi_bytes): # MK2 has different challenge and params if len(midi_bytes) == 10 and midi_bytes[:7] == (240, 0, 32, 41, 2, 24, 64): response = long(midi_bytes[7]) response += long(midi_bytes[8]) << 8 if response == Live.Application.encrypt_challenge2(self._challenge): self._mk2_rgb = True self.log_message("Challenge Response ok (mk2)") self._suppress_send_midi = False self.set_enabled(True) self.init() #MK1 Challenge elif len(midi_bytes) == 8 and 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.log_message("Challenge Response ok (mk1)") self._mk2_rgb = False self.init() self._suppress_send_midi = False self.set_enabled(True) else: ControlSurface.handle_sysex(self,midi_bytes) def build_midi_map(self, midi_map_handle): ControlSurface.build_midi_map(self, midi_map_handle) if self._selector!=None: if self._selector._main_mode_index==2 or self._selector._main_mode_index==1: mode = Settings.USER_MODES[ (self._selector._main_mode_index-1) * 3 + self._selector._sub_mode_index[self._selector._main_mode_index] ] #self._selector.mode_index == 1: #if self._selector._sub_mode_index[self._selector._mode_index] > 0: # disable midi map rebuild for instrument mode to prevent light feedback errors if mode != "instrument": new_channel = self._selector.channel_for_current_mode() for note in self._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 if self._user_byte_write_button != None: self._user_byte_write_button.send_value(1) self._wrote_user_byte = True self._suppress_send_midi = True self.set_enabled(False) self._suppress_send_midi = False self._send_challenge() def _send_challenge(self): # send challenge for all models to allow to detect which one is actually plugged # mk2 challenge_bytes = tuple([ self._challenge >> 8 * index & 127 for index in xrange(4) ]) self._send_midi((240, 0, 32, 41, 2, 24, 64) + challenge_bytes + (247,)) # mk1's 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): assert (value in range(128)) if not self._wrote_user_byte: enabled = (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.force_next_send() self._selector.set_mode(0) self.set_enabled(enabled) self._suppress_send_midi = False else: self._wrote_user_byte = False def _button_value(self, value): assert value in range(128) def _config_value(self, value): assert value in range(128) def _set_session_highlight(self, track_offset, scene_offset, width, height, include_return_tracks): if not self._suppress_session_highlight: ControlSurface._set_session_highlight(self, track_offset, scene_offset, width, height, include_return_tracks)
class OP1(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self.c_instance = c_instance self.retries_count = 0 self.device_connected = False self.clip_color_callbacks = {} self.slot_callbacks = {} self.text_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x03) self.text_end_sequence = (0xf7, ) self.enable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x02, 0xf7) self.disable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x00, 0xf7) self.id_sequence = (0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7) self.text_color_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x04) self.log('INITIALIZING') self.app = Live.Application.get_application() #maj = self.app.get_major_version() #min = self.app.get_minor_version() #bug = self.app.get_bugfix_version() #self.show_message(str(1) + "." + str(0) + "." + str(9)) self.show_message("Version " + VERSION) # reseting text self.write_text(' ') # reset display clips self.reset_display_clips() # getting browser visible state self.session_browser_visible = self.app.view.is_view_visible("Browser") # getting browser visible state self.arrange_browser_visible = self.app.view.is_view_visible("Browser") # getting session view visible state self.session_visible = self.app.view.is_view_visible("Session") # getting arrange view visible state self.arrange_visible = self.app.view.is_view_visible("Arranger") # getting detail view visible state self.detail_visible = self.app.view.is_view_visible("Detail") # getting back to arranger state self.back_to_arranger_state = self.song().back_to_arranger # initializing channel strip to null self._channel_strip = None # initializing transport component self._transport = TransportComponent() # initializing mixer component self._mixer = MixerComponent(NUM_TRACKS, 2) # initializing session component self._session = SessionComponent(NUM_TRACKS, NUM_ROWS) self._session.add_offset_listener(self.session_offset_changed) # configuring operation mode selector buttons self._operation_mode_buttons = ButtonElement( True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_1_BUTTON), ButtonElement( True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_2_BUTTON), ButtonElement( True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_3_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_4_BUTTON), # initializing operation mode selector self._operation_mode_selector = OP1ModeSelectorComponent( self, self._transport, self._mixer, self._session) # setting operation mode selector buttons self._operation_mode_selector.set_mode_buttons( self._operation_mode_buttons) # adding value listener for operation mode index self._operation_mode_selector.add_mode_index_listener( self.mode_index_changed) # setting global transport assignments self._transport.set_record_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_REC_BUTTON)) self._transport.set_play_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_PLAY_BUTTON)) self._transport.set_stop_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_STOP_BUTTON)) self._transport.set_metronome_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_METRONOME_BUTTON)) self._transport.set_tap_tempo_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_HELP_BUTTON)) self._transport.set_punch_buttons( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS1_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS2_BUTTON)) self._transport.set_loop_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS3_BUTTON)) self._transport.set_overdub_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS4_BUTTON)) # setting global session assignments self._session.set_scene_bank_buttons( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_COM), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MICRO)) # setting misc listeners self.browser_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 15) self.browser_toggle_button.add_value_listener( self.browser_toggle_button_callback) self.mainview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 16) self.mainview_toggle_button.add_value_listener( self.mainview_toggle_button_callback) self.detailview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 17) self.detailview_toggle_button.add_value_listener( self.detailview_toggle_button_callback) self.clear_track_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 25) self.clear_track_button.add_value_listener( self.clear_track_button_callback) self.back_to_arranger_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 26) self.back_to_arranger_button.add_value_listener( self.back_to_arranger_button_callback) # adding value listener for selected track change self.song().view.add_selected_track_listener( self.selected_track_changed) # adding value listener for selected scene change self.song().view.add_selected_scene_listener( self.selected_scene_changed) # setting assignments for currently selected track self.selected_track_changed() # setting assignments for currently selected scene self.selected_scene_changed() def handle_sysex(self, midi_bytes): if ((midi_bytes[6] == 32) and (midi_bytes[7] == 118)): self.device_connected = True self.log("OP-1 CONNECTED. SENDING ABLETON LIVE MODE INIT SEQUENCE") self._send_midi(self.enable_sequence) def add_clip_slot_listeners(self): #self.log('ADDING CLIP SLOT LISTENERS') # creating an empty list for all clip slots clip_slots = [] # getting a reference to all tracks tracks = self.song().tracks # appending all tracks clip slots to clip_slots for track in tracks: clip_slots.append(track.clip_slots) # iterating over all clip slots for t in range(len(clip_slots)): for c in range(len(clip_slots[t])): clip_slot = clip_slots[t][c] # adding has clip listener to clip slot self.add_slot_listener(clip_slot) # if clip slot has clip if clip_slot.has_clip: # adding clip listeners self.add_clip_listener(clip_slot.clip) def rem_clip_slot_listeners(self): #self.log('REMOVING CLIP SLOT LISTENERS') # iterate over all clip color change callbacks for c in self.clip_color_callbacks: # if clip still exists if c != None: # and it has a has clip listener if c.color_has_listener(self.clip_color_callbacks[c]) == 1: # remove it c.remove_color_listener(self.clip_color_callbacks[c]) # iterate over all clip slot callbacks for cs in self.slot_callbacks: # if clip slot still exists if cs != None: # and it has a has clip listener if cs.has_clip_has_listener(self.slot_callbacks[cs]) == 1: # remove it cs.remove_has_clip_listener(self.slot_callbacks[cs]) def add_slot_listener(self, cs): # setting has clip listener callback = lambda: self.has_clip_listener(cs) # if we don't have a clip slot has clip listener for this clip slot yet if not (self.slot_callbacks.has_key(cs)): # adding has clip callback to clip slot cs.add_has_clip_listener(callback) # saving callback for future release self.slot_callbacks[cs] = callback def add_clip_listener(self, clip): # setting callback for clip color change color_callback = lambda: self.update_display_clips() # if we don't have a clip color change callback for this clip yet if not (self.clip_color_callbacks.has_key(clip)): # adding clip color change callback clip.add_color_listener(color_callback) # saving callback for future release self.clip_color_callbacks[clip] = color_callback def has_clip_listener(self, cs): # clip slot has clip listener callback if cs.has_clip: # add clip listener self.add_clip_listener(cs.clip) else: # update display if clip slot was removed self.update_display_clips() def session_offset_changed(self): # if session component offset changes, update display self.update_display_clips() def selected_scene_changed(self): # if on clip mode update display if (self._operation_mode_selector.mode_index == OP1_MODE_CLIP): self.update_display_clip_mode() def mode_index_changed(self): # update display to current mode info if (self._operation_mode_selector.mode_index == OP1_MODE_PERFORM): self.update_display_perform_mode() elif (self._operation_mode_selector.mode_index == OP1_MODE_CLIP): self.update_display_clip_mode() elif (self._operation_mode_selector.mode_index == OP1_MODE_TRANSPORT): self.update_display_transport_mode() elif (self._operation_mode_selector.mode_index == OP1_MODE_MIXER): self.update_display_mixer_mode() def clear_track_button_callback(self, value): # if clear track button was called, reset track if (value == 127): for i in range(len(self.song().tracks)): self.song().tracks[i].arm = 0 self.song().tracks[i].solo = 0 self.song().tracks[i].mute = 0 for i in range(len(self.song().return_tracks)): self.song().tracks[i].solo = 0 self.song().tracks[i].mute = 0 def clear_return_track_assignment(self, strip): # clear return track assingments strip.set_volume_control(None) strip.set_pan_control(None) strip.set_mute_button(None) strip.set_solo_button(None) def clear_track_assignment(self, strip): # clear track assignments strip.set_volume_control(None) strip.set_pan_control(None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) def clear_tracks_assigments(self): # for all normal tracks, clear assignments for i in range(NUM_TRACKS): strip = self._mixer.channel_strip(i) if (strip != None): self.clear_track_assignment(strip) # for all return tracks, clear assignments for i in range(2): return_strip = self._mixer.return_strip(i) if (return_strip != None): self.clear_return_track_assignment(return_strip) def selected_track_changed(self): # if on mixer mode update display if (self._operation_mode_selector.mode_index == OP1_MODE_MIXER): self.update_display_mixer_mode() # clear track assignments self.clear_tracks_assigments() # getting selected strip self._channel_strip = self._mixer.selected_strip() # perform track assignments self._channel_strip.set_volume_control( EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_1, Live.MidiMap.MapMode.relative_two_compliment)) self._channel_strip.set_pan_control( EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_2, Live.MidiMap.MapMode.relative_two_compliment)) # setting a tuple of encoders to control sends send_controls = EncoderElement( MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_3, Live.MidiMap.MapMode.relative_two_compliment), EncoderElement( MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_4, Live.MidiMap.MapMode.relative_two_compliment), # setting send encoders self._channel_strip.set_send_controls(tuple(send_controls)) # setting solo button self._channel_strip.set_solo_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS6_BUTTON)) # if track can be armed, set arm button if (self._channel_strip._track.can_be_armed): self._channel_strip.set_arm_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS7_BUTTON)) # if track is no master, set mute button if (self._channel_strip._track != self.song().master_track): self._channel_strip.set_mute_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS5_BUTTON)) def browser_toggle_button_callback(self, value): if (value == 127): if (self.session_visible): if (self.session_browser_visible == True): self.session_browser_visible = False self.app.view.hide_view("Browser") else: self.session_browser_visible = True self.app.view.show_view("Browser") if (self.arrange_visible): if (self.arrange_browser_visible == True): self.arrange_browser_visible = False self.app.view.hide_view("Browser") else: self.arrange_browser_visible = True self.app.view.show_view("Browser") def back_to_arranger_button_callback(self, value): if (value == 127): self.song().back_to_arranger = False def mainview_toggle_button_callback(self, value): if (value == 127): if (self.session_visible == True): self.session_visible = False self.arrange_visible = True self.app.view.show_view("Arranger") self.arrange_browser_visible = self.app.view.is_view_visible( "Browser") else: self.session_visible = True self.arrange_visible = False self.app.view.show_view("Session") self.session_browser_visible = self.app.view.is_view_visible( "Browser") def detailview_toggle_button_callback(self, value): if (value == 127): if (self.detail_visible == True): self.detail_visible = False self.app.view.hide_view("Detail") else: self.detail_visible = True self.app.view.show_view("Detail") def write_text(self, msg): text_list = [] sequence = () text_list.append(len(msg.strip())) for i in msg.strip(): text_list.append(ord(i)) sequence = self.text_start_sequence + tuple( text_list) + self.text_end_sequence self._send_midi(sequence) def suggest_input_port(self): return "OP-1 Midi Device" def suggest_output_port(self): return "OP-1 Midi Device" def update_display_perform_mode(self): self.write_text("perform\rmode") def reset_display_clips(self): count = 0 colors = [] length = [] sequence = () for i in range(NUM_TRACKS): count += 1 colors.append(0x00) colors.append(0x00) colors.append(0x00) length.append(count) sequence = self.text_color_start_sequence + tuple(length) + tuple( colors) + self.text_end_sequence self._send_midi(sequence) def update_display_clips(self): #self.log("UPDATING DISPLAY CLIPS") count = 0 colors = [] length = [] sequence = () tracks_len = len(self.song().tracks) - self._session._track_offset if (tracks_len > NUM_TRACKS): tracks_len = NUM_TRACKS for i in range(tracks_len): count += 1 clip_slot = self._session.scene(0).clip_slot(i) if (clip_slot != None): if (clip_slot.has_clip() != False): clip_color = clip_slot._clip_slot.clip.color colors.append(((clip_color >> 16) & 0x000000ff) >> 1) colors.append(((clip_color >> 8) & 0x000000ff) >> 1) colors.append((clip_color & 0x000000ff) >> 1) else: colors.append(0x00) colors.append(0x00) colors.append(0x00) else: colors.append(0x00) colors.append(0x00) colors.append(0x00) length.append(count) sequence = self.text_color_start_sequence + tuple(length) + tuple( colors) + self.text_end_sequence self._send_midi(sequence) def update_display_clip_mode(self): self.write_text( "sel. scene\r" + str(self.song().view.selected_scene.name.lower().strip())) def update_display_transport_mode(self): song_time = str(self.song().get_current_beats_song_time()) self.write_text("song pos.\r" + song_time[:len(song_time) - 4]) def update_display_mixer_mode(self): self.write_text("sel. track\r" + str(self.song().view.selected_track.name.lower())) def update_display(self): if not (self.device_connected): if (self.retries_count < 5): self.log("TRYING OP-1 CONNECTION") self.retries_count += 1 self._send_midi(self.id_sequence) time.sleep(1) # if in transport mode, update display with song position if (self._operation_mode_selector.mode_index == OP1_MODE_TRANSPORT): self.update_display_transport_mode() # checking if app current view is session if (self.app.view.is_view_visible("Session")): # checking if session browser state is diferent from the internal if (self.session_browser_visible != self.app.view.is_view_visible("Browser")): self.session_browser_visible = self.app.view.is_view_visible( "Browser") # checking if app current view is arrange if (self.app.view.is_view_visible("Arranger")): # checking if arrange browser state is diferent from the internal if (self.arrange_browser_visible != self.app.view.is_view_visible("Browser")): self.arrange_browser_visible = self.app.view.is_view_visible( "Browser") # checking if app current view is detail if (self.app.view.is_view_visible("Detail")): # checking if detail state is diferent from the internal if (self.detail_visible != self.app.view.is_view_visible("Detail")): self.detail_visible = self.app.view.is_view_visible("Detail") def refresh_state(self): self.log("REFRESH STATE") self.retries_count = 0 self.device_connected = False def build_midi_map(self, midi_map_handle): #self.log("BUILD MIDI MAP") assert (self._suppress_requests_counter == 0) self._in_build_midi_map = True self._midi_map_handle = midi_map_handle self._forwarding_registry = {} for control in self.controls: if isinstance(control, InputControlElement): control.install_connections() self._midi_map_handle = None self._in_build_midi_map = False if (self._pad_translations != None): self._c_instance.set_pad_translation(self._pad_translations) # remove clip listeners self.rem_clip_slot_listeners() # add clip listeners self.add_clip_slot_listeners() # update display self.update_display_clips() def log(self, msg): self.c_instance.log_message("[TE OP-1] " + msg) def disconnect(self): # removing clip slots listeners self.rem_clip_slot_listeners() # removing value listener for track changed self.song().view.remove_selected_track_listener( self.selected_track_changed) # removing value listener for scene changed self.song().view.remove_selected_scene_listener( self.selected_scene_changed) # removing value listener for operation mode index self._operation_mode_selector.remove_mode_index_listener( self.mode_index_changed) # removing global transport assignments self._transport.set_punch_buttons(None, None) self._transport.set_loop_button(None) self._transport.set_overdub_button(None) self._transport.set_record_button(None) self._transport.set_play_button(None) self._transport.set_stop_button(None) self._transport.set_metronome_button(None) self._transport.set_tap_tempo_button(None) # removing global session assignments self._session.set_scene_bank_buttons(None, None) # removing misc listeners self.browser_toggle_button.remove_value_listener( self.browser_toggle_button_callback) self.mainview_toggle_button.remove_value_listener( self.mainview_toggle_button_callback) self.detailview_toggle_button.remove_value_listener( self.detailview_toggle_button_callback) self.clear_track_button.remove_value_listener( self.clear_track_button_callback) self.back_to_arranger_button.remove_value_listener( self.back_to_arranger_button_callback) # sending special ableton mode disable sequence self._send_midi(self.disable_sequence) # disconnecting control surface ControlSurface.disconnect(self) self.log("DISCONNECTED")
def init(self): #skip init if already done. if self._init_done: return self._init_done = True # second part of the __init__ after model has been identified using its challenge response if self._mk2_rgb: from SkinMK2 import make_skin self._skin = make_skin() self._side_notes = (89, 79, 69, 59, 49, 39, 29, 19) #self._drum_notes = (20, 30, 31, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126) self._drum_notes = (20, 30, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126) else: from SkinMK1 import make_skin self._skin = make_skin() self._side_notes = (8, 24, 40, 56, 72, 88, 104, 120) self._drum_notes = (41, 42, 43, 44, 45, 46, 47, 57, 58, 59, 60, 61, 62, 63, 73, 74, 75, 76, 77, 78, 79, 89, 90, 91, 92, 93, 94, 95, 105, 106, 107) with self.component_guard(): is_momentary = True self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False) self._config_button.add_value_listener(self._config_value) self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = 'User_Byte_Button' self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' for row in range(8): button_row = [] for column in range(8): if self._mk2_rgb: # for mk2 buttons are assigned "top to bottom" midi_note = (81 - (10 * row)) + column else: midi_note = row * 16 + column button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, midi_note, skin = self._skin, control_surface = self) button.name = str(column) + '_Clip_' + str(row) + '_Button' button_row.append(button) matrix.add_row(tuple(button_row)) top_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, skin = self._skin) for index in range(8)] side_buttons = [ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, self._side_notes[index], skin = self._skin) for index in range(8)] top_buttons[0].name = 'Bank_Select_Up_Button' top_buttons[1].name = 'Bank_Select_Down_Button' top_buttons[2].name = 'Bank_Select_Left_Button' top_buttons[3].name = 'Bank_Select_Right_Button' top_buttons[4].name = 'Session_Button' top_buttons[5].name = 'User1_Button' top_buttons[6].name = 'User2_Button' top_buttons[7].name = 'Mixer_Button' side_buttons[0].name = 'Vol_Button' side_buttons[1].name = 'Pan_Button' side_buttons[2].name = 'SndA_Button' side_buttons[3].name = 'SndB_Button' side_buttons[4].name = 'Stop_Button' side_buttons[5].name = 'Trk_On_Button' side_buttons[6].name = 'Solo_Button' side_buttons[7].name = 'Arm_Button' self._osd = M4LInterface() self._osd.name = "OSD" self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self._osd, self) self._selector.name = 'Main_Modes' self._do_combine() for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.add_value_listener(self._button_value) self.set_highlighting_session_component(self._selector.session_component()) self._suppress_session_highlight = False # due to our 2 stage init, we need to rebuild midi map self.request_rebuild_midi_map() # and request update self._selector.update() if self._mk2_rgb: self.log_message("LaunchPad95 (mk2) Loaded !") else: self.log_message("LaunchPad95 Loaded !")
class NoteRepeatComponent(CompoundComponent): """ Noter Repeat Handler""" __module__ = __name__ _knob_handler = None def __init__(self, note_repeat=None, *a, **k): super(NoteRepeatComponent, self).__init__(*a, **k) self._note_repeat = note_repeat self._adjust_cfg_value.subject = SliderElement(MIDI_CC_TYPE, 2, 105) self._note_repeat_button = ButtonElement(True, MIDI_CC_TYPE, 0, 102) self._do_note_repeat.subject = self._note_repeat_button self._cfg_adjust_button = ButtonElement(True, MIDI_CC_TYPE, 2, 106) self._cfg_adjust_button.add_value_listener(self._do_cfg_button) self._cfg_down = False self._hold_mode = False self.nr_down = False self._current_nr_button = None self._do_change_nr_1.subject = SliderElement(MIDI_CC_TYPE, 1, 76) self._do_change_nr_2.subject = SliderElement(MIDI_CC_TYPE, 1, 77) self._do_change_nr_3.subject = SliderElement(MIDI_CC_TYPE, 1, 78) self._do_change_nr_4.subject = SliderElement(MIDI_CC_TYPE, 1, 79) def createButton(ccindenfier, nr_freq): button = ButtonElement(True, MIDI_CC_TYPE, 1, ccindenfier) button.add_value_listener(self._select_value, True) button.active = False button.freq = nr_freq button.cfg = False button.hold = False return button def createCfgButton(ccindenfier, nr_freq_idx): button = ButtonElement(True, MIDI_CC_TYPE, 2, ccindenfier) button.add_value_listener(self._select_value, True) button.active = False button.fr_idx = nr_freq_idx button.freq = CFG_REPEAT_FREQUENCIES[nr_freq_idx] button.cfg = True button.hold = False return button self._cfg_buttons = [ createCfgButton(assign[0], assign[1]) for assign in CTRL_CFG_TO_FREQ ] for button in self._cfg_buttons: button.send_value(button.active and 1 or 0, True) self.nr_frq = CTRL_TO_FREQ[4][1] self._note_repeat.repeat_rate = 1.0 / self.nr_frq * 4.0 self.buttons = [ createButton(assign[0], assign[1]) for assign in CTRL_TO_FREQ ] self.buttons[4].active = True self._previous_button = self.buttons[4] self._last_active_button = self.buttons[4] for button in self.buttons: button.send_value(button.active and 1 or 0, True) return def update(self): pass def store_values(self, dict): for button, idx in zip(self._cfg_buttons, range(len(self._cfg_buttons))): dict['cofig-nr-val' + str(idx)] = button.fr_idx def recall_values(self, dict): for button, idx in zip(self._cfg_buttons, range(len(self._cfg_buttons))): key = 'cofig-nr-val' + str(idx) if key in dict: fqidx = dict[key] button.fr_idx = fqidx button.freq = CFG_REPEAT_FREQUENCIES[fqidx] def registerKnobHandler(self, handler): self._knob_handler = handler def show_note_rates(self): rates = '' for button, idx in zip(self._cfg_buttons, range(len(self._cfg_buttons))): rates += ' ' + CFG_REPEAT_DISPLAY[button.fr_idx].ljust(5) if idx < 3: rates += '|' self.canonical_parent.timed_message(2, rates) def mod_button(self, button, inc, which): cindex = button.fr_idx maxindex = len(CFG_REPEAT_FREQUENCIES) - 1 minindex = 0 if self.canonical_parent.isShiftDown(): inc *= 2 maxindex = cindex % 2 == 0 and maxindex or maxindex - 1 minindex = cindex % 2 new_idx = max(minindex, min(maxindex, cindex + inc)) if new_idx != cindex: self.canonical_parent.show_message('Note Repeat Button ' + str(which) + ' : ' + CFG_REPEAT_DISPLAY[new_idx]) button.fr_idx = new_idx button.freq = CFG_REPEAT_FREQUENCIES[new_idx] if button.active: self.nr_frq = CFG_REPEAT_FREQUENCIES[new_idx] self._note_repeat.repeat_rate = 1.0 / self.nr_frq * 4.0 @subject_slot('value') def _do_change_nr_1(self, value): self.mod_button(self._cfg_buttons[0], value == REL_KNOB_DOWN and -1 or 1, 1) self.show_note_rates() @subject_slot('value') def _do_change_nr_2(self, value): self.mod_button(self._cfg_buttons[1], value == REL_KNOB_DOWN and -1 or 1, 2) self.show_note_rates() @subject_slot('value') def _do_change_nr_3(self, value): self.mod_button(self._cfg_buttons[2], value == REL_KNOB_DOWN and -1 or 1, 3) self.show_note_rates() @subject_slot('value') def _do_change_nr_4(self, value): self.mod_button(self._cfg_buttons[3], value == REL_KNOB_DOWN and -1 or 1, 4) self.show_note_rates() def _do_cfg_button(self, value): if value != 0: self._cfg_down = True button = self._current_nr_button if button and button.cfg and button.fr_idx >= 0: self.canonical_parent.show_message( 'Note Repeat ' + CFG_REPEAT_DISPLAY[button.fr_idx]) else: self._cfg_down = False if self._knob_handler: self._knob_handler.do_main_push(value) @subject_slot('value') def _adjust_cfg_value(self, value): button = self._current_nr_button if button and button.cfg and (self.nr_down or button.hold or self._hold_mode and button.active): inc = value == 127 and -1 or 1 cindex = button.fr_idx maxindex = len(CFG_REPEAT_FREQUENCIES) - 1 minindex = 0 if self._cfg_down: inc *= 2 maxindex = cindex % 2 == 0 and maxindex or maxindex - 1 minindex = cindex % 2 new_idx = max(minindex, min(maxindex, cindex + inc)) self.canonical_parent.show_message('Note Repeat ' + CFG_REPEAT_DISPLAY[new_idx]) button.fr_idx = new_idx button.freq = CFG_REPEAT_FREQUENCIES[new_idx] self.nr_frq = CFG_REPEAT_FREQUENCIES[new_idx] self._note_repeat.repeat_rate = 1.0 / self.nr_frq * 4.0 else: if self._knob_handler: self._knob_handler.do_main(value) def _select_value(self, value, button): if value != 0: self._current_nr_button = button button.hold = True self.show_note_rates() if self._hold_mode: if self._previous_button == button: button.send_value(0, True) button.active = False self._last_active_button = button button.active = False self._note_repeat.repeat_rate = 32.0 self._previous_button = None elif self._previous_button == None or self._previous_button != button: button.send_value(1, True) button.active = True self.nr_frq = button.freq self._note_repeat.repeat_rate = 1.0 / self.nr_frq * 4.0 if not self._note_repeat.enabled: self._note_repeat.enabled = True if self._previous_button != None: self._previous_button.active = False self._previous_button.send_value(0, True) self._previous_button = button else: button.send_value(1, True) button.active = True self.nr_frq = button.freq self._note_repeat.repeat_rate = 1.0 / self.nr_frq * 4.0 if self._previous_button != None and self._previous_button != button: self._previous_button.active = False self._previous_button.send_value(0, True) self._previous_button = button else: button.hold = False return @subject_slot('value') def _do_note_repeat(self, value): self.nr_down = value > 0 if self._hold_mode: if value > 0: self._note_repeat_button.send_value(0) self._note_repeat.enabled = False self._hold_mode = False if self._previous_button == None and self._last_active_button != None: self._previous_button = self._last_active_button self._last_active_button.send_value(1) self._last_active_button.active = True self.nr_frq = self._last_active_button.freq self._note_repeat.repeat_rate = 1.0 / self.nr_frq * 4.0 else: if self.canonical_parent.isShiftDown() and value > 0: self._note_repeat_button.send_value(1) self._note_repeat.enabled = True self._hold_mode = True self._note_repeat.repeat_rate = 1.0 / self.nr_frq * 4.0 else: if value == 0: self._note_repeat.enabled = False self._note_repeat_button.send_value(0) else: self._note_repeat_button.send_value(1) self._note_repeat.repeat_rate = 1.0 / self.nr_frq * 4.0 self._note_repeat.enabled = True return def disconnect(self): super(NoteRepeatComponent, self).disconnect()
def make_button(cc_no, name): button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, cc_no) button.name = name return button