def _setup_session_control(self): is_momentary = True # Size of session box num_tracks = 8 # column num_scenes = 1 # row """ Buttons declaration """ # Navigation button_navig_up = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_session_up) button_navig_down = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_session_down) """ Declare our session box """ global session #We want to instantiate the global session as a SessionComponent object (it was a global "None" type up until now...) session = SessionComponent(num_tracks, num_scenes) #(num_tracks, num_scenes) A session highlight ("red box") will appear with any two non-zero values session.set_offsets(0, 0) #(track_offset, scene_offset) Sets the initial offset of the "red box" from top left session._do_show_highlight() #to ensure that this session will be highlighted """ Buttons association """ # Navigation up, down, left, right session.set_scene_bank_buttons(button_navig_down, button_navig_up) # Launch selected clip for index in range(num_tracks): session.scene(0).clip_slot(index).set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_session_launch_clip[index])) # Stop selected track stop_track_buttons = [] for index in range(num_tracks): stop_track_buttons.append(ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_session_stop_track[index])) session.set_stop_track_clip_buttons(tuple(stop_track_buttons)) #array size needs to match num_tracks
def _setup_session_control(self): is_momentary = True num_tracks = 1 #single column num_scenes = 7 #seven rows, which will be mapped to seven "white" notes global session #We want to instantiate the global session as a SessionComponent object (it was a global "None" type up until now...) session = SessionComponent( num_tracks, num_scenes ) #(num_tracks, num_scenes) A session highlight ("red box") will appear with any two non-zero values session.set_offsets( 0, 0 ) #(track_offset, scene_offset) Sets the initial offset of the "red box" from top left """set up the session navigation buttons""" session.set_select_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 25), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 27) ) # (next_button, prev_button) Scene select buttons - up & down - we'll also use a second ControlComponent for this (yellow box) session.set_scene_bank_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 51), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 49) ) # (up_button, down_button) This is to move the "red box" up or down (increment track up or down, not screen up or down, so they are inversed) #session.set_track_bank_buttons(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 56), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 54)) # (right_button, left_button) This moves the "red box" selection set left & right. We'll put our track selection in Part B of the script, rather than here... session.set_stop_all_clips_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 70)) session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 30)) """Here we set up the scene launch assignments for the session""" launch_notes = [ 60, 62, 64, 65, 67, 69, 71 ] #this is our set of seven "white" notes, starting at C4 for index in range( num_scenes ): #launch_button assignment must match number of scenes session.scene(index).set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, launch_notes[index]) ) #step through the scenes (in the session) and assign corresponding note from the launch_notes array """Here we set up the track stop launch assignment(s) for the session""" #The following code is set up for a longer array (we only have one track, so it's over-complicated, but good for future adaptation).. stop_track_buttons = [] for index in range(num_tracks): stop_track_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 58 + index) ) #this would need to be adjusted for a longer array (because we've already used the next note numbers elsewhere) session.set_stop_track_clip_buttons( tuple(stop_track_buttons)) #array size needs to match num_tracks """Here we set up the clip launch assignments for the session""" clip_launch_notes = [ 48, 50, 52, 53, 55, 57, 59 ] #this is a set of seven "white" notes, starting at C3 for index in range(num_scenes): session.scene(index).clip_slot(0).set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, clip_launch_notes[index]) ) #step through scenes and assign a note to first slot of each """Here we set up a mixer and channel strip(s) which move with the session""" session.set_mixer( mixer) #Bind the mixer to the session so that they move together
def _setup_session_control(self): is_momentary = True down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 89) up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 90) session = SessionComponent(NUM_TRACKS, 0) session.set_select_buttons(down_button, up_button) session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 87)) track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 68) for index in range(NUM_TRACKS) ] session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) for index in range(NUM_TRACKS): session.selected_scene().clip_slot(index).set_launch_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 69))
def _setup_session_control(self): is_momentary = True down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 89) up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 90) session = SessionComponent(NUM_TRACKS, 0) session.set_select_buttons(down_button, up_button) session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 87)) track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 68) for index in range(NUM_TRACKS) ] session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) for index in range(NUM_TRACKS): session.selected_scene().clip_slot(index).set_launch_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 69))
def _setup_session_control(self): num_tracks = 7 num_scenes = 4 session_nav_button = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SESSION_NAV_BUTTONS[index]) for index in range(2) ] session_stop_button = [] matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' global session session = SessionComponent(num_tracks, num_scenes) session.name = 'Session_Control' session.set_offsets(0, 0) session.set_scene_bank_buttons(session_nav_button[1], session_nav_button[0]) #session.set_track_bank_buttons(session_nav_button[3], session_nav_button[2]) for row in xrange(num_scenes): scene_launch_button = ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, SCENE_LAUNCH_BUTTONS[row]) session_row = [] scene = session.scene(row) scene.name = 'Scene' + str(row) scene.set_launch_button(scene_launch_button) scene.set_triggered_value(2) #scene_launch_button._set_skin_light(68) for column in xrange(num_tracks): clip_launch_button = ButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, CLIP_LAUNCH_BUTTONS[row][column]) clip_launch_button.name = str(column) + '_Clip_' + str( row) + '_Button' session_row.append(clip_launch_button) clip_slot = scene.clip_slot(column) clip_slot.name = str(column) + '_ClipSlot_' + str(row) clip_slot.set_launch_button(clip_launch_button) #clip_launch_button._set_skin_light(76) matrix.add_row(tuple(session_row)) for column in xrange(num_tracks): session_stop_button.append( ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, SESSION_STOP_BUTTONS[column])) self._supress_session_highlight = False self._supress_send_midi = False self.set_highlighting_session_component(session) session.set_stop_track_clip_buttons(tuple(session_stop_button))
def _setup_session_control(self): """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, UP_BUTTON) down_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, DOWN_BUTTON) left_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, LEFT_BUTTON) right_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, RIGHT_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, 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, 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_selection_box_control(self, indexDicer): is_momentary = True # Size of session box num_tracks = 1 #1 column num_scenes = 1 #1 row """ Buttons declaration """ # Navigation button_navig_up = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[0]) button_navig_down = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[1]) button_navig_left = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[3]) button_navig_right = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[4]) # Launch clip button_launch_clip = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[2]) # Stop track button_stop_track = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_shifted[2]) # Stop all tracks #button_stop_track_all """ Declare our session box """ global session #We want to instantiate the global session as a SessionComponent object (it was a global "None" type up until now...) session = SessionComponent( num_tracks, num_scenes ) #(num_tracks, num_scenes) A session highlight ("red box") will appear with any two non-zero values session.set_offsets( indexDicer * 4, 0 ) #(track_offset, scene_offset) Sets the initial offset of the "red box" from top left session._do_show_highlight( ) #to ensure that this session will be highlighted """ Buttons association """ # Navigation up, down, left, right session.set_scene_bank_buttons(button_navig_down, button_navig_up) session.set_track_bank_buttons(button_navig_right, button_navig_left) # Launch selected clip session.scene(0).clip_slot(0).set_launch_button(button_launch_clip) # Stop selected track stop_track_buttons = [] stop_track_buttons.append(button_stop_track) session.set_stop_track_clip_buttons( tuple(stop_track_buttons)) #array size needs to match num_tracks
def _create_session_control(self): is_momentary = True num_tracks = 1 num_scenes = 7 global session session = SessionComponent(num_tracks, num_scenes) session.set_offsets(0, 0) """set up the session navigation buttons""" session.set_select_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 25), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 27)) session.set_scene_bank_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 51), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 49)) session.set_stop_all_clips_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 70)) session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 30)) """Here we set up the scene launch assignments for the session""" launch_notes = [60, 62, 64, 65, 67, 69, 71] for index in range(num_scenes): session.scene(index).set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, launch_notes[index])) """Here we set up the track stop launch assignment(s) for the session""" stop_track_buttons = [] for index in range(num_tracks): stop_track_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 58 + index)) session.set_stop_track_clip_buttons(tuple(stop_track_buttons)) """Here we set up the clip launch assignments for the session""" clip_launch_notes = [48, 50, 52, 53, 55, 57, 59] for index in range(num_scenes): session.scene(index).clip_slot(0).set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, clip_launch_notes[index])) """Here we set up a mixer and channel strip(s) which move with the session""" self.log_message("Captain's log stardate 3")
def _setup_selection_box_control(self, indexDicer): is_momentary = True # Size of session box num_tracks = 1 #1 column num_scenes = 1 #1 row """ Buttons declaration """ # Navigation button_navig_up = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[0]) button_navig_down = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[1]) button_navig_left = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[3]) button_navig_right = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[4]) # Launch clip button_launch_clip = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_normal[2]) # Stop track button_stop_track = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel_red[indexDicer] - 1, midi_cc_shifted[2]) # Stop all tracks #button_stop_track_all """ Declare our session box """ global session #We want to instantiate the global session as a SessionComponent object (it was a global "None" type up until now...) session = SessionComponent(num_tracks, num_scenes) #(num_tracks, num_scenes) A session highlight ("red box") will appear with any two non-zero values session.set_offsets(indexDicer * 4, 0) #(track_offset, scene_offset) Sets the initial offset of the "red box" from top left session._do_show_highlight() #to ensure that this session will be highlighted """ Buttons association """ # Navigation up, down, left, right session.set_scene_bank_buttons(button_navig_down, button_navig_up) session.set_track_bank_buttons(button_navig_right, button_navig_left) # Launch selected clip session.scene(0).clip_slot(0).set_launch_button(button_launch_clip) # Stop selected track stop_track_buttons = [] stop_track_buttons.append(button_stop_track) session.set_stop_track_clip_buttons(tuple(stop_track_buttons)) #array size needs to match num_tracks
class Novation_Impulse2(ControlSurface): """ Script for Novation's Impulse keyboards """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self.c_instance = 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 self._shift_pressed = False self._shift_button.add_value_listener(self._shift_value) for component in self.components: component.set_enabled(False) def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(3, self._send_midi, SYSEX_START + (6, 1, 1, 1, 247)) def handle_sysex(self, midi_bytes): if midi_bytes[0:-2] == SYSEX_START + (7,) and midi_bytes[-2] != 0: self._has_sliders = midi_bytes[-2] != 25 self.schedule_message(1, self._show_startup_message) for control in self.controls: if isinstance(control, InputControlElement): control.clear_send_cache() for component in self.components: component.set_enabled(True) if self._has_sliders: self._mixer.master_strip().set_volume_control(self._master_slider) self._mixer.update() else: self._mixer.master_strip().set_volume_control(None) self._mixer.selected_strip().set_volume_control(self._master_slider) for index in range(len(self._sliders)): self._mixer.channel_strip(index).set_volume_control(None) slider = self._sliders[index] slider.release_parameter() if slider.value_has_listener(self._slider_value): slider.remove_value_listener(self._slider_value) self._encoder_modes.set_provide_volume_mode(not self._has_sliders) self.request_rebuild_midi_map() def disconnect(self): self.log('starting disconnect 1') self._name_display_data_source.set_display_string(' ') for encoder in self._encoders: encoder.remove_value_listener(self._encoder_value) self._master_slider.remove_value_listener(self._slider_value) if self._has_sliders: for slider in tuple(self._sliders): slider.remove_value_listener(self._slider_value) for button in self._strip_buttons: button.remove_value_listener(self._mixer_button_value) self._preview_button.remove_value_listener(self._preview_value) self.log('starting disconnect 3') ControlSurface.disconnect(self) self.log('starting disconnect 3') self._encoders = None self._sliders = None self._strip_buttons = None self._master_slider = None self._current_midi_map = None self._name_display = None self._prev_bank_button = None self._next_bank_button = None self._encoder_modes = None self._transport_view_modes = None self.log('starting disconnect 4') self._send_midi(SYSEX_START + (6, 0, 0, 0, 247)) self.log('starting disconnect 5') if self._shift_button != None: self._shift_button.remove_value_listener(self._shift_value) self._shift_button = None self.log('starting disconnect 6') def build_midi_map(self, midi_map_handle): self._current_midi_map = midi_map_handle ControlSurface.build_midi_map(self, midi_map_handle) def update_display(self): ControlSurface.update_display(self) if self._string_to_display != None: self._name_display_data_source.set_display_string(self._string_to_display) self._string_to_display = None if self._display_reset_delay >= 0: self._display_reset_delay -= 1 if self._display_reset_delay == -1: self._show_current_track_name() 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.c_instance) 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) #self._mixer.set_shift_button(self._shift_button) self._mixer.updateMixerButtons() self._button9 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + 8) def _setup_session(self): num_pads = len(PAD_TRANSLATIONS) self._session = SessionComponent(8, 0) self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.set_mixer(self._mixer) # for ableton 9.1.1 and lower #self._session.set_track_banking_increment(num_pads) #self._session.set_track_bank_buttons(ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 35), ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 36)) # for ableton 9.1.1 and higher self._track_left_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 36) self._track_right_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 35) self._session.set_page_left_button(self._track_left_button) self._session.set_page_right_button(self._track_right_button) pads = [] for index in range(num_pads): pads.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 60 + index)) pads[-1].name = 'Pad_' + str(index) clip_slot = self._session.selected_scene().clip_slot(index) clip_slot.set_triggered_to_play_value(GREEN_BLINK) clip_slot.set_triggered_to_record_value(RED_BLINK) clip_slot.set_stopped_value(AMBER_FULL) clip_slot.set_started_value(GREEN_FULL) clip_slot.set_recording_value(RED_FULL) clip_slot.set_launch_button(pads[-1]) clip_slot.name = str(index) + '_Selected_Clip_Slot' def _setup_transport(self): rwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 27) ffwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 28) stop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 29) play_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 30) loop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 31) rec_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 32) ffwd_button.name = 'FFwd_Button' rwd_button.name = 'Rwd_Button' loop_button.name = 'Loop_Button' play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' rec_button.name = 'Record_Button' self._transport = ShiftableTransportComponent(self.c_instance,self._session, self, ffwd_button, rwd_button) self._transport.name = 'Transport' self._transport.set_stop_buttonOnInit(stop_button) self._transport.set_play_button(play_button) self._transport.set_record_buttonOnInit(rec_button) # self._transport.set_shift_button(self._shift_button) self._transport.set_mixer9_button(self._button9) self._transport_view_modes = TransportViewModeSelector(self.c_instance,self._transport, self._session, ffwd_button, rwd_button, loop_button) self._transport_view_modes.name = 'Transport_View_Modes' def _setup_device(self): encoders = [] for index in range(8): encoders.append(PeekableEncoderElement(MIDI_CC_TYPE, 1, index, Live.MidiMap.MapMode.relative_binary_offset)) encoders[-1].set_feedback_delay(-1) encoders[-1].add_value_listener(self._encoder_value, identify_sender=True) encoders[-1].name = 'Device_Control_' + str(index) self._encoders = tuple(encoders) self._prev_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 12) self._next_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 11) self._prev_bank_button.name = 'Device_Bank_Down_Button' self._next_bank_button.name = 'Device_Bank_Up_Button' device = DeviceComponent() device.name = 'Device_Component' self.set_device_component(device) device.set_parameter_controls(self._encoders) device.set_bank_nav_buttons(self._prev_bank_button, self._next_bank_button) def _setup_name_display(self): self._name_display = PhysicalDisplayElement(16, 1) self._name_display.name = 'Display' self._name_display.set_message_parts(SYSEX_START + (8,), (247,)) self._name_display_data_source = DisplayDataSource() self._name_display.segment(0).set_data_source(self._name_display_data_source) def _encoder_value(self, value, sender): if not sender in self._encoders: raise AssertionError if not value in range(128): raise AssertionError # display_string = self._device_component.is_enabled() and ' - ' # display_string = sender.mapped_parameter() != None and sender.mapped_parameter().name display_string = '' if self._device_component.is_enabled(): # display_string = sender.name # track = self.song().view.selected_track # display_string = str(list(tracks).index(track) + 1) pass if (sender.mapped_parameter() != None): # display_string = display_string + '-' display_string = display_string + sender.mapped_parameter().name self._set_string_to_display(display_string) def _slider_value(self, value, sender): self.log ('_slider_value ' + str(value) + ' ' +str(sender)) if not sender in tuple(self._sliders) + (self._master_slider,): raise AssertionError if not value in range(128): raise AssertionError if self._mixer.is_enabled(): display_string = ' - ' master = self.song().master_track tracks = self.song().tracks returns = self.song().return_tracks track = None if sender.mapped_parameter() != None: self.log ('1') if sender == self._master_slider: self.log ('2') # track = self._has_sliders and master if self._has_sliders: track = master else: self.log ('2.1') track = self.song().view.selected_track else: self.log ('3') track = self._mixer.channel_strip(self._sliders.index(sender))._track else: self.log ('4') track = self.song().view.selected_track self.log('track='+str(track)) if track == master: display_string = 'Master' elif track in tracks: display_string = str(list(tracks).index(track) + 1) elif track in returns: display_string = str(chr(ord('A') + list(returns).index(track))) else: # raise False or AssertionError raise AssertionError display_string += ' Volume' self._set_string_to_display(display_string) def _mixer_button_value(self, value, sender): if not value in range(128): raise AssertionError #if self._mixer.is_enabled() and value > 0: if self._mixer.is_enabled(): strip = self._mixer.channel_strip(self._strip_buttons.index(sender)) #self._string_to_display = strip != None and None self._name_display.segment(0).set_data_source(strip.track_name_data_source()) self._name_display.update() self._display_reset_delay = STANDARD_DISPLAY_DELAY else: self._set_string_to_display(' - ') def _preview_value(self, value): if not value in range(128): raise AssertionError for encoder in self._encoders: encoder.set_peek_mode(value > 0) def _show_current_track_name(self): if self._name_display != None and self._mixer != None: self._string_to_display = None self._name_display.segment(0).set_data_source(self._mixer.selected_strip().track_name_data_source()) self._name_display.update() def _show_startup_message(self): self._name_display.display_message('LIVE') self._display_reset_delay = INITIAL_DISPLAY_DELAY def _set_string_to_display(self, string_to_display): if not isinstance(string_to_display, (str, unicode)): raise AssertionError self._name_display.segment(0).set_data_source(self._name_display_data_source) self._string_to_display = string_to_display self._display_reset_delay = STANDARD_DISPLAY_DELAY def _on_selected_track_changed(self): self.log('_on_selected_track_changed') ControlSurface._on_selected_track_changed(self) self._show_current_track_name() #all_tracks = self._has_sliders or self._session.tracks_to_use() all_tracks2 = self._session.tracks_to_use() selected_track = self.song().view.selected_track num_strips = self._session.width() if selected_track in all_tracks2: track_index = list(all_tracks2).index(selected_track) self.log('track_index '+ str(track_index)) new_offset = track_index - track_index % num_strips self.log('new_offset '+ str(new_offset)) if not new_offset / num_strips == int(new_offset / num_strips): raise AssertionError self._session.set_offsets(new_offset, self._session.scene_offset()) def _shift_value(self, value): self.log("root shift handler") if not self._shift_button != None: raise AssertionError if not value in range(128): raise AssertionError self.log("root shift handler 2") self._shift_pressed = value > 0 # calling other handlers self._mixer._shift_value(value) self._transport._shift_value(value) self._transport_view_modes._shift_value(value) #clip stop self.log("root shift handler 3") num_pads = len(PAD_TRANSLATIONS) pads = [] for index in range(num_pads): pads.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 60 + index)) pads[-1].name = 'Pad_' + str(index) clip_slot = self._session.selected_scene().clip_slot(index) if self._shift_pressed: clip_slot.set_launch_button(None) else: clip_slot.set_launch_button(pads[index]) if self._shift_pressed: self._session.set_stop_track_clip_buttons(tuple(pads)) else: self._session.set_stop_track_clip_buttons(None) self.log("root shift handler 4") def log(self, message): pass
class LaunchpadSimple(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._suggested_input_port = "Launchpad" self._suggested_output_port = "Launchpad" # Launchpad configuration self._send_midi(LAUNCHPAD_RESET) self._send_midi(LAUNCHPAD_ENABLE_BLINKING) # make buttons top_buttons = [make_button(MIDI_CC_TYPE, 104 + i) for i in range(8)] side_buttons = [make_button(MIDI_NOTE_TYPE, 8 + 16 * i) for i in range(8)] matrix = ButtonMatrixElement() for row in range(8): button_row = [make_button(MIDI_NOTE_TYPE, 16 * row + col) for col in range(8)] matrix.add_row(tuple(button_row)) # mixer and session components self._mixer = MixerComponent(8) self._session = SessionComponent(8, SCENES_AMOUNT) self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) # navigation for button in top_buttons[:4]: button.set_on_off_values(GREEN_FULL, GREEN_THIRD) self._session.set_scene_bank_buttons(top_buttons[1], top_buttons[0]) self._session.set_track_bank_buttons(top_buttons[3], top_buttons[2]) # clip launch for scene_index in range(SCENES_AMOUNT): scene = self._session.scene(scene_index) scene.set_launch_button(side_buttons[scene_index]) scene.set_triggered_value(GREEN_BLINK) scene.set_scene_value(GREEN_THIRD) scene.set_no_scene_value(LED_OFF) for track_index in range(8): clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(matrix.get_button(track_index, scene_index)) clip_slot.set_triggered_to_play_value(GREEN_BLINK) clip_slot.set_triggered_to_record_value(RED_BLINK) clip_slot.set_started_value(GREEN_FULL) clip_slot.set_stopped_value(AMBER_THIRD) clip_slot.set_recording_value(RED_FULL) # track stop self._session.set_stop_track_clip_buttons([matrix.get_button(i, ROW_STOP) for i in range(8)]) self._session.set_stop_clip_value(RED_THIRD) self._session.set_stop_clip_triggered_value(RED_BLINK) button_stop_all = side_buttons[ROW_STOP] button_stop_all.set_on_off_values(RED_FULL, RED_THIRD) self._session.set_stop_all_clips_button(button_stop_all) # track select self._mixer.set_track_select_buttons([matrix.get_button(i, ROW_SELECT) for i in range(8)]) self._mixer.set_track_select_values(AMBER_FULL, AMBER_THIRD, LED_OFF) button_select_master = side_buttons[ROW_SELECT] button_select_master.set_on_off_values(AMBER_FULL, AMBER_THIRD) self._mixer.set_master_select_button(button_select_master) # delete clip button self._delete_button = top_buttons[INDEX_DELETE_BUTTON] self._delete_button.set_on_off_values(RED_BLINK, RED_THIRD) self._delete_button.add_value_listener(self._delete_value_listener) self._del_pressed = False self._delete_button.turn_off() # quantization toggle self._quantization_toggle = QuantizationToggle( top_buttons[INDEX_QUANTIZATION_BUTTON], self.song(), GREEN_THIRD, RED_THIRD ) # browser view toggle self._browser_view_toggle = ViewToggle( side_buttons[INDEX_BROWSER_VIEW_BUTTON], ABLETON_VIEW_BROWSER, GREEN_THIRD, RED_THIRD ) # detail view toggle self._device_view_toggle = DetailViewToggle( side_buttons[INDEX_DETAIL_VIEW_BUTTON], GREEN_THIRD, RED_THIRD, LED_OFF ) def disconnect(self): self._send_midi(LAUNCHPAD_RESET) ControlSurface.disconnect(self) self._delete_button.remove_value_listener(self._delete_value_listener) self._delete_button = None self._quantization_toggle.disconnect() self._quantization_toggle = None self._browser_view_toggle.disconnect() self._browser_view_toggle = None self._device_view_toggle.disconnect() self._device_view_toggle = None self._session = None self._mixer = None def receive_midi(self, midi_bytes): if self._del_pressed and self._delete_clip(midi_bytes): return else: ControlSurface.receive_midi(self, midi_bytes) def _delete_value_listener(self, value): self._del_pressed = value == 127 self._delete_button.set_light(self._del_pressed) def _delete_clip(self, midi_bytes): if midi_bytes[0] == MIDI_NOTE_ON_VALUE: row, col = launchpad_button_loc(midi_bytes[1]) if row < SCENES_AMOUNT and col < 8: self._session.scene(row).clip_slot(col)._do_delete_clip() return True return False
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 MPD26' self._suggested_output_port = 'Akai MPD26' 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_NOTE_TYPE, CHANNEL, UP_BUTTON) down_button = ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, DOWN_BUTTON) left_button = ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, LEFT_BUTTON) right_button = ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, RIGHT_BUTTON) # session.set_scene_bank_buttons(down_button, up_button) #enabling these and disabling the below zoom buttons will move one scene/track per button press # 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 ) #these make it so you move the maximum number of scenes/tracks per button press. much more useful than moving by single scenes/tracks session_stop_buttons = [] for row in range(GRIDSIZE[0]): button_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) session_stop_buttons.append( (ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, TRACK_STOPS[row]))) for column in range(GRIDSIZE[1]): button = ConfigurableButtonElement( True, MIDI_NOTE_TYPE, CHANNEL, 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)) self._suppress_session_highlight = False self._suppress_send_midi = False self.set_highlighting_session_component(session) session.set_mixer(mixer) session.set_stop_track_clip_buttons(tuple(session_stop_buttons))
class MPK_mini_hero(ControlSurface): """ Script for Novation's Launchkey 25/49/61 keyboards """ def __init__(self, c_instance, identity_response=SIZE_RESPONSE): ControlSurface.__init__(self, c_instance) self._identity_response = identity_response with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) self._device_selection_follows_track_selection = True self._suggested_input_port = 'MPK mini' self._suggested_output_port = 'MPK mini' self._setup_buttons() self._setup_components() for component in self.components: component.set_enabled(True) # Puvodne False def refresh_state(self): ControlSurface.refresh_state(self) # for val in range(127): # self.schedule_message(2, self._send_midi, (144, val, 0)) # self.schedule_message(3, self._send_midi, (144, 9, 127)) def handle_sysex(self, midi_bytes): self._send_midi(LED_FLASHING_ON) self._update_mixer_offset() for control in self.controls: if isinstance(control, InputControlElement): control.clear_send_cache() for component in self.components: component.set_enabled(True) self.request_rebuild_midi_map() def disconnect(self): ControlSurface.disconnect(self) self._encoders = None self._transport_view_modes = None self._send_midi(LED_FLASHING_OFF) self._send_midi(LIVE_MODE_OFF) def _setup_buttons(self): # Pads CC Mode self._scene_launch_button = make_pad_button(PAD_MODE_CC, 1, 'Scene_Launch_Button') self._overdub_button = make_pad_button(PAD_MODE_CC, 2, 'Session_Overdub_Button') self._ffwd_button = make_pad_button(PAD_MODE_CC, 3, 'FFwd_Button') self._clip_undo_button = make_pad_button(PAD_MODE_CC, 4, 'Clip_Undo_Button') self._prev_track_button = make_pad_button(PAD_MODE_CC, 5, 'Prev_Track_Button') self._next_track_button = make_pad_button(PAD_MODE_CC, 6, 'Next_Track_Button') self._rwd_button = make_pad_button(PAD_MODE_CC, 7, 'Rwd_Button') self._scene_stop_button = make_pad_button(PAD_MODE_CC, 9, 'Scene_Stop_Button') self._stop_button = make_pad_button(PAD_MODE_CC, 10, 'Stop_Button') self._play_button = make_pad_button(PAD_MODE_CC, 11, 'Play_Button') self._loop_button = make_pad_button(PAD_MODE_CC, 12, 'Loop_Button') self._rec_button = make_pad_button(PAD_MODE_CC, 13, 'Record_Button') # Pads Notes Mode self._clip_launch_buttons = [ make_pad_button(PAD_MODE_NOTES, index, 'Clip_Launch_%d' % index) for index in xrange(8) ] self._clip_stop_buttons = [ make_pad_button(PAD_MODE_NOTES, 8 + index, 'Clip_Stop_%d' % index) for index in xrange(8) ] # Encoders self._encoders = tuple([ make_encoder(21 + index, 'Device_Control_%d' % index) for index in xrange(8) ]) # Scenes self._scene_launch_buttons = [] for key_no in [0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19, 21, 23, 24]: self._scene_launch_buttons.append( make_scene_button(key_no, 'Scene_Launch_%d' % key_no)) def _setup_components(self): # Session self._session = SessionComponent(8, len(self._scene_launch_buttons)) self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( self._scene_launch_button) self._session.set_stop_all_clips_button(self._scene_stop_button) for index in range(8): clip_slot = self._session.selected_scene().clip_slot(index) clip_slot.set_launch_button(self._clip_launch_buttons[index]) clip_slot.name = 'Selected_Clip_Slot_' + str(index) self._session.set_stop_track_clip_buttons( tuple(self._clip_stop_buttons)) # Undo self._do_undo.subject = self._clip_undo_button # Transport transport = TransportComponent() transport.name = 'Transport' transport.set_stop_button(self._stop_button) transport.set_play_button(self._play_button) transport.set_record_button(self._rec_button) transport.set_loop_button(self._loop_button) self._transport_view_modes = TransportViewModeSelector( transport, self._session, self._ffwd_button, self._rwd_button) self._transport_view_modes.name = 'Transport_View_Modes' session_recording = SessionRecordingComponent( ClipCreator(), ViewControlComponent(), name='Session_Recording', is_enabled=False, layer=Layer(record_button=self._overdub_button)) # Device # device = DeviceComponent() # device.name = 'Device_Component' # self.set_device_component(device) # device.set_parameter_controls(self._encoders) # Navigation self._session_navigation = SessionNavigationComponent( name='Session_Navigation') self._session_navigation.set_next_track_button(self._next_track_button) self._session_navigation.set_prev_track_button(self._prev_track_button) # Playing # self._session.set_scene_launch_buttons(tuple(self._scene_launch_buttons)) for index in range(len(self._scene_launch_buttons)): scene = self._session.scene(index) scene.set_launch_button(self._scene_launch_buttons[index]) @subject_slot('value') def _do_undo(self, value): if value: if self.song().can_undo == 1: self.song().undo() self.show_message(str('UNDO')) def _dummy_listener(self, value): pass def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) self._update_mixer_offset() def _update_mixer_offset(self): all_tracks = self._session.tracks_to_use() selected_track = self.song().view.selected_track num_strips = self._session.width() if selected_track in all_tracks: track_index = list(all_tracks).index(selected_track) new_offset = track_index - track_index % num_strips self._session.set_offsets(new_offset, self._session.scene_offset())
class Tweaker(ControlSurface): __module__ = __name__ __doc__ = " Tweaker control surface script " def __init__(self, c_instance, *a, **k): super(Tweaker, self).__init__(c_instance, *a, **k) with self.component_guard(): self._update_linked_device_selection = None self._tweaker_version_check = '0.3' self.log_message("--------------= Tweaker Session " + str(self._tweaker_version_check) + " log opened =--------------") self._timer = 0 self.flash_status = 1 self._last_selected_strip_number = 0 self._device_selection_follows_track_selection = False #self._pad_translations = PAD_TRANSLATION self._linked_session = None self._mixer_offset = 0 self._nav_lock = True self._setup_controls() self._setup_transport_control() self._setup_device_control() self._setup_mixer_control() self._setup_session_control() self._setup_crossfader() self._setup_modes() self._setup_pads() self._setup_navigation_lock() self._setup_arrange_session_toggle() #self.assign_main_configuration() #self.request_rebuild_midi_map() #self._mixer._reassign_tracks() #this is to update rebuild the cf_assign closure, otherwise the colors aren't correct #self.schedule_message(30, self._detect_devices) self.show_message('Tweaker Control Surface Loaded') self.show_message('Tweaker Control Surface Loaded') #self._shift_value(0) #this updates the pads so that they transmit to Live on the assigned PAD_CHANNEL...also, lights shift button self.assign_main_configuration() #self.schedule_message(2, self._shift_value, 0) self.schedule_message(3, self._mixer._reassign_tracks) """script initialization methods""" def _setup_controls(self): is_momentary = True self._grid = [None for index in range(8)] for column in range(8): self._grid[column] = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, column + (row * 8) + 1, 'Grid_' + str(column) + '_' + str(row), self) for row in range(4)] self._button = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_BUTTONS[index], 'Button_' + str(index), self) for index in range(len(TWEAKER_BUTTONS))] self._nav = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_NAVS[index], 'Nav_' + str(index), self) for index in range(len(TWEAKER_NAVS))] self._encoder_button = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_ENCODER_BUTTONS[index], 'Encoder_Button_' + str(index), self) for index in range(len(TWEAKER_ENCODER_BUTTONS))] self._dial = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_DIALS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_DIALS))] self._fader = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_FADERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_FADERS))] self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute) self._encoder = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_ENCODERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_ENCODERS))] self._pad = [TweakerMonoButtonElement(False, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_PADS[index], 'Pad_' + str(index), self) for index in range(len(TWEAKER_PADS))] for index in range(4): self._pad[index].set_enabled(False) self._pad[index].set_channel(PAD_CHANNEL) self._pad[index].set_identifier(index + 4) self._pad[index+4].set_enabled(False) self._pad[index+4].set_channel(PAD_CHANNEL) self._pad[index+4].set_identifier(index) self._pad_pressure = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_PAD_PRESSURES[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_PADS))] for index in range(8): self._pad_pressure[index]._last_sent = 0 self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' for row in range(4): button_row = [] for column in range(7): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) self._send_midi(tuple([240,0,1,106,01,07,21,21,247])) #set all pots to walk mode self._send_midi(tuple([240, 0, 1, 106, 1, 6, 127 , 127, 25, 0, 15, 0, 9, PAD_SENSITIVITY, 247])) #set pads to sensitivity set in Map file def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_mixer_control(self): is_momentary = True self._num_tracks = (2) #A mixer is one-dimensional; self._mixer = MixerComponent(2, 0, False, False) self._mixer.name = 'Mixer' self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer) self._device_navigator = [None for index in range(2)] self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(2): self._mixer.channel_strip(index).set_volume_control(self._fader[index]) self._mixer.channel_strip(index)._on_cf_assign_changed = self._channelstrip_on_cf_assign_changed(self._mixer.channel_strip(index)) self._mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) #mixer.track_filter(index).name = 'Mixer_TrackFilter_' + str(index) self._mixer.channel_strip(index)._invert_mute_feedback = True self._mixer.channel_strip(index)._device_component = self._device[index] self._mixer.channel_strip(index).update = self._channelstrip_update(self._mixer.channel_strip(index)) self._mixer.channel_strip(index)._select_value = self._channelstrip_select_value(self._mixer.channel_strip(index), index) self._device_navigator[index] = DetailViewControllerComponent(self, self._mixer.channel_strip(index)) self._device_navigator[index].name = 'Device_Navigator_'+str(index) self._mixer.channel_strip(0).set_track = self._channelstrip_set_track(self._mixer.channel_strip(0), self._channelstrip1_cb) self._mixer.channel_strip(1).set_track = self._channelstrip_set_track(self._mixer.channel_strip(1), self._channelstrip2_cb) self.song().view.selected_track = self._mixer.channel_strip(0)._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error #self._mixer._reassign_tracks() def _setup_session_control(self): is_momentary = True num_tracks = NUM_TRACKS num_scenes = NUM_SCENES self._session = SessionComponent(num_tracks, num_scenes) self._session.name = "Session" self._session.set_offsets(0, 0) self._session.set_stop_track_clip_value(STOP_CLIP) self._scene = [None for index in range(3)] for row in range(num_scenes): self._scene[row] = self._session.scene(row) self._scene[row].name = 'Scene_' + str(row) for column in range(num_tracks): clip_slot = self._scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_' + str(row) clip_slot.set_triggered_to_play_value(CLIP_TRG_PLAY) clip_slot.set_triggered_to_record_value(CLIP_TRG_REC) clip_slot.set_stopped_value(CLIP_STOP) clip_slot.set_started_value(CLIP_STARTED) clip_slot.set_recording_value(CLIP_RECORDING) self._session._stop_track_value = self._session_stop_track_value(self._session) self._session._on_fired_slot_index_changed = self._session_on_fired_slot_index_changed(self._session) self._session._change_offsets = self._session_change_offsets(self._session) self._session.update = self._session_update(self._session) #self._session.add_offset_listener(self._update_navigation_view) self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) self._session_zoom = SessionZoomingComponent(self._session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_stopped_value(ZOOM_STOPPED) self._session_zoom.set_playing_value(ZOOM_PLAYING) self._session_zoom.set_selected_value(ZOOM_SELECTED) #self._session_zoom.set_enabled(True) def _setup_device_control(self): self._device = [None for index in range(2)] for index in range(2): self._device[index] = DeviceComponent() self._device[index].name = 'Device_Component_'+str(index) self._device[index].set_enabled(True) self._device[index]._number_of_parameter_banks = self._device_number_of_parameter_banks(self._device[index]) self._device[index]._assign_parameters = self._device_assign_parameters(self._device[index]) self._device[index]._device_banks = DEVICE_DICT self._device[index]._device_best_banks = DEVICE_BOB_DICT self._device[index]._device_bank_names = BANK_NAME_DICT def _setup_crossfader(self): self._mixer.set_crossfader_control(self._crossfader) def _setup_modes(self): self._pad_offset = PadOffsetComponent(self) self._pad_offset._set_protected_mode_index(0) self._pad_offset.set_enabled(False) def _setup_pads(self): for pad in self._pad_pressure: pad.add_value_listener(self._light_pad, True) def _setup_navigation_lock(self): if(self._encoder_button[0].value_has_listener(self._nav_lock_value)): self._encoder_button[0].remove_value_listener(self._nav_lock_value) self._encoder_button[0].add_value_listener(self._nav_lock_value) def _setup_arrange_session_toggle(self): if(self._nav[1].value_has_listener(self._arrange_session_value)): self._nav[1].remove_value_listener(self._arrange_session_value) self._nav[1].add_value_listener(self._arrange_session_value) """configuration methods""" def assign_main_configuration(self): for column in range(7): for row in range(3): self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row]) self._session.set_stop_track_clip_buttons(tuple([self._grid[index][3] for index in range(7)])) for row in range(3): self._scene[row].set_launch_button(self._grid[7][row]) self._device[0].set_parameter_controls(tuple([self._encoder[index+1] for index in range(3)])) self._device[0].set_enabled(True) self._device[1].set_parameter_controls(tuple([self._encoder[index+4] for index in range(3)])) self._device[1].set_enabled(True) for track in range(2): self._mixer.channel_strip(track).set_volume_control(self._fader[track]) self._mixer.channel_strip(track).set_solo_button(self._button[track*3]) self._button[track*3].set_on_off_values(SOLO, 0) self._mixer.channel_strip(track).set_arm_button(self._button[1 + (track*3)]) self._button[1 + (track*3)].set_on_off_values(ARM, 0) self._mixer.channel_strip(track).set_crossfade_toggle(self._button[2 + (track*3)]) self._mixer.master_strip().set_volume_control(self._dial[1]) self._mixer.set_prehear_volume_control(self._dial[0]) self._session.set_track_bank_buttons(self._nav[4], self._nav[3]) self._session.set_scene_bank_buttons(self._nav[2], self._nav[0]) self._session_zoom.set_zoom_button(self._grid[7][3]) self._session_zoom.set_nav_buttons(self._nav[0], self._nav[2], self._nav[3], self._nav[4]) self._session_zoom.set_button_matrix(self._matrix) self._device[0].set_on_off_button(self._encoder_button[1]) self._device_navigator[0].set_device_nav_buttons(self._encoder_button[2], self._encoder_button[3]) self._device[1].set_on_off_button(self._encoder_button[4]) self._device_navigator[1].set_device_nav_buttons(self._encoder_button[5], self._encoder_button[6]) for track in range(2): self._update_device(self._mixer.channel_strip(track)) #self._device.set_bank_nav_buttons(self._menu[0], self._menu[3]) self.assign_track_selector(self._encoder[0]) #for index in range(8): # self._pad[index].send_value(1, True) # self._pad[index].set_channel(1) # self._pad[index].set_identifier(index) # self._pad[index].set_enabled(False) #this has to happen for translate to work if not self._grid[7][3].value_has_listener(self._shift_value): self._grid[7][3].add_value_listener(self._shift_value) self._grid[7][3].send_value(127, True) self.request_rebuild_midi_map() """Tweaker custom methods""" def _shift_value(self, value): self._pad_offset.set_enabled(value>0) if value > 0: self._update_navigation_view() for pad in self._pad: pad.use_default_message() pad.set_enabled(True) self._pad_offset.set_mode_buttons(tuple(self._pad)) self.schedule_message(1, self._pad_offset.update) if self._session.is_enabled(): #self._update_navigation_view() #self.schedule_message(1, self._update_navigation_veiw) self._update_navigation_view() self._grid[7][3].send_value(SHIFT_ON) for track in range(2): self._mixer.channel_strip(track).set_crossfade_toggle(None) self._mixer.channel_strip(track).set_select_button(self._button[2 + (track*3)]) else: self._pad_offset.set_mode_buttons(None) for index in range(4): self._pad[index].set_enabled(False) self._pad[index].set_channel(PAD_CHANNEL) self._pad[index].set_identifier(index + 4 + (self._pad_offset._mode_index * 8)) self._pad[index+4].set_enabled(False) self._pad[index+4].set_channel(PAD_CHANNEL) self._pad[index+4].set_identifier(index + (self._pad_offset._mode_index * 8)) self._grid[7][3].send_value(SHIFT_OFF) for track in range(2): self._mixer.channel_strip(track).set_select_button(None) self._mixer.channel_strip(track).set_crossfade_toggle(self._button[2 + (track*3)]) def assign_track_selector(self, encoder): assert isinstance(encoder, EncoderElement) if not encoder.value_has_listener(self._track_selector_value): encoder.add_value_listener(self._track_selector_value) def deassign_track_selector(self, encoder): if encoder.value_has_listener(self._track_selector_value): encoder.remove_value_listener(self._track_selector_value) def _nav_lock_value(self, value): if value > 0: if self._nav_lock: self._mixer_offset = self._mixer_offset + self._session._track_offset self._mixer.set_track_offset(self._mixer_offset) else: if self._mixer_offset in range(self._session._track_offset, self._session._track_offset + 5): self._mixer_offset = self._mixer_offset - self._session._track_offset elif self._mixer_offset < self._session._track_offset: self._mixer_offset = 0 else: self._mixer_offset = min(self._session._track_offset+5, len(self._session.tracks_to_use())-2) self._mixer.set_track_offset(self._session._track_offset + self._mixer_offset) self._nav_lock = not self._nav_lock self._session.update() def _arrange_session_value(self, value): if value > 0: if (self.application().view.is_view_visible('Arranger')): self.application().view.show_view('Session') else: self.application().view.show_view('Arranger') def _track_selector_value(self, value): if(value is 1): if self._nav_lock: self._mixer_offset = min(self._mixer_offset + 1, min(NUM_TRACKS - 2, len(self._session.tracks_to_use())-self._session._track_offset-2)) else: self._mixer_offset = min(self._mixer_offset + 1, len(self._session.tracks_to_use())-2) elif(value is 127): self._mixer_offset = max(self._mixer_offset - 1, 0) if self._nav_lock: self._mixer.set_track_offset(self._session._track_offset + self._mixer_offset) #self._session.set_offsets(self._session._track_offset) ?? else: self._mixer.set_track_offset(self._mixer_offset) self._session.update() if self._mixer.channel_strip(self._last_selected_strip_number)._track != None: self.song().view.selected_track = self._mixer.channel_strip(self._last_selected_strip_number)._track if self._linked_session != None: if self._linked_session._is_linked(): self._linked_session._unlink() self._linked_session.set_offsets(self._mixer._track_offset, self._linked_session._scene_offset) self._linked_session._link() def _update_navigation_view(self): dif = self._mixer._track_offset - self._session._track_offset for index in range(7): #if (index + self._session._track_offset) in range(len(self._session.tracks_to_use())): if (index + self._session._track_offset) in range(0, len(self.song().visible_tracks)): self._grid[index][3].send_value(NAV_COLORS[int(index in range(dif, dif + 2))], True) elif (index + self._session._track_offset) in range(len(self.song().visible_tracks), len(self._session.tracks_to_use())): self._grid[index][3].send_value(RETURN_NAV_COLORS[int(index in range(dif, dif + 2))], True) else: self._grid[index][3].send_value(0, True) self._send_midi(tuple([240,0,1,106,01,07,21,21,247])) #set all pots to walk mode def _update_device(self, channelstrip): for control in channelstrip._device_component._parameter_controls: control.send_value(0, True) if channelstrip._device_component._on_off_button != None: channelstrip._device_component._on_off_button.turn_off() if not channelstrip._track is None: if not channelstrip._device_component._device in channelstrip._track.devices: track = channelstrip._track device_to_select = track.view.selected_device if (device_to_select == None) and (len(track.devices) > 0): device_to_select = track.devices[0] elif channelstrip._device_component and not type(channelstrip._device_component) is type(None): channelstrip._device_component.set_device(device_to_select) else: channelstrip._device_component.set_device(None) else: pass else: channelstrip._device_component.set_device(None) channelstrip._device_component._on_on_off_changed() def _light_pad(self, value, sender): if not self._pad_offset.is_enabled(): if value > sender._last_sent: if self._pad[self._pad_pressure.index(sender)]._last_sent_value < 1: self._pad[self._pad_pressure.index(sender)].send_value(127, True) else: self._pad[self._pad_pressure.index(sender)].send_value(0, True) sender._last_sent = value """called on timer""" def update_display(self): super(Tweaker, self).update_display() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if(self.flash_status > 0): for control in self.controls: if isinstance(control, TweakerMonoButtonElement): control.flash(self._timer) """m4l bridge""" def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' return ret def notification_to_bridge(self, name, value, sender): if(isinstance(sender, MonoEncoderElement2)): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if(self._shift_mode._mode_index < 2): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched +=1 def check_touch(self): if(self._shift_mode._mode_index < 2): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def handle_sysex(self, midi_bytes): pass """general functionality""" def disconnect(self): """clean things up on disconnect""" #self._update_linked_device_selection = None if self._session.offset_has_listener(self._update_navigation_view): self._session.remove_offset_listener(self._update_navigation_view) if(self._nav[1].value_has_listener(self._arrange_session_value)): self._nav[1].remove_value_listener(self._arrange_session_value) if(self._encoder_button[0].value_has_listener(self._nav_lock_value)): self._encoder_button[0].remove_value_listener(self._nav_lock_value) for pad in self._pad_pressure: if pad.value_has_listener(self._light_pad): pad.remove_value_listener(self._light_pad) if self._grid[7][3].value_has_listener(self._shift_value): self._grid[7][3].remove_value_listener(self._shift_value) if self._session._is_linked(): self._session._unlink() self.deassign_track_selector(self._encoder[0]) self.log_message("--------------= Tweaker Session " + str(self._tweaker_version_check) + " log closed =--------------") #Create entry in log file super(Tweaker, self).disconnect() return None def _get_num_tracks(self): return self.num_tracks def _on_selected_track_changed(self): super(Tweaker, self)._on_selected_track_changed() if self._session.is_enabled(): self._session.update() for index in range(2): self._update_device(self._mixer.channel_strip(index)) self._mixer.on_selected_track_changed() def connect_script_instances(self, instanciated_scripts): link = False for s in instanciated_scripts: if '_tweaker_version' in dir(s): if s._tweaker_version == self._tweaker_version_check: link = True break if link == True: if not self._session._is_linked(): self._session._link() """SessionComponent overrides""" def _session_update(self, session): def _update(): SessionComponent.update(session) if session.is_enabled(): self._update_navigation_view() return _update def _session_change_offsets(self, session): def _change_offsets(track_increment, scene_increment): offsets_changed = (track_increment != 0) or (scene_increment != 0) if offsets_changed: session._track_offset += track_increment session._scene_offset += scene_increment assert (session._track_offset >= 0) assert (session._scene_offset >= 0) if (session._mixer != None): if(self._nav_lock): if (session.track_offset() + self._mixer_offset) > (len(session.tracks_to_use())-2): self._mixer_offset = max(len(session.tracks_to_use()) - session._track_offset - 2, 0) session._mixer.set_track_offset(max(0, session.track_offset() + self._mixer_offset)) session._reassign_tracks() if offsets_changed: session._reassign_scenes() # this is replaced by notify_offset() in Live9 #for callback in session._offset_callbacks: # this is replaced by notify_offset() in Live9 # callback() session.notify_offset() self._update_navigation_view() if self._mixer.channel_strip(self._last_selected_strip_number)._track != None: self.song().view.selected_track = self._mixer.channel_strip(self._last_selected_strip_number)._track if ((session.width() > 0) and (session.height() > 0)): session._do_show_highlight() return _change_offsets def _session_on_fired_slot_index_changed(self, session): def _on_fired_slot_index_changed(index): tracks_to_use = tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) track_index = index + session.track_offset() if session.is_enabled() and session._stop_track_clip_buttons != None: if index < len(session._stop_track_clip_buttons): button = session._stop_track_clip_buttons[index] if button != None: if(track_index < len(tracks_to_use)) and (tracks_to_use[track_index].clip_slots) and (tracks_to_use[track_index].fired_slot_index == -2): button.send_value(session._stop_track_clip_value) #elif index in range(len(session.tracks_to_use())): # dif = self._mixer._track_offset - self._session._track_offset # button.send_value(NAV_COLORS[int(index in range(dif, dif + 2))], True) #else: # button.turn_off() else: self._update_navigation_view() return _on_fired_slot_index_changed def _session_stop_track_value(self, session): def _stop_track_value(value, sender): assert (session._stop_track_clip_buttons != None) assert (list(session._stop_track_clip_buttons).count(sender) == 1) assert (value in range(128)) if session.is_enabled(): if ((value is not 0) or (not sender.is_momentary())): tracks = session.tracks_to_use() track_index = (list(session._stop_track_clip_buttons).index(sender) + session.track_offset()) if (track_index in range(len(tracks))) and (tracks[track_index] in session.song().tracks): tracks[track_index].stop_all_clips() sender.send_value(3, True) self.schedule_message(10, self._update_navigation_view) return _stop_track_value """ChannelStripComponent overrides""" def _channelstrip_update(self, channelstrip): def _update(): ChannelStripComponent.update(channelstrip) self._update_device(channelstrip) return _update def _channelstrip_set_track(self, channelstrip, cb): def _set_track(track): assert ((track == None) or isinstance(track, Live.Track.Track)) if channelstrip._track != None and isinstance(channelstrip._track, Live.Track.Track): if channelstrip._track.devices_has_listener(cb): channelstrip._track.remove_devices_listener(cb) if (track != None): track.add_devices_listener(cb) ChannelStripComponent.set_track(channelstrip, track) return _set_track def _channelstrip_select_value(self, channelstrip, index): def _select_value(value): ChannelStripComponent._select_value(channelstrip, value) self._last_selected_strip_number = index return _select_value def _channelstrip_on_cf_assign_changed(self, channel_strip): def _on_cf_assign_changed(): if (channel_strip.is_enabled() and (channel_strip._crossfade_toggle != None)): if (channel_strip._track != None) and (channel_strip._track in chain(self.song().tracks, self.song().return_tracks)): if channel_strip._track.mixer_device.crossfade_assign == 1: #modified channel_strip._crossfade_toggle.turn_off() elif channel_strip._track.mixer_device.crossfade_assign == 0: channel_strip._crossfade_toggle.send_value(CROSSFADE_A) else: channel_strip._crossfade_toggle.send_value(CROSSFADE_B) return _on_cf_assign_changed def _channelstrip1_cb(self): self._on_selected_track_changed() def _channelstrip2_cb(self): self._on_selected_track_changed() """MixerComponent overrides""" def _mixer_tracks_to_use(self, mixer): def tracks_to_use(): return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) return tracks_to_use """SessionComponent overrides""" def _device_number_of_parameter_banks(self, device): def _number_of_parameter_banks(): return number_of_parameter_banks(device._device) #added return _number_of_parameter_banks def _device_assign_parameters(self, device): def _assign_parameters(): assert device.is_enabled() assert (device._device != None) assert (device._parameter_controls != None) device._bank_name = ('Bank ' + str(device._bank_index + 1)) #added if (device._device.class_name in device._device_banks.keys()): #modified assert (device._device.class_name in device._device_best_banks.keys()) banks = device._device_banks[device._device.class_name] bank = None if (not device._is_banking_enabled()): banks = device._device_best_banks[device._device.class_name] device._bank_name = 'Best of Parameters' #added if (len(banks) > device._bank_index): bank = banks[device._bank_index] if device._is_banking_enabled(): #added if device._device.class_name in device._device_bank_names.keys(): #added device._bank_name[device._bank_index] = device._device_bank_names[device._device.class_name] #added *recheck assert ((bank == None) or (len(bank) >= len(device._parameter_controls))) for index in range(len(device._parameter_controls)): parameter = None if (bank != None): parameter = get_parameter_by_name(device._device, bank[index]) if (parameter != None): device._parameter_controls[index].connect_to(parameter) else: device._parameter_controls[index].release_parameter() else: parameters = device._device_parameters_to_map() num_controls = len(device._parameter_controls) index = (device._bank_index * num_controls) for control in device._parameter_controls: if (index < len(parameters)): control.connect_to(parameters[index]) else: control.release_parameter() index += 1 return _assign_parameters
class Launchkey(ControlSurface): """ Script for Novation's Launchkey 25/49/61 keyboards """ def __init__(self, c_instance, control_factory = LaunchkeyControlFactory(), identity_response = SIZE_RESPONSE): ControlSurface.__init__(self, c_instance) self._control_factory = control_factory self._identity_response = identity_response 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() self._setup_navigation() for component in self.components: component.set_enabled(False) return def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(2, self._send_midi, LIVE_MODE_ON) self.schedule_message(3, self._send_midi, SIZE_QUERY) def handle_sysex(self, midi_bytes): if midi_bytes[0:11] == self._identity_response: self._has_sliders = midi_bytes[11] != 48 self._send_midi(LED_FLASHING_ON) self._update_mixer_offset() for control in self.controls: if isinstance(control, InputControlElement): control.clear_send_cache() for component in self.components: component.set_enabled(True) if self._has_sliders: self._mixer.master_strip().set_volume_control(self._master_slider) self._mixer.update() else: self._mixer.master_strip().set_volume_control(None) for index in range(len(self._sliders)): self._mixer.channel_strip(index).set_volume_control(None) self._mixer.channel_strip(index).set_mute_button(None) slider = self._sliders[index] slider.release_parameter() self._mixer.selected_strip().set_volume_control(self._master_slider) self.request_rebuild_midi_map() return def disconnect(self): ControlSurface.disconnect(self) for button in self._modes_buttons: if button.value_has_listener(self._dummy_listener): button.remove_value_listener(self._dummy_listener) self._modes_buttons = None self._encoders = None self._sliders = None self._strip_buttons = None self._master_slider = None self._current_midi_map = None self._transport_view_modes = None self._send_midi(LED_FLASHING_OFF) self._send_midi(LIVE_MODE_OFF) return def build_midi_map(self, midi_map_handle): self._current_midi_map = midi_map_handle ControlSurface.build_midi_map(self, midi_map_handle) def _setup_mixer(self): mute_solo_flip_button = make_button(59, 'Master_Button') self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' 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 = [] self._strip_buttons = [] 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(make_slider(41 + index, 'Volume_Control_%d' % index)) strip.set_volume_control(self._sliders[-1]) self._strip_buttons.append(make_button(51 + index, 'Mute_Button_%d' % index)) self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button) def _setup_session(self): scene_launch_button = self._control_factory.create_scene_launch_button() scene_stop_button = self._control_factory.create_scene_stop_button() self._session = SessionComponent(8, 0) self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button(scene_launch_button) self._session.selected_scene().set_triggered_value(GREEN_BLINK) self._session.set_stop_all_clips_button(scene_stop_button) scene_stop_button.set_on_off_values(AMBER_FULL, LED_OFF) self._session.set_mixer(self._mixer) self._session.set_stop_clip_value(AMBER_HALF) self._session.set_stop_clip_triggered_value(GREEN_BLINK) clip_launch_buttons = [] clip_stop_buttons = [] for index in range(8): clip_launch_buttons.append(self._control_factory.create_clip_launch_button(index)) clip_stop_buttons.append(self._control_factory.create_clip_stop_button(index)) clip_slot = self._session.selected_scene().clip_slot(index) clip_slot.set_triggered_to_play_value(GREEN_BLINK) clip_slot.set_triggered_to_record_value(RED_BLINK) clip_slot.set_stopped_value(AMBER_FULL) clip_slot.set_started_value(GREEN_FULL) clip_slot.set_recording_value(RED_FULL) clip_slot.set_launch_button(clip_launch_buttons[-1]) clip_slot.name = 'Selected_Clip_Slot_' + str(index) self._session.set_stop_track_clip_buttons(tuple(clip_stop_buttons)) def _setup_transport(self): rwd_button = make_button(112, 'Rwd_Button') ffwd_button = make_button(113, 'FFwd_Button') stop_button = make_button(114, 'Stop_Button') play_button = make_button(115, 'Play_Button') loop_button = make_button(116, 'Loop_Button') rec_button = make_button(117, 'Record_Button') transport = TransportComponent() transport.name = 'Transport' transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_record_button(rec_button) transport.set_loop_button(loop_button) self._transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button) self._transport_view_modes.name = 'Transport_View_Modes' def _setup_device(self): encoders = [ make_encoder(21 + index, 'Device_Control_%d' % index) for index in xrange(8) ] self._encoders = tuple(encoders) device = DeviceComponent() device.name = 'Device_Component' self.set_device_component(device) device.set_parameter_controls(self._encoders) def _setup_navigation(self): self._next_track_button = self._control_factory.create_next_track_button() self._prev_track_button = self._control_factory.create_prev_track_button() self._session_navigation = SessionNavigationComponent(name='Session_Navigation') self._session_navigation.set_next_track_button(self._next_track_button) self._session_navigation.set_prev_track_button(self._prev_track_button) def _dummy_listener(self, value): pass def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) self._update_mixer_offset() def _update_mixer_offset(self): all_tracks = self._session.tracks_to_use() selected_track = self.song().view.selected_track num_strips = self._session.width() if selected_track in all_tracks: track_index = list(all_tracks).index(selected_track) new_offset = track_index - track_index % num_strips self._session.set_offsets(new_offset, self._session.scene_offset())
class LaunchpadSimple(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._suggested_input_port = 'Launchpad' self._suggested_output_port = 'Launchpad' # Launchpad configuration self._send_midi(LAUNCHPAD_RESET) self._send_midi(LAUNCHPAD_ENABLE_BLINKING) # make buttons top_buttons = [ make_button(MIDI_CC_TYPE, 104 + i) for i in range(8) ] side_buttons = [ make_button(MIDI_NOTE_TYPE, 8 + 16 * i) for i in range(8) ] matrix = ButtonMatrixElement() for row in range(8): button_row = [ make_button(MIDI_NOTE_TYPE, 16 * row + col) for col in range(8) ] matrix.add_row(tuple(button_row)) # mixer and session components self._mixer = MixerComponent(8) self._session = SessionComponent(8, SCENES_AMOUNT) self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) # navigation for button in top_buttons[:4]: button.set_on_off_values(GREEN_FULL, GREEN_THIRD) self._session.set_scene_bank_buttons(top_buttons[1], top_buttons[0]) self._session.set_track_bank_buttons(top_buttons[3], top_buttons[2]) # clip launch for scene_index in range(SCENES_AMOUNT): scene = self._session.scene(scene_index) scene.set_launch_button(side_buttons[scene_index]) scene.set_triggered_value(GREEN_BLINK) scene.set_scene_value(GREEN_THIRD) scene.set_no_scene_value(LED_OFF) for track_index in range(8): clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button( matrix.get_button(track_index, scene_index)) clip_slot.set_triggered_to_play_value(GREEN_BLINK) clip_slot.set_triggered_to_record_value(RED_BLINK) clip_slot.set_started_value(GREEN_FULL) clip_slot.set_stopped_value(AMBER_THIRD) clip_slot.set_recording_value(RED_FULL) # track stop self._session.set_stop_track_clip_buttons( [matrix.get_button(i, ROW_STOP) for i in range(8)]) self._session.set_stop_clip_value(RED_THIRD) self._session.set_stop_clip_triggered_value(RED_BLINK) button_stop_all = side_buttons[ROW_STOP] button_stop_all.set_on_off_values(RED_FULL, RED_THIRD) self._session.set_stop_all_clips_button(button_stop_all) # track select self._mixer.set_track_select_buttons( [matrix.get_button(i, ROW_SELECT) for i in range(8)]) self._mixer.set_track_select_values(AMBER_FULL, AMBER_THIRD, LED_OFF) button_select_master = side_buttons[ROW_SELECT] button_select_master.set_on_off_values(AMBER_FULL, AMBER_THIRD) self._mixer.set_master_select_button(button_select_master) # delete clip button self._delete_button = top_buttons[INDEX_DELETE_BUTTON] self._delete_button.set_on_off_values(RED_BLINK, RED_THIRD) self._delete_button.add_value_listener(self._delete_value_listener) self._del_pressed = False self._delete_button.turn_off() # quantization toggle self._quantization_toggle = QuantizationToggle( top_buttons[INDEX_QUANTIZATION_BUTTON], self.song(), GREEN_THIRD, RED_THIRD) # browser view toggle self._browser_view_toggle = ViewToggle( side_buttons[INDEX_BROWSER_VIEW_BUTTON], ABLETON_VIEW_BROWSER, GREEN_THIRD, RED_THIRD) # detail view toggle self._device_view_toggle = DetailViewToggle( side_buttons[INDEX_DETAIL_VIEW_BUTTON], GREEN_THIRD, RED_THIRD, LED_OFF) def disconnect(self): self._send_midi(LAUNCHPAD_RESET) ControlSurface.disconnect(self) self._delete_button.remove_value_listener(self._delete_value_listener) self._delete_button = None self._quantization_toggle.disconnect() self._quantization_toggle = None self._browser_view_toggle.disconnect() self._browser_view_toggle = None self._device_view_toggle.disconnect() self._device_view_toggle = None self._session = None self._mixer = None def receive_midi(self, midi_bytes): if self._del_pressed and self._delete_clip(midi_bytes): return else: ControlSurface.receive_midi(self, midi_bytes) def _delete_value_listener(self, value): self._del_pressed = (value == 127) self._delete_button.set_light(self._del_pressed) def _delete_clip(self, midi_bytes): if midi_bytes[0] == MIDI_NOTE_ON_VALUE: row, col = launchpad_button_loc(midi_bytes[1]) if row < SCENES_AMOUNT and col < 8: self._session.scene(row).clip_slot(col)._do_delete_clip() return True return False
class NanoKontrolShift(ControlSurface): __module__ = __name__ __doc__ = " NanoKontrolShift controller script " def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._suppress_session_highlight = True self._suppress_send_midi = True # Turn off rebuild MIDI map until after we're done setting up self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= NanoKontrolShift log opened =--------------") # Writes message into Live's main log file. This is a ControlSurface method. with self.component_guard(): # OBJECTS self.session = None #session object self.mixer = None #mixer object self.view = None #clip/device view object self.device = None #device object self.transport = None #transport object # MODES self._shift_button = None self._shift_button_pressed = False self._alt_button = None self._alt_button_pressed = False self._ctrl_button = None self._ctrl_button_pressed = False # INITIALIZE MIXER, SESSIONS self._setup_session_control() # Setup the session object self._setup_mixer_control() # Setup the mixer object self._setup_view_control() # Setup the clip/view toggler self.session.set_mixer(self.mixer) # Bind mixer to session self._setup_device_control() # Setup the device object self._setup_transport_control() # Setup transport object self.set_device_component(self.device) # Bind device to control surface # SET INITIAL SESSION/MIXER AND MODIFIERS BUTTONS self._set_modifiers_buttons() self.__update_matrix() # self.set_highlighting_session_component(self.session) for component in self.components: component.set_enabled(True) # self._suppress_session_highlight = True self._suppress_send_midi = True # Turn rebuild back on, once we're done setting up def _setup_session_control(self): self.show_message("#################### SESSION: ON ##############################") is_momentary = True # CREATE SESSION, SET OFFSETS, BUTTONS NAVIGATION AND BUTTON MATRIX self.session = SessionComponent(num_tracks, num_scenes) #(num_tracks, num_scenes) self.session.set_offsets(0, 0) # self.session.set_scene_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_down), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_up)) # self.session.set_track_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_right), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_left)) # (right_button, left_button) This moves the "red box" selection set left & right. We'll use the mixer track selection instead... def _setup_mixer_control(self): is_momentary = True #CREATE MIXER, SET OFFSET (SPECIALMIXERCOMPONENT USES SPECIALCHANNELSTRIP THAT ALLOWS US TO UNFOLD TRACKS WITH TRACK SELECT BUTTON) self.mixer = SpecialMixerComponent(num_tracks, 0, False, False) # 4 tracks, 2 returns, no EQ, no filters self.mixer.name = 'Mixer' self.mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) def _setup_view_control(self): # CREATES OBJECT SO WE CAN TOGGLE DEVICE/CLIP, LOCK DEVICE self.view = ViewTogglerComponent(num_tracks, self) def _setup_device_control(self): # CREATE DEVICE TO ASSIGN PARAMETERS BANK self.device = DeviceComponent() self.device.name = 'Device_Component' def _setup_transport_control(self): # CREATE TRANSPORT DEVICE self.transport = SpecialTransportComponent(self) def _on_selected_scene_changed(self): # ALLOWS TO GRAB THE FIRST DEVICE OF A SELECTED TRACK IF THERE'S ANY ControlSurface._on_selected_track_changed(self) track = self.song().view.selected_track if (track.devices is not None): self._ignore_track_selection = True device_to_select = track.devices[0] self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) self._ignore_track_selection = False """ LED ON, OFF, FLASH WITH SESSION CLIPS """ # UPDATING BUTTONS FROM CLIP MATRIX IN NK AS SESSION MOVES def __update_matrix(self): for scene_index in range(num_scenes): scene = self.session.scene(scene_index) for track_index in range(num_tracks): clip_slot = scene.clip_slot(track_index) button = clip_slot._launch_button_value.subject value_to_send = -1 if clip_slot._clip_slot != None: if clip_slot.has_clip(): value_to_send = 127 if clip_slot._clip_slot.clip.is_triggered: if clip_slot._clip_slot.clip.will_record_on_start: value_to_send = clip_slot._triggered_to_record_value else: value_to_send = clip_slot._triggered_to_play_value ''' elif clip_slot._clip_slot.clip.is_playing: if clip_slot._clip_slot.clip.is_recording: value_to_send = 127 ######### CLIPS PLAYING WILL FLASH for i in range(2000): if i % 50 == 0: button.send_value(127) else: button.send_value(0) else: for i in range(2000): if i % 50 == 0: button.send_value(127) else: button.send_value(0) ''' elif clip_slot._clip_slot.is_triggered: if clip_slot._clip_slot.will_record_on_start: value_to_send = clip_slot._triggered_to_record_value else: value_to_send = clip_slot._triggered_to_play_value elif clip_slot._clip_slot.is_playing: if clip_slot._clip_slot.is_recording: value_to_send = clip_slot._recording_value else: value_to_send = clip_slot._started_value elif clip_slot._clip_slot.controls_other_clips: value_to_send = 0 ''' if value_to_send in range(128): button.send_value(value_to_send) else: button.turn_off() ''' """ MODIFIERS, MODES, KEYS CONFIG """ #MODES ARE HERE: INITIALIZATIONS, DISCONNECTS BUTTONS, SLIDERS, ENCODERS def _clear_controls(self): # TURNING OFF ALL LEDS IN MATRIX self._turn_off_matrix() # SESSION resetsend_controls = [] self.mixer.send_controls = [] for scene_index in range(num_scenes): scene = self.session.scene(scene_index) scene.set_launch_button(None) for track_index in range(num_tracks): clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(None) self.session.set_stop_track_clip_buttons(None) self.session.set_stop_all_clips_button(None) # REMOVE LISTENER TO SESSION MOVES if self.session.offset_has_listener(self.__update_matrix): self.session.remove_offset_listener(self.__update_matrix) self.session.set_stop_all_clips_button(None) # MIXER self.mixer._set_send_nav(None, None) for track_index in range(num_tracks): strip = self.mixer.channel_strip(track_index) strip.set_solo_button(None) strip.set_mute_button(None) strip.set_arm_button(None) resetsend_controls.append(None) strip.set_select_button(None) for i in range(12): self.mixer.send_controls.append(None) strip.set_send_controls(tuple(self.mixer.send_controls)) self.mixer.set_resetsend_buttons(tuple(resetsend_controls)) # VIEW self.view.set_device_nav_buttons(None, None) detailclip_view_controls = [] for track_index in range(num_tracks): detailclip_view_controls.append(None) self.view.set_buttons(tuple(detailclip_view_controls)) # DEVICE PARAMETERS device_param_controls = [] self.device.set_parameter_controls(tuple(device_param_controls)) self.device.set_on_off_button(None) self.device.set_lock_button(None) # TRANSPORT self.transport.set_stop_button(None) self.transport.set_play_button(None) self.transport.set_record_button(None) self.transport._set_quant_toggle_button(None) self.transport.set_metronome_button(None) self.transport._set_tempo_buttons(None, None) self.log_message("Controls Cleared") def _set_normal_mode(self): is_momentary = True self.mixer._set_send_nav(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_up), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_down)) for index in range(num_tracks): strip = self.mixer.channel_strip(index) strip.name = 'Mixer_ChannelStrip_' + str(index) self.mixer._update_send_index(self.mixer.sends_index) strip.set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL, mixer_volumefader_cc[index])) self.mixer.send_controls[self.mixer.sends_index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, mixer_sendknob_cc[index], Live.MidiMap.MapMode.absolute) strip.set_send_controls(tuple(self.mixer.send_controls)) strip._invert_mute_feedback = True ### SET ARM, SOLO, MUTE for index in range(num_tracks): strip = self.mixer.channel_strip(index) strip.set_send_controls(tuple(self.mixer.send_controls)) strip.set_solo_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_solo_cc[index])) strip.set_mute_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_mute_cc[index])) strip.set_arm_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_arm_cc[index])) # self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_stop_cc)) for i in range(12): self.mixer.send_controls.append(None) self.mixer.send_controls[self.mixer.sends_index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, mixer_sendknob_cc[index], Live.MidiMap.MapMode.absolute) strip.set_send_controls(tuple(self.mixer.send_controls)) strip._invert_mute_feedback = True self.mixer._update_send_index(self.mixer.sends_index) def _set_alt_mode(self): is_momentary = True self.mixer._set_send_nav(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_up), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_down)) stop_track_controls = [] resetsend_controls = [] button = None buttons = None # SET SESSION TRACKSTOP, TRACK SELECT, RESET SEND KNOB for index in range(num_tracks): strip = self.mixer.channel_strip(index) strip.set_select_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_select_cc[index])) button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, stop_track_cc[index]) stop_track_controls.append(button) buttons = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_resetsend_cc[index]) resetsend_controls.append(buttons) self.session.set_stop_track_clip_buttons(tuple(stop_track_controls)) self.mixer.set_resetsend_buttons(tuple(resetsend_controls)) self.mixer._update_send_index(self.mixer.sends_index) def _set_ctrl_mode(self): # CLIP/DEVICE VIEW TOGGLE is_momentary = True self.view.set_device_nav_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, device_left_cc), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, device_right_cc)) button = None detailclip_view_controls = [] for index in range(num_tracks): button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, detailclip_view_cc[index]) detailclip_view_controls.append(button) self.view.set_buttons(tuple(detailclip_view_controls)) # DEVICE ON/OFF, LOCK AND PARAMETERS device_param_controls = [] onoff_control = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, onoff_device_cc) setlock_control = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, lock_device_cc) for index in range(num_tracks): knob = None knob = EncoderElement(MIDI_CC_TYPE, CHANNEL, device_param_cc[index], Live.MidiMap.MapMode.absolute) device_param_controls.append(knob) if None not in device_param_controls: self.device.set_parameter_controls(tuple(device_param_controls)) self.device.set_on_off_button(onoff_control) self.device.set_lock_button(setlock_control) # TRANSPORT # self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_stop_cc)) # self.transport.set_play_button(ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, transport_play_cc)) # self.transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_record_cc)) self.transport._set_quant_toggle_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_quantization_cc)) self.transport.set_metronome_button(ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, transport_metronome_cc)) self.transport._set_tempo_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_tempodown_cc), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_tempoup_cc)) # SESSION STOP ALL CLIPS AND SCENE LAUNCH self.session.set_stop_all_clips_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_stopall_cc)) for index in range(num_scenes): self.session.scene(index).set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_scenelaunch_cc[index])) 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) # MODIFIERS LISTENERS FUNCS ARE HERE def _shift_value(self, value): assert isinstance(value, int) assert isinstance(self._shift_button, ButtonElement) if value == 127: if self._shift_button_pressed is False: self._unpress_modes() self._shift_button_pressed = True self._manage_modes(0) def _alt_value(self, value): assert isinstance(value, int) assert isinstance(self._alt_button, ButtonElement) if value == 127: if self._alt_button_pressed is False: self._unpress_modes() self._alt_button_pressed = True self._manage_modes(2) def _ctrl_value(self, value): assert isinstance(value, int) assert isinstance(self._ctrl_button, ButtonElement) if value == 127: if self._ctrl_button_pressed is False: self._unpress_modes() self._ctrl_button_pressed = True self._manage_modes(3) def _manage_modes(self, mode_index): if mode_index == 0: self._clear_controls() self._set_normal_mode() # self._shift_button.turn_on() self._alt_button.turn_on() self._ctrl_button.turn_on() self.log_message("NORMAL ON") elif mode_index == 2: self._clear_controls() self._set_alt_mode() self._alt_button.turn_on() self._shift_button.turn_off() self._ctrl_button.turn_off() self.log_message("ALT ON") elif mode_index == 3: self._clear_controls() self._set_ctrl_mode() self._ctrl_button.turn_on() self._shift_button.turn_off() self._alt_button.turn_off() self.log_message("CTRL ON") def _unpress_modes(self): self._shift_button_pressed = False self._alt_button_pressed = False self._ctrl_button_pressed = False def _turn_off_matrix(self): for index in range(24): self._send_midi(tuple([176,index+16,0])) def disconnect(self): """clean things up on disconnect""" self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= NanoKontrolShift log closed =--------------") #Create entry in log file self._clear_controls() self.session = None self.mixer = None self.view = None self.device = None self.transport = None # MODES self._shift_button = None self._alt_button = None self._ctrl_button = None # SENDS self.send_button_up = None self.send_button_down = None self.send_controls = [] self.send_reset = [] self.set_device_component(None) ControlSurface.disconnect(self) return None
class XoneK2(ControlSurface): def __init__(self, instance): global g_logger g_logger = self.log_message super(XoneK2, self).__init__(instance, False) with self.component_guard(): self._set_suppress_rebuild_requests(True) self.init_session() self.init_mixer() self.init_matrix() self.init_tempo() # connect mixer to session self.session.set_mixer(self.mixer) self.session.update() self.set_highlighting_session_component(self.session) self._set_suppress_rebuild_requests(False) def init_session(self): self.session = SessionComponent(NUM_TRACKS, NUM_SCENES) self.session.name = 'Session' self.session.set_scene_bank_buttons(button(BUTTON_LL), button(BUTTON_LR)) self.session.update() def init_mixer(self): self.mixer = MixerWithDevices( num_tracks=NUM_TRACKS, device_select=[button(PUSH_ENCODERS[i]) for i in range(NUM_TRACKS)], device_encoders=ENCODERS ) self.mixer.id = 'Mixer' self.song().view.selected_track = self.mixer.channel_strip(0)._track for i in range(NUM_TRACKS): self.mixer.channel_strip(i).set_volume_control(fader(FADERS[i])) self.mixer.channel_strip(i).set_solo_button(button(BUTTONS3[i])) self.mixer.set_eq_controls(i, ( knob(KNOBS3[i]), knob(KNOBS2[i]), knob(KNOBS1[i]))) self.mixer.set_device_controls(i, button(BUTTONS1[i])) self.master_encoder = DynamicEncoder( ENCODER_LR, self.song().master_track.mixer_device.volume) self.cue_encoder = DynamicEncoder( ENCODER_LL, self.song().master_track.mixer_device.cue_volume) self.mixer.update() def init_matrix(self): self.matrix = ButtonMatrixElement() for scene_index in range(NUM_SCENES): scene = self.session.scene(scene_index) scene.name = 'Scene ' + str(scene_index) button_row = [] for track_index in range(NUM_TRACKS): note_nr = GRID[scene_index][track_index] b = button(note_nr, name='Clip %d, %d button' % (scene_index, track_index)) button_row.append(b) clip_slot = scene.clip_slot(track_index) clip_slot.name = 'Clip slot %d, %d' % (scene_index, track_index) clip_slot.set_stopped_value(0) clip_slot.set_started_value(64) clip_slot.set_launch_button(b) self.matrix.add_row(tuple(button_row)) stop_buttons = [button(note_nr) for note_nr in BUTTONS2] self.session.set_stop_track_clip_buttons(stop_buttons) def init_tempo(self): self.transport = CustomTransportComponent() self.transport.set_tempo_bumpers(button(PUSH_ENCODER_LR), button(PUSH_ENCODER_LL))
class midi_twister_110(ControlSurface): def __init__(self, c_instance): super(midi_twister_110, self).__init__(c_instance) with self.component_guard(): global active_mode active_mode = "_mode1" self._set_active_mode() self.show_message("Modified by XXPW") def _mode1(self): self.show_message("_mode1 is active") # mixer global mixer num_tracks = 32 num_returns = 7 self.mixer = MixerComponent(num_tracks, num_returns) self.mixer.set_track_offset(0) self.song().view.selected_track = self.mixer.channel_strip(0)._track # sends send0_controls = ( SliderElement(MIDI_CC_TYPE, 0, 32), SliderElement(MIDI_CC_TYPE, 0, 36), SliderElement(MIDI_CC_TYPE, 0, 40), None, None, None, None, None, ) self.mixer.channel_strip(0).set_send_controls(tuple(send0_controls)) self.mixer.channel_strip(0).set_volume_control( SliderElement(MIDI_CC_TYPE, 0, 44)) send1_controls = ( SliderElement(MIDI_CC_TYPE, 0, 33), SliderElement(MIDI_CC_TYPE, 0, 37), SliderElement(MIDI_CC_TYPE, 0, 41), None, None, None, None, None, ) self.mixer.channel_strip(1).set_send_controls(tuple(send1_controls)) self.mixer.channel_strip(1).set_volume_control( SliderElement(MIDI_CC_TYPE, 0, 45)) send2_controls = ( SliderElement(MIDI_CC_TYPE, 0, 34), SliderElement(MIDI_CC_TYPE, 0, 38), SliderElement(MIDI_CC_TYPE, 0, 42), None, None, None, None, None, ) self.mixer.channel_strip(2).set_send_controls(tuple(send2_controls)) self.mixer.channel_strip(2).set_volume_control( SliderElement(MIDI_CC_TYPE, 0, 46)) send3_controls = ( SliderElement(MIDI_CC_TYPE, 0, 35), SliderElement(MIDI_CC_TYPE, 0, 39), SliderElement(MIDI_CC_TYPE, 0, 43), None, None, None, None, None, ) self.mixer.channel_strip(3).set_send_controls(tuple(send3_controls)) self.mixer.channel_strip(3).set_volume_control( SliderElement(MIDI_CC_TYPE, 0, 47)) # session global _session num_tracks = 4 num_scenes = 3 session_buttons = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] self._pads = [ ButtonElement(1, MIDI_CC_TYPE, 1, session_buttons[index]) for index in range(num_tracks * num_scenes) ] self._grid = ButtonMatrixElement(rows=[ self._pads[(index * num_tracks):(index * num_tracks) + num_tracks] for index in range(num_scenes) ]) self._session = SessionComponent(num_tracks, num_scenes) self._session.set_clip_launch_buttons(self._grid) self.set_highlighting_session_component(self._session) # session track stop stop_track_buttons = [12, 13, 14, 15] self._track_stop_buttons = [ ButtonElement(1, MIDI_CC_TYPE, 1, stop_track_buttons[index]) for index in range(num_tracks) ] self._session.set_stop_track_clip_buttons( tuple(self._track_stop_buttons)) # session navigation self.session_left = ButtonElement(1, MIDI_CC_TYPE, 3, 8) self._session.set_page_left_button(self.session_left) self.session_left.add_value_listener(self._reload_active_devices, identify_sender=False) self.session_right = ButtonElement(1, MIDI_CC_TYPE, 3, 11) self._session.set_page_right_button(self.session_right) self.session_right.add_value_listener(self._reload_active_devices, identify_sender=False) self.session_up = ButtonElement(1, MIDI_CC_TYPE, 3, 10) self._session.set_page_up_button(self.session_up) self.session_up.add_value_listener(self._reload_active_devices, identify_sender=False) self.session_down = ButtonElement(1, MIDI_CC_TYPE, 3, 13) self._session.set_page_down_button(self.session_down) self.session_down.add_value_listener(self._reload_active_devices, identify_sender=False) self._session._link() self._session.set_mixer(self.mixer) #self._session.set_mixer(self.mixer) self._mode1_devices() self.add_device_listeners() # button: next device self.next_device = ButtonElement(0, MIDI_CC_TYPE, 1, 25) self.next_device.add_value_listener(self._next_device_value, identify_sender=False) # button: prev device self.previous_device = ButtonElement(1, MIDI_CC_TYPE, 1, 24) self.previous_device.add_value_listener(self._prev_device_value, identify_sender=False) # transport global transport self.transport = TransportComponent() self.transport.name = 'Transport' loop_button = ButtonElement(1, MIDI_CC_TYPE, 1, 50) loop_button.name = 'loop_button' self.transport.set_loop_button(loop_button) stop_button = ButtonElement(1, MIDI_CC_TYPE, 1, 49) stop_button.name = 'stop_button' self.transport.set_stop_button(stop_button) play_button = ButtonElement(1, MIDI_CC_TYPE, 1, 48) play_button.name = 'play_button' self.transport.set_play_button(play_button) # button: track navigation right self.track_navigation_right = ButtonElement(1, MIDI_CC_TYPE, 3, 17) self.track_navigation_right.add_value_listener( self._track_navigation_right_track_nav, identify_sender=False) # button: track navigation left self.track_navigation_left = ButtonElement(1, MIDI_CC_TYPE, 3, 14) self.track_navigation_left.add_value_listener( self._track_navigation_left_track_nav, identify_sender=False) def _remove_mode1(self): # mixer global mixer self._remove_mode1_devices() self.remove_device_listeners() send0_controls = ( None, None, None, None, None, None, None, None, ) self.mixer.channel_strip(0).set_send_controls(tuple(send0_controls)) send1_controls = ( None, None, None, None, None, None, None, None, ) self.mixer.channel_strip(1).set_send_controls(tuple(send1_controls)) send2_controls = ( None, None, None, None, None, None, None, None, ) self.mixer.channel_strip(2).set_send_controls(tuple(send2_controls)) send3_controls = ( None, None, None, None, None, None, None, None, ) self.mixer.channel_strip(3).set_send_controls(tuple(send3_controls)) # session global _session self._session.set_clip_launch_buttons(None) self.set_highlighting_session_component(None) self._session.set_mixer(None) self._session.set_stop_all_clips_button(None) # session track stop self._track_stop_buttons = None self._session.set_stop_track_clip_buttons(None) # session scene launch self._scene_launch_buttons = None self._session.set_scene_launch_buttons(None) # session navigation self.session_left.remove_value_listener(self._reload_active_devices) self._session.set_page_left_button(None) self.session_right.remove_value_listener(self._reload_active_devices) self._session.set_page_right_button(None) self.session_up.remove_value_listener(self._reload_active_devices) self._session.set_page_up_button(None) self.session_down.remove_value_listener(self._reload_active_devices) self._session.set_page_down_button(None) self._session = None self.next_device.remove_value_listener(self._next_device_value) self.next_device = None self.previous_device.remove_value_listener(self._prev_device_value) self.previous_device = None # transport global transport self.transport.set_loop_button(None) self.transport.set_stop_button(None) self.transport.set_play_button(None) self.transport = None self.track_navigation_right.remove_value_listener( self._track_navigation_right_track_nav) self.track_navigation_right = None self.track_navigation_left.remove_value_listener( self._track_navigation_left_track_nav) self.track_navigation_left = None def _mode1_devices(self): global mixer global _session # device self.mixer.selected_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, 0, 28)) self.mixer.selected_strip().set_pan_control( SliderElement(MIDI_CC_TYPE, 0, 29)) self.mixer.selected_strip().set_mute_button( ButtonElement(1, MIDI_CC_TYPE, 1, 28)) self.mixer.selected_strip().set_solo_button( ButtonElement(1, MIDI_CC_TYPE, 1, 29)) if (len(self.mixer.selected_strip()._track.devices) > 0): global device_tracktype_selected__chain_number_selected self.device_tracktype_selected__chain_number_selected = DeviceComponent( ) device_controls = ( SliderElement(MIDI_CC_TYPE, 0, 16), SliderElement(MIDI_CC_TYPE, 0, 17), SliderElement(MIDI_CC_TYPE, 0, 18), SliderElement(MIDI_CC_TYPE, 0, 19), SliderElement(MIDI_CC_TYPE, 0, 20), SliderElement(MIDI_CC_TYPE, 0, 21), SliderElement(MIDI_CC_TYPE, 0, 22), SliderElement(MIDI_CC_TYPE, 0, 23), ) self.device_tracktype_selected__chain_number_selected.set_parameter_controls( tuple(device_controls)) self.set_device_component( self.device_tracktype_selected__chain_number_selected) self.device_tracktype_selected__chain_number_selected.set_on_off_button( ButtonElement(1, MIDI_CC_TYPE, 1, 26)) self.device_tracktype_selected__chain_number_selected.set_bank_nav_buttons( ButtonElement(0, MIDI_CC_TYPE, 1, 31), ButtonElement(1, MIDI_CC_TYPE, 1, 33)) def _remove_mode1_devices(self): global mixer global _session # device if (hasattr(self, 'device_tracktype_selected__chain_number_selected')): global device_tracktype_selected__chain_number_selected device_controls = ( None, None, None, None, None, None, None, None, ) self.device_tracktype_selected__chain_number_selected.set_parameter_controls( tuple(device_controls)) self.device_tracktype_selected__chain_number_selected.set_on_off_button( None) self.device_tracktype_selected__chain_number_selected.set_bank_nav_buttons( None, None) self.set_device_component( self.device_tracktype_selected__chain_number_selected) def add_device_listeners(self): global mixer num_of_tracks = len(self.song().tracks) value = "add device listener" for index in range(num_of_tracks): self.song().tracks[index].add_devices_listener( self._reload_active_devices) def remove_device_listeners(self): global mixer num_of_tracks = len(self.song().tracks) value = "remove device listener" for index in range(num_of_tracks): self.song().tracks[index].remove_devices_listener( self._reload_active_devices) def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) self._display_reset_delay = 0 value = "selected track changed" self._reload_active_devices(value) def _reload_active_devices(self, value=None): self._remove_active_devices() self._set_active_devices() def _set_active_devices(self): global active_mode # activate mode if (active_mode == "_mode1") and (hasattr(self, '_mode1_devices')): self._mode1_devices() def _remove_active_devices(self): global active_mode # remove activate mode if (active_mode == "_mode1") and (hasattr(self, '_mode1_devices')): self._remove_mode1_devices() def _next_device_value(self, value): if value > 0: self._device = self.song().view.selected_track.view.selected_device if self._device is not None: self.song().view.select_device( self.song().view.selected_track.devices[ self.selected_device_idx() + 1]) def _prev_device_value(self, value): if value > 0: self._device = self.song().view.selected_track.view.selected_device if self._device is not None: self.song().view.select_device( self.song().view.selected_track.devices[ self.selected_device_idx() - 1]) def selected_device_idx(self): self._device = self.song().view.selected_track.view.selected_device return self.tuple_index(self.song().view.selected_track.devices, self._device) def _track_navigation_right_track_nav(self, value): if value > 0: self.song().view.selected_track = self.song().tracks[ self.selected_track_idx() + 1] def _track_navigation_left_track_nav(self, value): if value > 0: self.song().view.selected_track = self.song().tracks[ self.selected_track_idx() - 1] def selected_track_idx(self): return self.tuple_index(self.song().tracks, self.song().view.selected_track) def _set_active_mode(self): global active_mode # activate mode if active_mode == "_mode1": self._mode1() def _remove_active_mode(self): global active_mode # remove activate mode if active_mode == "_mode1": self._remove_mode1() def _activate_mode1(self, value): global active_mode if value > 0: self._remove_active_mode() active_mode = "_mode1" self._set_active_mode() def _activate_shift_mode1(self, value): global active_mode if value > 0: self._remove_active_mode() self._mode1() else: self._remove_mode1() self._set_active_mode() def tuple_index(self, tuple, obj): for i in xrange(0, len(tuple)): if (tuple[i] == obj): return i return (False) def disconnect(self): super(midi_twister_110, self).disconnect()
class joyMIDI(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.setup_transport() self.setup_mixer() self.setup_session() def setup_transport(self): # elements self.play_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 93) self.stop_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 94) self.record_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 95) # transport self.transport = TransportComponent() self.transport.set_play_button(self.play_button) self.transport.set_stop_button(self.stop_button) self.transport.set_record_button(self.record_button) def setup_mixer(self): # elements self.mute_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 92) # tracks, return_tracks self.solo_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 84) # tracks, return_tracks self.arm_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 85) # tracks self.senda_up_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 96) # tracks, return_tracks self.senda_down_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 88) # tracks, return_tracks self.sendb_up_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 97) # tracks, return_tracks self.sendb_down_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 89) # tracks, return_tracks self.pan_up_button = ButtonElement( True, MIDI_NOTE_TYPE, 0, 98) # tracks, return_tracks, master_track self.pan_down_button = ButtonElement( True, MIDI_NOTE_TYPE, 0, 90) # tracks, return_tracks, master_track self.volume_up_button = ButtonElement( True, MIDI_NOTE_TYPE, 0, 99) # tracks, return_tracks, master_track self.volume_down_button = ButtonElement( True, MIDI_NOTE_TYPE, 0, 91) # tracks, return_tracks, master_track self.track_nav_encoder = EncoderElement( MIDI_CC_TYPE, 0, 14, Live.MidiMap.MapMode.relative_binary_offset) # mixer self.mixer = MixerComponent(7, 2) self.mixer.selected_strip().set_mute_button(self.mute_button) self.mixer.selected_strip().set_solo_button(self.solo_button) self.mixer.selected_strip().set_arm_button(self.arm_button) # send A/B, pan, volume self.senda_up_button.add_value_listener(self.on_senda_up_changed) self.senda_down_button.add_value_listener(self.on_senda_down_changed) self.sendb_up_button.add_value_listener(self.on_sendb_up_changed) self.sendb_down_button.add_value_listener(self.on_sendb_down_changed) self.pan_up_button.add_value_listener(self.on_pan_up_changed) self.pan_down_button.add_value_listener(self.on_pan_down_changed) self.volume_up_button.add_value_listener(self.on_volume_up_changed) self.volume_down_button.add_value_listener(self.on_volume_down_changed) # nav self.track_nav_encoder.add_value_listener(self.on_mixer_track_nav) def on_senda_up_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.sends[0] param.value = max( param.min, min(param.max, param.value + ((param.max - param.min) / SEND_STEPS))) def on_senda_down_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.sends[0] param.value = max( param.min, min(param.max, param.value - ((param.max - param.min) / SEND_STEPS))) def on_sendb_up_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.sends[1] param.value = max( param.min, min(param.max, param.value + ((param.max - param.min) / SEND_STEPS))) def on_sendb_down_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.sends[1] param.value = max( param.min, min(param.max, param.value - ((param.max - param.min) / SEND_STEPS))) def on_pan_up_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.panning param.value = max( param.min, min(param.max, param.value + ((param.max - param.min) / PAN_STEPS))) def on_pan_down_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.panning param.value = max( param.min, min(param.max, param.value - ((param.max - param.min) / PAN_STEPS))) def on_volume_up_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.volume param.value = max( param.min, min(param.max, param.value + ((param.max - param.min) / VOLUME_STEPS))) def on_volume_down_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.volume param.value = max( param.min, min(param.max, param.value - ((param.max - param.min) / VOLUME_STEPS))) def on_mixer_track_nav(self, value): move = -1 if value > 64 else +1 # get tracks-info tracks = self.song().tracks return_tracks = self.song().return_tracks master_track = self.song().master_track all_tracks = list(chain(tracks, return_tracks)) all_tracks.append(master_track) num_tracks = len(tracks) num_return_tracks = len(return_tracks) num_master_track = 1 num_all_tracks = num_tracks + num_return_tracks + num_master_track # update selected-track index = index_if(lambda t: t == self.song().view.selected_track, all_tracks) index += move index = min(max(index, 0), num_all_tracks - 1) self.song().view.selected_track = all_tracks[index] def setup_session(self): num_tracks = 7 num_scenes = 1 track_offset = 0 scene_offset = 0 # elements self.clip_launch_buttons = ButtonMatrixElement(rows=[[ ButtonElement(True, MIDI_NOTE_TYPE, 0, 76 + i) for i in range(num_tracks) ]]) self.clip_stop_buttons = [ ButtonElement(True, MIDI_NOTE_TYPE, 0, 68 + i) for i in range(num_tracks) ] self.scene_launch_buttons = ButtonMatrixElement(rows=[[ ButtonElement(True, MIDI_NOTE_TYPE, 0, 83 + i) for i in range(num_scenes) ]]) self.scene_stop_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 75) self.session_scene_nav_encoder = EncoderElement( MIDI_CC_TYPE, 0, 15, Live.MidiMap.MapMode.relative_binary_offset) # session self.session = SessionComponent(num_tracks, num_scenes) self.session.set_offsets(track_offset, scene_offset) self.session.add_offset_listener(self.on_session_offset_changed) self.set_highlighting_session_component(self.session) # clips self.session.set_clip_launch_buttons(self.clip_launch_buttons) self.session.set_stop_track_clip_buttons(self.clip_stop_buttons) self.session.set_scene_launch_buttons(self.scene_launch_buttons) self.session.set_stop_all_clips_button(self.scene_stop_button) # nav self.session_scene_nav_encoder.add_value_listener( self.on_session_scene_nav) def on_session_offset_changed(self): pass def on_session_scene_nav(self, value): value -= 64 value = -value track_offset = self.session.track_offset() scene_offset = max(0, self.session.scene_offset() + value) self.session.set_offsets(track_offset, scene_offset) def disconnect(self): u"""Live -> Script Called right before we get disconnected from Live. """ self.log_message('disconnect') self.show_message('disconnect')
class MPK_mini_hero(ControlSurface): """ Script for Novation's Launchkey 25/49/61 keyboards """ def __init__(self, c_instance, identity_response = SIZE_RESPONSE): ControlSurface.__init__(self, c_instance) self._identity_response = identity_response with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) self._device_selection_follows_track_selection = True self._suggested_input_port = 'MPK mini' self._suggested_output_port = 'MPK mini' self._setup_buttons() self._setup_components() for component in self.components: component.set_enabled(True) # Puvodne False def refresh_state(self): ControlSurface.refresh_state(self) # for val in range(127): # self.schedule_message(2, self._send_midi, (144, val, 0)) # self.schedule_message(3, self._send_midi, (144, 9, 127)) def handle_sysex(self, midi_bytes): self._send_midi(LED_FLASHING_ON) self._update_mixer_offset() for control in self.controls: if isinstance(control, InputControlElement): control.clear_send_cache() for component in self.components: component.set_enabled(True) self.request_rebuild_midi_map() def disconnect(self): ControlSurface.disconnect(self) self._encoders = None self._transport_view_modes = None self._send_midi(LED_FLASHING_OFF) self._send_midi(LIVE_MODE_OFF) def _setup_buttons(self): # Pads CC Mode self._scene_launch_button = make_pad_button(PAD_MODE_CC, 1, 'Scene_Launch_Button') self._overdub_button = make_pad_button(PAD_MODE_CC, 2, 'Session_Overdub_Button') self._ffwd_button = make_pad_button(PAD_MODE_CC, 3, 'FFwd_Button') self._clip_undo_button = make_pad_button(PAD_MODE_CC, 4, 'Clip_Undo_Button') self._prev_track_button = make_pad_button(PAD_MODE_CC, 5, 'Prev_Track_Button') self._next_track_button = make_pad_button(PAD_MODE_CC, 6, 'Next_Track_Button') self._rwd_button = make_pad_button(PAD_MODE_CC, 7, 'Rwd_Button') self._scene_stop_button = make_pad_button(PAD_MODE_CC, 9, 'Scene_Stop_Button') self._stop_button = make_pad_button(PAD_MODE_CC, 10, 'Stop_Button') self._play_button = make_pad_button(PAD_MODE_CC, 11, 'Play_Button') self._loop_button = make_pad_button(PAD_MODE_CC, 12, 'Loop_Button') self._rec_button = make_pad_button(PAD_MODE_CC, 13, 'Record_Button') # Pads Notes Mode self._clip_launch_buttons = [ make_pad_button(PAD_MODE_NOTES, index, 'Clip_Launch_%d' % index) for index in xrange(8) ] self._clip_stop_buttons = [ make_pad_button(PAD_MODE_NOTES, 8 + index, 'Clip_Stop_%d' % index) for index in xrange(8) ] # Encoders self._encoders = tuple([ make_encoder(21 + index, 'Device_Control_%d' % index) for index in xrange(8) ]) # Scenes self._scene_launch_buttons = [] for key_no in [0,2,4,5,7,9,11, 12,14,16,17,19,21,23, 24]: self._scene_launch_buttons.append(make_scene_button(key_no, 'Scene_Launch_%d' % key_no)) def _setup_components(self): # Session self._session = SessionComponent(8, len(self._scene_launch_buttons)) self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button(self._scene_launch_button) self._session.set_stop_all_clips_button(self._scene_stop_button) for index in range(8): clip_slot = self._session.selected_scene().clip_slot(index) clip_slot.set_launch_button(self._clip_launch_buttons[index]) clip_slot.name = 'Selected_Clip_Slot_' + str(index) self._session.set_stop_track_clip_buttons(tuple(self._clip_stop_buttons)) # Undo self._do_undo.subject = self._clip_undo_button; # Transport transport = TransportComponent() transport.name = 'Transport' transport.set_stop_button(self._stop_button) transport.set_play_button(self._play_button) transport.set_record_button(self._rec_button) transport.set_loop_button(self._loop_button) self._transport_view_modes = TransportViewModeSelector(transport, self._session, self._ffwd_button, self._rwd_button) self._transport_view_modes.name = 'Transport_View_Modes' session_recording = SessionRecordingComponent(ClipCreator(), ViewControlComponent(), name='Session_Recording', is_enabled=False, layer=Layer(record_button=self._overdub_button)) # Device # device = DeviceComponent() # device.name = 'Device_Component' # self.set_device_component(device) # device.set_parameter_controls(self._encoders) # Navigation self._session_navigation = SessionNavigationComponent(name='Session_Navigation') self._session_navigation.set_next_track_button(self._next_track_button) self._session_navigation.set_prev_track_button(self._prev_track_button) # Playing # self._session.set_scene_launch_buttons(tuple(self._scene_launch_buttons)) for index in range(len(self._scene_launch_buttons)): scene = self._session.scene(index) scene.set_launch_button(self._scene_launch_buttons[index]) @subject_slot('value') def _do_undo(self, value): if value: if self.song().can_undo == 1: self.song().undo() self.show_message(str('UNDO')) def _dummy_listener(self, value): pass def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) self._update_mixer_offset() def _update_mixer_offset(self): all_tracks = self._session.tracks_to_use() selected_track = self.song().view.selected_track num_strips = self._session.width() if selected_track in all_tracks: track_index = list(all_tracks).index(selected_track) new_offset = track_index - track_index % num_strips self._session.set_offsets(new_offset, self._session.scene_offset())
class DC1(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) is_momentary = True self._timer = 0 #used for flashing states, and is incremented by each call from self._update_display() self._touched = 0 self.flash_status = 1 # Used in FlashingButtonElement (kludge for our purposes) self._device_selection_follows_track_selection = True with self.component_guard(): self._setup_transport_control() if USE_MIXER_CONTROLS == True: self.mixer_control() if USE_SESSION_VIEW == True: self.session_control() self.setup_device_control() def _setup_transport_control(self): is_momentary = True # We'll only be using momentary buttons here self.transport = TransportComponent() #Instantiate a Transport Component """set up the buttons""" self.transport.set_play_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 60)) #ButtonElement(is_momentary, msg_type, channel, identifier) Note that the MIDI_NOTE_TYPE constant is defined in the InputControlElement module self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 61)) self.transport.set_record_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 62)) def mixer_control(self): is_momentary = True self.num_tracks = N_TRACKS if(USE_SENDS == True): self.mixer = MixerComponent(N_TRACKS, N_SENDS_PER_TRACK, USE_MIXER_EQ, USE_MIXER_FILTERS) else: self.mixer = MixerComponent(N_TRACKS,0, USE_MIXER_EQ, USE_MIXER_FILTERS) self.mixer.name = 'Mixer' self.mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(N_TRACKS): self.mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) self.mixer.channel_strip(index)._invert_mute_feedback = True if(USE_SELECT_BUTTONS == True): self.selectbuttons = [None for index in range(N_TRACKS)] for index in range(len(SELECT_BUTTONS)): self.selectbuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,SELECT_BUTTONS[index], 'Select_Button', self) self.mixer.channel_strip(index).set_select_button(self.selectbuttons[index]) self.selectbuttons[index].set_on_value(SELECT_BUTTON_ON_COLOR) self.selectbuttons[index].set_off_value(SELECT_BUTTON_OFF_COLOR) if(USE_SOLO_BUTTONS == True): self.solobuttons = [None for index in range(N_TRACKS)] for index in range(len(SOLO_BUTTONS)): self.solobuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,SOLO_BUTTONS[index], 'Solo_Button', self) self.mixer.channel_strip(index).set_solo_button(self.solobuttons[index]) self.solobuttons[index].set_on_value(SOLO_BUTTON_ON_COLOR) self.solobuttons[index].set_off_value(SOLO_BUTTON_OFF_COLOR) if(USE_ARM_BUTTONS == True): self.armbuttons = [None for index in range(N_TRACKS)] for index in range(len(ARM_BUTTONS)): self.armbuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,ARM_BUTTONS[index], 'Arm_Button', self) self.mixer.channel_strip(index).set_arm_button(self.armbuttons[index]) self.armbuttons[index].set_on_value(ARM_BUTTON_ON_COLOR) self.armbuttons[index].set_off_value(ARM_BUTTON_OFF_COLOR) if(USE_MUTE_BUTTONS == True): self.mutebuttons = [None for index in range(N_TRACKS)] for index in range(len(MUTE_BUTTONS)): self.mutebuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,MUTE_BUTTONS[index], 'Mute_Button', self) self.mixer.channel_strip(index).set_mute_button(self.mutebuttons[index]) self.mutebuttons[index].set_on_value(MUTE_BUTTON_ON_COLOR) self.mutebuttons[index].set_off_value(MUTE_BUTTON_OFF_COLOR) if(USE_SENDS == True): self.sendencoders = [None for index in range(len(SEND_ENCODERS))] for index in range(len(SEND_ENCODERS)): self.sendencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, SEND_ENCODERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(SEND_ENCODERS)/N_SENDS_PER_TRACK): self.mixer.channel_strip(index).set_send_controls(tuple(self.sendencoders[(index*N_SENDS_PER_TRACK):((index*N_SENDS_PER_TRACK)+N_SENDS_PER_TRACK-1)])) if(USE_VOLUME_CONTROLS == True): self.volencoders = [None for index in range(len(VOLUME_ENCODERS))] for index in range (len(VOLUME_ENCODERS)): self.volencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, VOLUME_ENCODERS[index], Live.MidiMap.MapMode.absolute) self.mixer.channel_strip(index).set_volume_control(self.volencoders[index]) def session_control(self): is_momentary = True self._timer = 0 self.flash_status = 1 self.grid = [None for index in range(N_TRACKS*N_SCENES)] for index in range(N_TRACKS*N_SCENES): self.grid[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,TRACK_CLIP_BUTTONS[index], 'Grid' + str(index), self) self.grid[index].set_off_value(0) self.grid[index].turn_off() self.matrix = ButtonMatrixElement() for row in range(N_SCENES): button_row = [] for column in range(N_TRACKS): button_row.append(self.grid[row+(column*N_SCENES)]) self.matrix.add_row(tuple(button_row)) self.session = SessionComponent(N_TRACKS,N_SCENES) self.session.name = "Session" self.session.set_offsets(0,0) self.scene = [None for index in range(N_SCENES)] for row in range(N_SCENES): self.scene[row] = self.session.scene(row) self.scene[row].name = 'Scene_'+str(row) for column in range(N_TRACKS): clip_slot = self.scene[row].clip_slot(column) clip_slot.name = str(column)+'_Clip_Slot'+str(row) self.scene[row].clip_slot(column).set_triggered_to_play_value(CLIP_TRG_PLAY_COLOR) self.scene[row].clip_slot(column).set_stopped_value(CLIP_STOP_COLOR) self.scene[row].clip_slot(column).set_started_value(CLIP_STARTED_COLOR) self.set_highlighting_session_component(self.session) self.session_zoom = DeprecatedSessionZoomingComponent(self.session) #this creates the ZoomingComponent that allows navigation when the shift button is pressed self.session_zoom.name = 'Session_Overview' #name it so we can access it in m4l self.session_zoom.set_stopped_value(ZOOM_STOPPED) #set the zooms stopped color self.session_zoom.set_playing_value(ZOOM_PLAYING) #set the zooms playing color self.session_zoom.set_selected_value(ZOOM_SELECTED) #set the zooms selected color self.session_zoom.set_button_matrix(self.matrix) #assign the ButtonMatrixElement that we created in _setup_controls() to the zooming component so that we can control it self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 63) self.session_zoom.set_zoom_button(self._shift_button) #assign a shift button so that we can switch states between the SessionComponent and the SessionZoomingComponent self.looper = LooperComponent(self) self.log_message(str(len(STOP_BUTTONS))) if(USE_STOP_BUTTONS == True): self.stopbuttons = [None for index in range(N_TRACKS)] for index in range(len(STOP_BUTTONS)): self.stopbuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,STOP_BUTTONS[index], 'Stop_Button', self) self.session.set_stop_track_clip_buttons(self.stopbuttons) self.stopbuttons[index].set_on_value(STOP_BUTTON_ON_COLOR) self.stopbuttons[index].set_off_value(STOP_BUTTON_OFF_COLOR) self.scrollencoder = ScrollEncoderElement(MIDI_CC_TYPE, CHANNEL, 32, Live.MidiMap.MapMode.absolute, self.session, self.transport, self.mixer, self.looper) self.scrollencoder.set_nav_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 0)) self.scrollencoder.set_transport_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 7)) self.scrollencoder.set_scene_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 3)) self.scrollencoder.set_library_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 4)) self.scrollencoder.set_button1(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 1)) self.scrollencoder.set_button2(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 2)) self.scrollencoder.set_button3(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 5)) self.scrollencoder.set_button4(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 6)) self.scrollencoder.set_encoder_button(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 32)) for column in range(N_TRACKS): for row in range(N_SCENES): self.scene[row].clip_slot(column).set_launch_button(self.grid[row+(column*N_SCENES)]) for index in range(N_TRACKS*N_SCENES): self.grid[index].clear_send_cache() if USE_MIXER_CONTROLS == True: self.session.set_mixer(self.mixer) self.refresh_state() self.session.set_enabled(True) self.session.update() def setup_device_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') for index in range(4): device_bank_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 16 + index)) device_bank_buttons[-1].name = bank_button_labels[index] for index in range(8): #ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, 21 + index) ringed_encoder = CMDEncoderElement(MIDI_CC_TYPE, CHANNEL, 16 + index, Live.MidiMap.MapMode.relative_binary_offset, 20) #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) detail_view_toggler = DetailViewControllerComponent(self) 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_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3]) def update_display(self): ControlSurface.update_display(self) self._timer = (self._timer + 1) % 256 def disconnect(self): self._hosts = [] ControlSurface.disconnect(self) return None
class MPK_SessionControl(ControlSurface): __module__ = __name__ __doc__ = "MPK Session Control Script" def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._setup_mixer_control() self._setup_transport_control() self._setup_session_control() self._setup_channel_strip_control() self.set_highlighting_session_component(self.session) # Sets up the control surface ('colored box') def _setup_session_control(self): num_tracks = 3 # 3 columns (tracks) num_scenes = 1 # 1 row (scenes) # a session highlight ("red box") will appear with any two non-zero values self.session = SessionComponent(num_tracks, num_scenes) # (track_offset, scene_offset) Sets the initial offset of the "red box" from top left self.session.set_offsets(0, 0) self.session.set_select_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_HIGH_C - 7), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_HIGH_C - 6)) # These calls control the actual movement of the box; however, we're just # using scene and track select to move around # self.session.set_scene_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 86), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 85)) # self.session.set_track_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 15), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 14)) # Launch current scene with top right pad self.session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, BANK_B[3])) # Stop all clips with bottom right pad self.session.set_stop_all_clips_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, BANK_B[7])) # First three pads launch clips in box clip_launch_notes = [BANK_B[0], BANK_B[1], BANK_B[2]] clip_select_notes = [ KEYBOARD_MID_C - 6, KEYBOARD_MID_C - 4, KEYBOARD_MID_C - 2 ] for tracks in range(num_tracks): self.session.scene(0).clip_slot(tracks).set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, clip_launch_notes[tracks])) self.session.scene(0).clip_slot(tracks).set_select_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, clip_select_notes[tracks])) self.session.scene(0).clip_slot(tracks).set_started_value(1) self.session.scene(0).clip_slot(tracks).set_stopped_value(0) # Bottom three pads stop current tracks in box track_stop_notes = [BANK_B[4], BANK_B[5], BANK_B[6]] # This looks unnecessary but I don't know the actual API call to to set the stop track button for the selected track stop_track_buttons = [] for tracks in range(num_tracks): stop_track_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, track_stop_notes[tracks])) self.session.set_stop_track_clip_buttons(tuple(stop_track_buttons)) #here we set up a mixer and channel strip(s) which move with the session self.session.set_mixer( self.mixer ) #bind the mixer to the session so that they move together selected_scene = self.song( ).view.selected_scene #this is from the Live API all_scenes = self.song().scenes index = list(all_scenes).index(selected_scene) self.session.set_offsets(0, index) #(track_offset, scene_offset) def _setup_transport_control(self): self.transport = TransportComponent() self.transport.set_stop_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_LOW_C)) self.transport.set_play_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 113)) self.transport.set_metronome_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 114)) self.transport.set_tap_tempo_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 81)) def _setup_mixer_control(self): #set up the mixer self.mixer = MixerComponent( NUM_TRACKS, 2) #(num_tracks, num_returns, with_eqs, with_filters) self.mixer.set_track_offset( 0) #sets start point for mixer strip (offset from left) self.mixer.selected_strip().set_arm_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_HIGH_C)) self.mixer.set_select_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_HIGH_C - 2), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_HIGH_C - 4)) self.mixer.master_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[3])) #self.mixer.master_strip().set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[7])) #set the selected strip to the first track, so that we don't assign a button to arm the master track, which would cause an assertion error self.song().view.selected_track = self.mixer.channel_strip(0)._track self.mixer.selected_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[0])) #self.mixer.selected_strip().set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[4])) selected_track = self.song().view.selected_track all_tracks = ((self.song().tracks + self.song().return_tracks) + (self.song().master_track, )) currentTrackIndex = list(all_tracks).index(selected_track) if currentTrackIndex < len(all_tracks) - 1: self.mixer.channel_strip(currentTrackIndex + 1).set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[1])) #self.mixer.channel_strip(currentTrackIndex + 1).set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[5])) if currentTrackIndex < len(all_tracks) - 2: self.mixer.channel_strip(currentTrackIndex + 2).set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[2])) #self.mixer.channel_strip(currentTrackIndex + 2).set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[6])) def _setup_channel_strip_control(self): self.channelstrip = ChannelStripComponent() self.channelstrip.set_track(self.mixer.channel_strip(0)._track) def _on_selected_track_changed(self): """This is an override, to add special functionality (we want to move the session to the selected track, when it changes) Note that it is sometimes necessary to reload Live (not just the script) when making changes to this function""" ControlSurface._on_selected_track_changed( self ) # This will run component.on_selected_track_changed() for all components """here we set the mixer and session to the selected track, when the selected track changes""" selected_track = self.song( ).view.selected_track #this is how to get the currently selected track, using the Live API self.mixer.channel_strip(0).set_track(selected_track) all_tracks = ( (self.song().tracks + self.song().return_tracks) + (self.song().master_track, ) ) #this is from the MixerComponent's _next_track_value method index = list(all_tracks).index(selected_track) #and so is this self.session.set_offsets( index, self.session._scene_offset ) #(track_offset, scene_offset); we leave scene_offset unchanged, but set track_offset to the selected track. This allows us to jump the red box to the selected track. def _on_selected_scene_changed(self): """This is an override, to add special functionality (we want to move the session to the selected scene, when it changes)""" """When making changes to this function on the fly, it is sometimes necessary to reload Live (not just the script)...""" ControlSurface._on_selected_scene_changed( self ) # This will run component.on_selected_scene_changed() for all components """Here we set the mixer and session to the selected track, when the selected track changes""" selected_scene = self.song( ).view.selected_scene #this is how we get the currently selected scene, using the Live API all_scenes = self.song().scenes #then get all of the scenes index = list(all_scenes).index( selected_scene ) #then identify where the selected scene sits in relation to the full list self.session.set_offsets( self.session._track_offset, index ) #(track_offset, scene_offset) Set the session's scene offset to match the selected track (but make no change to the track offset) def disconnect(self): #clean things up on disconnect #create entry in log file self.log_message( time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "----------MPK SessionControl log closed----------") ControlSurface.disconnect(self) return None
def _setup_session_control(self): is_momentary = True self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87) right_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 107) #78 left_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 106) #77 right_button.name = 'Bank_Select_Right_Button' left_button.name = 'Bank_Select_Left_Button' global session session = SessionComponent(8, 40) session.name = 'Session_Control' session.set_track_bank_buttons(right_button, left_button) matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' scene_launch_notes = [56, 57, 58, 59, 60, 61, 62, 63] scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, scene_launch_notes[index]) for index in range(8) ] track_stop_buttons = [ ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, (index + 28)) for index in range(8) ] for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_' + str( index) + '_Launch_Button' for index in range(len(track_stop_buttons)): track_stop_buttons[index].name = 'Track_' + str( index) + '_Stop_Button' session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) for scene_index in range(8): scene = 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(7): button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, (track_index * 8) + scene_index) button.name = str(track_index) + '_Clip_' + str( scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.set_stopped_value(0) clip_slot.set_started_value(64) 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)) session.selected_scene().name = 'Selected_Scene' #session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) #session_zoom = SessionZoomingComponent(session) #session_zoom.name = 'Session_Overview' #session_zoom.set_button_matrix(matrix) #session_zoom.set_zoom_button(self._shift_button) #session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button) #session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) #session_zoom.set_stopped_value(0) #session_zoom.set_selected_value(127) session.set_mixer(mixer) return None #return session
class Novation_Impulse2(ControlSurface): """ Script for Novation's Impulse keyboards """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self.c_instance = 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 self._shift_pressed = False self._shift_button.add_value_listener(self._shift_value) for component in self.components: component.set_enabled(False) def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(3, self._send_midi, SYSEX_START + (6, 1, 1, 1, 247)) def handle_sysex(self, midi_bytes): if midi_bytes[0:-2] == SYSEX_START + (7, ) and midi_bytes[-2] != 0: self._has_sliders = midi_bytes[-2] != 25 self.schedule_message(1, self._show_startup_message) for control in self.controls: if isinstance(control, InputControlElement): control.clear_send_cache() for component in self.components: component.set_enabled(True) if self._has_sliders: self._mixer.master_strip().set_volume_control( self._master_slider) self._mixer.update() else: self._mixer.master_strip().set_volume_control(None) self._mixer.selected_strip().set_volume_control( self._master_slider) for index in range(len(self._sliders)): self._mixer.channel_strip(index).set_volume_control(None) slider = self._sliders[index] slider.release_parameter() if slider.value_has_listener(self._slider_value): slider.remove_value_listener(self._slider_value) self._encoder_modes.set_provide_volume_mode(not self._has_sliders) self.request_rebuild_midi_map() def disconnect(self): self.log('starting disconnect 1') self._name_display_data_source.set_display_string(' ') for encoder in self._encoders: encoder.remove_value_listener(self._encoder_value) self._master_slider.remove_value_listener(self._slider_value) if self._has_sliders: for slider in tuple(self._sliders): slider.remove_value_listener(self._slider_value) for button in self._strip_buttons: button.remove_value_listener(self._mixer_button_value) self._preview_button.remove_value_listener(self._preview_value) self.log('starting disconnect 3') ControlSurface.disconnect(self) self.log('starting disconnect 3') self._encoders = None self._sliders = None self._strip_buttons = None self._master_slider = None self._current_midi_map = None self._name_display = None self._prev_bank_button = None self._next_bank_button = None self._encoder_modes = None self._transport_view_modes = None self.log('starting disconnect 4') self._send_midi(SYSEX_START + (6, 0, 0, 0, 247)) self.log('starting disconnect 5') if self._shift_button != None: self._shift_button.remove_value_listener(self._shift_value) self._shift_button = None self.log('starting disconnect 6') def build_midi_map(self, midi_map_handle): self._current_midi_map = midi_map_handle ControlSurface.build_midi_map(self, midi_map_handle) def update_display(self): ControlSurface.update_display(self) if self._string_to_display != None: self._name_display_data_source.set_display_string( self._string_to_display) self._string_to_display = None if self._display_reset_delay >= 0: self._display_reset_delay -= 1 if self._display_reset_delay == -1: self._show_current_track_name() 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.c_instance) 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) #self._mixer.set_shift_button(self._shift_button) self._mixer.updateMixerButtons() self._button9 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + 8) def _setup_session(self): num_pads = len(PAD_TRANSLATIONS) self._session = SessionComponent(8, 0) self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.set_mixer(self._mixer) # for ableton 9.1.1 and lower #self._session.set_track_banking_increment(num_pads) #self._session.set_track_bank_buttons(ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 35), ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 36)) # for ableton 9.1.1 and higher self._track_left_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 36) self._track_right_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 35) self._session.set_page_left_button(self._track_left_button) self._session.set_page_right_button(self._track_right_button) pads = [] for index in range(num_pads): pads.append( ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 60 + index)) pads[-1].name = 'Pad_' + str(index) clip_slot = self._session.selected_scene().clip_slot(index) clip_slot.set_triggered_to_play_value(GREEN_BLINK) clip_slot.set_triggered_to_record_value(RED_BLINK) clip_slot.set_stopped_value(AMBER_FULL) clip_slot.set_started_value(GREEN_FULL) clip_slot.set_recording_value(RED_FULL) clip_slot.set_launch_button(pads[-1]) clip_slot.name = str(index) + '_Selected_Clip_Slot' def _setup_transport(self): rwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 27) ffwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 28) stop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 29) play_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 30) loop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 31) rec_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 32) ffwd_button.name = 'FFwd_Button' rwd_button.name = 'Rwd_Button' loop_button.name = 'Loop_Button' play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' rec_button.name = 'Record_Button' self._transport = ShiftableTransportComponent(self.c_instance, self._session, self, ffwd_button, rwd_button) self._transport.name = 'Transport' self._transport.set_stop_buttonOnInit(stop_button) self._transport.set_play_button(play_button) self._transport.set_record_buttonOnInit(rec_button) # self._transport.set_shift_button(self._shift_button) self._transport.set_mixer9_button(self._button9) self._transport_view_modes = TransportViewModeSelector( self.c_instance, self._transport, self._session, ffwd_button, rwd_button, loop_button) self._transport_view_modes.name = 'Transport_View_Modes' def _setup_device(self): encoders = [] for index in range(8): encoders.append( PeekableEncoderElement( MIDI_CC_TYPE, 1, index, Live.MidiMap.MapMode.relative_binary_offset)) encoders[-1].set_feedback_delay(-1) encoders[-1].add_value_listener(self._encoder_value, identify_sender=True) encoders[-1].name = 'Device_Control_' + str(index) self._encoders = tuple(encoders) self._prev_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 12) self._next_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 11) self._prev_bank_button.name = 'Device_Bank_Down_Button' self._next_bank_button.name = 'Device_Bank_Up_Button' device = DeviceComponent() device.name = 'Device_Component' self.set_device_component(device) device.set_parameter_controls(self._encoders) device.set_bank_nav_buttons(self._prev_bank_button, self._next_bank_button) def _setup_name_display(self): self._name_display = PhysicalDisplayElement(16, 1) self._name_display.name = 'Display' self._name_display.set_message_parts(SYSEX_START + (8, ), (247, )) self._name_display_data_source = DisplayDataSource() self._name_display.segment(0).set_data_source( self._name_display_data_source) def _encoder_value(self, value, sender): if not sender in self._encoders: raise AssertionError if not value in range(128): raise AssertionError # display_string = self._device_component.is_enabled() and ' - ' # display_string = sender.mapped_parameter() != None and sender.mapped_parameter().name display_string = '' if self._device_component.is_enabled(): # display_string = sender.name # track = self.song().view.selected_track # display_string = str(list(tracks).index(track) + 1) pass if (sender.mapped_parameter() != None): # display_string = display_string + '-' display_string = display_string + sender.mapped_parameter().name self._set_string_to_display(display_string) def _slider_value(self, value, sender): self.log('_slider_value ' + str(value) + ' ' + str(sender)) if not sender in tuple(self._sliders) + (self._master_slider, ): raise AssertionError if not value in range(128): raise AssertionError if self._mixer.is_enabled(): display_string = ' - ' master = self.song().master_track tracks = self.song().tracks returns = self.song().return_tracks track = None if sender.mapped_parameter() != None: self.log('1') if sender == self._master_slider: self.log('2') # track = self._has_sliders and master if self._has_sliders: track = master else: self.log('2.1') track = self.song().view.selected_track else: self.log('3') track = self._mixer.channel_strip( self._sliders.index(sender))._track else: self.log('4') track = self.song().view.selected_track self.log('track=' + str(track)) if track == master: display_string = 'Master' elif track in tracks: display_string = str(list(tracks).index(track) + 1) elif track in returns: display_string = str( chr(ord('A') + list(returns).index(track))) else: # raise False or AssertionError raise AssertionError display_string += ' Volume' self._set_string_to_display(display_string) def _mixer_button_value(self, value, sender): if not value in range(128): raise AssertionError #if self._mixer.is_enabled() and value > 0: if self._mixer.is_enabled(): strip = self._mixer.channel_strip( self._strip_buttons.index(sender)) #self._string_to_display = strip != None and None self._name_display.segment(0).set_data_source( strip.track_name_data_source()) self._name_display.update() self._display_reset_delay = STANDARD_DISPLAY_DELAY else: self._set_string_to_display(' - ') def _preview_value(self, value): if not value in range(128): raise AssertionError for encoder in self._encoders: encoder.set_peek_mode(value > 0) def _show_current_track_name(self): if self._name_display != None and self._mixer != None: self._string_to_display = None self._name_display.segment(0).set_data_source( self._mixer.selected_strip().track_name_data_source()) self._name_display.update() def _show_startup_message(self): self._name_display.display_message('LIVE') self._display_reset_delay = INITIAL_DISPLAY_DELAY def _set_string_to_display(self, string_to_display): if not isinstance(string_to_display, (str, unicode)): raise AssertionError self._name_display.segment(0).set_data_source( self._name_display_data_source) self._string_to_display = string_to_display self._display_reset_delay = STANDARD_DISPLAY_DELAY def _on_selected_track_changed(self): self.log('_on_selected_track_changed') ControlSurface._on_selected_track_changed(self) self._show_current_track_name() #all_tracks = self._has_sliders or self._session.tracks_to_use() all_tracks2 = self._session.tracks_to_use() selected_track = self.song().view.selected_track num_strips = self._session.width() if selected_track in all_tracks2: track_index = list(all_tracks2).index(selected_track) self.log('track_index ' + str(track_index)) new_offset = track_index - track_index % num_strips self.log('new_offset ' + str(new_offset)) if not new_offset / num_strips == int(new_offset / num_strips): raise AssertionError self._session.set_offsets(new_offset, self._session.scene_offset()) def _shift_value(self, value): self.log("root shift handler") if not self._shift_button != None: raise AssertionError if not value in range(128): raise AssertionError self.log("root shift handler 2") self._shift_pressed = value > 0 # calling other handlers self._mixer._shift_value(value) self._transport._shift_value(value) self._transport_view_modes._shift_value(value) #clip stop self.log("root shift handler 3") num_pads = len(PAD_TRANSLATIONS) pads = [] for index in range(num_pads): pads.append( ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 60 + index)) pads[-1].name = 'Pad_' + str(index) clip_slot = self._session.selected_scene().clip_slot(index) if self._shift_pressed: clip_slot.set_launch_button(None) else: clip_slot.set_launch_button(pads[index]) if self._shift_pressed: self._session.set_stop_track_clip_buttons(tuple(pads)) else: self._session.set_stop_track_clip_buttons(None) self.log("root shift handler 4") def log(self, message): 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)
class XoneK2(ControlSurface): def __init__(self, instance): global g_logger g_logger = self.log_message super(XoneK2, self).__init__(instance, False) with self.component_guard(): self._set_suppress_rebuild_requests(True) self.init_session() self.init_mixer() self.init_matrix() self.init_tempo() # connect mixer to session self.session.set_mixer(self.mixer) self.session.update() self.set_highlighting_session_component(self.session) self._set_suppress_rebuild_requests(False) def init_session(self): self.session = SessionComponent(NUM_TRACKS, NUM_SCENES) self.session.name = 'Session' self.session.set_scene_bank_buttons(button(BUTTON_LL), button(BUTTON_LR)) self.session.update() def init_mixer(self): self.mixer = MixerWithDevices(num_tracks=NUM_TRACKS, device_select=[ button(PUSH_ENCODERS[i]) for i in range(NUM_TRACKS) ], device_encoders=ENCODERS) self.mixer.id = 'Mixer' self.song().view.selected_track = self.mixer.channel_strip(0)._track for i in range(NUM_TRACKS): self.mixer.channel_strip(i).set_volume_control(fader(FADERS[i])) self.mixer.channel_strip(i).set_solo_button(button(BUTTONS3[i])) self.mixer.set_eq_controls( i, (knob(KNOBS3[i]), knob(KNOBS2[i]), knob(KNOBS1[i]))) self.mixer.set_device_controls(i, button(BUTTONS1[i])) self.master_encoder = DynamicEncoder( ENCODER_LR, self.song().master_track.mixer_device.volume) self.cue_encoder = DynamicEncoder( ENCODER_LL, self.song().master_track.mixer_device.cue_volume) self.mixer.update() def init_matrix(self): self.matrix = ButtonMatrixElement() for scene_index in range(NUM_SCENES): scene = self.session.scene(scene_index) scene.name = 'Scene ' + str(scene_index) button_row = [] for track_index in range(NUM_TRACKS): note_nr = GRID[scene_index][track_index] b = button(note_nr, name='Clip %d, %d button' % (scene_index, track_index)) button_row.append(b) clip_slot = scene.clip_slot(track_index) clip_slot.name = 'Clip slot %d, %d' % (scene_index, track_index) clip_slot.set_stopped_value(0) clip_slot.set_started_value(64) clip_slot.set_launch_button(b) self.matrix.add_row(tuple(button_row)) stop_buttons = [button(note_nr) for note_nr in BUTTONS2] self.session.set_stop_track_clip_buttons(stop_buttons) def init_tempo(self): self.transport = CustomTransportComponent() self.transport.set_tempo_bumpers(button(PUSH_ENCODER_LR), button(PUSH_ENCODER_LL))
class Launchkey(ControlSurface): """ Script for Novation's Launchkey 25/49/61 keyboards """ def __init__(self, c_instance, control_factory=LaunchkeyControlFactory(), identity_response=SIZE_RESPONSE): ControlSurface.__init__(self, c_instance) self._control_factory = control_factory self._identity_response = identity_response with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) 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() self._setup_navigation() for component in self.components: component.set_enabled(False) return def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(2, self._send_midi, LIVE_MODE_ON) self.schedule_message(3, self._send_midi, SIZE_QUERY) def handle_sysex(self, midi_bytes): if midi_bytes[0:11] == self._identity_response: self._has_sliders = midi_bytes[11] != 48 self._send_midi(LED_FLASHING_ON) self._update_mixer_offset() for control in self.controls: if isinstance(control, InputControlElement): control.clear_send_cache() for component in self.components: component.set_enabled(True) if self._has_sliders: self._mixer.master_strip().set_volume_control( self._master_slider) self._mixer.update() else: self._mixer.master_strip().set_volume_control(None) for index in range(len(self._sliders)): self._mixer.channel_strip(index).set_volume_control(None) self._mixer.channel_strip(index).set_mute_button(None) slider = self._sliders[index] slider.release_parameter() self._mixer.selected_strip().set_volume_control( self._master_slider) self.request_rebuild_midi_map() return def disconnect(self): ControlSurface.disconnect(self) for button in self._modes_buttons: if button.value_has_listener(self._dummy_listener): button.remove_value_listener(self._dummy_listener) self._modes_buttons = None self._encoders = None self._sliders = None self._strip_buttons = None self._master_slider = None self._current_midi_map = None self._transport_view_modes = None self._send_midi(LED_FLASHING_OFF) self._send_midi(LIVE_MODE_OFF) return def build_midi_map(self, midi_map_handle): self._current_midi_map = midi_map_handle ControlSurface.build_midi_map(self, midi_map_handle) def _setup_mixer(self): mute_solo_flip_button = make_button(59, 'Master_Button') self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' 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 = [] self._strip_buttons = [] 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( make_slider(41 + index, 'Volume_Control_%d' % index)) strip.set_volume_control(self._sliders[-1]) self._strip_buttons.append( make_button(51 + index, 'Mute_Button_%d' % index)) self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button) def _setup_session(self): scene_launch_button = self._control_factory.create_scene_launch_button( ) scene_stop_button = self._control_factory.create_scene_stop_button() self._session = SessionComponent(8, 0) self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button(scene_launch_button) self._session.selected_scene().set_triggered_value(GREEN_BLINK) self._session.set_stop_all_clips_button(scene_stop_button) scene_stop_button.set_on_off_values(AMBER_FULL, LED_OFF) self._session.set_mixer(self._mixer) self._session.set_stop_clip_value(AMBER_HALF) self._session.set_stop_clip_triggered_value(GREEN_BLINK) clip_launch_buttons = [] clip_stop_buttons = [] for index in range(8): clip_launch_buttons.append( self._control_factory.create_clip_launch_button(index)) clip_stop_buttons.append( self._control_factory.create_clip_stop_button(index)) clip_slot = self._session.selected_scene().clip_slot(index) clip_slot.set_triggered_to_play_value(GREEN_BLINK) clip_slot.set_triggered_to_record_value(RED_BLINK) clip_slot.set_stopped_value(AMBER_FULL) clip_slot.set_started_value(GREEN_FULL) clip_slot.set_recording_value(RED_FULL) clip_slot.set_launch_button(clip_launch_buttons[-1]) clip_slot.name = 'Selected_Clip_Slot_' + str(index) self._session.set_stop_track_clip_buttons(tuple(clip_stop_buttons)) def _setup_transport(self): rwd_button = make_button(112, 'Rwd_Button') ffwd_button = make_button(113, 'FFwd_Button') stop_button = make_button(114, 'Stop_Button') play_button = make_button(115, 'Play_Button') loop_button = make_button(116, 'Loop_Button') rec_button = make_button(117, 'Record_Button') transport = TransportComponent() transport.name = 'Transport' transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_record_button(rec_button) transport.set_loop_button(loop_button) self._transport_view_modes = TransportViewModeSelector( transport, self._session, ffwd_button, rwd_button) self._transport_view_modes.name = 'Transport_View_Modes' def _setup_device(self): encoders = [ make_encoder(21 + index, 'Device_Control_%d' % index) for index in xrange(8) ] self._encoders = tuple(encoders) device = DeviceComponent(device_selection_follows_track_selection=True) device.name = 'Device_Component' self.set_device_component(device) device.set_parameter_controls(self._encoders) def _setup_navigation(self): self._next_track_button = self._control_factory.create_next_track_button( ) self._prev_track_button = self._control_factory.create_prev_track_button( ) self._session_navigation = SessionNavigationComponent( name='Session_Navigation') self._session_navigation.set_next_track_button(self._next_track_button) self._session_navigation.set_prev_track_button(self._prev_track_button) def _dummy_listener(self, value): pass def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) self._update_mixer_offset() def _update_mixer_offset(self): all_tracks = self._session.tracks_to_use() selected_track = self.song().view.selected_track num_strips = self._session.width() if selected_track in all_tracks: track_index = list(all_tracks).index(selected_track) new_offset = track_index - track_index % num_strips self._session.set_offsets(new_offset, self._session.scene_offset())
class NanoKontrolShift(ControlSurface): __module__ = __name__ __doc__ = " NanoKontrolShift controller script " def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._suppress_session_highlight = True self._suppress_send_midi = True # Turn off rebuild MIDI map until after we're done setting up self.log_message( time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= NanoKontrolShift log opened =--------------" ) # Writes message into Live's main log file. This is a ControlSurface method. with self.component_guard(): # OBJECTS self.session = None # session object self.mixer = None # mixer object self.view = None # clip/device view object self.device = None # device object self.transport = None # transport object # MODES self._shift_button = None self._shift_button_pressed = False self._alt_button = None self._alt_button_pressed = False self._ctrl_button = None self._ctrl_button_pressed = False # INITIALIZE MIXER, SESSIONS self._setup_session_control() # Setup the session object self._setup_mixer_control() # Setup the mixer object self._setup_view_control() # Setup the clip/view toggler self.session.set_mixer(self.mixer) # Bind mixer to session self._setup_device_control() # Setup the device object self._setup_transport_control() # Setup transport object self.set_device_component( self.device) # Bind device to control surface # SET INITIAL SESSION/MIXER AND MODIFIERS BUTTONS self._set_modifiers_buttons() self.__update_matrix() self.set_highlighting_session_component(self.session) for component in self.components: component.set_enabled(True) # self._suppress_session_highlight = True self._suppress_send_midi = True # Turn rebuild back on, once we're done setting up def _setup_session_control(self): self.show_message( "#################### SESSION: ON ##############################") is_momentary = True # CREATE SESSION, SET OFFSETS, BUTTONS NAVIGATION AND BUTTON MATRIX self.session = SessionComponent(num_tracks, num_scenes) # (num_tracks, num_scenes) self.session.set_offsets(0, 0) # self.session.set_scene_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_down), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_up)) self.session.set_track_bank_buttons( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_right), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_left) ) # (right_button, left_button) This moves the "red box" selection set left & right. We'll use the mixer track selection instead... def _setup_mixer_control(self): is_momentary = True # CREATE MIXER, SET OFFSET (SPECIALMIXERCOMPONENT USES SPECIALCHANNELSTRIP THAT ALLOWS US TO UNFOLD TRACKS WITH TRACK SELECT BUTTON) self.mixer = SpecialMixerComponent( num_tracks, 0, False, False) # 4 tracks, 2 returns, no EQ, no filters self.mixer.name = 'Mixer' self.mixer.set_track_offset( 0) # Sets start point for mixer strip (offset from left) def _setup_view_control(self): # CREATES OBJECT SO WE CAN TOGGLE DEVICE/CLIP, LOCK DEVICE self.view = ViewTogglerComponent(num_tracks, self) def _setup_device_control(self): # CREATE DEVICE TO ASSIGN PARAMETERS BANK self.device = DeviceComponent() self.device.name = 'Device_Component' def _setup_transport_control(self): # CREATE TRANSPORT DEVICE self.transport = SpecialTransportComponent(self) def _on_selected_scene_changed(self): # ALLOWS TO GRAB THE FIRST DEVICE OF A SELECTED TRACK IF THERE'S ANY ControlSurface._on_selected_track_changed(self) track = self.song().view.selected_track if (track.devices is not None): self._ignore_track_selection = True device_to_select = track.devices[0] self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) self._ignore_track_selection = False """ LED ON, OFF, FLASH WITH SESSION CLIPS """ # UPDATING BUTTONS FROM CLIP MATRIX IN NK AS SESSION MOVES def __update_matrix(self): for scene_index in range(num_scenes): scene = self.session.scene(scene_index) for track_index in range(num_tracks): clip_slot = scene.clip_slot(track_index) button = clip_slot._launch_button_value.subject value_to_send = -1 if clip_slot._clip_slot != None: if clip_slot.has_clip(): value_to_send = 127 if clip_slot._clip_slot.clip.is_triggered: if clip_slot._clip_slot.clip.will_record_on_start: value_to_send = clip_slot._triggered_to_record_value else: value_to_send = clip_slot._triggered_to_play_value ''' elif clip_slot._clip_slot.clip.is_playing: if clip_slot._clip_slot.clip.is_recording: value_to_send = 127 ######### CLIPS PLAYING WILL FLASH for i in range(2000): if i % 50 == 0: button.send_value(127) else: button.send_value(0) else: for i in range(2000): if i % 50 == 0: button.send_value(127) else: button.send_value(0) ''' elif clip_slot._clip_slot.is_triggered: if clip_slot._clip_slot.will_record_on_start: value_to_send = clip_slot._triggered_to_record_value else: value_to_send = clip_slot._triggered_to_play_value elif clip_slot._clip_slot.is_playing: if clip_slot._clip_slot.is_recording: value_to_send = clip_slot._recording_value else: value_to_send = clip_slot._started_value elif clip_slot._clip_slot.controls_other_clips: value_to_send = 0 ''' if value_to_send in range(128): button.send_value(value_to_send) else: button.turn_off() ''' """ MODIFIERS, MODES, KEYS CONFIG """ # MODES ARE HERE: INITIALIZATIONS, DISCONNECTS BUTTONS, SLIDERS, ENCODERS def _clear_controls(self): # TURNING OFF ALL LEDS IN MATRIX self._turn_off_matrix() # SESSION resetsend_controls = [] self.mixer.send_controls = [] for scene_index in range(num_scenes): scene = self.session.scene(scene_index) scene.set_launch_button(None) for track_index in range(num_tracks): clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(None) self.session.set_stop_track_clip_buttons(None) self.session.set_stop_all_clips_button(None) # REMOVE LISTENER TO SESSION MOVES if self.session.offset_has_listener(self.__update_matrix): self.session.remove_offset_listener(self.__update_matrix) self.session.set_stop_all_clips_button(None) # MIXER self.mixer._set_send_nav(None, None) for track_index in range(num_tracks): strip = self.mixer.channel_strip(track_index) strip.set_solo_button(None) strip.set_mute_button(None) strip.set_arm_button(None) resetsend_controls.append(None) strip.set_select_button(None) for i in range(12): self.mixer.send_controls.append(None) strip.set_send_controls(tuple(self.mixer.send_controls)) self.mixer.set_resetsend_buttons(tuple(resetsend_controls)) # VIEW self.view.set_device_nav_buttons(None, None) detailclip_view_controls = [] for track_index in range(num_tracks): detailclip_view_controls.append(None) self.view.set_buttons(tuple(detailclip_view_controls)) # DEVICE PARAMETERS device_param_controls = [] self.device.set_parameter_controls(tuple(device_param_controls)) self.device.set_on_off_button(None) self.device.set_lock_button(None) # TRANSPORT self.transport.set_stop_button(None) self.transport.set_play_button(None) self.transport.set_record_button(None) self.transport._set_quant_toggle_button(None) self.transport.set_metronome_button(None) self.transport._set_tempo_buttons(None, None) self.log_message("Controls Cleared") def _set_normal_mode(self): is_momentary = True self.mixer._set_send_nav( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_up), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_down)) for index in range(num_tracks): strip = self.mixer.channel_strip(index) strip.name = 'Mixer_ChannelStrip_' + str(index) self.mixer._update_send_index(self.mixer.sends_index) strip.set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, mixer_volumefader_cc[index])) self.mixer.send_controls[self.mixer.sends_index] = EncoderElement( MIDI_CC_TYPE, CHANNEL, mixer_sendknob_cc[index], Live.MidiMap.MapMode.absolute) strip.set_send_controls(tuple(self.mixer.send_controls)) strip._invert_mute_feedback = True ### SET ARM, SOLO, MUTE for index in range(num_tracks): strip = self.mixer.channel_strip(index) strip.set_send_controls(tuple(self.mixer.send_controls)) strip.set_solo_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_solo_cc[index])) strip.set_mute_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_mute_cc[index])) strip.set_arm_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_arm_cc[index])) # self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_stop_cc)) for i in range(12): self.mixer.send_controls.append(None) self.mixer.send_controls[self.mixer.sends_index] = EncoderElement( MIDI_CC_TYPE, CHANNEL, mixer_sendknob_cc[index], Live.MidiMap.MapMode.absolute) strip.set_send_controls(tuple(self.mixer.send_controls)) strip._invert_mute_feedback = True self.mixer._update_send_index(self.mixer.sends_index) def _set_alt_mode(self): is_momentary = True self.mixer._set_send_nav( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_up), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_down)) stop_track_controls = [] resetsend_controls = [] button = None buttons = None # SET SESSION TRACKSTOP, TRACK SELECT, RESET SEND KNOB for index in range(num_tracks): strip = self.mixer.channel_strip(index) strip.set_select_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_select_cc[index])) button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, stop_track_cc[index]) stop_track_controls.append(button) buttons = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, track_resetsend_cc[index]) resetsend_controls.append(buttons) self.session.set_stop_track_clip_buttons(tuple(stop_track_controls)) self.mixer.set_resetsend_buttons(tuple(resetsend_controls)) self.mixer._update_send_index(self.mixer.sends_index) def _set_ctrl_mode(self): # CLIP/DEVICE VIEW TOGGLE is_momentary = True self.view.set_device_nav_buttons( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, device_left_cc), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, device_right_cc)) button = None detailclip_view_controls = [] for index in range(num_tracks): button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, detailclip_view_cc[index]) detailclip_view_controls.append(button) self.view.set_buttons(tuple(detailclip_view_controls)) # DEVICE ON/OFF, LOCK AND PARAMETERS device_param_controls = [] onoff_control = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, onoff_device_cc) setlock_control = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, lock_device_cc) for index in range(num_tracks): knob = None knob = EncoderElement(MIDI_CC_TYPE, CHANNEL, device_param_cc[index], Live.MidiMap.MapMode.absolute) device_param_controls.append(knob) if None not in device_param_controls: self.device.set_parameter_controls(tuple(device_param_controls)) self.device.set_on_off_button(onoff_control) self.device.set_lock_button(setlock_control) # TRANSPORT # self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_stop_cc)) # self.transport.set_play_button(ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, transport_play_cc)) # self.transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_record_cc)) self.transport._set_quant_toggle_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_quantization_cc)) self.transport.set_metronome_button( ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, transport_metronome_cc)) self.transport._set_tempo_buttons( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_tempodown_cc), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_tempoup_cc)) # SESSION STOP ALL CLIPS AND SCENE LAUNCH self.session.set_stop_all_clips_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_stopall_cc)) for index in range(num_scenes): self.session.scene(index).set_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_scenelaunch_cc[index])) 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) # MODIFIERS LISTENERS FUNCS ARE HERE def _shift_value(self, value): assert isinstance(value, int) assert isinstance(self._shift_button, ButtonElement) if value == 127: if self._shift_button_pressed is False: self._unpress_modes() self._shift_button_pressed = True self._manage_modes(0) def _alt_value(self, value): assert isinstance(value, int) assert isinstance(self._alt_button, ButtonElement) if value == 127: if self._alt_button_pressed is False: self._unpress_modes() self._alt_button_pressed = True self._manage_modes(2) def _ctrl_value(self, value): assert isinstance(value, int) assert isinstance(self._ctrl_button, ButtonElement) if value == 127: if self._ctrl_button_pressed is False: self._unpress_modes() self._ctrl_button_pressed = True self._manage_modes(3) def _manage_modes(self, mode_index): if mode_index == 0: self._clear_controls() self._set_normal_mode() # self._shift_button.turn_on() self._alt_button.turn_on() self._ctrl_button.turn_on() self.log_message("NORMAL ON") elif mode_index == 2: self._clear_controls() self._set_alt_mode() self._alt_button.turn_on() self._shift_button.turn_off() self._ctrl_button.turn_off() self.log_message("ALT ON") elif mode_index == 3: self._clear_controls() self._set_ctrl_mode() self._ctrl_button.turn_on() self._shift_button.turn_off() self._alt_button.turn_off() self.log_message("CTRL ON") def _unpress_modes(self): self._shift_button_pressed = False self._alt_button_pressed = False self._ctrl_button_pressed = False def _turn_off_matrix(self): for index in range(24): self._send_midi(tuple([176, index + 16, 0])) def disconnect(self): """clean things up on disconnect""" self.log_message( time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= NanoKontrolShift log closed =--------------" ) # Create entry in log file self._clear_controls() self.session = None self.mixer = None self.view = None self.device = None self.transport = None # MODES self._shift_button = None self._alt_button = None self._ctrl_button = None # SENDS self.send_button_up = None self.send_button_down = None self.send_controls = [] self.send_reset = [] self.set_device_component(None) ControlSurface.disconnect(self) return None