def _setup_mixer_control(self): is_momentary = True self._num_tracks = (7) #A mixer is one-dimensional; global mixer mixer = SpecialMixerComponent(7, 0, True, False) mixer.name = 'Mixer' self._mixer = mixer mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(7): mixer.channel_strip(index).set_volume_control(self._fader[index]) for index in range(7): mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) mixer.track_eq(index).name = 'Mixer_EQ_' + str(index) mixer.channel_strip(index)._invert_mute_feedback = True self.song().view.selected_track = 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
def _init_mixer(self): make_button = partial(make_launch_control_button, channel=8) make_encoder = partial(make_launch_control_encoder, channel=8) bottom_encoders, top_encoders = make_all_encoders("Mixer", make_encoder) pan_volume_layer = Layer( volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders]), ) sends_layer = Layer(sends_controls=ButtonMatrixElement(rows=[bottom_encoders, top_encoders])) modes_layer = Layer( pan_volume_button=make_button(114, "Pan_Volume_Mode_Button"), sends_button=make_button(115, "Sends_Mode_Button"), ) self._mixer = SpecialMixerComponent(8, modes_layer, pan_volume_layer, sends_layer) self._mixer.name = "Mixer" self._mixer.selected_strip().name = "Selected_Channel_Strip" self._mixer.master_strip().name = "Master_Channel_Strip" self._mixer_track_nav_layer = Layer( track_bank_left_button=make_button(116, "Mixer_Track_Left_Button"), track_bank_right_button=make_button(117, "Mixer_Track_Right_Button"), ) for index in xrange(8): strip = self._mixer.channel_strip(index) strip.name = "Channel_Strip_" + str(index) strip.empty_color = Colors.LED_OFF strip.set_invert_mute_feedback(True) mute_button = make_button(pad_identifiers[index], "Track_Mute_Button_" + str(index), is_pad=True) mute_button.set_on_off_values(Colors.AMBER_FULL, Colors.AMBER_THIRD) strip.set_mute_button(mute_button) self._on_selected_send_index.subject = self._mixer self._on_selected_mixer_mode.subject = self._mixer
def __init__(self, matrix, side_buttons, session): raise isinstance(matrix, ButtonMatrixElement) or AssertionError raise matrix.width() == 8 and matrix.height() == 8 or AssertionError raise isinstance(side_buttons, tuple) or AssertionError raise len(side_buttons) == 8 or AssertionError raise isinstance(session, SessionComponent) or AssertionError ModeSelectorComponent.__init__(self) self._session = session self._mixer = SpecialMixerComponent(matrix.width()) self._matrix = matrix self._sliders = [] self._mixer.name = "Mixer" self._mixer.master_strip().name = "Master_Channel_strip" self._mixer.selected_strip().name = "Selected_Channel_strip" for column in range(matrix.width()): self._mixer.channel_strip(column).name = "Channel_Strip_" + str(column) self._sliders.append( PreciseButtonSliderElement(tuple([matrix.get_button(column, 7 - row) for row in range(8)])) ) self._sliders[-1].name = "Button_Slider_" + str(column) self._side_buttons = side_buttons[4:] self._update_callback = None self._session.set_mixer(self._mixer) self.set_modes_buttons(side_buttons[:4])
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): is_momentary = True self._suggested_input_port = 'Oxygen' self._suggested_output_port = 'Oxygen' self._has_slider_section = True self._device_selection_follows_track_selection = True self._shift_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 57) self._shift_button.add_value_listener(self._shift_value) self._mixer = SpecialMixerComponent(NUM_TRACKS) self._mute_solo_buttons = [] self._track_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 111) self._track_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 110) self._master_slider = SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 41) for index in range(NUM_TRACKS): self._mute_solo_buttons.append(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 49 + index)) self._mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 33 + index)) self._shift_value(0) self._mixer.master_strip().set_volume_control(self._master_slider) self._mixer.selected_strip().set_volume_control(None) device = DeviceComponent() device.set_parameter_controls(tuple([ EncoderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 17 + index, Live.MidiMap.MapMode.absolute) for index in range(8) ])) self.set_device_component(device) ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 115) rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 114) loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 113) transport = TransportComponent() transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 116)) transport.set_play_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 117)) transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 118)) session = SessionComponent(0, 0) transport_view_modes = TransportViewModeSelector(transport, session, ffwd_button, rwd_button, loop_button) return
def _setup_mixer(self): mute_solo_flip_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 34) self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 37) self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 38) self._strip_buttons = [] mute_solo_flip_button.name = 'Mute_Solo_Flip_Button' self._next_nav_button.name = 'Next_Track_Button' self._prev_nav_button.name = 'Prev_Track_Button' self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button) self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.master_strip().set_volume_control(self._master_slider) self._sliders = [] for index in range(8): strip = self._mixer.channel_strip(index) strip.name = 'Channel_Strip_' + str(index) strip.set_invert_mute_feedback(True) self._sliders.append(SliderElement(MIDI_CC_TYPE, 0, index)) self._sliders[-1].name = str(index) + '_Volume_Control' self._sliders[-1].set_feedback_delay(-1) self._sliders[-1].add_value_listener(self._slider_value, identify_sender=True) strip.set_volume_control(self._sliders[-1]) self._strip_buttons.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + index)) self._strip_buttons[-1].name = str(index) + '_Mute_Button' self._strip_buttons[-1].add_value_listener(self._mixer_button_value, identify_sender=True) self._mixer.master_strip().set_mute_button(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 17)) self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)
def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._solo_buttons = [] for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, self) self._solo_buttons.append(solo_button) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) master_volume_control.name = 'Master_Volume_Control' prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_prehear_volume_control(prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control)
def _setup_mixer_control(self): self.mixer = SpecialMixerComponent(self.num_tracks, self) self.mixer.name = 'Mixer' self.mixer.set_track_offset(0) self.mixer.set_select_buttons(self.button(PAD_CHANNEL, TRACK_RIGHT), self.button(PAD_CHANNEL, TRACK_LEFT)) self.mixer.set_crossfader_control(self.slider(SLIDER_CHANNEL, CROSSFADER)) for index in range(4): self.mixer.channel_strip(index).set_volume_control(self.slider(SLIDER_CHANNEL, TRACK_VOL[index])) self.num_o_tracks = self.song().visible_tracks if self.num_o_tracks != None: index_count = -1 index_table = [] for index in self.song().visible_tracks: index_count += 1 if index.has_midi_output != True: index_table.append(index_count) else: None if index_table != None: for index in range(len(index_table)): x = index_table[index] if x > 3: None else: None
def _setup_mixer_control(self): self.mixer = SpecialMixerComponent(self.box_width, self) # get a local mixer object ready self.mixer.name = 'Mixer' # name self.mixer.set_track_offset(self.gutter) # gutter ----marwei # compare width with track vol count to qualify -- put somewhere else for index in range(self.box_width): # @marwei must kill this style and count self.mixer.channel_strip(index).set_volume_control(self.slider(midi_channel, track_volume[index]))
def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(self, 8) #added self for parent self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) master_select_button.name = 'Master_Select_Button' self._mixer.master_strip().set_select_button(master_select_button) #set in ShiftableSelectorComponent instead if used for Note Mode self._mixer.selected_strip().name = 'Selected_Channel_Strip' select_buttons = [] #added arm_buttons = [] #added sliders = [] #added for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) #volume_control = SliderElement(MIDI_CC_TYPE, track, 7) #set in ShiftableSelectorComponent instead #arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) #see below solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) solo_button.name = str(track) + '_Solo_Button' strip.set_solo_button(solo_button) if track < 4: mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) mute_button.name = str(track) + '_Mute_Button' strip.set_mute_button(mute_button) strip.set_invert_mute_feedback(True) strip.set_shift_button(self._shift_button) select_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) #added select_buttons[-1].name = str(track) + '_Select_Button' #added #strip.set_select_button(select_buttons[-1]) #added arm_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) #added arm_buttons[-1].name = str(track) + '_Arm_Button' #added sliders.append(SliderElement(MIDI_CC_TYPE, track, 7)) #added sliders[-1].name = str(track) + '_Volume_Control' #added self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) self._prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) self._crossfader.name = 'Crossfader' #not used in APC20 master_volume_control.name = 'Master_Volume_Control' self._prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_shift_button(self._shift_button) #added for shifting prehear self._mixer.set_crossfader_control(self._crossfader) #not used in APC20 self._mixer.set_prehear_volume_control(self._prehear_control) #functionality overridden in SpecialMixerComponent self._mixer.master_strip().set_volume_control(master_volume_control) self._slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) #added from APC20 script self._slider_modes.name = 'Slider_Modes' #added from APC20 script matrix_modes = MatrixModesComponent(self._matrix, self._session, self._session_zoom, tuple(self._track_stop_buttons), self) #added new matrix_modes.name = 'Matrix_Modes' #added new # Original method args for ShiftableSelectorComponent: (self, select_buttons, master_button, arm_buttons, matrix, session, zooming, mixer, transport, slider_modes, mode_callback) #self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message) self._shift_modes = ShiftableSelectorComponent(self, tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, self._slider_modes, matrix_modes) #, self._send_introduction_message) #also added self for _parent self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button)
def _setup_mixer_control(self): global mixer is_momentary = True self._num_tracks = 7 mixer = SpecialMixerComponent(7, 0, True, False) mixer.name = 'Mixer' self._mixer = mixer for index in range(7): mixer.channel_strip(index).set_volume_control(self._fader[index]) for index in range(7): mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) mixer.track_eq(index).name = 'Mixer_EQ_' + str(index) mixer.channel_strip(index)._invert_mute_feedback = True self.song().view.selected_track = mixer.channel_strip(0)._track
def _setup_mixer_control(self): is_momentary = True ## Quirksmode self.arm_buttons = [] self._mixer = SpecialMixerComponent(self, 8) #added self for parent self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.selected_strip().name = 'Selected_Channel_Strip' for track in range(8): self.strip = self._mixer.channel_strip(track) self.strip.name = 'Channel_Strip_' + str(track) volume_control = SliderElement(MIDI_CC_TYPE, track, 7) arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51) volume_control.name = str(track) + '_Volume_Control' arm_button.name = str(track) + '_Arm_Button' solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' select_button.name = str(track) + '_Select_Button' self.strip.set_volume_control(volume_control) ##Quirksmode self.arm_buttons.append(arm_button) self.strip.set_arm_button(arm_button) self.strip.set_solo_button(solo_button) self.strip.set_mute_button(mute_button) self.strip.set_select_button(select_button) self.strip.set_shift_button(self._shift_button) self.strip.set_invert_mute_feedback(True) crossfader = SliderElement(MIDI_CC_TYPE, 0, 15) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) ##self._prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' master_select_button.name = 'Master_Select_Button' ##self._prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_crossfader_control(crossfader) ##self._mixer.set_prehear_volume_control(self._prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) self._mixer.master_strip().set_select_button(master_select_button)
def __init__(self, matrix, side_buttons, session): assert isinstance(matrix, ButtonMatrixElement) assert ((matrix.width() == 8) and (matrix.height() == 8)) assert isinstance(side_buttons, tuple) assert (len(side_buttons) == 8) assert isinstance(session, SessionComponent) ModeSelectorComponent.__init__(self) self._session = session self._mixer = SpecialMixerComponent(matrix.width()) self._matrix = matrix self._sliders = [] for column in range(8): self._sliders.append(PreciseButtonSliderElement(tuple([ matrix.get_button(column, (7 - row)) for row in range(8) ]))) self._side_buttons = side_buttons[4:] self._update_callback = None self._session.set_mixer(self._mixer) self.set_modes_buttons(side_buttons[:4])
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_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._solo_buttons = [] # added a self._select_buttons = [] # added a for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) volume_control = MonoEncoderElement2(MIDI_CC_TYPE, track, 7, Live.MidiMap.MapMode.absolute, 'Slider_' + str(track), track, self) arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, self) self._solo_buttons.append(solo_button) # added a mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) select_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51, self) self._select_buttons.append(select_button) # added a #volume_control.name = str(track) + '_Volume_Control' arm_button.name = str(track) + '_Arm_Button' solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' select_button.name = str(track) + '_Select_Button' strip.set_volume_control(volume_control) strip.set_arm_button(arm_button) strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_select_button(select_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) crossfader = SliderElement(MIDI_CC_TYPE, 0, 15) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) self._master_select_button = master_select_button prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' master_select_button.name = 'Master_Select_Button' prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_crossfader_control(crossfader) self._mixer.set_prehear_volume_control(prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) self._mixer.master_strip().set_select_button(master_select_button)
def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = "Mixer" self._mixer.master_strip().name = "Master_Channel_Strip" self._mixer.selected_strip().name = "Selected_Channel_Strip" for track in range(8): strip = self._mixer.channel_strip(track) strip.name = "Channel_Strip_" + str(track) volume_control = SliderElement(MIDI_CC_TYPE, track, 7) arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51) volume_control.name = str(track) + "_Volume_Control" arm_button.name = str(track) + "_Arm_Button" solo_button.name = str(track) + "_Solo_Button" mute_button.name = str(track) + "_Mute_Button" select_button.name = str(track) + "_Select_Button" strip.set_volume_control(volume_control) strip.set_arm_button(arm_button) strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_select_button(select_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) crossfader = SliderElement(MIDI_CC_TYPE, 0, 15) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) self.prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) self._mixer.set_shift_button(self._shift_button) # added for shifting prehear crossfader.name = "Crossfader" master_volume_control.name = "Master_Volume_Control" master_select_button.name = "Master_Select_Button" self.prehear_control.name = "Prehear_Volume_Control" self._mixer.set_crossfader_control(crossfader) self._mixer.set_prehear_volume_control(self.prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) self._mixer.master_strip().set_select_button(master_select_button)
def _setup_mixer(self): self._next_nav_button = make_button(103, "Next_Track_Button") self._prev_nav_button = make_button(102, "Prev_Track_Button") mute_solo_flip_button = make_button(59, "Master_Button") self._mixer = SpecialMixerComponent(8) self._mixer.name = "Mixer" self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button) self._mixer.selected_strip().name = "Selected_Channel_Strip" self._mixer.master_strip().name = "Master_Channel_Strip" self._mixer.master_strip().set_volume_control(self._master_slider) self._sliders = [] 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_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.master_strip().set_select_button(self._note_map[MASTERSEL]) self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._mixer.set_select_buttons(self._note_map[TRACKRIGHT], self._note_map[TRACKLEFT]) self._mixer.set_crossfader_control(self._ctrl_map[CROSSFADER]) self._mixer.set_prehear_volume_control(self._ctrl_map[CUELEVEL]) self._mixer.master_strip().set_volume_control(self._ctrl_map[MASTERVOLUME]) for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) strip.set_arm_button(self._note_map[TRACKREC[track]]) strip.set_solo_button(self._note_map[TRACKSOLO[track]]) strip.set_mute_button(self._note_map[TRACKMUTE[track]]) strip.set_select_button(self._note_map[TRACKSEL[track]]) strip.set_volume_control(self._ctrl_map[TRACKVOL[track]]) strip.set_pan_control(self._ctrl_map[TRACKPAN[track]]) strip.set_send_controls((self._ctrl_map[TRACKSENDA[track]], self._ctrl_map[TRACKSENDB[track]], self._ctrl_map[TRACKSENDC[track]])) strip.set_invert_mute_feedback(True)
def __init__(self, matrix, side_buttons, session): assert isinstance(matrix, ButtonMatrixElement) assert ((matrix.width() == 8) and (matrix.height() == 8)) assert isinstance(side_buttons, tuple) assert (len(side_buttons) == 8) assert isinstance(session, SessionComponent) ModeSelectorComponent.__init__(self) self._session = session self._mixer = SpecialMixerComponent(len(self.song().tracks)) self._matrix = matrix self._mixer.name = "Mixer" self._mixer.master_strip().name = "Master_Channel_strip" self._mixer.selected_strip().name = "Selected_Channel_strip" for column in range(len(self.song().tracks)): button_index = 0 if self.song().tracks[column].is_foldable: if button_index < GROUPS_CONSIDERED: self._mixer.channel_strip(column).name = ("Channel_Strip_" + str(column)) button_index = button_index + 1 self._side_buttons = side_buttons[5:] self._update_callback = None self._session.set_mixer(self._mixer)
def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(NUM_TRACKS) self._mixer.set_serato_interface(self._serato_interface) self._mixer.master_strip().set_serato_interface(self._serato_interface) self._track_arm_buttons = [] self._track_solo_buttons = [] self._track_mute_buttons = [] self._track_select_buttons = [] self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for track in range(NUM_TRACKS): strip = self._mixer.channel_strip(track) strip.set_serato_interface(self._serato_interface) self._track_arm_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_solo_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_mute_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_select_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) strip.set_arm_button(self._track_arm_buttons[-1]) strip.set_solo_button(self._track_solo_buttons[-1]) strip.set_mute_button(self._track_mute_buttons[-1]) strip.set_select_button(self._track_select_buttons[-1]) strip.set_shift_button(self._shift_button)
def __init__(self, matrix, side_buttons, session, skin): assert isinstance(matrix, ButtonMatrixElement) assert ((matrix.width() == 8) and (matrix.height() == 8)) assert isinstance(side_buttons, tuple) assert (len(side_buttons) == 8) assert isinstance(session, SessionComponent) ModeSelectorComponent.__init__(self) self._skin = skin self._session = session self._mixer = SpecialMixerComponent(matrix.width()) self._matrix = matrix self._sliders = [] self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_strip' self._mixer.selected_strip().name = 'Selected_Channel_strip' for column in range(matrix.width()): self._mixer.channel_strip(column).name = 'Channel_Strip_' + str(column) self._sliders.append(PreciseButtonSliderElement(tuple([matrix.get_button(column, 7 - row) for row in range(8)]))) self._sliders[-1].name = 'Button_Slider_' + str(column) self._side_buttons = side_buttons[4:] self._update_callback = None self._session.set_mixer(self._mixer) self.set_modes_buttons(side_buttons[:4])
def _init_session(self): make_button = partial(make_launch_control_button, channel=9) make_encoder = partial(make_launch_control_encoder, channel=9) bottom_encoders, top_encoders = make_all_encoders('Session_Mixer', make_encoder) pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders])) self._session_mixer = SpecialMixerComponent(8, Layer(), pan_volume_layer, Layer()) self._session_mixer.set_enabled(False) self._session_mixer.name = 'Session_Mixer' clip_launch_buttons = [ make_button(identifier, 'Clip_Launch_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ] self._session = SpecialSessionComponent(num_tracks=8, num_scenes=0, name='Session') self._session.set_enabled(False) self._session.set_mixer(self._session_mixer) self._session_layer = Layer(track_bank_left_button=make_button(116, 'Track_Bank_Left_Button'), track_bank_right_button=make_button(117, 'Track_Bank_Right_Button'), select_prev_button=make_button(114, 'Scene_Bank_Up_Button'), select_next_button=make_button(115, 'Scene_Bank_Down_Button'), clip_launch_buttons=ButtonMatrixElement(rows=[clip_launch_buttons])) scene = self._session.selected_scene() for index in range(8): clip_slot = scene.clip_slot(index) clip_slot.set_triggered_to_play_value(Colors.GREEN_BLINK) clip_slot.set_triggered_to_record_value(Colors.RED_BLINK) clip_slot.set_stopped_value(Colors.AMBER_FULL) clip_slot.set_started_value(Colors.GREEN_FULL) clip_slot.set_recording_value(Colors.RED_FULL) clip_slot.name = 'Selected_Clip_Slot_' + str(index) self._on_track_offset.subject = self._session
def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(self, 8) #added self for parent self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) master_select_button.name = 'Master_Select_Button' self._mixer.master_strip().set_select_button( master_select_button ) #set in ShiftableSelectorComponent instead if used for Note Mode self._mixer.selected_strip().name = 'Selected_Channel_Strip' select_buttons = [] #added arm_buttons = [] #added sliders = [] #added for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) #volume_control = SliderElement(MIDI_CC_TYPE, track, 7) #set in ShiftableSelectorComponent instead #arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) #see below solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) solo_button.name = str(track) + '_Solo_Button' strip.set_solo_button(solo_button) if track < 4: mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) mute_button.name = str(track) + '_Mute_Button' strip.set_mute_button(mute_button) strip.set_invert_mute_feedback(True) strip.set_shift_button(self._shift_button) select_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) #added select_buttons[-1].name = str(track) + '_Select_Button' #added #strip.set_select_button(select_buttons[-1]) #added arm_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) #added arm_buttons[-1].name = str(track) + '_Arm_Button' #added sliders.append(SliderElement(MIDI_CC_TYPE, track, 7)) #added sliders[-1].name = str(track) + '_Volume_Control' #added self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) self._prehear_control = EncoderElement( MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) self._crossfader.name = 'Crossfader' #not used in APC20 master_volume_control.name = 'Master_Volume_Control' self._prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_shift_button( self._shift_button) #added for shifting prehear self._mixer.set_crossfader_control( self._crossfader) #not used in APC20 self._mixer.set_prehear_volume_control( self._prehear_control ) #functionality overridden in SpecialMixerComponent self._mixer.master_strip().set_volume_control(master_volume_control) self._slider_modes = SliderModesComponent( self._mixer, tuple(sliders)) #added from APC20 script self._slider_modes.name = 'Slider_Modes' #added from APC20 script matrix_modes = MatrixModesComponent(self._matrix, self._session, self._session_zoom, tuple(self._track_stop_buttons), self) #added new matrix_modes.name = 'Matrix_Modes' #added new # Original method args for ShiftableSelectorComponent: (self, select_buttons, master_button, arm_buttons, matrix, session, zooming, mixer, transport, slider_modes, mode_callback) #self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message) self._shift_modes = ShiftableSelectorComponent( self, tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, self._slider_modes, matrix_modes ) #, self._send_introduction_message) #also added self for _parent self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button)
class Launchkey(ControlSurface): """ Script for Novation's Launchkey 25/49/61 keyboards """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) self._device_selection_follows_track_selection = True self._suggested_input_port = "Launchkey InControl" self._suggested_output_port = "Launchkey InControl" self._has_sliders = True self._current_midi_map = None self._master_slider = make_slider(7, "Master_Volume_Control") self._modes_buttons = [] for index in range(3): button = ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, 0, 13 + index) self._modes_buttons.append(button) self._modes_buttons[-1].add_value_listener(self._dummy_listener) self._setup_mixer() self._setup_session() self._setup_transport() self._setup_device() for component in self.components: component.set_enabled(False) def 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] == SIZE_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() 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) 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): self._next_nav_button = make_button(103, "Next_Track_Button") self._prev_nav_button = make_button(102, "Prev_Track_Button") mute_solo_flip_button = make_button(59, "Master_Button") self._mixer = SpecialMixerComponent(8) self._mixer.name = "Mixer" self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button) self._mixer.selected_strip().name = "Selected_Channel_Strip" self._mixer.master_strip().name = "Master_Channel_Strip" self._mixer.master_strip().set_volume_control(self._master_slider) self._sliders = [] 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 = make_configurable_button(104, "Scene_Launch_Button") scene_stop_button = make_configurable_button(120, "Scene_Stop_Button") self._session = SpecialSessionComponent(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_track_banking_increment(8) self._session.set_stop_track_clip_value(GREEN_BLINK) clip_launch_buttons = [] clip_stop_buttons = [] for index in range(8): clip_launch_buttons.append(make_configurable_button(96 + index, "Clip_Launch_%d" % index)) clip_stop_buttons.append(make_configurable_button(112 + index, "Clip_Stop_%d" % 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 _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 Axiom_AIR_25_49_61(ControlSurface): """ Script for the M-Audio Axiom A.I.R. 25, 49 and 61 """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._alt_device_component = None with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) self._device_selection_follows_track_selection = True self._suggested_input_port = 'HyperControl' self._suggested_output_port = 'HyperControl' self._single_fader_button_modes = None self._has_faders = True self._display_reset_delay = -1 self._hc_byte = HC_BYTE self._waiting_for_first_response = True self._setup_controls() self._setup_displays() self._setup_mixer() self._setup_session() self._setup_transport() self._setup_device() self._setup_modes() self._drum_group_midi_button = None self._drum_group_hyper_button = None for component in self.components: component.set_enabled(False) def disconnect(self): self._scheduled_messages = [] for encoder in self._encoders: encoder.remove_value_listener(self._encoder_value) for fader in self._faders: fader.remove_value_listener(self._fader_value) for fader_button in self._fader_buttons: fader_button.remove_value_listener(self._fader_button_value) self._master_fader.remove_value_listener(self._fader_value) self._master_fader_button.remove_value_listener( self._fader_button_value) self._select_button.remove_value_listener(self._select_button_value) self._identify_button.remove_value_listener(self._identify_value) self._fader_group_midi_button.remove_value_listener( self._midi_button_value) self._fader_group_mix_button.remove_value_listener( self._hyper_button_value) self._fader_group_fx_button.remove_value_listener( self._hyper_button_value) self._encoder_group_midi_button.remove_value_listener( self._midi_button_value) self._encoder_group_mix_button.remove_value_listener( self._hyper_button_value) self._encoder_group_fx_button.remove_value_listener( self._hyper_button_value) if self._drum_group_midi_button != None: self._drum_group_midi_button.remove_value_listener( self._midi_button_value) if self._drum_group_hyper_button != None: self._drum_group_hyper_button.remove_value_listener( self._hyper_button_value) self._alt_device_component = None self._name_display = None self._value_display = None self._bank_display = None self._pad_display = None self._name_display_data_source = None self._value_display_data_source = None self._bank_display_data_source = None self._pad_display_data_source = None self._select_button = None self._left_button = None self._right_button = None self._up_button = None self._down_button = None self._loop_button = None self._ffwd_button = None self._rwd_button = None self._play_button = None self._stop_button = None self._rec_button = None self._master_fader_button = None self._fader_buttons = None self._faders = None self._encoders = None self._drum_pads = None self._identify_button = None self._main_group_hyper_button = None self._main_group_track_button = None self._main_group_fx_button = None self._encoder_group_midi_button = None self._encoder_group_mix_button = None self._encoder_group_fx_button = None self._fader_group_mode_button = None self._fader_group_midi_button = None self._fader_group_mix_button = None self._fader_group_fx_button = None self._drum_group_midi_button = None self._drum_group_roll_button = None self._drum_group_hyper_button = None self._mixer_for_encoders = None self._mixer_for_faders = None self._device_for_encoders = None self._device_for_faders = None self._transport = None self._session = None ControlSurface.disconnect(self) self._send_midi(SYSEX_START + DISABLE_HYPERCONTROL) def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(5, self._send_midi, IDENTITY_REQUEST) def handle_sysex(self, midi_bytes): if midi_bytes[0:10] == AXIOM_AIR_RESPONSE: if midi_bytes[12:15] < AXIOM_REV4_RESPONSE: self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL) self.schedule_message(2, self._send_midi, SYSEX_START + CLEAR_ALL) self.schedule_message(3, self._name_display.display_message, 'Firmware') self.schedule_message(13, self._name_display.display_message, 'Update') self.schedule_message(23, self._name_display.display_message, 'Required') self.schedule_message(33, self._send_midi, SYSEX_START + DISABLE_HYPERCONTROL) elif midi_bytes[12:15] >= AXIOM_REV4_RESPONSE: if self._waiting_for_first_response == True: self._waiting_for_first_response = False self._has_faders = midi_bytes[10] != 50 self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL) self.schedule_message(2, self._send_midi, SYSEX_START + SPECIAL_HYPERCONTROL) self.schedule_message(3, self._complete_setup) else: self._display_reset_delay = 0 elif midi_bytes[0:8] == REQUEST_HYPERCONTROL: self.schedule_message(5, self._send_midi, IDENTITY_REQUEST) def update_display(self): ControlSurface.update_display(self) if self._display_reset_delay >= 0: self._display_reset_delay -= 1 if self._display_reset_delay == -1: self._set_displays_to_default() def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) self._display_reset_delay = 0 def restore_bank(self, bank_index): ControlSurface.restore_bank(self, bank_index) if self._alt_device_component != None: self._alt_device_component.restore_bank(bank_index) def set_appointed_device(self, device): ControlSurface.set_appointed_device(self, device) with self.component_guard(): if self._alt_device_component != None: self._alt_device_component.set_device(device) def set_alt_device_component(self, device_component): self._alt_device_component = device_component def _update_device_selection(self): track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) if self._alt_device_component != None: self._alt_device_component.set_device(device_to_select) def _setup_controls(self): self._left_button = create_button(99, 'Left_Button') self._right_button = create_button(100, 'Right_Button') self._up_button = create_button(101, 'Up_Button') self._down_button = create_button(102, 'Down_Button') self._loop_button = create_button(113, 'Loop_Button') self._rwd_button = create_button(114, 'Rwd_Button') self._ffwd_button = create_button(115, 'FFwd_Button') self._stop_button = create_button(116, 'Stop_Button') self._play_button = create_button(117, 'Play_Button') self._rec_button = create_button(118, 'Record_Button') self._select_button = ConfigurableButtonElement( IS_MOMENTARY, MIDI_CC_TYPE, GLOBAL_CHANNEL, 98) self._select_button.name = 'Select_Button' self._select_button.add_value_listener(self._select_button_value) self._main_group_hyper_button = create_configurable_button( 104, 'Fader_Group_HyperControl_Button', 2, 14) self._main_group_track_button = create_configurable_button( 105, 'Main_Group_Track_Button', 2, 11) self._main_group_fx_button = create_configurable_button( 106, 'Main_Group_Inst_FX_Button', 2, 11) self._identify_button = create_configurable_button( 97, 'Identify_Button', 2, 16) self._identify_button.add_value_listener(self._identify_value) self._fader_buttons = [] for index in range(8): self._fader_buttons.append( create_configurable_button(49 + index, 'Fader_Button_%d' % index)) self._fader_buttons[-1].add_value_listener( self._fader_button_value, identify_sender=True) self._faders = [] for index in range(8): self._faders.append(create_slider(33 + index, 'Fader_%d' % index)) self._faders[-1].add_value_listener(self._fader_value, identify_sender=True) self._master_fader_button = create_configurable_button( 57, 'Master_Fader_Button') self._master_fader_button.add_value_listener(self._fader_button_value, identify_sender=True) self._master_fader = create_slider(41, 'Master_Fader') self._master_fader.add_value_listener(self._fader_value, identify_sender=True) self._fader_group_mode_button = create_configurable_button( 61, 'Fader_Group_Mode_Button') self._fader_group_midi_button = create_configurable_button( 60, 'Fader_Group_MIDI_Button') self._fader_group_midi_button.add_value_listener( self._midi_button_value, identify_sender=True) self._fader_group_mix_button = create_configurable_button( 58, 'Fader_Group_Mix_Button', 0, 1) self._fader_group_mix_button.add_value_listener( self._hyper_button_value, identify_sender=True) self._fader_group_fx_button = create_configurable_button( 59, 'Fader_Group_Inst_FX_Button', 0, -1) self._fader_group_fx_button.add_value_listener( self._hyper_button_value, identify_sender=True) self._encoders = [] for index in range(8): self._encoders.append( create_encoder(17 + index, 'Encoder_%d' % index)) self._encoders[-1].add_value_listener(self._encoder_value, identify_sender=True) self._encoder_group_midi_button = create_configurable_button( 27, 'Encoder_Group_MIDI_Button', 0, 72) self._encoder_group_midi_button.add_value_listener( self._midi_button_value, identify_sender=True) self._encoder_group_mix_button = create_configurable_button( 25, 'Encoder_Group_Mix_Button', 0, 72) self._encoder_group_mix_button.add_value_listener( self._hyper_button_value, identify_sender=True) self._encoder_group_fx_button = create_configurable_button( 26, 'Encoder_Group_Inst_FX_Button', 0, 72) self._encoder_group_fx_button.add_value_listener( self._hyper_button_value, identify_sender=True) def _setup_drum_pads(self): self._drum_pads = [] num_pads = 12 if self._has_faders else 16 for index in range(8): self._drum_pads.append( create_configurable_button(81 + index, 'Pad_%d' % index, 0, 0, MIDI_CC_TYPE)) for index in range(num_pads - 8): self._drum_pads.append( ConfigurableButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, GLOBAL_CHANNEL - 1, 81 + index, GLOBAL_SEND_CHANNEL, 8, MIDI_CC_TYPE)) self._drum_pads[-1].name = 'Pad_' + str(index + 8) self._drum_group_midi_button = create_configurable_button( 91, 'Drum_Group_MIDI_Button', 2, -2) self._drum_group_midi_button.add_value_listener( self._midi_button_value, identify_sender=True) self._drum_group_roll_button = create_configurable_button( 90, 'Drum_Group_Roll_Button', -1) self._drum_group_hyper_button = create_configurable_button( 89, 'Drum_Group_HyperControl_Button', 2, 2) self._drum_group_hyper_button.add_value_listener( self._hyper_button_value, identify_sender=True) def _setup_displays(self): self._name_display = PhysicalDisplayElement(12, 1) self._name_display.name = 'Name_Display' self._name_display.set_message_parts(SYSEX_START + (21, ), (0, 247)) self._name_display.set_clear_all_message(CLEAR_NAME) self._name_display_data_source = DisplayDataSource() self._name_display.segment(0).set_data_source( self._name_display_data_source) self._value_display = NumericalDisplayElement(3, 1) self._value_display.name = 'Value_Display' self._value_display.set_message_parts(SYSEX_START + (20, 48), (0, 247)) self._value_display.set_clear_all_message(CLEAR_VALUE) self._value_display_data_source = DisplayDataSource() self._value_display.segment(0).set_data_source( self._value_display_data_source) self._bank_display = NumericalDisplayElement(3, 1) self._bank_display.name = 'Bank_Display' self._bank_display.set_message_parts(SYSEX_START + (19, ), (0, 247)) self._bank_display.set_clear_all_message(CLEAR_BANK) self._bank_display_data_source = DisplayDataSource() self._bank_display.segment(0).set_data_source( self._bank_display_data_source) self._pad_display = NumericalDisplayElement(2, 1) self._pad_display.name = 'Pad_Display' self._pad_display.set_message_parts(SYSEX_START + (18, ), (0, 247)) self._pad_display.set_clear_all_message(CLEAR_PAD) self._pad_display_data_source = DisplayDataSource() self._pad_display.segment(0).set_data_source( self._pad_display_data_source) def _setup_mixer(self): self._mixer_for_encoders = SpecialMixerComponent( self._name_display, self._value_display, 8) self._mixer_for_encoders.name = 'Mixer_for_encoders' self._mixer_for_faders = SpecialMixerComponent(self._name_display, self._value_display, 8) self._mixer_for_faders.name = 'Mixer_for_faders' def _setup_session(self): self._session = SpecialSessionComponent(8, 0) self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.set_mixer(self._mixer_for_encoders) self._session.set_alt_mixer(self._mixer_for_faders) self._session.add_offset_listener(self._update_bank_value) def _setup_transport(self): self._transport = TransportComponent() self._transport.name = 'Transport' self._transport.set_stop_button(self._stop_button) self._transport.set_play_button(self._play_button) self._transport.set_record_button(self._rec_button) transport_view_modes = TransportViewModeSelector( self._transport, self._session, self._ffwd_button, self._rwd_button, self._loop_button) transport_view_modes.name = 'Transport_View_Modes' def _setup_device(self): self._device_for_encoders = BestBankDeviceComponent() self._device_for_encoders.name = 'Device_Component_for_encoders' self._device_for_faders = BestBankDeviceComponent() self._device_for_faders.name = 'Device_Component_for_faders' self.set_device_component(self._device_for_encoders) self.set_alt_device_component(self._device_for_faders) self._device_nav = DeviceNavComponent() self._device_nav.name = 'Device_Nav_Component' def _setup_modes(self): self._fader_button_modes = FaderButtonModeSelector( self._mixer_for_faders, tuple(self._fader_buttons)) self._fader_button_modes.name = 'Fader_Button_Modes' self._fader_button_modes.set_mode_toggle(self._fader_group_mode_button) self._fader_modes = FaderModeSelector(self._mixer_for_faders, self._device_for_faders, tuple(self._faders), self._fader_button_modes, self._master_fader_button) self._fader_modes.name = 'Fader_Modes' self._fader_modes.set_mode_buttons( (self._fader_group_mix_button, self._fader_group_fx_button)) self._encoder_modes = EncoderModeSelector(self._mixer_for_encoders, self._device_for_encoders, tuple(self._encoders)) self._encoder_modes.name = 'Encoder_Modes' self._encoder_modes.set_mode_buttons( (self._encoder_group_mix_button, self._encoder_group_fx_button)) main_modes = MainModeSelector(self._device_for_encoders, self._device_for_faders, self._session, self._mixer_for_faders, self._device_nav, self._up_button, self._down_button, self._left_button, self._right_button, self._select_button) main_modes.name = 'Main_Modes' main_modes.set_mode_buttons( (self._main_group_track_button, self._main_group_fx_button)) def _setup_master_fader(self): if self._has_faders: self._mixer_for_encoders.master_strip().set_volume_control( self._master_fader) else: self._mixer_for_encoders.selected_strip().set_volume_control( self._master_fader) def _setup_single_fader_button_modes(self): self._single_fader_button_modes = SingleFaderButtonModeSelector( self._mixer_for_encoders, self._fader_group_midi_button) self._single_fader_button_modes.name = 'Single_Fader_Button_Modes' self._single_fader_button_modes.set_mode_toggle( self._fader_group_mode_button) def _complete_setup(self): self._setup_drum_pads() self._set_drum_pads_to_hc() self._setup_master_fader() if not self._has_faders: self._setup_single_fader_button_modes() for control in self.controls: if isinstance(control, InputControlElement): control.clear_send_cache() for component in self.components: component.set_enabled(True) self._fader_group_midi_button.send_value(LED_OFF, True) self._encoder_group_midi_button.send_value(LED_OFF, True) self._main_group_hyper_button.send_value(AMB_FULL, True) self.request_rebuild_midi_map() self._on_selected_track_changed() self.schedule_message(1, self._show_startup_message) def _show_startup_message(self): self._send_midi(SYSEX_START + CLEAR_ALL) self._name_display.display_message('Ableton Live') self._display_reset_delay = INITIAL_DISPLAY_DELAY def _select_button_value(self, value): self._display_reset_delay = STANDARD_DISPLAY_DELAY def _identify_value(self, value): for encoder in self._encoders: encoder.set_identify_mode(value > 0) for fader in self._faders: fader.set_identify_mode(value > 0) self._master_fader.set_identify_mode(value > 0) self._display_reset_delay = 0 self._identify_button.turn_on( ) if value > 0 else self._identify_button.turn_off() def _midi_button_value(self, value, sender): if value > 0: if sender is self._drum_group_midi_button: hc_byte = self._hc_byte ^ PADS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._drum_group_hyper_button.send_value(LED_OFF, True) self.schedule_message( 1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) elif sender is self._encoder_group_midi_button: hc_byte = self._hc_byte ^ ENCODERS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._encoder_group_mix_button.send_value(LED_OFF, True) self._encoder_group_fx_button.send_value(LED_OFF, True) if self._encoder_modes.mode_index < 3: self._encoder_modes.set_enabled(False) self.schedule_message( 1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) elif sender is self._fader_group_midi_button: if self._has_faders: hc_byte = self._hc_byte ^ FADERS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._fader_group_mix_button.send_value(LED_OFF, True) self._fader_group_fx_button.send_value(LED_OFF, True) self._fader_group_mode_button.send_value(LED_OFF, True) if self._fader_modes.mode_index < 2: self._fader_modes.set_enabled(False) self._fader_button_modes.set_enabled(False) self.schedule_message( 1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) else: self._display_reset_delay = STANDARD_DISPLAY_DELAY def _hyper_button_value(self, value, sender): if value > 0: if sender is self._drum_group_hyper_button: if self._hc_byte | PADS != self._hc_byte: self._hc_byte = self._hc_byte | PADS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self.schedule_message(1, self._set_drum_pads_to_hc) elif sender is self._encoder_group_fx_button or sender is self._encoder_group_mix_button: if self._hc_byte | ENCODERS != self._hc_byte: self._hc_byte = self._hc_byte | ENCODERS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self._encoder_group_midi_button.turn_off() if sender is self._encoder_group_fx_button: self._encoder_modes.set_enabled(True) self._display_reset_delay = 0 return else: self.schedule_message(1, self._encoder_modes.set_enabled, True) self.schedule_message(1, self._encoder_modes.update) self._display_reset_delay = 2 return elif sender is self._fader_group_fx_button or sender is self._fader_group_mix_button: if self._hc_byte | FADERS != self._hc_byte: self._hc_byte = self._hc_byte | FADERS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self._fader_group_midi_button.turn_off() self._fader_button_modes.set_enabled(True) if sender is self._fader_group_fx_button: self._fader_modes.set_enabled(True) self._fader_button_modes.set_enabled(True) self._display_reset_delay = 0 return else: self.schedule_message(1, self._fader_modes.set_enabled, True) self.schedule_message(1, self._fader_modes.update) self.schedule_message( 1, self._fader_button_modes.set_enabled, True) self.schedule_message(1, self._fader_button_modes.update) self._display_reset_delay = 2 return self._display_reset_delay = 0 def _set_drum_pads_to_hc(self): self._drum_group_midi_button.send_value(LED_OFF, True) self._drum_group_hyper_button.send_value(RED_FULL, True) for index in range(len(self._drum_pads)): self._drum_pads[index].send_value(RED_LOW, True) def _fader_button_value(self, value, sender): self._display_reset_delay = STANDARD_DISPLAY_DELAY def _fader_value(self, value, sender): param = sender.mapped_parameter() if param != None: param_range = param.max - param.min if param.name == 'Track Volume': if sender == self._master_fader: if self._has_faders: name_string = 'Master Vol' else: name_string = self._mixer_for_faders.selected_strip( ).track_name_data_source().display_string() + ' Vol' else: name_string = self._mixer_for_faders.channel_strip( self._faders.index(sender)).track_name_data_source( ).display_string() + ' Vol' else: name_string = param.name value = int((param.value - param.min) / param_range * 127) value_string = str(value) else: name_string = '<unmapped>' value_string = None self.schedule_message(1, self._set_value_string) self._set_name_string(name_string) self._set_value_string(value_string) def _encoder_value(self, value, sender): param = sender.mapped_parameter() if param != None: param_range = param.max - param.min if param.name == 'Track Volume': name_string = self._mixer_for_encoders.channel_strip( self._encoders.index(sender)).track_name_data_source( ).display_string() + ' Vol' value = int((param.value - param.min) / param_range * 127) elif param.name == 'Track Panning': name_string = self._mixer_for_encoders.channel_strip( self._encoders.index(sender)).track_name_data_source( ).display_string() + ' Pan' value = int(param.value / param_range * 127) if value < 0: name_string += ' L' elif value > 0: name_string += ' R' else: name_string += ' C' else: name_string = param.name value = int((param.value - param.min) / param_range * 127) value_string = str(value) else: name_string = '<unmapped>' value_string = None self.schedule_message(1, self._set_value_string) self._set_name_string(name_string) self._set_value_string(value_string) def _set_displays_to_default(self): self._name_display.segment(0).set_data_source( self._mixer_for_encoders.selected_strip().track_name_data_source()) self._name_display.update() self._update_bank_value() self._set_value_string(None) self._send_midi(SYSEX_START + LCD_HC_DEFAULT) def _set_name_string(self, name_string): self._name_display.segment(0).set_data_source( self._name_display_data_source) self._name_display_data_source.set_display_string(name_string) self._display_reset_delay = STANDARD_DISPLAY_DELAY def _set_value_string(self, value_string=None): if value_string != None: self._value_display_data_source.set_display_string(value_string) else: self._value_display.reset() def _set_bank_string(self, bank_string=None): if bank_string != None: self._bank_display_data_source.set_display_string(bank_string) else: self._bank_display.reset() def _update_bank_value(self): bank = (self._session.track_offset() + 1) / self._session.width() + 1 self._set_bank_string(str(bank)) def _install_mapping(self, midi_map_handle, control, parameter, feedback_delay, feedback_map): if not self._in_build_midi_map: raise AssertionError raise midi_map_handle != None or AssertionError raise control != None and parameter != None or AssertionError raise isinstance( parameter, Live.DeviceParameter.DeviceParameter) or AssertionError raise isinstance(control, InputControlElement) or AssertionError raise isinstance(feedback_delay, int) or AssertionError if not isinstance(feedback_map, tuple): raise AssertionError success = False feedback_rule = None feedback_rule = control.message_type( ) is MIDI_NOTE_TYPE and Live.MidiMap.NoteFeedbackRule() feedback_rule.note_no = 0 feedback_rule.vel_map = (0, ) elif control.message_type() is MIDI_CC_TYPE: feedback_rule = Live.MidiMap.CCFeedbackRule() feedback_rule.cc_no = 0 feedback_rule.cc_value_map = (0, ) elif control.message_type() is MIDI_PB_TYPE: feedback_rule = Live.MidiMap.PitchBendFeedbackRule() feedback_rule.value_pair_map = feedback_map raise feedback_rule != None or AssertionError feedback_rule.channel = control.message_channel() feedback_rule.delay_in_ms = feedback_delay success = control.message_type( ) is MIDI_NOTE_TYPE and Live.MidiMap.map_midi_note_with_feedback_map( midi_map_handle, parameter, control.message_channel(), control.message_identifier(), feedback_rule) elif control.message_type() is MIDI_CC_TYPE: success = Live.MidiMap.map_midi_cc_with_feedback_map( midi_map_handle, parameter, control.message_channel(), control.message_identifier(), control.message_map_mode(), feedback_rule, not control.needs_takeover()) elif control.message_type() is MIDI_PB_TYPE: success = Live.MidiMap.map_midi_pitchbend_with_feedback_map( midi_map_handle, parameter, control.message_channel(), feedback_rule, not control.needs_takeover()) return success
class Generic(ControlSurface): __doc__ = " Script for FCB1010 in APC emulation mode " _active_instances = [] def _combine_active_instances(): track_offset = 0 scene_offset = 0 for instance in Generic._active_instances: instance._activate_combination_mode(track_offset, scene_offset) track_offset += instance._session.width() _combine_active_instances = staticmethod(_combine_active_instances) def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._note_map_scenes = [] self._note_map_buttons = [] self._ctrl_map_sliders = [] self._note_map_trk_stop_buttons = [] self._note_map_trk_sel_buttons = [] self._note_map_trk_mute_buttons = [] self._note_map_trk_solo_buttons = [] self._note_map_trk_rec_buttons = [] self._ctrl_map_trk_volume = [] self._ctrl_map_trk_pan = [] self._ctrl_map_senda = [] self._ctrl_map_sendb = [] self._ctrl_map_sendc = [] self._note_map_bank_buttons = [] self._ctrl_map_parameter = [] self._load_MIDI_map() self._session = None self._session_zoom = None self._mixer = None self._setup_session_control() self._setup_mixer_control() self._session.set_mixer(self._mixer) self._setup_device_and_transport_control() self.set_highlighting_session_component(self._session) self._pads = [] self._load_pad_translations() self._do_combine() def disconnect(self): self._note_map_scenes = None self._note_map_buttons = None self._ctrl_map_sliders = None self._note_map_trk_stop_buttons = None self._note_map_trk_sel_buttons = None self._note_map_trk_mute_buttons = None self._note_map_trk_solo_buttons = None self._note_map_trk_rec_buttons = None self._ctrl_map_trk_volume = None self._ctrl_map_trk_pan = None self._ctrl_map_senda = None self._ctrl_map_sendb = None self._ctrl_map_sendc = None self._note_map_bank_buttons = None self._ctrl_map_parameter = None self._pads = None self._do_uncombine() self._shift_button = None self._session = None self._session_zoom = None self._mixer = None ControlSurface.disconnect(self) def _do_combine(self): if self not in Generic._active_instances: Generic._active_instances.append(self) Generic._combine_active_instances() def _do_uncombine(self): if ((self in Generic._active_instances) and Generic._active_instances.remove(self)): self._session.unlink() Generic._combine_active_instances() def _activate_combination_mode(self, track_offset, scene_offset): if TRACK_OFFSET != -1: track_offset = TRACK_OFFSET if SCENE_OFFSET != -1: scene_offset = SCENE_OFFSET self._session.link_with_track_offset(track_offset, scene_offset) def _setup_session_control(self): is_momentary = True self._session = SpecialSessionComponent(TRACK_NUMBER, MATRIX_DEPTH) self._session.name = 'Session_Control' self._session.set_track_bank_buttons(self._note_map_buttons[25], self._note_map_buttons[24]) self._session.set_scene_bank_buttons(self._note_map_buttons[27], self._note_map_buttons[26]) self._session.set_select_buttons(self._note_map_buttons[34], self._note_map_buttons[35]) self._scene_launch_buttons = [ self._note_map_scenes[index] for index in range(MATRIX_DEPTH) ] self._track_stop_buttons = [ self._note_map_trk_stop_buttons[index] for index in range(TRACK_NUMBER) ] self._session.set_stop_all_clips_button(self._note_map_buttons[38]) self._session.set_stop_track_clip_buttons( tuple(self._track_stop_buttons)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( self._note_map_buttons[36]) self._session.set_slot_launch_button(self._note_map_buttons[37]) for scene_index in range(MATRIX_DEPTH): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(self._scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(TRACK_NUMBER): if (CLIPNOTEMAP[scene_index][track_index] == -1): button = None else: button = ButtonElement( is_momentary, CLIPNOTEMAP_TYPE[scene_index][track_index], CLIPNOTEMAP_CH[scene_index][track_index], CLIPNOTEMAP[scene_index][track_index]) button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) clip_slot.set_launch_button(button) self._session_zoom = SpecialZoomingComponent(self._session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_nav_buttons(self._note_map_buttons[28], self._note_map_buttons[29], self._note_map_buttons[30], self._note_map_buttons[31]) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(TRACK_NUMBER) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.master_strip().set_select_button( self._note_map_buttons[39]) self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._mixer.set_select_buttons(self._note_map_buttons[33], self._note_map_buttons[32]) self._mixer.set_crossfader_control(self._ctrl_map_sliders[2]) self._mixer.set_prehear_volume_control(self._ctrl_map_sliders[1]) self._mixer.master_strip().set_volume_control( self._ctrl_map_sliders[0]) for track in range(TRACK_NUMBER): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) strip.set_arm_button(self._note_map_trk_rec_buttons[track]) strip.set_solo_button(self._note_map_trk_solo_buttons[track]) strip.set_mute_button(self._note_map_trk_mute_buttons[track]) strip.set_select_button(self._note_map_trk_sel_buttons[track]) strip.set_volume_control(self._ctrl_map_trk_volume[track]) strip.set_pan_control(self._ctrl_map_trk_pan[track]) strip.set_send_controls( (self._ctrl_map_senda[track], self._ctrl_map_sendb[track], self._ctrl_map_sendc[track])) strip.set_invert_mute_feedback(True) def _setup_device_and_transport_control(self): is_momentary = True self._device = DeviceComponent() self._device.name = 'Device_Component' device_bank_buttons = [] device_param_controls = [] for index in range(PARAMS_NUMBER): device_param_controls.append(self._ctrl_map_parameter[index]) for index in range(BANKS_NUMBER): device_bank_buttons.append(self._note_map_bank_buttons[index]) if None not in device_bank_buttons: self._device.set_bank_buttons(tuple(device_bank_buttons)) if None not in device_param_controls: self._device.set_parameter_controls(tuple(device_param_controls)) self._device.set_on_off_button(self._note_map_buttons[17]) self._device.set_bank_nav_buttons(self._note_map_buttons[20], self._note_map_buttons[21]) self._device.set_lock_button(self._note_map_buttons[16]) self.set_device_component(self._device) detail_view_toggler = DetailViewControllerComponent() detail_view_toggler.name = 'Detail_View_Control' detail_view_toggler.set_device_clip_toggle_button( self._note_map_buttons[15]) detail_view_toggler.set_detail_toggle_button( self._note_map_buttons[14]) detail_view_toggler.set_device_nav_buttons(self._note_map_buttons[18], self._note_map_buttons[19]) transport = SpecialTransportComponent() transport.name = 'Transport' transport.set_play_button(self._note_map_buttons[0]) transport.set_stop_button(self._note_map_buttons[1]) transport.set_record_button(self._note_map_buttons[2]) transport.set_nudge_buttons(self._note_map_buttons[4], self._note_map_buttons[5]) transport.set_undo_button(self._note_map_buttons[6]) transport.set_redo_button(self._note_map_buttons[7]) transport.set_tap_tempo_button(self._note_map_buttons[3]) transport.set_quant_toggle_button(self._note_map_buttons[13]) transport.set_overdub_button(self._note_map_buttons[11]) transport.set_metronome_button(self._note_map_buttons[12]) transport.set_tempo_control(self._ctrl_map_sliders[3]) transport.set_loop_button(self._note_map_buttons[8]) transport.set_seek_buttons(self._note_map_buttons[22], self._note_map_buttons[23]) transport.set_punch_buttons(self._note_map_buttons[9], self._note_map_buttons[10]) def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) def _load_pad_translations(self): if -1 not in DRUM_PADS: pad = [] for row in range(PAD_Y_NUMBER): for col in range(PAD_X_NUMBER): pad = ( col, row, DRUM_PADS[row * 4 + col], PADCHANNEL, ) self._pads.append(pad) self.set_pad_translations(tuple(self._pads)) def _load_MIDI_map(self): is_momentary = True # SCENELAUNCH Buttons for scene_id in range(MATRIX_DEPTH): if (SCENELAUNCH[scene_id] == -1): button = None else: button = ButtonElement(is_momentary, SCENELAUNCH_TYPE[scene_id], SCENELAUNCH_CH[scene_id], SCENELAUNCH[scene_id]) button.name = 'Scene_' + str(scene_id) self._note_map_scenes.append(button) # BUTTON_VECTOR Buttons for button_id in range(NUMBER_BUTTONS): if (BUTTON_VECTOR[button_id] == -1): button = None else: button = ButtonElement(is_momentary, BUTTON_VECTOR_TYPE[button_id], BUTTON_VECTOR_CH[button_id], BUTTON_VECTOR[button_id]) button.name = 'Global_Button_' + str(button_id) self._note_map_buttons.append(button) # SLIDER_VECTOR Sliders for slider_id in range(NUMBER_SLIDERS): if (SLIDER_VECTOR[slider_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, SLIDER_VECTOR_CH[slider_id], SLIDER_VECTOR[slider_id]) control.name = 'Global_Slider_' + str(slider_id) self._ctrl_map_sliders.append(control) # TRACKSTOP Buttons for track_id in range(TRACK_NUMBER): if (TRACKSTOP[track_id] == -1): button = None else: button = ButtonElement(is_momentary, TRACKSTOP_TYPE[track_id], TRACKSTOP_CH[track_id], TRACKSTOP[track_id]) button.name = 'Trk_Stop_Button_' + str(track_id) self._note_map_trk_stop_buttons.append(button) # TRACKSEL Buttons for track_id in range(TRACK_NUMBER): if (TRACKSEL[track_id] == -1): button = None else: button = ButtonElement(is_momentary, TRACKSEL_TYPE[track_id], TRACKSEL_CH[track_id], TRACKSEL[track_id]) button.name = 'Trk_Sel_Button_' + str(track_id) self._note_map_trk_sel_buttons.append(button) # TRACKMUTE Buttons for track_id in range(TRACK_NUMBER): if (TRACKMUTE[track_id] == -1): button = None else: button = ButtonElement(is_momentary, TRACKMUTE_TYPE[track_id], TRACKMUTE_CH[track_id], TRACKMUTE[track_id]) button.name = 'Trk_Mute_Button_' + str(track_id) self._note_map_trk_mute_buttons.append(button) # TRACKSOLO Buttons for track_id in range(TRACK_NUMBER): if (TRACKSOLO[track_id] == -1): button = None else: button = ButtonElement(is_momentary, TRACKSOLO_TYPE[track_id], TRACKSOLO_CH[track_id], TRACKSOLO[track_id]) button.name = 'Trk_Solo_Button_' + str(track_id) self._note_map_trk_solo_buttons.append(button) # TRACKREC Buttons for track_id in range(TRACK_NUMBER): if (TRACKREC[track_id] == -1): button = None else: button = ButtonElement(is_momentary, TRACKREC_TYPE[track_id], TRACKREC_CH[track_id], TRACKREC[track_id]) button.name = 'Trk_Rec_Button_' + str(track_id) self._note_map_trk_rec_buttons.append(button) # TRACKVOL Sliders for track_id in range(TRACK_NUMBER): if (TRACKVOL[track_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, TRACKVOL_CH[track_id], TRACKVOL[track_id]) control.name = 'Trk_Vol_Slider_' + str(track_id) self._ctrl_map_trk_volume.append(control) # TRACKPAN Sliders for track_id in range(TRACK_NUMBER): if (TRACKPAN[track_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, TRACKPAN_CH[track_id], TRACKPAN[track_id]) control.name = 'Trk_Pan_Slider_' + str(track_id) self._ctrl_map_trk_pan.append(control) # TRACKSENDA Sliders for track_id in range(TRACK_NUMBER): if (TRACKSENDA[track_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, TRACKSENDA_CH[track_id], TRACKSENDA[track_id]) control.name = 'Trk_SendA_Slider_' + str(track_id) self._ctrl_map_senda.append(control) # TRACKSENDB Sliders for track_id in range(TRACK_NUMBER): if (TRACKSENDB[track_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, TRACKSENDB_CH[track_id], TRACKSENDB[track_id]) control.name = 'Trk_SendB_Slider_' + str(track_id) self._ctrl_map_sendb.append(control) # TRACKSENDC Sliders for track_id in range(TRACK_NUMBER): if (TRACKSENDC[track_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, TRACKSENDC_CH[track_id], TRACKSENDC[track_id]) control.name = 'Trk_SendC_Slider_' + str(track_id) self._ctrl_map_sendc.append(control) # DEVICEBANK Buttons for bank_id in range(BANKS_NUMBER): if (DEVICEBANK[bank_id] == -1): button = None else: button = ButtonElement(is_momentary, DEVICEBANK_TYPE[bank_id], DEVICEBANK_CH[bank_id], DEVICEBANK[bank_id]) button.name = 'Bank_Button_' + str(bank_id) self._note_map_bank_buttons.append(button) # PARAMCONTROL Sliders for param_id in range(PARAMS_NUMBER): if (PARAMCONTROL[param_id] == -1): control = None else: control = SliderElement(MIDI_CC_TYPE, PARAMCONTROL_CH[param_id], PARAMCONTROL[param_id]) control.name = 'Slider_Param_' + str(param_id) self._ctrl_map_parameter.append(control)
class Midi_Fighter_Twister(ControlSurface): __doc__ = " Script for Midi_Fighter_Twister in APC emulation mode " _active_instances = [] def _combine_active_instances(): track_offset = 0 scene_offset = 0 for instance in Midi_Fighter_Twister._active_instances: instance._activate_combination_mode(track_offset, scene_offset) track_offset += instance._session.width() _combine_active_instances = staticmethod(_combine_active_instances) def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) #self.set_suppress_rebuild_requests(True) with self.component_guard(): self._note_map = [] self._ctrl_map = [] self._shift_encoder_map = [] self._shift_bank_map = [] self._load_MIDI_map() self._session = None self._session_zoom = None self._mixer = None self._setup_session_control() self._setup_mixer_control() self._session.set_mixer(self._mixer) self._setup_device_and_transport_control() self.set_highlighting_session_component(self._session) #self.set_suppress_rebuild_requests(False) self._pads = [] self._load_pad_translations() self._do_combine() def disconnect(self): self._note_map = None self._ctrl_map = None self._shift_encoder_map = None self._shift_bank_map = None self._pads = None self._do_uncombine() self._shift_button = None self._session = None self._session_zoom = None self._mixer = None self._device = None ControlSurface.disconnect(self) def _do_combine(self): if self not in Midi_Fighter_Twister._active_instances: Midi_Fighter_Twister._active_instances.append(self) Midi_Fighter_Twister._combine_active_instances() def _do_uncombine(self): if ((self in Midi_Fighter_Twister._active_instances) and Midi_Fighter_Twister._active_instances.remove(self)): self._session.unlink() Midi_Fighter_Twister._combine_active_instances() def _activate_combination_mode(self, track_offset, scene_offset): if TRACK_OFFSET != -1: track_offset = TRACK_OFFSET if SCENE_OFFSET != -1: scene_offset = SCENE_OFFSET self._session.link_with_track_offset(track_offset, scene_offset) def _setup_session_control(self): is_momentary = True # sessionRight = ButtonElement(is_momentary, 1, 3, 11) # sessionLeft = ButtonElement(is_momentary, 1, 3, 8) self._session = SpecialSessionComponent(4, 4) self._session.name = 'Session_Control' self._session.set_track_bank_buttons( self._shift_bank_map[SESSIONRIGHT], self._shift_bank_map[SESSIONLEFT]) # self._session.set_track_bank_buttons(sessionRight, sessionLeft) self._session.set_scene_bank_buttons(self._note_map[SESSIONDOWN], self._note_map[SESSIONUP]) self._session.set_select_buttons(self._note_map[SCENEDN], self._note_map[SCENEUP]) self._scene_launch_buttons = [ self._note_map[SCENELAUNCH[index]] for index in range(4) ] self._track_stop_buttons = [ self._note_map[TRACKSTOP[index]] for index in range(4) ] self._session.set_stop_all_clips_button(self._note_map[STOPALLCLIPS]) self._session.set_stop_track_clip_buttons( tuple(self._track_stop_buttons)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( self._note_map[SELSCENELAUNCH]) self._session.set_slot_launch_button(self._note_map[SELCLIPLAUNCH]) for scene_index in range(4): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(self._scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(4): button = self._note_map[CLIPNOTEMAP[scene_index][track_index]] button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) clip_slot.set_launch_button(button) self._session_zoom = SpecialZoomingComponent(self._session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_nav_buttons(self._note_map[ZOOMUP], self._note_map[ZOOMDOWN], self._note_map[ZOOMLEFT], self._note_map[ZOOMRIGHT]) def _setup_mixer_control(self): is_momentary = True MasterVol = ButtonElement(is_momentary, 1, 4, 3) self._mixer = SpecialMixerComponent(4) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.master_strip().set_select_button(self._note_map[MASTERSEL]) self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._mixer.set_select_buttons(self._note_map[TRACKRIGHT], self._note_map[TRACKLEFT]) self._mixer.set_crossfader_control(self._ctrl_map[CROSSFADER]) self._mixer.set_prehear_volume_control(self._ctrl_map[CUELEVEL]) self._mixer.master_strip().set_volume_control( self._shift_encoder_map[MASTERVOLUME]) for track in range(4): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) strip.set_arm_button(self._note_map[TRACKREC[track]]) strip.set_solo_button(self._note_map[TRACKSOLO[track]]) strip.set_mute_button(self._note_map[TRACKMUTE[track]]) strip.set_select_button(self._note_map[TRACKSEL[track]]) strip.set_volume_control(self._ctrl_map[TRACKVOL[track]]) strip.set_pan_control(self._ctrl_map[TRACKPAN[track]]) strip.set_send_controls((self._ctrl_map[TRACKSENDA[track]], self._ctrl_map[TRACKSENDB[track]], self._ctrl_map[TRACKSENDC[track]])) strip.set_invert_mute_feedback(True) # have right side btns act as device next/prev & toggle on/off? def _setup_device_and_transport_control(self): is_momentary = True # self._device = DeviceComponent() # self._device.name = 'Device_Component' # uses BestBankDeviceComponent as pseudo for Device_Component self._device = BestBankDeviceComponent( device_selection_follows_track_selection=True) self._device.name = u'Device_Component' # device_bank_buttons = [] device_param_controls = [] # Accounts for mappings on top two rows of MFT for index in range(16): # handles all 16 encoder knobs device_param_controls.append(self._ctrl_map[PARAMCONTROL[index]]) for index in range(4): # 1st row, shift encoder hold device_param_controls.append( self._shift_encoder_map[PARAMCONTROL[index]]) for index in range(6): # 2nd row & left-half of 3rd row, CC hold device_param_controls.append(self._note_map[PARAMCONTROL[index + 4]]) # Accounts for mappings on third row of MFT # for index in range(4): # device_param_controls.append(self._shift_encoder_map[PARAMCONTROL[index + 8]]) # device_bank_buttons.append(self._note_map[DEVICEBANK[index]]) # if None not in device_bank_buttons: # self._device.set_bank_buttons(tuple(device_bank_buttons)) if None not in device_param_controls: self._device.set_parameter_controls(tuple(device_param_controls)) self._device.set_on_off_button(self._shift_bank_map[DEVICEONOFF]) # self._device.set_bank_nav_buttons(self._shift_bank_map[DEVICEBANKNAVLEFT], self._shift_bank_map[DEVICEBANKNAVRIGHT]) self._device.set_bank_nav_buttons(self._note_map[DEVICEBANKNAVLEFT], self._note_map[DEVICEBANKNAVRIGHT]) self._device.set_lock_button(self._note_map[DEVICELOCK]) self.set_device_component(self._device) detail_view_toggler = DetailViewControllerComponent() detail_view_toggler.name = 'Detail_View_Control' detail_view_toggler.set_device_clip_toggle_button( self._shift_bank_map[CLIPTRACKVIEW]) detail_view_toggler.set_detail_toggle_button( self._shift_bank_map[DETAILVIEW]) # detail_view_toggler.set_device_nav_buttons(self._note_map[DEVICENAVLEFT], self._note_map[DEVICENAVRIGHT] ) detail_view_toggler.set_device_nav_buttons( self._shift_bank_map[DEVICENAVLEFT], self._shift_bank_map[DEVICENAVRIGHT]) transport = SpecialTransportComponent() transport.name = 'Transport' transport.set_play_button(self._note_map[PLAY]) transport.set_stop_button(self._note_map[STOP]) transport.set_record_button(self._note_map[REC]) transport.set_nudge_buttons(self._note_map[NUDGEUP], self._note_map[NUDGEDOWN]) transport.set_undo_button(self._shift_bank_map[UNDO]) transport.set_redo_button(self._note_map[REDO]) transport.set_tap_tempo_button(self._note_map[TAPTEMPO]) transport.set_quant_toggle_button(self._note_map[RECQUANT]) transport.set_overdub_button(self._note_map[OVERDUB]) transport.set_metronome_button(self._note_map[METRONOME]) transport.set_tempo_control(self._ctrl_map[TEMPOCONTROL]) transport.set_loop_button(self._note_map[LOOP]) transport.set_seek_buttons(self._note_map[SEEKFWD], self._note_map[SEEKRWD]) transport.set_punch_buttons(self._note_map[PUNCHIN], self._note_map[PUNCHOUT]) ##transport.set_song_position_control(self._ctrl_map[SONGPOSITION]) #still not implemented as of Live 8.1.6 def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) # From Axiom_AIR_25_49_61.py line 202 track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) # BEGIN update(self) FROM EncoderModeSelector.py # # todo: Move this block to a file where 'self._ctrl_map[PARAMCONTROL[index]]' # is accessible (MFT see line 164 for example) # if self.is_enabled(): # self._device.set_allow_update(False) # self._mixer.set_allow_update(False) # self._device.set_parameter_controls(()) # self._mixer.set_send_controls(()) # for index in range(len(self._encoders)): # strip = self._mixer.channel_strip(index) # encoder = self._encoders[index] # strip.set_volume_control(None) # strip.set_pan_control(None) # encoder.release_parameter() # if self._mode_index == 0: # strip.set_volume_control(encoder) # encoder.set_on_off_values(AMB_FULL, LED_OFF) # elif self._mode_index == 1: # strip.set_pan_control(encoder) # encoder.set_on_off_values(RED_FULL, LED_OFF) # elif self._mode_index == 2: # encoder.set_on_off_values(GRN_FULL, LED_OFF) # elif self._mode_index == 3: # encoder.set_on_off_values(RED_FULL, LED_OFF) # if self._mode_index == 0: # self._modes_buttons[0].send_value(AMB_FULL, True) # self._modes_buttons[1].send_value(LED_OFF, True) # elif self._mode_index == 1: # self._modes_buttons[0].send_value(RED_FULL, True) # self._modes_buttons[1].send_value(LED_OFF, True) # elif self._mode_index == 2: # self._modes_buttons[0].send_value(GRN_FULL, True) # self._modes_buttons[1].send_value(LED_OFF, True) # self._mixer.set_send_controls(self._encoders) # elif self._mode_index == 3: # self._modes_buttons[0].send_value(LED_OFF, True) # self._modes_buttons[1].send_value(RED_FULL, True) # self._device.set_parameter_controls(self._encoders) # self._device.set_allow_update(True) # # END update(self) FROM EncoderModeSelector.py def _load_pad_translations(self): if -1 not in DRUM_PADS: pad = [] for row in range(4): for col in range(4): pad = ( col, row, DRUM_PADS[row * 4 + col], PADCHANNEL, ) self._pads.append(pad) self.set_pad_translations(tuple(self._pads)) def _load_MIDI_map(self): is_momentary = True for note in range(128): button = ButtonElement(is_momentary, MESSAGETYPE, BUTTONCHANNEL, note) button.name = 'Note_' + str(note) self._note_map.append(button) # CC Hold, CC Toggle shift_bank_button = ButtonElement(is_momentary, MESSAGETYPE, SHIFTBANKCHANNEL, note) shift_bank_button.name = 'Note_' + str(note) self._shift_bank_map.append(shift_bank_button) # Shift Bank shift_encoder = ButtonElement(is_momentary, 1, ENCODERSHIFTCHANNEL, note) shift_encoder.name = 'Note_' + str(note) self._shift_encoder_map.append(shift_encoder) # Shift Encoder Hold self._note_map.append( None) #add None to the end of the list, selectable with [-1] self._shift_encoder_map.append(None) self._shift_bank_map.append(None) if MESSAGETYPE == MIDI_CC_TYPE and BUTTONCHANNEL == SLIDERCHANNEL: for ctrl in range(128): self._ctrl_map.append(None) else: for ctrl in range(128): control = SliderElement(MIDI_CC_TYPE, SLIDERCHANNEL, ctrl) control.name = 'Ctrl_' + str(ctrl) self._ctrl_map.append(control) # Standard Encoder self._ctrl_map.append(None)
def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(self, 8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) master_select_button.name = 'Master_Select_Button' self._mixer.master_strip().set_select_button(master_select_button) self._mixer.selected_strip().name = 'Selected_Channel_Strip' select_buttons = [] arm_buttons = [] solo_buttons = [] mute_buttons = [] sliders = [] for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) solo_buttons.append(solo_button) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) mute_buttons.append(mute_button) solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) select_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) select_buttons[-1].name = str(track) + '_Select_Button' arm_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) arm_buttons[-1].name = str(track) + '_Arm_Button' sliders.append(SliderElement(MIDI_CC_TYPE, track, 7)) sliders[-1].name = str(track) + '_Volume_Control' self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) self._prehear_control = EncoderElement( MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) self._crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' self._prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_shift_button(self._shift_button) self._mixer.set_crossfader_control(self._crossfader) self._mixer.set_prehear_volume_control(self._prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) self._slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) self._slider_modes.name = 'Slider_Modes' self._matrix_modes = MatrixModesComponent( self._matrix, self._session, self._session_zoom, tuple(self._track_stop_buttons), self) self._matrix_modes.name = 'Matrix_Modes' self._sequencer = StepSequencerComponent( self, self._session, self._matrix, tuple(self._track_stop_buttons)) self._sequencer.set_bank_buttons(tuple(select_buttons)) self._sequencer.set_nav_buttons(self._up_button, self._down_button, self._left_button, self._right_button) self._sequencer.set_button_matrix(self._matrix) self._sequencer.set_follow_button(master_select_button) self._sequencer.set_velocity_buttons(tuple(arm_buttons)) self._sequencer.set_shift_button(self._shift_button) self._sequencer.set_lane_mute_buttons(tuple( self._scene_launch_buttons)) self._sequencer.set_loop_start_buttons(tuple(mute_buttons)) self._sequencer.set_loop_length_buttons(tuple(solo_buttons)) self._shift_modes = ShiftableSelectorComponent( self, tuple(select_buttons), master_select_button, tuple(self._track_stop_buttons), self._stop_all_button, tuple(mute_buttons), tuple(solo_buttons), tuple(arm_buttons), tuple(self._scene_launch_buttons), self._matrix, self._session, self._session_zoom, self._mixer, self._slider_modes, self._matrix_modes, self._sequencer) self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button)
class Novation_Impulse(ControlSurface): """ Script for Novation's Impulse keyboards """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) self._device_selection_follows_track_selection = True self._suggested_input_port = 'Impulse' self._suggested_output_port = 'Impulse' self._has_sliders = True self._current_midi_map = None self._display_reset_delay = -1 self._shift_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 39) self._preview_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 41) self._master_slider = SliderElement(MIDI_CC_TYPE, 0, 8) self._shift_button.name = 'Shift_Button' self._master_slider.name = 'Master_Volume_Control' self._master_slider.add_value_listener(self._slider_value, identify_sender=True) self._preview_button.add_value_listener(self._preview_value) self._setup_mixer() self._setup_session() self._setup_transport() self._setup_device() self._setup_name_display() device_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1, 10) mixer_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1, 9) device_button.name = 'Encoder_Device_Mode' mixer_button.name = 'Encoder_Mixer_Mode' self._encoder_modes = EncoderModeSelector(self._device_component, self._mixer, self._next_bank_button, self._prev_bank_button, self._encoders) self._encoder_modes.set_device_mixer_buttons(device_button, mixer_button) self._string_to_display = None for component in self.components: component.set_enabled(False) def 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._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) ControlSurface.disconnect(self) self._encoders = None self._sliders = None self._strip_buttons = None self._master_slider = None self._current_midi_map = None self._shift_button = 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._send_midi(SYSEX_START + (6, 0, 0, 0, 247)) 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._mixer.name = 'Mixer' self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button) self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.master_strip().set_volume_control(self._master_slider) self._sliders = [] for index in range(8): strip = self._mixer.channel_strip(index) strip.name = 'Channel_Strip_' + str(index) strip.set_invert_mute_feedback(True) self._sliders.append(SliderElement(MIDI_CC_TYPE, 0, index)) self._sliders[-1].name = str(index) + '_Volume_Control' self._sliders[-1].set_feedback_delay(-1) self._sliders[-1].add_value_listener(self._slider_value, identify_sender=True) strip.set_volume_control(self._sliders[-1]) self._strip_buttons.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + index)) self._strip_buttons[-1].name = str(index) + '_Mute_Button' self._strip_buttons[-1].add_value_listener(self._mixer_button_value, identify_sender=True) self._mixer.master_strip().set_mute_button(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 17)) self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button) def _setup_session(self): num_pads = len(PAD_TRANSLATIONS) 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 = SessionComponent(8, 0) self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.set_mixer(self._mixer) 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' transport = ShiftableTransportComponent() transport.name = 'Transport' transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_record_button(rec_button) transport.set_shift_button(self._shift_button) self._transport_view_modes = TransportViewModeSelector(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 self._set_string_to_display(display_string) def _slider_value(self, value, 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 = ' - ' if sender.mapped_parameter() != None: master = self.song().master_track tracks = self.song().tracks returns = self.song().return_tracks track = None if sender == self._master_slider: track = self._has_sliders and master else: track = self.song().view.selected_track else: track = self._mixer.channel_strip(self._sliders.index(sender))._track display_string = track == master and '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 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: 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): raise value in range(128) or 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): raise isinstance(string_to_display, (str, unicode)) or 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): ControlSurface._on_selected_track_changed(self) self._show_current_track_name() all_tracks = self._has_sliders or 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 if not new_offset / num_strips == int(new_offset / num_strips): raise AssertionError self._session.set_offsets(new_offset, self._session.scene_offset())
class SubSelectorComponent(ModeSelectorComponent): """ Class that handles different mixer modes """ def __init__(self, matrix, side_buttons, session, control_surface): assert isinstance(matrix, ButtonMatrixElement) assert ((matrix.width() == 8) and (matrix.height() == 8)) assert isinstance(side_buttons, tuple) assert (len(side_buttons) == 8) assert isinstance(session, SessionComponent) ModeSelectorComponent.__init__(self) self._control_surface = control_surface self._session = session self._mixer = SpecialMixerComponent(matrix.width()) self._matrix = matrix self._sliders = [] self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_strip' self._mixer.selected_strip().name = 'Selected_Channel_strip' for column in range(matrix.width()): self._mixer.channel_strip( column).name = 'Channel_Strip_' + str(column) self._sliders.append( PreciseButtonSliderElement( tuple([ matrix.get_button(column, 7 - row) for row in range(8) ]))) self._sliders[-1].name = 'Button_Slider_' + str(column) self._side_buttons = side_buttons[4:] self._update_callback = None self._session.set_mixer(self._mixer) self.set_modes_buttons(side_buttons[:4]) def disconnect(self): for button in self._modes_buttons: button.remove_value_listener(self._mode_value) self._session = None self._mixer = None for slider in self._sliders: slider.release_parameter() slider.set_disabled(True) self._sliders = None self._matrix = None self._side_buttons = None self._update_callback = None ModeSelectorComponent.disconnect(self) def set_update_callback(self, callback): assert (dir(callback).count("im_func") is 1) self._update_callback = callback def set_modes_buttons(self, buttons): assert ((buttons == None) or (isinstance(buttons, tuple) or (len(buttons) == self.number_of_modes()))) identify_sender = True for button in self._modes_buttons: button.remove_value_listener(self._mode_value) self._modes_buttons = [] if buttons != None: for button in buttons: assert isinstance(button, ButtonElement) self._modes_buttons.append(button) button.add_value_listener(self._mode_value, identify_sender) def set_mode(self, mode): assert isinstance(mode, int) assert (mode in range(-1, self.number_of_modes())) if ((self._mode_index != mode) or (mode == -1)): self._mode_index = mode self.update() def mode(self): result = 0 if self.is_enabled(): result = self._mode_index + 1 return result def number_of_modes(self): return 4 def on_enabled_changed(self): enabled = self.is_enabled() for index in range(self._matrix.width()): self._sliders[index].set_disabled(not enabled) self._mixer.set_enabled(enabled) self.set_mode(-1) def release_controls(self): for track in range(self._matrix.width()): for row in range(self._matrix.height()): self._matrix.get_button(track, row).set_on_off_values( 127, "DefaultButton.Disabled") strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_send_controls((None, None)) strip.set_pan_control(None) strip.set_volume_control(None) self._session.set_stop_track_clip_buttons(None) self._mixer.set_global_buttons(None, None, None) self._session.set_stop_all_clips_button(None) def update(self): assert (self._modes_buttons != None) if self.is_enabled(): if (self._modes_buttons != None): for index in range(len(self._modes_buttons)): button = self._modes_buttons[index] if index == 0: button.set_on_off_values("Mixer.Volume") elif index == 1: button.set_on_off_values("Mixer.Pan") elif index == 2: button.set_on_off_values("Mixer.Sends") elif index == 3: button.set_on_off_values("Mixer.Sends") elif index == 4: button.set_on_off_values("Mixer.Stop") elif index == 5: button.set_on_off_values("Mixer.Mute") elif index == 6: button.set_on_off_values("Mixer.Solo") elif index == 7: button.set_on_off_values("Mixer.Arm") if (index == self._mode_index): button.turn_on() else: button.turn_off() for button in self._side_buttons: button.set_on_off_values(127, "DefaultButton.Disabled") button.turn_off() for index in range(self._matrix.width()): self._sliders[index].set_disabled((self._mode_index == -1)) self._mixer.set_allow_update(False) self._session.set_allow_update(False) if self._mode_index == -1: self._setup_mixer_overview() elif self._mode_index == 0: self._setup_volume_mode() elif self._mode_index == 1: self._setup_pan_mode() elif self._mode_index == 2: self._setup_send1_mode() elif self._mode_index == 3: self._setup_send2_mode() else: assert False if (self._update_callback != None): self._update_callback() self._mixer.set_allow_update(True) self._session.set_allow_update(True) #else: #self.release_controls() def _setup_mixer_overview(self): stop_buttons = [] for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_send_controls((None, None)) strip.set_pan_control(None) strip.set_volume_control(None) self._sliders[track].release_parameter() for row in range(self._matrix.height()): if row == 0: self._matrix.get_button( track, row).set_on_off_values("Mixer.Volume") elif row == 1: self._matrix.get_button(track, row).set_on_off_values("Mixer.Pan") elif row == 2: self._matrix.get_button( track, row).set_on_off_values("Mixer.Sends") elif row == 3: self._matrix.get_button( track, row).set_on_off_values("Mixer.Sends") elif row == 4: self._matrix.get_button( track, row).set_on_off_values("Mixer.Stop") elif row == 5: self._matrix.get_button( track, row).set_on_off_values("Mixer.Mute") elif row == 6: self._matrix.get_button( track, row).set_on_off_values("Mixer.Solo") elif row == 7: self._matrix.get_button(track, row).set_on_off_values("Mixer.Arm") strip.set_default_buttons(self._matrix.get_button(track, 0), self._matrix.get_button(track, 1), self._matrix.get_button(track, 2), self._matrix.get_button(track, 3)) stop_buttons.append(self._matrix.get_button(track, 4)) strip.set_mute_button(self._matrix.get_button(track, 5)) strip.set_solo_button(self._matrix.get_button(track, 6)) strip.set_arm_button(self._matrix.get_button(track, 7)) for button in self._side_buttons: if row == 0: button.set_on_off_values("Mixer.Volume") elif row == 1: button.set_on_off_values("Mixer.Pan") elif row == 2: button.set_on_off_values("Mixer.Sends") elif row == 3: button.set_on_off_values("Mixer.Sends") elif row == 4: button.set_on_off_values("Mixer.Stop") elif row == 5: button.set_on_off_values("Mixer.Mute") elif row == 6: button.set_on_off_values("Mixer.Solo") elif row == 7: button.set_on_off_values("Mixer.Arm") button.force_next_send() button.turn_on() self._session.set_stop_track_clip_buttons(tuple(stop_buttons)) self._session.set_stop_all_clips_button(self._side_buttons[0]) self._mixer.set_global_buttons(self._side_buttons[3], self._side_buttons[2], self._side_buttons[1]) def _setup_volume_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_send_controls((None, None)) strip.set_pan_control(None) for row in range(self._matrix.height()): self._matrix.get_button( track, row).set_on_off_values("Mixer.VolumeSlider") self._sliders[track].set_mode(SLIDER_MODE_VOLUME) self._sliders[track].set_value_map(VOL_VALUE_MAP) strip.set_volume_control(self._sliders[track]) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None) def _setup_pan_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_send_controls((None, None)) strip.set_volume_control(None) for row in range(self._matrix.height()): self._matrix.get_button( track, row).set_on_off_values("Mixer.PanSlider") self._sliders[track].set_mode(SLIDER_MODE_PAN) self._sliders[track].set_value_map(PAN_VALUE_MAP) strip.set_pan_control(self._sliders[track]) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None) def _setup_send1_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_volume_control(None) strip.set_pan_control(None) for row in range(self._matrix.height()): self._matrix.get_button( track, row).set_on_off_values("Mixer.SendsSlider") self._sliders[track].set_mode(SLIDER_MODE_VOLUME) self._sliders[track].set_value_map(SEND_VALUE_MAP) strip.set_send_controls((self._sliders[track], None)) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None) def _setup_send2_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_volume_control(None) strip.set_pan_control(None) for row in range(self._matrix.height()): self._matrix.get_button( track, row).set_on_off_values("Mixer.SendsSlider") self._sliders[track].set_mode(SLIDER_MODE_VOLUME) self._sliders[track].set_value_map(SEND_VALUE_MAP) strip.set_send_controls((None, self._sliders[track])) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None)
class LaunchControl(ControlSurface): def __init__(self, c_instance): super(LaunchControl, self).__init__(c_instance) with self.component_guard(): self._device_selection_follows_track_selection = True self._init_mixer() self._init_session() self._init_device() self._init_modes() self._refresh_state_task = self._tasks.add(Task.sequence(Task.delay(3), Task.run(self._do_refresh_state))) self._refresh_state_task.kill() self.log_message('Launch Control script loaded') def disconnect(self): super(LaunchControl, self).disconnect() for channel in xrange(16): self._send_midi((CC_STATUS + channel, 0, 0)) def refresh_state(self): self._refresh_state_task.restart() def _do_refresh_state(self): self._send_current_mode() self._update_hardware() self.schedule_message(3, super(LaunchControl, self).refresh_state) def _update_hardware(self): for channel in xrange(8, 11): self._send_midi(Sysex.make_automatic_flashing_message(channel)) def _send_current_mode(self): try: self._send_midi(MODE_SYSEX_MAP[self._modes.selected_mode]) except KeyError: pass def _init_mixer(self): make_button = partial(make_launch_control_button, channel=8) make_encoder = partial(make_launch_control_encoder, channel=8) bottom_encoders, top_encoders = make_all_encoders('Mixer', make_encoder) pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders])) sends_layer = Layer(sends_controls=ButtonMatrixElement(rows=[bottom_encoders, top_encoders])) modes_layer = Layer(pan_volume_button=make_button(114, 'Pan_Volume_Mode_Button'), sends_button=make_button(115, 'Sends_Mode_Button')) self._mixer = SpecialMixerComponent(8, modes_layer, pan_volume_layer, sends_layer) self._mixer.set_enabled(False) self._mixer.name = 'Mixer' self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer_track_nav_layer = Layer(track_bank_left_button=make_button(116, 'Mixer_Track_Left_Button'), track_bank_right_button=make_button(117, 'Mixer_Track_Right_Button')) for index in xrange(8): strip = self._mixer.channel_strip(index) strip.name = 'Channel_Strip_' + str(index) strip.empty_color = Colors.LED_OFF strip.set_invert_mute_feedback(True) mute_button = make_button(pad_identifiers[index], 'Track_Mute_Button_' + str(index), is_pad=True) mute_button.set_on_off_values(Colors.AMBER_FULL, Colors.AMBER_THIRD) strip.set_mute_button(mute_button) self._on_selected_send_index.subject = self._mixer self._on_selected_mixer_mode.subject = self._mixer def _init_session(self): make_button = partial(make_launch_control_button, channel=9) make_encoder = partial(make_launch_control_encoder, channel=9) bottom_encoders, top_encoders = make_all_encoders('Session_Mixer', make_encoder) pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders])) self._session_mixer = SpecialMixerComponent(8, Layer(), pan_volume_layer, Layer()) self._session_mixer.set_enabled(False) self._session_mixer.name = 'Session_Mixer' clip_launch_buttons = [ make_button(identifier, 'Clip_Launch_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ] self._session = SpecialSessionComponent(num_tracks=8, num_scenes=0, name='Session') self._session.set_enabled(False) self._session.set_mixer(self._session_mixer) self._session_layer = Layer(track_bank_left_button=make_button(116, 'Track_Bank_Left_Button'), track_bank_right_button=make_button(117, 'Track_Bank_Right_Button'), select_prev_button=make_button(114, 'Scene_Bank_Up_Button'), select_next_button=make_button(115, 'Scene_Bank_Down_Button'), clip_launch_buttons=ButtonMatrixElement(rows=[clip_launch_buttons])) scene = self._session.selected_scene() for index in range(8): clip_slot = scene.clip_slot(index) clip_slot.set_triggered_to_play_value(Colors.GREEN_BLINK) clip_slot.set_triggered_to_record_value(Colors.RED_BLINK) clip_slot.set_stopped_value(Colors.AMBER_FULL) clip_slot.set_started_value(Colors.GREEN_FULL) clip_slot.set_recording_value(Colors.RED_FULL) clip_slot.name = 'Selected_Clip_Slot_' + str(index) self._on_track_offset.subject = self._session def _init_device(self): make_button = partial(make_launch_control_button, channel=10) make_encoder = partial(make_launch_control_encoder, channel=10) bottom_encoders, top_encoders = make_all_encoders('Device', make_encoder) parameter_controls = top_encoders[:4] + bottom_encoders[:4] bank_buttons = [ make_button(identifier, 'Device_Bank_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ] for button in bank_buttons: button.set_on_off_values(Colors.LED_ON, Colors.LED_OFF) self._device_bank_registry = DeviceBankRegistry() self._device = DeviceComponent(device_bank_registry=self._device_bank_registry, name='Device') self._device.set_enabled(False) self._device.layer = Layer(parameter_controls=ButtonMatrixElement(rows=[parameter_controls]), bank_buttons=ButtonMatrixElement(rows=[bank_buttons])) self.set_device_component(self._device) self._device_navigation = DeviceNavigationComponent() self._device_navigation.set_enabled(False) self._device_navigation.name = 'Device_Navigation' self._device_navigation.layer = Layer(next_device_button=make_button(115, 'Next_Device_Button'), previous_device_button=make_button(114, 'Prev_Device_Button')) self._view_control = ViewControlComponent() self._view_control.set_enabled(False) self._view_control.name = 'View_Control' self._view_control.layer = Layer(next_track_button=make_button(117, 'Device_Next_Track_Button'), prev_track_button=make_button(116, 'Device_Prev_Track_Button')) def _init_modes(self): self._modes = ModesComponent(is_root=True) self._modes.add_mode('mixer', [partial(self._session.set_mixer, self._mixer), LayerMode(self._session, self._mixer_track_nav_layer), self._mixer, self._session, self._show_controlled_tracks_message]) self._modes.add_mode('session', [partial(self._session.set_mixer, self._session_mixer), LayerMode(self._session, self._session_layer), self._session_mixer, self._session, self._show_controlled_tracks_message]) self._modes.add_mode('device', [self._device, self._device_navigation, self._view_control]) self._modes.add_mode('user', None) self._modes.selected_mode = 'mixer' self._modes.layer = Layer(mixer_button=ButtonSysexControl(Sysex.MIXER_MODE), session_button=ButtonSysexControl(Sysex.SESSION_MODE), device_button=ButtonSysexControl(Sysex.DEVICE_MODE)) @subject_slot('offset') def _on_track_offset(self): self._show_controlled_tracks_message() @subject_slot('selected_send_index') def _on_selected_send_index(self, index): self._show_controlled_sends_message() @subject_slot('selected_mixer_mode') def _on_selected_mixer_mode(self, mode): if mode == 'sends': self._show_controlled_sends_message() else: self.show_message('Controlling Pan and Volume') def _show_controlled_tracks_message(self): start = self._session.track_offset() + 1 end = min(start + 8, len(self._session.tracks_to_use())) if start < end: self.show_message('Controlling Track %d to %d' % (start, end)) else: self.show_message('Controlling Track %d' % start) def _show_controlled_sends_message(self): send_index = self._mixer.selected_send_index send_name1 = chr(ord('A') + send_index) if send_index + 1 < self._mixer.num_sends: send_name2 = chr(ord('A') + send_index + 1) self.show_message('Controlling Send %s and %s' % (send_name1, send_name2)) else: self.show_message('Controlling Send %s' % send_name1) def handle_sysex(self, midi_bytes): super(LaunchControl, self).handle_sysex(midi_bytes) if self._is_user_mode_message(midi_bytes): self._modes.selected_mode = 'user' self.request_rebuild_midi_map() def _is_user_mode_message(self, midi_bytes): """ True if midi_byes refer to a mode change, but none of the three predefined Live modes """ return midi_bytes[:7] == Sysex.MODE_CHANGE_PREFIX and midi_bytes not in SYSEX_MODE_MAP
class 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 SubSelectorComponent(ModeSelectorComponent): """ Class that handles different mixer modes """ def __init__(self, matrix, side_buttons, session): raise isinstance(matrix, ButtonMatrixElement) or AssertionError raise matrix.width() == 8 and matrix.height() == 8 or AssertionError raise isinstance(side_buttons, tuple) or AssertionError raise len(side_buttons) == 8 or AssertionError raise isinstance(session, SessionComponent) or AssertionError ModeSelectorComponent.__init__(self) self._session = session self._mixer = SpecialMixerComponent(matrix.width()) self._matrix = matrix self._sliders = [] self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_strip' self._mixer.selected_strip().name = 'Selected_Channel_strip' for column in range(matrix.width()): self._mixer.channel_strip(column).name = 'Channel_Strip_' + str(column) self._sliders.append(PreciseButtonSliderElement(tuple([ matrix.get_button(column, 7 - row) for row in range(8) ]))) self._sliders[-1].name = 'Button_Slider_' + str(column) self._side_buttons = side_buttons[4:] self._update_callback = None self._session.set_mixer(self._mixer) self.set_modes_buttons(side_buttons[:4]) def disconnect(self): for button in self._modes_buttons: button.remove_value_listener(self._mode_value) self._session = None self._mixer = None for slider in self._sliders: slider.release_parameter() slider.set_disabled(True) self._sliders = None self._matrix = None self._side_buttons = None self._update_callback = None ModeSelectorComponent.disconnect(self) def set_update_callback(self, callback): raise dir(callback).count('im_func') is 1 or AssertionError self._update_callback = callback def set_modes_buttons(self, buttons): raise buttons == None or isinstance(buttons, tuple) or len(buttons) == self.number_of_modes() or AssertionError identify_sender = True for button in self._modes_buttons: button.remove_value_listener(self._mode_value) self._modes_buttons = [] if buttons != None: for button in buttons: raise isinstance(button, ButtonElement) or AssertionError self._modes_buttons.append(button) button.add_value_listener(self._mode_value, identify_sender) def set_mode(self, mode): if not isinstance(mode, int): raise AssertionError raise mode in range(-1, self.number_of_modes()) or AssertionError self._mode_index = (self._mode_index != mode or mode == -1) and mode self.update() def mode(self): result = 0 if self.is_enabled(): result = self._mode_index + 1 return result def number_of_modes(self): return 4 def on_enabled_changed(self): enabled = self.is_enabled() for index in range(self._matrix.width()): self._sliders[index].set_disabled(not enabled) self._mixer.set_enabled(enabled) self.set_mode(-1) def release_controls(self): for track in range(self._matrix.width()): for row in range(self._matrix.height()): self._matrix.get_button(track, row).set_on_off_values(127, LED_OFF) strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_send_controls((None, None)) strip.set_pan_control(None) strip.set_volume_control(None) self._session.set_stop_track_clip_buttons(None) self._mixer.set_global_buttons(None, None, None) self._session.set_stop_all_clips_button(None) def update(self): super(SubSelectorComponent, self).update() if not self._modes_buttons != None: raise AssertionError if self.is_enabled(): if self._modes_buttons != None: for index in range(len(self._modes_buttons)): self._modes_buttons[index].set_on_off_values(GREEN_FULL, GREEN_THIRD) if index == self._mode_index: self._modes_buttons[index].turn_on() else: self._modes_buttons[index].turn_off() for button in self._side_buttons: button.set_on_off_values(127, LED_OFF) button.turn_off() for index in range(self._matrix.width()): self._sliders[index].set_disabled(self._mode_index == -1) self._mixer.set_allow_update(False) self._session.set_allow_update(False) if self._mode_index == -1: self._setup_mixer_overview() elif self._mode_index == 0: self._setup_volume_mode() elif self._mode_index == 1: self._setup_pan_mode() elif self._mode_index == 2: self._setup_send1_mode() elif self._mode_index == 3: self._setup_send2_mode() else: raise False or AssertionError self._update_callback != None and self._update_callback() self._mixer.set_allow_update(True) self._session.set_allow_update(True) else: self.release_controls() def _setup_mixer_overview(self): trkon_index = 5 stop_buttons = [] for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_send_controls((None, None)) strip.set_pan_control(None) strip.set_volume_control(None) self._sliders[track].release_parameter() for row in range(self._matrix.height()): full_value = GREEN_THIRD third_value = GREEN_FULL if row == trkon_index: full_value = AMBER_FULL third_value = AMBER_THIRD elif row > 3: full_value = RED_FULL third_value = RED_THIRD self._matrix.get_button(track, row).set_on_off_values(full_value, third_value) strip.set_default_buttons(self._matrix.get_button(track, 0), self._matrix.get_button(track, 1), self._matrix.get_button(track, 2), self._matrix.get_button(track, 3)) stop_buttons.append(self._matrix.get_button(track, 4)) strip.set_mute_button(self._matrix.get_button(track, 5)) strip.set_solo_button(self._matrix.get_button(track, 6)) strip.set_arm_button(self._matrix.get_button(track, 7)) for button in self._side_buttons: if list(self._side_buttons).index(button) == trkon_index - 4: button.set_on_off_values(AMBER_FULL, AMBER_THIRD) else: button.set_on_off_values(RED_FULL, RED_THIRD) button.set_force_next_value() button.turn_off() self._session.set_stop_track_clip_buttons(tuple(stop_buttons)) self._session.set_stop_all_clips_button(self._side_buttons[0]) self._mixer.set_global_buttons(self._side_buttons[3], self._side_buttons[2], self._side_buttons[1]) def _setup_volume_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_send_controls((None, None)) strip.set_pan_control(None) for row in range(self._matrix.height()): self._matrix.get_button(track, row).set_on_off_values(GREEN_FULL, LED_OFF) self._sliders[track].set_mode(SLIDER_MODE_VOLUME) self._sliders[track].set_value_map(VOL_VALUE_MAP) strip.set_volume_control(self._sliders[track]) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None) def _setup_pan_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_send_controls((None, None)) strip.set_volume_control(None) for row in range(self._matrix.height()): self._matrix.get_button(track, row).set_on_off_values(AMBER_FULL, LED_OFF) self._sliders[track].set_mode(SLIDER_MODE_PAN) self._sliders[track].set_value_map(PAN_VALUE_MAP) strip.set_pan_control(self._sliders[track]) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None) def _setup_send1_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_volume_control(None) strip.set_pan_control(None) for row in range(self._matrix.height()): self._matrix.get_button(track, row).set_on_off_values(RED_FULL, LED_OFF) self._sliders[track].set_mode(SLIDER_MODE_VOLUME) self._sliders[track].set_value_map(SEND_VALUE_MAP) strip.set_send_controls((self._sliders[track], None)) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None) def _setup_send2_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_volume_control(None) strip.set_pan_control(None) for row in range(self._matrix.height()): self._matrix.get_button(track, row).set_on_off_values(RED_FULL, LED_OFF) self._sliders[track].set_mode(SLIDER_MODE_VOLUME) self._sliders[track].set_value_map(SEND_VALUE_MAP) strip.set_send_controls((None, self._sliders[track])) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None)
class Serato(ControlSurface): def __init__(self, c_instance): publish_in_cs_list = True ControlSurface.__init__(self, c_instance, not publish_in_cs_list) self._device_selection_follows_track_selection = True with self.component_guard(): self._matrix = None self._session = None self._mixer = None self._device = None self._scene_launch_buttons = None self._track_arm_buttons = None self._track_solo_buttons = None self._track_mute_buttons = None self._track_stop_buttons = None self._track_select_buttons = None self._device_on_off_button = None self._shift_button = None self._serato_interface = PySCAClipControl() self._serato_interface.PySCA_InitializeClipControl() self._setup_session_control() self._setup_mixer_control() self._setup_device_control() self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) def disconnect(self): ControlSurface.disconnect(self) self._serato_interface.PySCA_DeinitializeClipControl() self._serato_interface = None def connect_script_instances(self, instanciated_scripts): """ Called by the Application as soon as all scripts are initialized. You can connect yourself to other running scripts here, as we do it connect the extension modules (MackieControlXTs). """ for control_surface in self._control_surfaces(): control_surface_session = control_surface.highlighting_session_component( ) if control_surface_session: self._session.sync_to(control_surface_session) self._on_track_list_changed() break def build_midi_map(self, midi_map_handle): pass def update_display(self): ControlSurface.update_display(self) while self._serato_interface.PySCA_HasIncomingEvent(): new_event = self._serato_interface.PySCA_GetIncomingEvent() if not self._handle_session_event(new_event): if not self._handle_mixer_event(new_event): if not self._handle_device_event(new_event): print 'Unhandled Event: ' + str(new_event) def _setup_session_control(self): is_momentary = True self._session = SpecialSessionComponent(NUM_TRACKS, NUM_SCENES) self._session.set_serato_interface(self._serato_interface) self._matrix = ButtonMatrixElement() self._scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_SCENES) ] self._track_stop_buttons = [ ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_TRACKS) ] stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) self._session.set_stop_all_clips_button(stop_all_button) self._session.set_stop_track_clip_buttons( tuple(self._track_stop_buttons)) for scene_index in range(NUM_SCENES): scene = self._session.scene(scene_index) button_row = [] scene.set_launch_button(self._scene_launch_buttons[scene_index]) scene.set_index(scene_index) scene.set_serato_interface(self._serato_interface) for track_index in range(NUM_TRACKS): button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(button) clip_slot.set_serato_interface(self._serato_interface) self._matrix.add_row(tuple(button_row)) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(NUM_TRACKS) self._mixer.set_serato_interface(self._serato_interface) self._mixer.master_strip().set_serato_interface(self._serato_interface) self._track_arm_buttons = [] self._track_solo_buttons = [] self._track_mute_buttons = [] self._track_select_buttons = [] self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for track in range(NUM_TRACKS): strip = self._mixer.channel_strip(track) strip.set_serato_interface(self._serato_interface) self._track_arm_buttons.append( ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_solo_buttons.append( ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_mute_buttons.append( ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_select_buttons.append( ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) strip.set_arm_button(self._track_arm_buttons[-1]) strip.set_solo_button(self._track_solo_buttons[-1]) strip.set_mute_button(self._track_mute_buttons[-1]) strip.set_select_button(self._track_select_buttons[-1]) strip.set_shift_button(self._shift_button) def _setup_device_control(self): is_momentary = True self._device_on_off_button = ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0) self._device = SpecialDeviceComponent() self._device.set_serato_interface(self._serato_interface) self._device.set_parameter_controls( tuple([ SliderElement(MIDI_CC_TYPE, 0, 0) for index in range(NUM_PARAMS) ])) self._device.set_on_off_button(self._device_on_off_button) self.set_device_component(self._device) def _handle_session_event(self, event): result = False if event.type in CLIP_EVENTS: value = 127 * int(event.type == libInterprocessCommsAPIPython. kAbletonClipControlEventClipPlayedDown) track_index = event.key1 - 1 scene_index = event.key2 - 1 if track_index in range(NUM_TRACKS) and scene_index in range( NUM_SCENES): self._matrix.get_button(track_index, scene_index).receive_value(value) result = True elif event.type in SCENE_EVENTS: value = 127 * int(event.type == libInterprocessCommsAPIPython. kAbletonClipControlEventScenePlayedDown) scene_index = event.key1 - 1 if scene_index in range(NUM_SCENES): self._scene_launch_buttons[scene_index].receive_value(value) result = True elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixSizeChanged: new_width = event.key1 new_height = event.key2 self._session.set_size(new_width, new_height) result = True elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixOffsetChanged: x_increment = event.key1 y_increment = event.key2 self._session.move_by(x_increment, y_increment) result = True return result def _handle_mixer_event(self, event): result = True track_index = event.key1 - 1 value = event.key2 if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackMasterGainChange: self._mixer.master_strip().set_track_volume(fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackStopped: self.song().stop_all_clips() elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackSelect: self.song().view.selected_track = self.song().master_track else: result = track_index in range( NUM_TRACKS) and self._handle_strip_event(event) return result def _handle_strip_event(self, event): result = True track_index = event.key1 - 1 value = event.key2 if value == 0: self._shift_button.receive_value(127) if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSolo: self._track_solo_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackRecord: self._track_arm_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackActive: self._track_mute_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackStopped: self._track_stop_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSelect: self._track_select_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackGainChange: self._mixer.channel_strip(track_index).set_track_volume( fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendAChange: self._mixer.channel_strip(track_index).set_send( 0, fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendBChange: self._mixer.channel_strip(track_index).set_send( 1, fixed_value(value)) else: result = False self._shift_button.receive_value(0) return result def _handle_device_event(self, event): result = True if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceValueChanged: self._device.set_parameter_value(event.key1 - 1, fixed_value(event.key2)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceActivate: self._device_on_off_button.receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceFocusMove: self._move_device_focus(event.key1) else: result = False return result def _move_device_focus(self, increment): if not self.application().view.is_view_visible( 'Detail') or not self.application().view.is_view_visible( 'Detail/DeviceChain'): self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: modifier_pressed = True direction = Live.Application.Application.View.NavDirection.left if increment > 0: direction = Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)
class LaunchControl(ControlSurface): def __init__(self, c_instance): super(LaunchControl, self).__init__(c_instance) with self.component_guard(): self._device_selection_follows_track_selection = True self._init_mixer() self._init_session() self._init_device() self._init_modes() self._refresh_state_task = self._tasks.add(Task.sequence(Task.delay(3), Task.run(self._do_refresh_state))) self._refresh_state_task.kill() self.log_message('Launch Control script loaded') def disconnect(self): super(LaunchControl, self).disconnect() for channel in xrange(16): self._send_midi((CC_STATUS + channel, 0, 0)) def refresh_state(self): self._refresh_state_task.restart() def _do_refresh_state(self): self._send_current_mode() self._update_hardware() self.schedule_message(3, super(LaunchControl, self).refresh_state) def _update_hardware(self): for channel in xrange(8, 11): self._send_midi(Sysex.make_automatic_flashing_message(channel)) def _send_current_mode(self): try: self._send_midi(MODE_SYSEX_MAP[self._modes.selected_mode]) except KeyError: pass def _init_mixer(self): make_button = partial(make_launch_control_button, channel=8) make_encoder = partial(make_launch_control_encoder, channel=8) bottom_encoders, top_encoders = make_all_encoders('Mixer', make_encoder) pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders])) sends_layer = Layer(sends_controls=ButtonMatrixElement(rows=[bottom_encoders, top_encoders])) modes_layer = Layer(pan_volume_button=make_button(114, 'Pan_Volume_Mode_Button'), sends_button=make_button(115, 'Sends_Mode_Button')) self._mixer = SpecialMixerComponent(8, modes_layer, pan_volume_layer, sends_layer) self._mixer.set_enabled(False) self._mixer.name = 'Mixer' self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer_track_nav_layer = Layer(track_bank_left_button=make_button(116, 'Mixer_Track_Left_Button'), track_bank_right_button=make_button(117, 'Mixer_Track_Right_Button')) for index in xrange(8): strip = self._mixer.channel_strip(index) strip.name = 'Channel_Strip_' + str(index) strip.empty_color = Colors.LED_OFF strip.set_invert_mute_feedback(True) mute_button = make_button(pad_identifiers[index], 'Track_Mute_Button_' + str(index), is_pad=True) mute_button.set_on_off_values(Colors.AMBER_FULL, Colors.AMBER_THIRD) strip.set_mute_button(mute_button) self._on_selected_send_index.subject = self._mixer self._on_selected_mixer_mode.subject = self._mixer def _init_session(self): make_button = partial(make_launch_control_button, channel=9) make_encoder = partial(make_launch_control_encoder, channel=9) bottom_encoders, top_encoders = make_all_encoders('Session_Mixer', make_encoder) pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders])) self._session_mixer = SpecialMixerComponent(8, Layer(), pan_volume_layer, Layer()) self._session_mixer.set_enabled(False) self._session_mixer.name = 'Session_Mixer' clip_launch_buttons = [ make_button(identifier, 'Clip_Launch_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ] self._session = SpecialSessionComponent(num_tracks=8, num_scenes=0, name='Session') self._session.set_enabled(False) self._session.set_mixer(self._session_mixer) self._session_layer = Layer(track_bank_left_button=make_button(116, 'Track_Bank_Left_Button'), track_bank_right_button=make_button(117, 'Track_Bank_Right_Button'), select_prev_button=make_button(114, 'Scene_Bank_Up_Button'), select_next_button=make_button(115, 'Scene_Bank_Down_Button'), clip_launch_buttons=ButtonMatrixElement(rows=[clip_launch_buttons])) scene = self._session.selected_scene() for index in range(8): clip_slot = scene.clip_slot(index) clip_slot.set_triggered_to_play_value(Colors.GREEN_BLINK) clip_slot.set_triggered_to_record_value(Colors.RED_BLINK) clip_slot.set_stopped_value(Colors.AMBER_FULL) clip_slot.set_started_value(Colors.GREEN_FULL) clip_slot.set_recording_value(Colors.RED_FULL) clip_slot.name = 'Selected_Clip_Slot_' + str(index) self._on_track_offset.subject = self._session def _init_device(self): make_button = partial(make_launch_control_button, channel=10) make_encoder = partial(make_launch_control_encoder, channel=10) bottom_encoders, top_encoders = make_all_encoders('Device', make_encoder) parameter_controls = top_encoders[:4] + bottom_encoders[:4] bank_buttons = [ make_button(identifier, 'Device_Bank_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ] for button in bank_buttons: button.set_on_off_values(Colors.LED_ON, Colors.LED_OFF) self._device_bank_registry = DeviceBankRegistry() self._device = DeviceComponent(device_bank_registry=self._device_bank_registry, name='Device') self._device.set_enabled(False) self._device.layer = Layer(parameter_controls=ButtonMatrixElement(rows=[parameter_controls]), bank_buttons=ButtonMatrixElement(rows=[bank_buttons])) self.set_device_component(self._device) self._device_navigation = DeviceNavigationComponent() self._device_navigation.set_enabled(False) self._device_navigation.name = 'Device_Navigation' self._device_navigation.layer = Layer(next_device_button=make_button(115, 'Next_Device_Button'), previous_device_button=make_button(114, 'Prev_Device_Button')) self._view_control = ViewControlComponent() self._view_control.set_enabled(False) self._view_control.name = 'View_Control' self._view_control.layer = Layer(next_track_button=make_button(117, 'Device_Next_Track_Button'), prev_track_button=make_button(116, 'Device_Prev_Track_Button')) def _init_modes(self): self._modes = ModesComponent(is_root=True) self._modes.add_mode('mixer', [partial(self._session.set_mixer, self._mixer), LayerMode(self._session, self._mixer_track_nav_layer), self._mixer, self._session, self._show_controlled_tracks_message]) self._modes.add_mode('session', [partial(self._session.set_mixer, self._session_mixer), LayerMode(self._session, self._session_layer), self._session_mixer, self._session, self._show_controlled_tracks_message]) self._modes.add_mode('device', [self._device, self._device_navigation, self._view_control]) self._modes.add_mode('user', None) self._modes.selected_mode = 'mixer' self._modes.layer = Layer(mixer_button=ButtonSysexControl(Sysex.MIXER_MODE), session_button=ButtonSysexControl(Sysex.SESSION_MODE), device_button=ButtonSysexControl(Sysex.DEVICE_MODE)) return @subject_slot('offset') def _on_track_offset(self): self._show_controlled_tracks_message() @subject_slot('selected_send_index') def _on_selected_send_index(self, index): self._show_controlled_sends_message() @subject_slot('selected_mixer_mode') def _on_selected_mixer_mode(self, mode): if mode == 'sends': self._show_controlled_sends_message() else: self.show_message('Controlling Pan and Volume') def _show_controlled_tracks_message(self): start = self._session.track_offset() + 1 end = min(start + 8, len(self._session.tracks_to_use())) if start < end: self.show_message('Controlling Track %d to %d' % (start, end)) else: self.show_message('Controlling Track %d' % start) def _show_controlled_sends_message(self): send_index = self._mixer.selected_send_index send_name1 = chr(ord('A') + send_index) if send_index + 1 < self._mixer.num_sends: send_name2 = chr(ord('A') + send_index + 1) self.show_message('Controlling Send %s and %s' % (send_name1, send_name2)) else: self.show_message('Controlling Send %s' % send_name1) def handle_sysex(self, midi_bytes): super(LaunchControl, self).handle_sysex(midi_bytes) if self._is_user_mode_message(midi_bytes): self._modes.selected_mode = 'user' self.request_rebuild_midi_map() def _is_user_mode_message(self, midi_bytes): """ True if midi_byes refer to a mode change, but none of the three predefined Live modes """ return midi_bytes[:7] == Sysex.MODE_CHANGE_PREFIX and midi_bytes not in SYSEX_MODE_MAP
class Oxygen_3rd_Gen(ControlSurface): """ Script for the 3rd generation of M-Audio's Oxygen controllers """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): is_momentary = True self._suggested_input_port = 'Oxygen' self._suggested_output_port = 'Oxygen' self._has_slider_section = True self._device_selection_follows_track_selection = True self._shift_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 57) self._shift_button.add_value_listener(self._shift_value) self._mixer = SpecialMixerComponent(NUM_TRACKS) self._mute_solo_buttons = [] self._track_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 111) self._track_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 110) self._master_slider = SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 41) for index in range(NUM_TRACKS): self._mute_solo_buttons.append( ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 49 + index)) self._mixer.channel_strip(index).set_volume_control( SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 33 + index)) self._shift_value(0) self._mixer.master_strip().set_volume_control(self._master_slider) self._mixer.selected_strip().set_volume_control(None) device = DeviceComponent() device.set_parameter_controls( tuple([ EncoderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 17 + index, Live.MidiMap.MapMode.absolute) for index in range(8) ])) self.set_device_component(device) ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 115) rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 114) loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 113) transport = TransportComponent() transport.set_stop_button( ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 116)) transport.set_play_button( ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 117)) transport.set_record_button( ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 118)) session = SessionComponent(0, 0) transport_view_modes = TransportViewModeSelector( transport, session, ffwd_button, rwd_button, loop_button) def disconnect(self): self._shift_button.remove_value_listener(self._shift_value) self._shift_button = None ControlSurface.disconnect(self) def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(5, self._send_midi, IDENTITY_REQUEST) def handle_sysex(self, midi_bytes): if midi_bytes[0:5] == IDENTITY_RESPONSE: if midi_bytes[10] == 38: self._mixer.master_strip().set_volume_control(None) self._mixer.selected_strip().set_volume_control( self._master_slider) def _shift_value(self, value): raise value in range(128) or AssertionError for index in range(NUM_TRACKS): if value == 0: self._mixer.channel_strip(index).set_solo_button(None) self._mixer.channel_strip(index).set_mute_button( self._mute_solo_buttons[index]) self._mixer.set_bank_buttons(None, None) self._mixer.set_select_buttons(self._track_up_button, self._track_down_button) else: self._mixer.channel_strip(index).set_mute_button(None) self._mixer.channel_strip(index).set_solo_button( self._mute_solo_buttons[index]) self._mixer.set_select_buttons(None, None) self._mixer.set_bank_buttons(self._track_up_button, self._track_down_button)
def _init_mixer_component(self, volume_controls, trackarm_controls, mixer_options, global_channel, volume_map_mode): if volume_controls != None and trackarm_controls != None: num_strips = max(len(volume_controls), len(trackarm_controls)) send_info = [] momentary_buttons = False mixer = SpecialMixerComponent(num_strips) mixer.name = 'Mixer' mixer.master_strip().name = 'Master_Channel_Strip' mixer.selected_strip().name = 'Selected_Channel_Strip' if mixer_options != None: if 'MASTERVOLUME' in mixer_options.keys() and mixer_options['MASTERVOLUME'] in range(128): encoder = EncoderElement(MIDI_CC_TYPE, global_channel, mixer_options['MASTERVOLUME'], volume_map_mode) encoder.name = 'Master_Volume_Control' mixer.master_strip().set_volume_control(encoder) if 'NUMSENDS' in mixer_options.keys() and mixer_options['NUMSENDS'] > 0: for send in range(mixer_options['NUMSENDS']): key = 'SEND' + str(send + 1) raise key in mixer_options.keys() or AssertionError send_info.append(mixer_options[key]) momentary_buttons = 'NOTOGGLE' in mixer_options.keys() next_bank_button = None prev_bank_button = None if 'NEXTBANK' in mixer_options.keys() and mixer_options['NEXTBANK'] in range(128): next_bank_button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, mixer_options['NEXTBANK']) next_bank_button.name = 'Mixer_Next_Bank_Button' if 'PREVBANK' in mixer_options.keys() and mixer_options['PREVBANK'] in range(128): prev_bank_button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, mixer_options['PREVBANK']) prev_bank_button.name = 'Mixer_Previous_Bank_Button' mixer.set_bank_buttons(next_bank_button, prev_bank_button) for track in range(num_strips): strip = mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) if track in range(len(volume_controls)): channel = global_channel cc = volume_controls[track] if isinstance(volume_controls[track], (tuple, list)): cc = volume_controls[track][0] if volume_controls[track][1] in range(16): channel = volume_controls[track][1] if cc in range(128) and channel in range(16): encoder = EncoderElement(MIDI_CC_TYPE, channel, cc, volume_map_mode) encoder.name = str(track) + '_Volume_Control' strip.set_volume_control(encoder) if track in range(len(trackarm_controls)) and trackarm_controls[track] in range(128): button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, trackarm_controls[track]) button.name = str(track) + '_Arm_Button' strip.set_arm_button(button) send_controls = [] for send in send_info: encoder = None if track in range(len(send)): channel = global_channel cc = send[track] if isinstance(send[track], (tuple, list)): cc = send[track][0] if send[track][1] in range(16): channel = send[track][1] if cc in range(128) and channel in range(16): encoder = EncoderElement(MIDI_CC_TYPE, channel, cc, volume_map_mode) encoder.name = str(track) + '_Send_' + str(list(send_info).index(send)) + '_Control' send_controls.append(encoder) strip.set_send_controls(tuple(send_controls))
class QuNeo(ControlSurface): """ Script for Keith McMillen's QuNeo Multi-Touchpad Controller """ __module__ = __name__ _active_instances = [] def _combine_active_instances(): support_devices = False for instance in QuNeo._active_instances: support_devices |= instance._device_component != None track_offset = 0 for instance in QuNeo._active_instances: instance._activate_combination_mode(track_offset, support_devices) track_offset += instance._session.width() _combine_active_instances = staticmethod(_combine_active_instances) def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self.set_suppress_rebuild_requests(True) self._suppress_session_highlight = True self._suppress_send_midi = True self._suggested_input_port = 'QUNEO' self._suggested_output_port = 'QUNEO' self.num_tracks = 7 self.num_scenes = 4 self.session = None self.mixer = None self.transport = None self.led_value = None self._note_input = [] self.shift_button = None self.sequencer_button = None self.launch_button = None self.seq_offset_down = None self.seq_offset_up = None self.seq_offset_left = None self.seq_offset_right = None self.stop_all_clips = None self.track_bank_right = None self.track_bank_left = None self.scene_bank_down = None self.scene_bank_up = None self.beat_table = [] self.sends = [] self.arm_buttons = None self.mute_buttons = None self.solo_buttons = None self.shift_buttons = [] self.sequencer_buttons = None self.scene_launch_buttons = None self.stop_track_buttons = None self.clip_slot_buttons = None self.instrument_buttons = None self.volume_control = None self.pan_control = None self.current_mode = 0 self.set_shift_button(ConfigurableButtonElement(True, MIDI_NOTE_TYPE, PAD_CHANNEL, SHIFT_BUTTON, 127)) self._setup_transport_control() self._setup_mixer_control() self._setup_session_control() self.session.set_mixer(self.mixer) self._shift_mode(0) self._set_mode(0) app = Live.Application.get_application() maj = app.get_major_version() min = app.get_minor_version() bug = app.get_bugfix_version() self.show_message(str(maj) + '.' + str(min) + '.' + str(bug)) self.set_suppress_rebuild_requests(False) def disconnect(self): self.mixer self.session if self.shift_button != None: self.shift_button.remove_value_listener(self._shift_value) self.shift_button = None if self.shift_buttons != None: for button in self.shift_buttons: button.remove_value_listener(self._shift_buttons_value) self.shift_buttons = None self._note_input = None ControlSurface.disconnect(self) def refresh_state(self): ControlSurface.refresh_state(self) def set_shift_button(self, button): if not (button == None or isinstance(button, ButtonElement)): raise AssertionError if self.shift_button != button: if self.shift_button != None: self.shift_button.remove_value_listener(self._shift_value) self.shift_button = button self.shift_button != None and self.shift_button.add_value_listener(self._shift_value) def update_mode(self, mode): if mode != None: self._set_mode(mode) self.current_mode = mode def set_shift_buttons(self, buttons): if buttons != None: if self.shift_buttons != buttons: self.shift_buttons.remove_value_listener(self._shift_buttons_value) self.shift_buttons = buttons if self.shift_buttons != None: for button in self.shift_buttons: raise isinstance(button, ButtonElement) or AssertionError button.add_value_listener(self._shift_buttons_value, identify_sender=True) else: if self.shift_buttons != None: for button in self.shift_buttons: button.remove_value_listener(self._shift_buttons_value) self.shift_buttons = None def _shift_buttons_value(self, value, sender): raise self.shift_buttons != None or AssertionError raise value in range(128) or AssertionError mode = int(sender._note * 0.5) self.update_mode(mode) def _shift_value(self, value): if not value in range(128): raise AssertionError raise self.shift_button != None or AssertionError value != 0 and self._shift_mode(1) self.shift_button.turn_on() else: self._shift_mode(0) self.shift_button.turn_off() def _shift_mode(self, value): if value != 0: self.set_suppress_rebuild_requests(True) self._reassign_grid(0) self._reassign_mixer_control(1) self.set_suppress_rebuild_requests(False) else: None self._set_mode(self.current_mode) self._reassign_mixer_control(1) def _update_grid(self): if self.sequencer_buttons != None: self.session.set_sequencer_buttons(self.sequencer_buttons) else: self.session.set_sequencer_buttons(None) if self.seq_offset_left != None and self.seq_offset_right != None: self.session.set_seq_measure_offset(self.seq_offset_left, self.seq_offset_right) else: self.session.set_seq_measure_offset(None, None) if self.seq_offset_up != None and self.seq_offset_down != None: self.session.set_seq_note_offset(self.seq_offset_up, self.seq_offset_down) else: self.session.set_seq_note_offset(None, None) if self.launch_button != None: self.session.set_slot_launch_button(self.launch_button) else: self.session.set_slot_launch_button(None) if self.scene_launch_buttons != None: for index in range(len(self.scene_launch_buttons)): self.session.scene(index).set_launch_button(self.scene_launch_buttons[index]) else: for index in range(4): self.session.scene(index).set_launch_button(None) if self.stop_track_buttons != None: self.session.set_stop_track_clip_buttons(tuple(self.stop_track_buttons)) else: self.session.set_stop_track_clip_buttons(None) if self.stop_all_clips != None: self.session.set_stop_all_clips_button(self.stop_all_clips) else: self.session.set_stop_all_clips_button(None) if self.track_bank_right != None and self.track_bank_left != None: self.session.set_track_bank_buttons(self.track_bank_right, self.track_bank_left) else: self.session.set_track_bank_buttons(None, None) if self.scene_bank_up != None and self.scene_bank_down != None: self.session.set_scene_bank_buttons(self.scene_bank_up, self.scene_bank_down) else: self.session.set_scene_bank_buttons(None, None) for row in range(4): for col in range(7): self.clip = self.session.scene(row).clip_slot(col) if self.clip_slot_buttons != None: self.clip.set_triggered_to_play_value(30) self.clip.set_triggered_to_record_value(RED_HI) self.clip.set_started_value(30) self.clip.set_recording_value(RED_HI) self.clip.set_stopped_value(80) self.clip.set_triggered_to_record_value(6) self.clip.set_launch_button(self.clip_slot_buttons[row][col]) else: self.clip.set_launch_button(None) def turn_off_all_buttons(self): self.arm_buttons = None self.mute_buttons = None self.solo_buttons = None self.scene_launch_buttons = None self.stop_track_buttons = None if self.clip_slot_buttons != None: for row in range(4): for col in range(7): button = self.clip_slot_buttons[row][col] button.turn_off() self.clip_slot_buttons = None if self.shift_buttons != None: for button in self.shift_buttons: button.turn_off() button.remove_value_listener(self._shift_buttons_value) if self.sequencer_buttons != None: for button in self.sequencer_buttons: button.count = 0 button.note_on() self.instrument_buttons = None self.shift_buttons = None self.sequencer_buttons = None self.clip_slot_buttons = None self.launch_button = None self.stop_all_clips = None self.track_bank_left = None self.track_bank_right = None self.scene_bank_up = None self.scene_bank_down = None self.seq_offset_left = None self.seq_offset_right = None self.seq_offset_up = None self.seq_offset_down = None def _set_mode(self, mode): self.turn_off_all_buttons() if mode == 0: self.stop_track_buttons = [] self.scene_launch_buttons = [] self.track_bank_left = self.button(PAD_CHANNEL, SESSION_LEFT) self.track_bank_right = self.button(PAD_CHANNEL, SESSION_RIGHT) self.scene_bank_up = self.button(PAD_CHANNEL, SESSION_UP) self.scene_bank_down = self.button(PAD_CHANNEL, SESSION_DOWN) self.stop_all_clips = self.led_button(GRID_CHANNEL, STOP_ALL_CLIPS, 100) self.launch_button = self.led_button(GRID_CHANNEL, SLOT_LAUNCH, RED_HI) self.clip_slot_buttons = [] for row in range(4): self.clip_slot_buttons.append([]) for col in range(7): self.clip_slot_buttons[row].append(self.button(GRID_CHANNEL, CLIP_NOTE_MAP[row][col])) self.mute_buttons = [] self.solo_buttons = [] self.arm_buttons = [] for index in range(7): self.mute_buttons.append(self.led_button(GRID_CHANNEL, TRACK_MUTE[index], GREEN_HI)) self.solo_buttons.append(self.led_button(GRID_CHANNEL, TRACK_SOLO[index], ORANGE_HI)) self.arm_buttons.append(self.led_button(GRID_CHANNEL, TRACK_ARM[index], RED_HI)) self.stop_track_buttons.append(self.led_button(GRID_CHANNEL, STOP_TRACK[index], 100)) for scene in range(4): self.scene_launch_buttons.append(self.led_button(GRID_CHANNEL, SCENE_LAUNCH[scene], GREEN_LO)) self._update_session() self._update_grid() elif mode == 1: self.seq_offset_left = self.button(PAD_CHANNEL, SESSION_LEFT) self.seq_offset_right = self.button(PAD_CHANNEL, SESSION_RIGHT) self.seq_offset_up = self.button(PAD_CHANNEL, SESSION_UP) self.seq_offset_down = self.button(PAD_CHANNEL, SESSION_DOWN) self.sequencer_buttons = [] for row in range(8): for col in range(8): self.sequencer_buttons.append(self.led_button(GRID_CHANNEL, CLIP_NOTE_MAP[row][col], GREEN_HI)) self._update_session() self._update_grid() self.session.clear_led() self.session.update_notes() self.session.on_device_changed() else: self.track_bank_left = self.button(PAD_CHANNEL, SESSION_LEFT) self.track_bank_right = self.button(PAD_CHANNEL, SESSION_RIGHT) self.scene_bank_up = self.button(PAD_CHANNEL, SESSION_UP) self.scene_bank_down = self.button(PAD_CHANNEL, SESSION_DOWN) self._update_session() self._update_grid() def _reassign_grid(self, value): if value == 0: self.turn_off_all_buttons() self.shift_buttons = [] for index in range(2): self.shift_buttons.append(self.led_button(GRID_CHANNEL, TRACK_ARM[index], 127)) if index == self.current_mode: self.shift_buttons[index].send_value(127, True) else: self.shift_buttons[index].send_value(40, True) self._update_session() self._update_grid() else: None def button(self, channel, value): is_momentary = True if value != -1: return ButtonElement(is_momentary, MIDI_NOTE_TYPE, channel, value) else: return None def led_button(self, channel, value, vel): is_momentary = True if value != -1: return ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, channel, value, vel) else: return None def slider(self, channel, value): if value != -1: return SliderElement(MIDI_CC_TYPE, channel, value) else: return None def assign_encoder(self, channel, value): if value != -1: return EncoderElement(MIDI_CC_TYPE, channel, value, Live.MidiMap.MapMode.relative_two_compliment) else: return None def _reassign_mixer_control(self, shift_value): if shift_value == 1: for index in range(2): self.sends.append(self.slider(SLIDER_CHANNEL, SELECTED_SENDS[index])) self.volume_control = self.slider(SLIDER_CHANNEL, SELECTED_VOL) self.pan_control = self.slider(SLIDER_CHANNEL, SELECTED_PAN) if self.sends != None: self.mixer.selected_strip().set_send_controls(tuple(self.sends)) else: self.mixer.selected_strip().set_send_controls(tuple(None)) if self.volume_control != None: self.mixer.selected_strip().set_volume_control(self.volume_control) else: self.mixer.selected_strip().set_volume_control(None) if self.pan_control != None: self.mixer.selected_strip().set_pan_control(self.pan_control) else: self.mixer.selected_strip().set_pan_control(None) def _update_session(self): if self.shift_buttons != None: self.set_shift_buttons(self.shift_buttons) else: self.set_shift_buttons(None) for index in range(7): if self.arm_buttons != None: self.mixer.channel_strip(index).set_arm_button(self.arm_buttons[index]) else: self.mixer.channel_strip(index).set_arm_button(None) if self.solo_buttons != None: self.mixer.channel_strip(index).set_solo_button(self.solo_buttons[index]) else: self.mixer.channel_strip(index).set_solo_button(None) if self.mute_buttons != None: self.mixer.channel_strip(index).set_invert_mute_feedback(True) self.mixer.channel_strip(index).set_mute_button(self.mute_buttons[index]) else: self.mixer.channel_strip(index).set_mute_button(None) def _setup_transport_control(self): self.transport = SpecialTransportComponent() self.transport.set_metronome_button(self.led_button(PAD_CHANNEL, METRONOME, 127)) self.transport.set_play_button(self.led_button(PAD_CHANNEL, PLAY, 127)) self.transport.set_stop_button(self.led_button(PAD_CHANNEL, STOP, 127)) self.transport.set_record_button(self.led_button(PAD_CHANNEL, REC, 127)) self.transport.set_overdub_button(self.led_button(PAD_CHANNEL, OVERDUB, 127)) self.transport.set_tempo_buttons(self.led_button(PAD_CHANNEL, TEMPO_UP, 127), self.led_button(PAD_CHANNEL, TEMPO_DOWN, 127)) def _setup_mixer_control(self): self.mixer = SpecialMixerComponent(self.num_tracks, self) self.mixer.name = 'Mixer' self.mixer.set_track_offset(0) self.mixer.set_select_buttons(self.button(PAD_CHANNEL, TRACK_RIGHT), self.button(PAD_CHANNEL, TRACK_LEFT)) self.mixer.set_crossfader_control(self.slider(SLIDER_CHANNEL, CROSSFADER)) for index in range(4): self.mixer.channel_strip(index).set_volume_control(self.slider(SLIDER_CHANNEL, TRACK_VOL[index])) self.num_o_tracks = self.song().visible_tracks if self.num_o_tracks != None: index_count = -1 index_table = [] for index in self.song().visible_tracks: index_count += 1 if index.has_midi_output != True: index_table.append(index_count) else: None if index_table != None: for index in range(len(index_table)): x = index_table[index] if x > 3: None else: None def _setup_session_control(self): self.session = SpecialSessionComponent(self.num_tracks, self.num_scenes, self) self.session.set_offsets(0, 0) self.session.set_select_buttons(self.button(PAD_CHANNEL, SCENE_DOWN), self.button(PAD_CHANNEL, SCENE_UP)) self.session.set_clip_loop_start(self.slider(SLIDER_CHANNEL, 6)) self.session.set_clip_loop_length(self.slider(SLIDER_CHANNEL, 7)) def _on_selected_scene_changed(self): ControlSurface._on_selected_scene_changed(self) def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) def _activate_combination_mode(self, track_offset, support_devices): self._session.link_with_track_offset(track_offset)
class AumPC20(APC): __doc__ = " Script for Akai's APC20 Controller " def __init__(self, c_instance): self._shift_modes = None APC.__init__(self, c_instance) return None def disconnect(self): self._shift_modes = None APC.disconnect(self) return None def _activate_combination_mode(self, track_offset, support_devices): APC._activate_combination_mode(self, track_offset, support_devices) if support_devices: self._shift_modes.invert_assignment() def _setup_session_control(self): is_momentary = True self._shift_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81, self) self._session = APCSessionComponent(8, 5) self._session.name = 'Session_Control' self._matrix = ButtonMatrixElement() self._matrix.name = 'Button_Matrix' scene_launch_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82), self) for index in range(5) ] self._scene_launch_buttons = scene_launch_buttons track_stop_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52, self) for index in range(8) ] self._track_stop_buttons = track_stop_buttons 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' self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session.set_stop_track_clip_value(2) for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53), self) button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(5) clip_slot.set_started_value(1) clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) self._matrix.add_row(tuple(button_row)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = ShiftableZoomingComponent(self._session, tuple(track_stop_buttons)) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(self._matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._solo_buttons = [] for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, self) self._solo_buttons.append(solo_button) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) master_volume_control.name = 'Master_Volume_Control' prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_prehear_volume_control(prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) def _setup_custom_components(self): is_momentary = True master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) self._master_select_button = master_select_button master_select_button.name = 'Master_Select_Button' select_buttons = [] self._select_buttons = [] arm_buttons = [] sliders = [] for track in range(8): select_buttons.append(FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51, self)) self._select_buttons.append(select_buttons[track]) arm_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) if track is 7: self._user3 = arm_buttons[track] sliders.append(MonoEncoderElement2(MIDI_CC_TYPE, track, 7, Live.MidiMap.MapMode.absolute, 'Slider_' + str(track), track, self)) #sliders.append(MonoEncoderElement2(MIDI_CC_TYPE, track, 7)) select_buttons[-1].name = str(track) + '_Select_Button' arm_buttons[-1].name = str(track) + '_Arm_Button' #sliders[-1].name = str(track) + '_Volume_Control' transport = TransportComponent() transport.name = 'Transport' slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) slider_modes.name = 'Slider_Modes' self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message, self) self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button) def _product_model_id_byte(self): return 123 def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_monomod(self): self._host = MonomodComponent(self) self._host.name = 'Monomod_Host' self._host._set_nav_buttons = self._mod_set_nav_buttons(self._host) self._host._update_nav_buttons = self._mod_update_nav_buttons(self._host) self._host._set_nav_buttons = self._mod_set_nav_buttons(self._host) self.hosts = [self._host] self._monomod = ButtonMatrixElement() self._monomod.name = 'Monomod' for row in range(5): button_row = [] for column in range(8): button_row.append(self._matrix.get_button(column, row)) self._monomod.add_row(tuple(button_row)) self._monomod.add_row(tuple(self._track_stop_buttons)) self._monomod.add_row(tuple(self._select_buttons)) self._monomod.add_row(tuple(self._solo_buttons)) self._monomod_mode = MonomodModeComponent(self._monomod_mode_update, self) self._monomod_mode.name = "Monomod_Mode_Component" def _monomod_mode_update(self): if(self._monomod_mode._mode_index == 0) or (self._host._active_client == None): self.flash_status = 0 self._host.set_enabled(False) self._host._set_button_matrix(None) #self._host._set_nav_buttons(None) self._host._set_lock_button(None) self._host._set_alt_button(None) self._host._set_shift_button(None) self._host._set_nav_buttons(None) self._scene_launch_buttons[2].set_on_off_values(127, 0) self._scene_launch_buttons[3].set_on_off_values(127, 0) self._monomod.reset() self._shift_modes.set_enabled(True) #self._session.set_track_bank_buttons(self._right_button, self._left_button) #self._session.set_scene_bank_buttons(self._down_button, self._up_button) for track in range(8): self._mixer.channel_strip(track).set_select_button(self._select_buttons[track]) self._mixer.channel_strip(track).set_solo_button(self._solo_buttons[track]) #self._transport.set_nudge_buttons(self._nudge_up_button, self._nudge_down_button) self._session.set_enabled(True) self._session_zoom._is_zoomed_out = False self._session_zoom.set_enabled(True) self.request_rebuild_midi_map() self._master_select_button.turn_off() elif(self._monomod_mode._mode_index == 1): if self._shift_modes._note_mode_active is True: self._shift_modes._mode_callback(ABLETON_MODE) self._shift_modes._note_mode_active = False self._session_zoom.set_ignore_buttons(False) self._shift_modes._transport.update() self._shift_modes._on_note_mode_changed() #self._transport.set_nudge_buttons(None, None) self._shift_modes.set_enabled(False) for track in range(8): self._mixer.channel_strip(track).set_select_button(None) self._mixer.channel_strip(track).set_solo_button(None) for scene in range(5): self._scene_launch_buttons[scene].turn_off() self._session.set_enabled(False) self._session_zoom.set_enabled(False) #self._session.set_track_bank_buttons(None, None) #self._session.set_scene_bank_buttons(None, None) self.flash_status = 1 self._monomod.reset() self._host._set_button_matrix(self._monomod) #self._host._set_nav_buttons([self._up_button, self._down_button, self._left_button, self._right_button]) self._host._set_shift_button(self._shift_button) self._host._set_lock_button(self._scene_launch_buttons[0]) self._host._set_alt_button(self._scene_launch_buttons[1]) self._host._set_nav_buttons([self._scene_launch_buttons[2], self._scene_launch_buttons[3]]) self._host.set_enabled(True) self.request_rebuild_midi_map() self._master_select_button.turn_on() """m4l bridge""" def generate_strip_string(self, display_string): #self.log_message(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 += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) 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._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched +=1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip() is True: clip_names.append(clip_slot._clip_slot)##.clip.name) return clip_slot._clip_slot ##self.log_message(str(clip_slot._clip_slot.clip.name)) return clip_names def update_display(self): """ Live -> Script Aka on_timer. Called every 100 ms and should be used to update display relevant parts of the controller """ for message in self._scheduled_messages: message['Delay'] -= 1 if (message['Delay'] == 0): if (message['Parameter'] != None): message['Message'](message['Parameter']) else: message['Message']() del self._scheduled_messages[self._scheduled_messages.index(message)] for callback in self._timer_callbacks: callback() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if(self.flash_status > 0): for row in range(8): for column in range(8): button = self._monomod.get_button(column, row) if(button._flash_state > 0): button.flash(self._timer) ### Mod Overrides #### def _mod_set_nav_buttons(self, mod): def _set_nav_buttons(buttons): if mod._nav_buttons != None: mod._nav_buttons[0].remove_value_listener(mod._nav_up_value) mod._nav_buttons[1].remove_value_listener(mod._nav_down_value) mod._nav_buttons = buttons if buttons != None: assert len(buttons) == 2 for button in buttons: assert isinstance(button, FlashingButtonElement) mod._nav_buttons[0].set_on_off_values(8, 2) mod._nav_buttons[0].add_value_listener(mod._nav_up_value) mod._nav_buttons[1].set_on_off_values(8, 2) mod._nav_buttons[1].add_value_listener(mod._nav_down_value) return _set_nav_buttons def _mod_update_nav_buttons(self, mod): def _update_nav_buttons(): if mod._nav_buttons != None: if(mod._y > 0): mod._nav_buttons[0].turn_on() else: mod._nav_buttons[0].turn_off() if(mod._y < 8): mod._nav_buttons[1].turn_on() else: mod._nav_buttons[1].turn_off() return _update_nav_buttons
class Serato(ControlSurface): def __init__(self, c_instance): publish_in_cs_list = True ControlSurface.__init__(self, c_instance, not publish_in_cs_list) self._device_selection_follows_track_selection = True with self.component_guard(): self._matrix = None self._session = None self._mixer = None self._device = None self._scene_launch_buttons = None self._track_arm_buttons = None self._track_solo_buttons = None self._track_mute_buttons = None self._track_stop_buttons = None self._track_select_buttons = None self._device_on_off_button = None self._shift_button = None self._serato_interface = PySCAClipControl() self._serato_interface.PySCA_InitializeClipControl() self._setup_session_control() self._setup_mixer_control() self._setup_device_control() self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) return def disconnect(self): ControlSurface.disconnect(self) self._serato_interface.PySCA_DeinitializeClipControl() self._serato_interface = None return def connect_script_instances(self, instanciated_scripts): """ Called by the Application as soon as all scripts are initialized. You can connect yourself to other running scripts here, as we do it connect the extension modules (MackieControlXTs). """ for control_surface in self._control_surfaces(): control_surface_session = control_surface.highlighting_session_component() if control_surface_session: self._session.sync_to(control_surface_session) self._on_track_list_changed() break def build_midi_map(self, midi_map_handle): pass def update_display(self): ControlSurface.update_display(self) while self._serato_interface.PySCA_HasIncomingEvent(): new_event = self._serato_interface.PySCA_GetIncomingEvent() if not self._handle_session_event(new_event): if not self._handle_mixer_event(new_event): if not self._handle_device_event(new_event): print 'Unhandled Event: ' + str(new_event) def _setup_session_control(self): is_momentary = True self._session = SpecialSessionComponent(NUM_TRACKS, NUM_SCENES) self._session.set_serato_interface(self._serato_interface) self._matrix = ButtonMatrixElement() self._scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_SCENES) ] self._track_stop_buttons = [ ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_TRACKS) ] stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) self._session.set_stop_all_clips_button(stop_all_button) self._session.set_stop_track_clip_buttons(tuple(self._track_stop_buttons)) for scene_index in range(NUM_SCENES): scene = self._session.scene(scene_index) button_row = [] scene.set_launch_button(self._scene_launch_buttons[scene_index]) scene.set_index(scene_index) scene.set_serato_interface(self._serato_interface) for track_index in range(NUM_TRACKS): button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(button) clip_slot.set_serato_interface(self._serato_interface) self._matrix.add_row(tuple(button_row)) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(NUM_TRACKS) self._mixer.set_serato_interface(self._serato_interface) self._mixer.master_strip().set_serato_interface(self._serato_interface) self._track_arm_buttons = [] self._track_solo_buttons = [] self._track_mute_buttons = [] self._track_select_buttons = [] self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for track in range(NUM_TRACKS): strip = self._mixer.channel_strip(track) strip.set_serato_interface(self._serato_interface) self._track_arm_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_solo_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_mute_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_select_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) strip.set_arm_button(self._track_arm_buttons[-1]) strip.set_solo_button(self._track_solo_buttons[-1]) strip.set_mute_button(self._track_mute_buttons[-1]) strip.set_select_button(self._track_select_buttons[-1]) strip.set_shift_button(self._shift_button) def _setup_device_control(self): is_momentary = True self._device_on_off_button = ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0) self._device = SpecialDeviceComponent() self._device.set_serato_interface(self._serato_interface) self._device.set_parameter_controls(tuple([ SliderElement(MIDI_CC_TYPE, 0, 0) for index in range(NUM_PARAMS) ])) self._device.set_on_off_button(self._device_on_off_button) self.set_device_component(self._device) def _handle_session_event(self, event): result = False if event.type in CLIP_EVENTS: value = 127 * int(event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventClipPlayedDown) track_index = event.key1 - 1 scene_index = event.key2 - 1 if track_index in range(NUM_TRACKS) and scene_index in range(NUM_SCENES): self._matrix.get_button(track_index, scene_index).receive_value(value) result = True elif event.type in SCENE_EVENTS: value = 127 * int(event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventScenePlayedDown) scene_index = event.key1 - 1 if scene_index in range(NUM_SCENES): self._scene_launch_buttons[scene_index].receive_value(value) result = True elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixSizeChanged: new_width = event.key1 new_height = event.key2 self._session.set_size(new_width, new_height) result = True elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixOffsetChanged: x_increment = event.key1 y_increment = event.key2 self._session.move_by(x_increment, y_increment) result = True return result def _handle_mixer_event(self, event): result = True track_index = event.key1 - 1 value = event.key2 if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackMasterGainChange: self._mixer.master_strip().set_track_volume(fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackStopped: self.song().stop_all_clips() elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackSelect: self.song().view.selected_track = self.song().master_track else: result = track_index in range(NUM_TRACKS) and self._handle_strip_event(event) return result def _handle_strip_event(self, event): result = True track_index = event.key1 - 1 value = event.key2 if value == 0: self._shift_button.receive_value(127) if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSolo: self._track_solo_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackRecord: self._track_arm_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackActive: self._track_mute_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackStopped: self._track_stop_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSelect: self._track_select_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackGainChange: self._mixer.channel_strip(track_index).set_track_volume(fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendAChange: self._mixer.channel_strip(track_index).set_send(0, fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendBChange: self._mixer.channel_strip(track_index).set_send(1, fixed_value(value)) else: result = False self._shift_button.receive_value(0) return result def _handle_device_event(self, event): result = True if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceValueChanged: self._device.set_parameter_value(event.key1 - 1, fixed_value(event.key2)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceActivate: self._device_on_off_button.receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceFocusMove: self._move_device_focus(event.key1) else: result = False return result def _move_device_focus(self, increment): if not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain'): self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: modifier_pressed = True direction = Live.Application.Application.View.NavDirection.left if increment > 0: direction = Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)
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) 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() 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) 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 Novation_Impulse(ControlSurface): """ Script for Novation's Impulse keyboards """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) self._device_selection_follows_track_selection = True self._suggested_input_port = 'Impulse' self._suggested_output_port = 'Impulse' self._has_sliders = True self._current_midi_map = None self._display_reset_delay = -1 self._shift_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 39) self._preview_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 41) self._master_slider = SliderElement(MIDI_CC_TYPE, 0, 8) self._shift_button.name = 'Shift_Button' self._master_slider.name = 'Master_Volume_Control' self._master_slider.add_value_listener(self._slider_value, identify_sender=True) self._preview_button.add_value_listener(self._preview_value) self._setup_mixer() self._setup_session() self._setup_transport() self._setup_device() self._setup_name_display() device_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1, 10) mixer_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1, 9) device_button.name = 'Encoder_Device_Mode' mixer_button.name = 'Encoder_Mixer_Mode' self._encoder_modes = EncoderModeSelector(self._device_component, self._mixer, self._next_bank_button, self._prev_bank_button, self._encoders) self._encoder_modes.set_device_mixer_buttons( device_button, mixer_button) self._string_to_display = None for component in self.components: component.set_enabled(False) def 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._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) ControlSurface.disconnect(self) self._encoders = None self._sliders = None self._strip_buttons = None self._master_slider = None self._current_midi_map = None self._shift_button = 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._send_midi(SYSEX_START + (6, 0, 0, 0, 247)) 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._mixer.name = 'Mixer' self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button) self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.master_strip().set_volume_control(self._master_slider) self._sliders = [] for index in range(8): strip = self._mixer.channel_strip(index) strip.name = 'Channel_Strip_' + str(index) strip.set_invert_mute_feedback(True) self._sliders.append(SliderElement(MIDI_CC_TYPE, 0, index)) self._sliders[-1].name = str(index) + '_Volume_Control' self._sliders[-1].set_feedback_delay(-1) self._sliders[-1].add_value_listener(self._slider_value, identify_sender=True) strip.set_volume_control(self._sliders[-1]) self._strip_buttons.append( ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + index)) self._strip_buttons[-1].name = str(index) + '_Mute_Button' self._strip_buttons[-1].add_value_listener( self._mixer_button_value, identify_sender=True) self._mixer.master_strip().set_mute_button( ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 17)) self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button) def _setup_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) 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)) 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' transport = ShiftableTransportComponent() transport.name = 'Transport' transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_record_button(rec_button) transport.set_shift_button(self._shift_button) self._transport_view_modes = TransportViewModeSelector( 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 self._set_string_to_display(display_string) def _slider_value(self, value, 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 = ' - ' if sender.mapped_parameter() != None: master = self.song().master_track tracks = self.song().tracks returns = self.song().return_tracks track = None if sender == self._master_slider: track = self._has_sliders and master else: track = self.song().view.selected_track else: track = self._mixer.channel_strip( self._sliders.index(sender))._track display_string = track == master and '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 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: 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): raise value in range(128) or 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): raise isinstance(string_to_display, (str, unicode)) or 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): ControlSurface._on_selected_track_changed(self) self._show_current_track_name() all_tracks = self._has_sliders or 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 if not new_offset / num_strips == int(new_offset / num_strips): raise AssertionError self._session.set_offsets(new_offset, self._session.scene_offset())
class APC40plus22(APC): __doc__ = " Script for Akai's APC40 Controller with extra features added " def __init__(self, c_instance): self._c_instance = c_instance self._shift_modes = None #added from APC20 script self._encoder_modes = None #added self._slider_modes = None #added APC.__init__(self, c_instance) self.show_message("APC40_22 script loaded") # Disabling the scene launch buttons and assigning them to the first 5 repeats on Master self._device_buttons = [] self.setup_device_buttons() def disconnect(self): #this is from the APC20 script for button in self._device_buttons: button.remove_value_listener(self._device_toggle) self._device_buttons = None self._shift_modes = None self._encoder_modes = None self._slider_modes = None APC.disconnect(self) def setup_device_buttons(self): repeat = RepeatComponent(self) repeat.set_shift_button(self._shift_button) def _setup_session_control(self): is_momentary = True self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98) right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96) left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97) up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94) down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95) right_button.name = 'Bank_Select_Right_Button' left_button.name = 'Bank_Select_Left_Button' up_button.name = 'Bank_Select_Up_Button' down_button.name = 'Bank_Select_Down_Button' self._session = PedaledSessionComponent(8, 5) self._session.name = 'Session_Control' self._session.set_track_bank_buttons(right_button, left_button) self._session.set_scene_bank_buttons(down_button, up_button) self._matrix = ButtonMatrixElement( ) #was: matrix = ButtonMatrixElement() self._matrix.name = 'Button_Matrix' #was: matrix.name = 'Button_Matrix' scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82)) for index in range(5) ] #self._track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ] self._track_stop_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) 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(self._track_stop_buttons)): self._track_stop_buttons[index].name = 'Track_' + str( index) + '_Stop_Button' stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) stop_all_button.name = 'Stop_All_Clips_Button' self._session.set_stop_all_clips_button(stop_all_button) self._session.set_stop_track_clip_buttons( tuple(self._track_stop_buttons)) self._session.set_stop_track_clip_value(2) self._button_rows = [] for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): #button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53)) button = ConfigurableButtonElement( is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53)) #use Launchpad configurable button instead button.name = str(track_index) + '_Clip_' + str( scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(3) clip_slot.set_started_value(1) clip_slot.set_recording_value(5) clip_slot.set_launch_button(button) self._matrix.add_row( tuple(button_row)) #matrix.add_row(tuple(button_row)) self._button_rows.append(button_row) # Removing the launch selected clip footpedal option #self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = SessionZoomingComponent( self._session) #use APC20 Zooming instead self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix( self._matrix) #was: self._session_zoom.set_button_matrix(matrix) self._session_zoom.set_zoom_button( self._shift_button) #set in MatrixModesComponent instead self._session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button) self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5) return None def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(self, 8) #added self for parent self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) master_select_button.name = 'Master_Select_Button' self._mixer.master_strip().set_select_button( master_select_button ) #set in ShiftableSelectorComponent instead if used for Note Mode self._mixer.selected_strip().name = 'Selected_Channel_Strip' select_buttons = [] #added arm_buttons = [] #added sliders = [] #added for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) #volume_control = SliderElement(MIDI_CC_TYPE, track, 7) #set in ShiftableSelectorComponent instead #arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) #see below solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) solo_button.name = str(track) + '_Solo_Button' strip.set_solo_button(solo_button) if track < 4: mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) mute_button.name = str(track) + '_Mute_Button' strip.set_mute_button(mute_button) strip.set_invert_mute_feedback(True) strip.set_shift_button(self._shift_button) select_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) #added select_buttons[-1].name = str(track) + '_Select_Button' #added #strip.set_select_button(select_buttons[-1]) #added arm_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) #added arm_buttons[-1].name = str(track) + '_Arm_Button' #added sliders.append(SliderElement(MIDI_CC_TYPE, track, 7)) #added sliders[-1].name = str(track) + '_Volume_Control' #added self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) self._prehear_control = EncoderElement( MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) self._crossfader.name = 'Crossfader' #not used in APC20 master_volume_control.name = 'Master_Volume_Control' self._prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_shift_button( self._shift_button) #added for shifting prehear self._mixer.set_crossfader_control( self._crossfader) #not used in APC20 self._mixer.set_prehear_volume_control( self._prehear_control ) #functionality overridden in SpecialMixerComponent self._mixer.master_strip().set_volume_control(master_volume_control) self._slider_modes = SliderModesComponent( self._mixer, tuple(sliders)) #added from APC20 script self._slider_modes.name = 'Slider_Modes' #added from APC20 script matrix_modes = MatrixModesComponent(self._matrix, self._session, self._session_zoom, tuple(self._track_stop_buttons), self) #added new matrix_modes.name = 'Matrix_Modes' #added new # Original method args for ShiftableSelectorComponent: (self, select_buttons, master_button, arm_buttons, matrix, session, zooming, mixer, transport, slider_modes, mode_callback) #self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message) self._shift_modes = ShiftableSelectorComponent( self, tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, self._slider_modes, matrix_modes ) #, self._send_introduction_message) #also added self for _parent self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button) def _setup_custom_components(self): self._setup_looper_control() self._setup_device_and_transport_control() self._setup_global_control() def _setup_looper_control(self): is_momentary = True #pedal = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67) loop_on = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 4, 50) loop_start = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 5, 50) halve = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 6, 50) double = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 7, 50) looper = LooperComponent(self) looper.set_shift_button(self._shift_button) looper.set_loop_toggle_button(loop_on) looper.set_loop_start_button(loop_start) looper.set_loop_double_button(double) looper.set_loop_halve_button(halve) def _setup_device_and_transport_control(self): is_momentary = True device_bank_buttons = [] device_param_controls = [] bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Device_Lock_Button', 'Metronome_Button') for index in range(8): device_bank_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 58 + index)) device_bank_buttons[-1].name = bank_button_labels[index] ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 24 + index) ringed_encoder = RingedEncoderElement( MIDI_CC_TYPE, 0, 16 + index, Live.MidiMap.MapMode.absolute) ringed_encoder.set_ring_mode_button(ring_mode_button) ringed_encoder.set_feedback_delay( -1) #added from Axiom DirectLink example ringed_encoder.name = 'Device_Control_' + str(index) ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button' device_param_controls.append(ringed_encoder) self._device = ShiftableDeviceComponent() self._device.name = 'Device_Component' self._device.set_bank_buttons(tuple(device_bank_buttons)) self._device.set_shift_button(self._shift_button) self._device.set_parameter_controls(tuple(device_param_controls)) self._device.set_on_off_button(device_bank_buttons[1]) self.set_device_component(self._device) detail_view_toggler = DetailViewControllerComponent() detail_view_toggler.name = 'Detail_View_Control' detail_view_toggler.set_shift_button(self._shift_button) detail_view_toggler.set_device_clip_toggle_button( device_bank_buttons[0]) detail_view_toggler.set_detail_toggle_button(device_bank_buttons[4]) detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3]) # VU Meters vu = VUMeters(self) transport = ShiftableTransportComponent() transport.name = 'Transport' play_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 91) stop_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 92) record_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 93) nudge_up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 100) nudge_down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 101) tap_tempo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99) play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' record_button.name = 'Record_Button' nudge_up_button.name = 'Nudge_Up_Button' nudge_down_button.name = 'Nudge_Down_Button' tap_tempo_button.name = 'Tap_Tempo_Button' transport.set_shift_button(self._shift_button) transport.set_play_button(play_button) transport.set_stop_button(stop_button) transport.set_record_button(record_button) transport.set_nudge_buttons(nudge_up_button, nudge_down_button) transport.set_undo_button(nudge_down_button) #shifted nudge transport.set_redo_button(nudge_up_button) #shifted nudge transport.set_tap_tempo_button(tap_tempo_button) self._device.set_lock_button(tap_tempo_button) #shifted tap tempo transport.set_quant_toggle_button(device_bank_buttons[5]) transport.set_overdub_button(device_bank_buttons[6]) transport.set_metronome_button(device_bank_buttons[7]) transport.set_tempo_encoder(self._prehear_control) #shifted prehear bank_button_translator = ShiftableTranslatorComponent() bank_button_translator.set_controls_to_translate( tuple(device_bank_buttons)) bank_button_translator.set_shift_button(self._shift_button) def _setup_global_control(self): is_momentary = True self._global_bank_buttons = [] self._global_param_controls = [] for index in range(8): ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 56 + index) ringed_encoder = RingedEncoderElement( MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute) ringed_encoder.name = 'Track_Control_' + str(index) ringed_encoder.set_feedback_delay(-1) ring_button.name = ringed_encoder.name + '_Ring_Mode_Button' ringed_encoder.set_ring_mode_button(ring_button) self._global_param_controls.append(ringed_encoder) self._global_bank_buttons = [] global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button') for index in range(4): self._global_bank_buttons.append( ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87 + index) ) #(not is_momentary, MIDI_NOTE_TYPE, 0, 87 + index)) self._global_bank_buttons[-1].name = global_bank_labels[index] self._encoder_modes = EncoderMixerModeSelectorComponent(self._mixer) self._encoder_modes.name = 'Track_Control_Modes' #self._encoder_modes.set_modes_buttons(self._global_bank_buttons) # set in ShiftableEncoderSelectorComponent self._encoder_modes.set_controls(tuple(self._global_param_controls)) #self._encoder_device_modes = EncoderDeviceModeSelectorComponent(self._mixer, self._device) #new self._encoder_device_modes = EncoderDeviceComponent( self._mixer, self._device, self) self._encoder_device_modes.name = 'Alt_Device_Control_Modes' #new self._encoder_eq_modes = EncoderEQComponent( self._mixer, self) #EncoderEQModeSelectorComponent(self._mixer) #new self._encoder_eq_modes.name = 'EQ_Control_Modes' #new global_translation_selector = ChannelTranslationSelector( ) #translate track encoders to channels 1 through 4, based on button selection (pan = 1, send A = 2, send B = 3, send C = 4) global_translation_selector.name = 'Global_Translations' global_translation_selector.set_controls_to_translate( tuple(self._global_param_controls)) global_translation_selector.set_mode_buttons( tuple(self._global_bank_buttons)) encoder_user_modes = EncoderUserModesComponent( self, self._encoder_modes, tuple(self._global_param_controls), tuple(self._global_bank_buttons), self._mixer, self._device, self._encoder_device_modes, self._encoder_eq_modes) #self._mixer, tuple(sliders)) #added encoder_user_modes.name = 'Encoder_User_Modes' #added self._encoder_shift_modes = ShiftableEncoderSelectorComponent( self, tuple(self._global_bank_buttons), encoder_user_modes, self._encoder_modes, self._encoder_eq_modes, self._encoder_device_modes ) #tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, slider_modes, matrix_modes) #, self._send_introduction_message) #also added self for _parent self._encoder_shift_modes.name = 'Encoder_Shift_Modes' self._encoder_shift_modes.set_mode_toggle(self._shift_button) def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) #self._slider_modes.update() #added to update alternate slider assignments track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) return None def _product_model_id_byte(self): return 115
class Axiom_AIR_25_49_61(ControlSurface): """ Script for the M-Audio Axiom A.I.R. 25, 49 and 61 """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._alt_device_component = None with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) self._device_selection_follows_track_selection = True self._suggested_input_port = "HyperControl" self._suggested_output_port = "HyperControl" self._single_fader_button_modes = None self._has_faders = True self._display_reset_delay = -1 self._hc_byte = HC_BYTE self._waiting_for_first_response = True self._setup_controls() self._setup_displays() self._setup_mixer() self._setup_session() self._setup_transport() self._setup_device() self._setup_modes() self._drum_group_midi_button = None self._drum_group_hyper_button = None for component in self.components: component.set_enabled(False) def disconnect(self): self._scheduled_messages = [] for encoder in self._encoders: encoder.remove_value_listener(self._encoder_value) for fader in self._faders: fader.remove_value_listener(self._fader_value) for fader_button in self._fader_buttons: fader_button.remove_value_listener(self._fader_button_value) self._master_fader.remove_value_listener(self._fader_value) self._master_fader_button.remove_value_listener(self._fader_button_value) self._select_button.remove_value_listener(self._select_button_value) self._identify_button.remove_value_listener(self._identify_value) self._fader_group_midi_button.remove_value_listener(self._midi_button_value) self._fader_group_mix_button.remove_value_listener(self._hyper_button_value) self._fader_group_fx_button.remove_value_listener(self._hyper_button_value) self._encoder_group_midi_button.remove_value_listener(self._midi_button_value) self._encoder_group_mix_button.remove_value_listener(self._hyper_button_value) self._encoder_group_fx_button.remove_value_listener(self._hyper_button_value) if self._drum_group_midi_button != None: self._drum_group_midi_button.remove_value_listener(self._midi_button_value) if self._drum_group_hyper_button != None: self._drum_group_hyper_button.remove_value_listener(self._hyper_button_value) self._alt_device_component = None self._name_display = None self._value_display = None self._bank_display = None self._pad_display = None self._name_display_data_source = None self._value_display_data_source = None self._bank_display_data_source = None self._pad_display_data_source = None self._select_button = None self._left_button = None self._right_button = None self._up_button = None self._down_button = None self._loop_button = None self._ffwd_button = None self._rwd_button = None self._play_button = None self._stop_button = None self._rec_button = None self._master_fader_button = None self._fader_buttons = None self._faders = None self._encoders = None self._drum_pads = None self._identify_button = None self._main_group_hyper_button = None self._main_group_track_button = None self._main_group_fx_button = None self._encoder_group_midi_button = None self._encoder_group_mix_button = None self._encoder_group_fx_button = None self._fader_group_mode_button = None self._fader_group_midi_button = None self._fader_group_mix_button = None self._fader_group_fx_button = None self._drum_group_midi_button = None self._drum_group_roll_button = None self._drum_group_hyper_button = None self._mixer_for_encoders = None self._mixer_for_faders = None self._device_for_encoders = None self._device_for_faders = None self._transport = None self._session = None ControlSurface.disconnect(self) self._send_midi(SYSEX_START + DISABLE_HYPERCONTROL) def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(5, self._send_midi, IDENTITY_REQUEST) def handle_sysex(self, midi_bytes): if midi_bytes[0:10] == AXIOM_AIR_RESPONSE: if midi_bytes[12:15] < AXIOM_REV4_RESPONSE: self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL) self.schedule_message(2, self._send_midi, SYSEX_START + CLEAR_ALL) self.schedule_message(3, self._name_display.display_message, "Firmware") self.schedule_message(13, self._name_display.display_message, "Update") self.schedule_message(23, self._name_display.display_message, "Required") self.schedule_message(33, self._send_midi, SYSEX_START + DISABLE_HYPERCONTROL) elif midi_bytes[12:15] >= AXIOM_REV4_RESPONSE: if self._waiting_for_first_response == True: self._waiting_for_first_response = False self._has_faders = midi_bytes[10] != 50 self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL) self.schedule_message(2, self._send_midi, SYSEX_START + SPECIAL_HYPERCONTROL) self.schedule_message(3, self._complete_setup) else: self._display_reset_delay = 0 elif midi_bytes[0:8] == REQUEST_HYPERCONTROL: self.schedule_message(5, self._send_midi, IDENTITY_REQUEST) def update_display(self): ControlSurface.update_display(self) if self._display_reset_delay >= 0: self._display_reset_delay -= 1 if self._display_reset_delay == -1: self._set_displays_to_default() def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) self._display_reset_delay = 0 def restore_bank(self, bank_index): ControlSurface.restore_bank(self, bank_index) if self._alt_device_component != None: self._alt_device_component.restore_bank(bank_index) def set_appointed_device(self, device): ControlSurface.set_appointed_device(self, device) with self.component_guard(): if self._alt_device_component != None: self._alt_device_component.set_device(device) def set_alt_device_component(self, device_component): self._alt_device_component = device_component def _update_device_selection(self): track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) if self._alt_device_component != None: self._alt_device_component.set_device(device_to_select) def _setup_controls(self): self._left_button = create_button(99, "Left_Button") self._right_button = create_button(100, "Right_Button") self._up_button = create_button(101, "Up_Button") self._down_button = create_button(102, "Down_Button") self._loop_button = create_button(113, "Loop_Button") self._rwd_button = create_button(114, "Rwd_Button") self._ffwd_button = create_button(115, "FFwd_Button") self._stop_button = create_button(116, "Stop_Button") self._play_button = create_button(117, "Play_Button") self._rec_button = create_button(118, "Record_Button") self._select_button = ConfigurableButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, GLOBAL_CHANNEL, 98) self._select_button.name = "Select_Button" self._select_button.add_value_listener(self._select_button_value) self._main_group_hyper_button = create_configurable_button(104, "Fader_Group_HyperControl_Button", 2, 14) self._main_group_track_button = create_configurable_button(105, "Main_Group_Track_Button", 2, 11) self._main_group_fx_button = create_configurable_button(106, "Main_Group_Inst_FX_Button", 2, 11) self._identify_button = create_configurable_button(97, "Identify_Button", 2, 16) self._identify_button.add_value_listener(self._identify_value) self._fader_buttons = [] for index in range(8): self._fader_buttons.append(create_configurable_button(49 + index, "Fader_Button_%d" % index)) self._fader_buttons[-1].add_value_listener(self._fader_button_value, identify_sender=True) self._faders = [] for index in range(8): self._faders.append(create_slider(33 + index, "Fader_%d" % index)) self._faders[-1].add_value_listener(self._fader_value, identify_sender=True) self._master_fader_button = create_configurable_button(57, "Master_Fader_Button") self._master_fader_button.add_value_listener(self._fader_button_value, identify_sender=True) self._master_fader = create_slider(41, "Master_Fader") self._master_fader.add_value_listener(self._fader_value, identify_sender=True) self._fader_group_mode_button = create_configurable_button(61, "Fader_Group_Mode_Button") self._fader_group_midi_button = create_configurable_button(60, "Fader_Group_MIDI_Button") self._fader_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True) self._fader_group_mix_button = create_configurable_button(58, "Fader_Group_Mix_Button", 0, 1) self._fader_group_mix_button.add_value_listener(self._hyper_button_value, identify_sender=True) self._fader_group_fx_button = create_configurable_button(59, "Fader_Group_Inst_FX_Button", 0, -1) self._fader_group_fx_button.add_value_listener(self._hyper_button_value, identify_sender=True) self._encoders = [] for index in range(8): self._encoders.append(create_encoder(17 + index, "Encoder_%d" % index)) self._encoders[-1].add_value_listener(self._encoder_value, identify_sender=True) self._encoder_group_midi_button = create_configurable_button(27, "Encoder_Group_MIDI_Button", 0, 72) self._encoder_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True) self._encoder_group_mix_button = create_configurable_button(25, "Encoder_Group_Mix_Button", 0, 72) self._encoder_group_mix_button.add_value_listener(self._hyper_button_value, identify_sender=True) self._encoder_group_fx_button = create_configurable_button(26, "Encoder_Group_Inst_FX_Button", 0, 72) self._encoder_group_fx_button.add_value_listener(self._hyper_button_value, identify_sender=True) def _setup_drum_pads(self): self._drum_pads = [] num_pads = 12 if self._has_faders else 16 for index in range(8): self._drum_pads.append(create_configurable_button(81 + index, "Pad_%d" % index, 0, 0, MIDI_CC_TYPE)) for index in range(num_pads - 8): self._drum_pads.append( ConfigurableButtonElement( IS_MOMENTARY, MIDI_NOTE_TYPE, GLOBAL_CHANNEL - 1, 81 + index, GLOBAL_SEND_CHANNEL, 8, MIDI_CC_TYPE ) ) self._drum_pads[-1].name = "Pad_" + str(index + 8) self._drum_group_midi_button = create_configurable_button(91, "Drum_Group_MIDI_Button", 2, -2) self._drum_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True) self._drum_group_roll_button = create_configurable_button(90, "Drum_Group_Roll_Button", -1) self._drum_group_hyper_button = create_configurable_button(89, "Drum_Group_HyperControl_Button", 2, 2) self._drum_group_hyper_button.add_value_listener(self._hyper_button_value, identify_sender=True) def _setup_displays(self): self._name_display = PhysicalDisplayElement(12, 1) self._name_display.name = "Name_Display" self._name_display.set_message_parts(SYSEX_START + (21,), (0, 247)) self._name_display.set_clear_all_message(CLEAR_NAME) self._name_display_data_source = DisplayDataSource() self._name_display.segment(0).set_data_source(self._name_display_data_source) self._value_display = NumericalDisplayElement(3, 1) self._value_display.name = "Value_Display" self._value_display.set_message_parts(SYSEX_START + (20, 48), (0, 247)) self._value_display.set_clear_all_message(CLEAR_VALUE) self._value_display_data_source = DisplayDataSource() self._value_display.segment(0).set_data_source(self._value_display_data_source) self._bank_display = NumericalDisplayElement(3, 1) self._bank_display.name = "Bank_Display" self._bank_display.set_message_parts(SYSEX_START + (19,), (0, 247)) self._bank_display.set_clear_all_message(CLEAR_BANK) self._bank_display_data_source = DisplayDataSource() self._bank_display.segment(0).set_data_source(self._bank_display_data_source) self._pad_display = NumericalDisplayElement(2, 1) self._pad_display.name = "Pad_Display" self._pad_display.set_message_parts(SYSEX_START + (18,), (0, 247)) self._pad_display.set_clear_all_message(CLEAR_PAD) self._pad_display_data_source = DisplayDataSource() self._pad_display.segment(0).set_data_source(self._pad_display_data_source) def _setup_mixer(self): self._mixer_for_encoders = SpecialMixerComponent(self._name_display, self._value_display, 8) self._mixer_for_encoders.name = "Mixer_for_encoders" self._mixer_for_faders = SpecialMixerComponent(self._name_display, self._value_display, 8) self._mixer_for_faders.name = "Mixer_for_faders" def _setup_session(self): self._session = SpecialSessionComponent(8, 0) self._session.name = "Session_Control" self._session.selected_scene().name = "Selected_Scene" self._session.set_mixer(self._mixer_for_encoders) self._session.set_alt_mixer(self._mixer_for_faders) self._session.add_offset_listener(self._update_bank_value) def _setup_transport(self): self._transport = TransportComponent() self._transport.name = "Transport" self._transport.set_stop_button(self._stop_button) self._transport.set_play_button(self._play_button) self._transport.set_record_button(self._rec_button) transport_view_modes = TransportViewModeSelector( self._transport, self._session, self._ffwd_button, self._rwd_button, self._loop_button ) transport_view_modes.name = "Transport_View_Modes" def _setup_device(self): self._device_for_encoders = BestBankDeviceComponent() self._device_for_encoders.name = "Device_Component_for_encoders" self._device_for_faders = BestBankDeviceComponent() self._device_for_faders.name = "Device_Component_for_faders" self.set_device_component(self._device_for_encoders) self.set_alt_device_component(self._device_for_faders) self._device_nav = DeviceNavComponent() self._device_nav.name = "Device_Nav_Component" def _setup_modes(self): self._fader_button_modes = FaderButtonModeSelector(self._mixer_for_faders, tuple(self._fader_buttons)) self._fader_button_modes.name = "Fader_Button_Modes" self._fader_button_modes.set_mode_toggle(self._fader_group_mode_button) self._fader_modes = FaderModeSelector( self._mixer_for_faders, self._device_for_faders, tuple(self._faders), self._fader_button_modes, self._master_fader_button, ) self._fader_modes.name = "Fader_Modes" self._fader_modes.set_mode_buttons((self._fader_group_mix_button, self._fader_group_fx_button)) self._encoder_modes = EncoderModeSelector( self._mixer_for_encoders, self._device_for_encoders, tuple(self._encoders) ) self._encoder_modes.name = "Encoder_Modes" self._encoder_modes.set_mode_buttons((self._encoder_group_mix_button, self._encoder_group_fx_button)) main_modes = MainModeSelector( self._device_for_encoders, self._device_for_faders, self._session, self._mixer_for_faders, self._device_nav, self._up_button, self._down_button, self._left_button, self._right_button, self._select_button, ) main_modes.name = "Main_Modes" main_modes.set_mode_buttons((self._main_group_track_button, self._main_group_fx_button)) def _setup_master_fader(self): if self._has_faders: self._mixer_for_encoders.master_strip().set_volume_control(self._master_fader) else: self._mixer_for_encoders.selected_strip().set_volume_control(self._master_fader) def _setup_single_fader_button_modes(self): self._single_fader_button_modes = SingleFaderButtonModeSelector( self._mixer_for_encoders, self._fader_group_midi_button ) self._single_fader_button_modes.name = "Single_Fader_Button_Modes" self._single_fader_button_modes.set_mode_toggle(self._fader_group_mode_button) def _complete_setup(self): self._setup_drum_pads() self._set_drum_pads_to_hc() self._setup_master_fader() if not self._has_faders: self._setup_single_fader_button_modes() for control in self.controls: if isinstance(control, InputControlElement): control.clear_send_cache() for component in self.components: component.set_enabled(True) self._fader_group_midi_button.send_value(LED_OFF, True) self._encoder_group_midi_button.send_value(LED_OFF, True) self._main_group_hyper_button.send_value(AMB_FULL, True) self.request_rebuild_midi_map() self._on_selected_track_changed() self.schedule_message(1, self._show_startup_message) def _show_startup_message(self): self._send_midi(SYSEX_START + CLEAR_ALL) self._name_display.display_message("Ableton Live") self._display_reset_delay = INITIAL_DISPLAY_DELAY def _select_button_value(self, value): self._display_reset_delay = STANDARD_DISPLAY_DELAY def _identify_value(self, value): for encoder in self._encoders: encoder.set_identify_mode(value > 0) for fader in self._faders: fader.set_identify_mode(value > 0) self._master_fader.set_identify_mode(value > 0) self._display_reset_delay = 0 self._identify_button.turn_on() if value > 0 else self._identify_button.turn_off() def _midi_button_value(self, value, sender): if value > 0: if sender is self._drum_group_midi_button: hc_byte = self._hc_byte ^ PADS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._drum_group_hyper_button.send_value(LED_OFF, True) self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) elif sender is self._encoder_group_midi_button: hc_byte = self._hc_byte ^ ENCODERS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._encoder_group_mix_button.send_value(LED_OFF, True) self._encoder_group_fx_button.send_value(LED_OFF, True) if self._encoder_modes.mode_index < 3: self._encoder_modes.set_enabled(False) self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) elif sender is self._fader_group_midi_button: if self._has_faders: hc_byte = self._hc_byte ^ FADERS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._fader_group_mix_button.send_value(LED_OFF, True) self._fader_group_fx_button.send_value(LED_OFF, True) self._fader_group_mode_button.send_value(LED_OFF, True) if self._fader_modes.mode_index < 2: self._fader_modes.set_enabled(False) self._fader_button_modes.set_enabled(False) self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) else: self._display_reset_delay = STANDARD_DISPLAY_DELAY def _hyper_button_value(self, value, sender): if value > 0: if sender is self._drum_group_hyper_button: if self._hc_byte | PADS != self._hc_byte: self._hc_byte = self._hc_byte | PADS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self.schedule_message(1, self._set_drum_pads_to_hc) elif sender is self._encoder_group_fx_button or sender is self._encoder_group_mix_button: if self._hc_byte | ENCODERS != self._hc_byte: self._hc_byte = self._hc_byte | ENCODERS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self._encoder_group_midi_button.turn_off() if sender is self._encoder_group_fx_button: self._encoder_modes.set_enabled(True) self._display_reset_delay = 0 return else: self.schedule_message(1, self._encoder_modes.set_enabled, True) self.schedule_message(1, self._encoder_modes.update) self._display_reset_delay = 2 return elif sender is self._fader_group_fx_button or sender is self._fader_group_mix_button: if self._hc_byte | FADERS != self._hc_byte: self._hc_byte = self._hc_byte | FADERS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self._fader_group_midi_button.turn_off() self._fader_button_modes.set_enabled(True) if sender is self._fader_group_fx_button: self._fader_modes.set_enabled(True) self._fader_button_modes.set_enabled(True) self._display_reset_delay = 0 return else: self.schedule_message(1, self._fader_modes.set_enabled, True) self.schedule_message(1, self._fader_modes.update) self.schedule_message(1, self._fader_button_modes.set_enabled, True) self.schedule_message(1, self._fader_button_modes.update) self._display_reset_delay = 2 return self._display_reset_delay = 0 def _set_drum_pads_to_hc(self): self._drum_group_midi_button.send_value(LED_OFF, True) self._drum_group_hyper_button.send_value(RED_FULL, True) for index in range(len(self._drum_pads)): self._drum_pads[index].send_value(RED_LOW, True) def _fader_button_value(self, value, sender): self._display_reset_delay = STANDARD_DISPLAY_DELAY def _fader_value(self, value, sender): param = sender.mapped_parameter() if param != None: param_range = param.max - param.min if param.name == "Track Volume": if sender == self._master_fader: if self._has_faders: name_string = "Master Vol" else: name_string = ( self._mixer_for_faders.selected_strip().track_name_data_source().display_string() + " Vol" ) else: name_string = ( self._mixer_for_faders.channel_strip(self._faders.index(sender)) .track_name_data_source() .display_string() + " Vol" ) else: name_string = param.name value = int((param.value - param.min) / param_range * 127) value_string = str(value) else: name_string = "<unmapped>" value_string = None self.schedule_message(1, self._set_value_string) self._set_name_string(name_string) self._set_value_string(value_string) def _encoder_value(self, value, sender): param = sender.mapped_parameter() if param != None: param_range = param.max - param.min if param.name == "Track Volume": name_string = ( self._mixer_for_encoders.channel_strip(self._encoders.index(sender)) .track_name_data_source() .display_string() + " Vol" ) value = int((param.value - param.min) / param_range * 127) elif param.name == "Track Panning": name_string = ( self._mixer_for_encoders.channel_strip(self._encoders.index(sender)) .track_name_data_source() .display_string() + " Pan" ) value = int(param.value / param_range * 127) if value < 0: name_string += " L" elif value > 0: name_string += " R" else: name_string += " C" else: name_string = param.name value = int((param.value - param.min) / param_range * 127) value_string = str(value) else: name_string = "<unmapped>" value_string = None self.schedule_message(1, self._set_value_string) self._set_name_string(name_string) self._set_value_string(value_string) def _set_displays_to_default(self): self._name_display.segment(0).set_data_source( self._mixer_for_encoders.selected_strip().track_name_data_source() ) self._name_display.update() self._update_bank_value() self._set_value_string(None) self._send_midi(SYSEX_START + LCD_HC_DEFAULT) def _set_name_string(self, name_string): self._name_display.segment(0).set_data_source(self._name_display_data_source) self._name_display_data_source.set_display_string(name_string) self._display_reset_delay = STANDARD_DISPLAY_DELAY def _set_value_string(self, value_string=None): if value_string != None: self._value_display_data_source.set_display_string(value_string) else: self._value_display.reset() def _set_bank_string(self, bank_string=None): if bank_string != None: self._bank_display_data_source.set_display_string(bank_string) else: self._bank_display.reset() def _update_bank_value(self): bank = (self._session.track_offset() + 1) / self._session.width() + 1 self._set_bank_string(str(bank)) def _install_mapping(self, midi_map_handle, control, parameter, feedback_delay, feedback_map): if not self._in_build_midi_map: raise AssertionError raise midi_map_handle != None or AssertionError raise control != None and parameter != None or AssertionError raise isinstance(parameter, Live.DeviceParameter.DeviceParameter) or AssertionError raise isinstance(control, InputControlElement) or AssertionError raise isinstance(feedback_delay, int) or AssertionError if not isinstance(feedback_map, tuple): raise AssertionError success = False feedback_rule = None feedback_rule = control.message_type() is MIDI_NOTE_TYPE and Live.MidiMap.NoteFeedbackRule() feedback_rule.note_no = 0 feedback_rule.vel_map = (0,) elif control.message_type() is MIDI_CC_TYPE: feedback_rule = Live.MidiMap.CCFeedbackRule() feedback_rule.cc_no = 0 feedback_rule.cc_value_map = (0,) elif control.message_type() is MIDI_PB_TYPE: feedback_rule = Live.MidiMap.PitchBendFeedbackRule() feedback_rule.value_pair_map = feedback_map raise feedback_rule != None or AssertionError feedback_rule.channel = control.message_channel() feedback_rule.delay_in_ms = feedback_delay success = control.message_type() is MIDI_NOTE_TYPE and Live.MidiMap.map_midi_note_with_feedback_map( midi_map_handle, parameter, control.message_channel(), control.message_identifier(), feedback_rule ) elif control.message_type() is MIDI_CC_TYPE: success = Live.MidiMap.map_midi_cc_with_feedback_map( midi_map_handle, parameter, control.message_channel(), control.message_identifier(), control.message_map_mode(), feedback_rule, not control.needs_takeover(), ) elif control.message_type() is MIDI_PB_TYPE: success = Live.MidiMap.map_midi_pitchbend_with_feedback_map( midi_map_handle, parameter, control.message_channel(), feedback_rule, not control.needs_takeover() ) return success
class Schwa_Launchpad_Test(ControlSurface): __doc__ = " Script for Schwa_Launchpad_Test in APC emulation mode " _active_instances = [] def _combine_active_instances(): track_offset = 0 scene_offset = 0 for instance in Schwa_Launchpad_Test._active_instances: instance._activate_combination_mode(track_offset, scene_offset) track_offset += instance._session.width() _combine_active_instances = staticmethod(_combine_active_instances) def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) #self.set_suppress_rebuild_requests(True) with self.component_guard(): self._note_map = [] self._ctrl_map = [] self._load_MIDI_map() self._session = None self._session_zoom = None self._mixer = None self._setup_session_control() self._setup_mixer_control() self._session.set_mixer(self._mixer) self._setup_device_and_transport_control() self.set_highlighting_session_component(self._session) #self.set_suppress_rebuild_requests(False) self._pads = [] self._load_pad_translations() self._do_combine() def disconnect(self): self._note_map = None self._ctrl_map = None self._pads = None self._do_uncombine() self._shift_button = None self._session = None self._session_zoom = None self._mixer = None ControlSurface.disconnect(self) def _do_combine(self): if self not in Schwa_Launchpad_Test._active_instances: Schwa_Launchpad_Test._active_instances.append(self) Schwa_Launchpad_Test._combine_active_instances() def _do_uncombine(self): if ((self in Schwa_Launchpad_Test._active_instances) and Schwa_Launchpad_Test._active_instances.remove(self)): self._session.unlink() Schwa_Launchpad_Test._combine_active_instances() def _activate_combination_mode(self, track_offset, scene_offset): if TRACK_OFFSET != -1: track_offset = TRACK_OFFSET if SCENE_OFFSET != -1: scene_offset = SCENE_OFFSET self._session.link_with_track_offset(track_offset, scene_offset) def _setup_session_control(self): is_momentary = True self._session = SpecialSessionComponent(8, 8) self._session.name = 'Session_Control' self._session.set_track_bank_buttons(self._note_map[SESSIONRIGHT], self._note_map[SESSIONLEFT]) self._session.set_scene_bank_buttons(self._note_map[SESSIONDOWN], self._note_map[SESSIONUP]) self._session.set_select_buttons(self._note_map[SCENEDN], self._note_map[SCENEUP]) self._scene_launch_buttons = [ self._note_map[SCENELAUNCH[index]] for index in range(8) ] self._track_stop_buttons = [ self._note_map[TRACKSTOP[index]] for index in range(8) ] self._session.set_stop_all_clips_button(self._note_map[STOPALLCLIPS]) self._session.set_stop_track_clip_buttons( tuple(self._track_stop_buttons)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( self._note_map[SELSCENELAUNCH]) self._session.set_slot_launch_button(self._note_map[SELCLIPLAUNCH]) for scene_index in range(8): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(self._scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = self._note_map[CLIPNOTEMAP[scene_index][track_index]] button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) clip_slot.set_launch_button(button) self._session_zoom = SpecialZoomingComponent(self._session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_nav_buttons(self._note_map[ZOOMUP], self._note_map[ZOOMDOWN], self._note_map[ZOOMLEFT], self._note_map[ZOOMRIGHT]) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.master_strip().set_select_button(self._note_map[MASTERSEL]) self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._mixer.set_select_buttons(self._note_map[TRACKRIGHT], self._note_map[TRACKLEFT]) self._mixer.set_crossfader_control(self._ctrl_map[CROSSFADER]) self._mixer.set_prehear_volume_control(self._ctrl_map[CUELEVEL]) self._mixer.master_strip().set_volume_control( self._ctrl_map[MASTERVOLUME]) for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) strip.set_arm_button(self._note_map[TRACKREC[track]]) strip.set_solo_button(self._note_map[TRACKSOLO[track]]) strip.set_mute_button(self._note_map[TRACKMUTE[track]]) strip.set_select_button(self._note_map[TRACKSEL[track]]) strip.set_volume_control(self._ctrl_map[TRACKVOL[track]]) strip.set_pan_control(self._ctrl_map[TRACKPAN[track]]) strip.set_send_controls((self._ctrl_map[TRACKSENDA[track]], self._ctrl_map[TRACKSENDB[track]], self._ctrl_map[TRACKSENDC[track]])) strip.set_invert_mute_feedback(True) def _setup_device_and_transport_control(self): is_momentary = True self._device = DeviceComponent() self._device.name = 'Device_Component' device_bank_buttons = [] device_param_controls = [] for index in range(8): device_param_controls.append(self._ctrl_map[PARAMCONTROL[index]]) device_bank_buttons.append(self._note_map[DEVICEBANK[index]]) if None not in device_bank_buttons: self._device.set_bank_buttons(tuple(device_bank_buttons)) if None not in device_param_controls: self._device.set_parameter_controls(tuple(device_param_controls)) self._device.set_on_off_button(self._note_map[DEVICEONOFF]) self._device.set_bank_nav_buttons(self._note_map[DEVICEBANKNAVLEFT], self._note_map[DEVICEBANKNAVRIGHT]) self._device.set_lock_button(self._note_map[DEVICELOCK]) self.set_device_component(self._device) detail_view_toggler = DetailViewControllerComponent() detail_view_toggler.name = 'Detail_View_Control' detail_view_toggler.set_device_clip_toggle_button( self._note_map[CLIPTRACKVIEW]) detail_view_toggler.set_detail_toggle_button( self._note_map[DETAILVIEW]) detail_view_toggler.set_device_nav_buttons( self._note_map[DEVICENAVLEFT], self._note_map[DEVICENAVRIGHT]) transport = SpecialTransportComponent() transport.name = 'Transport' transport.set_play_button(self._note_map[PLAY]) transport.set_stop_button(self._note_map[STOP]) transport.set_record_button(self._note_map[REC]) transport.set_nudge_buttons(self._note_map[NUDGEUP], self._note_map[NUDGEDOWN]) transport.set_undo_button(self._note_map[UNDO]) transport.set_redo_button(self._note_map[REDO]) transport.set_tap_tempo_button(self._note_map[TAPTEMPO]) transport.set_quant_toggle_button(self._note_map[RECQUANT]) transport.set_overdub_button(self._note_map[OVERDUB]) transport.set_metronome_button(self._note_map[METRONOME]) transport.set_tempo_control(self._ctrl_map[TEMPOCONTROL]) transport.set_loop_button(self._note_map[LOOP]) transport.set_seek_buttons(self._note_map[SEEKFWD], self._note_map[SEEKRWD]) transport.set_punch_buttons(self._note_map[PUNCHIN], self._note_map[PUNCHOUT]) ##transport.set_song_position_control(self._ctrl_map[SONGPOSITION]) #still not implemented as of Live 8.1.6 def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) def _load_pad_translations(self): if -1 not in DRUM_PADS: pad = [] for row in range(4): for col in range(4): pad = ( col, row, DRUM_PADS[row * 4 + col], PADCHANNEL, ) self._pads.append(pad) self.set_pad_translations(tuple(self._pads)) def _load_MIDI_map(self): is_momentary = True for note in range(128): button = ButtonElement(is_momentary, MESSAGETYPE, BUTTONCHANNEL, note) button.name = 'Note_' + str(note) self._note_map.append(button) self._note_map.append( None) #add None to the end of the list, selectable with [-1] if MESSAGETYPE == MIDI_CC_TYPE and BUTTONCHANNEL == SLIDERCHANNEL: for ctrl in range(128): self._ctrl_map.append(None) else: for ctrl in range(128): control = SliderElement(MIDI_CC_TYPE, SLIDERCHANNEL, ctrl) control.name = 'Ctrl_' + str(ctrl) self._ctrl_map.append(control) self._ctrl_map.append(None)
class Oxygen_3rd_Gen(ControlSurface): """ Script for the 3rd generation of M-Audio's Oxygen controllers """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): is_momentary = True self._suggested_input_port = 'Oxygen' self._suggested_output_port = 'Oxygen' self._has_slider_section = True self._device_selection_follows_track_selection = True self._shift_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 57) self._shift_button.add_value_listener(self._shift_value) self._mixer = SpecialMixerComponent(NUM_TRACKS) self._mute_solo_buttons = [] self._track_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 111) self._track_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 110) self._master_slider = SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 41) for index in range(NUM_TRACKS): self._mute_solo_buttons.append(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 49 + index)) self._mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 33 + index)) self._shift_value(0) self._mixer.master_strip().set_volume_control(self._master_slider) self._mixer.selected_strip().set_volume_control(None) device = DeviceComponent() device.set_parameter_controls(tuple([ EncoderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 17 + index, Live.MidiMap.MapMode.absolute) for index in range(8) ])) self.set_device_component(device) ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 115) rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 114) loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 113) transport = TransportComponent() transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 116)) transport.set_play_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 117)) transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 118)) session = SessionComponent(0, 0) transport_view_modes = TransportViewModeSelector(transport, session, ffwd_button, rwd_button, loop_button) return def disconnect(self): self._shift_button.remove_value_listener(self._shift_value) self._shift_button = None ControlSurface.disconnect(self) return def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(5, self._send_midi, IDENTITY_REQUEST) def handle_sysex(self, midi_bytes): if midi_bytes[0:5] == IDENTITY_RESPONSE: if midi_bytes[10] == 38: self._mixer.master_strip().set_volume_control(None) self._mixer.selected_strip().set_volume_control(self._master_slider) return def _shift_value(self, value): raise value in range(128) or AssertionError for index in range(NUM_TRACKS): if value == 0: self._mixer.channel_strip(index).set_solo_button(None) self._mixer.channel_strip(index).set_mute_button(self._mute_solo_buttons[index]) self._mixer.set_bank_buttons(None, None) self._mixer.set_select_buttons(self._track_up_button, self._track_down_button) else: self._mixer.channel_strip(index).set_mute_button(None) self._mixer.channel_strip(index).set_solo_button(self._mute_solo_buttons[index]) self._mixer.set_select_buttons(None, None) self._mixer.set_bank_buttons(self._track_up_button, self._track_down_button) return
class APC_64_40_9_vu(APC): """ Script for Akai's APC40 Controller """ def __init__(self, c_instance): self._c_instance = c_instance self._shift_modes = None self._encoder_modes = None self._slider_modes = None self._sequencer = None APC.__init__(self, c_instance) self._device_selection_follows_track_selection = True def disconnect(self): self._shift_modes = None self._encoder_modes = None self._slider_modes = None self._sequencer = None APC.disconnect(self) def _setup_session_control(self): is_momentary = True self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98) self._right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96) self._left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97) self._up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94) self._down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95) self._right_button.name = 'Bank_Select_Right_button' self._left_button.name = 'Bank_Select_Left_button' self._up_button.name = 'Bank_Select_Up_button' self._down_button.name = 'Bank_Select_Down_button' self._session = PedaledSessionComponent(8, 5) self._session.name = 'Session_Control' self._session.set_track_bank_buttons(self._right_button, self._left_button) self._session.set_scene_bank_buttons(self._down_button, self._up_button) self._matrix = ButtonMatrixElement() self._matrix.name = 'Button_Matrix' self._scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, index + 82) for index in range(5) ] self._track_stop_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ] for index in range(len(self._scene_launch_buttons)): self._scene_launch_buttons[index].name = 'Scene_' + str( index) + '_Launch_Button' for index in range(len(self._track_stop_buttons)): self._track_stop_buttons[index].name = 'Track_' + str( index) + '_Stop_Button' self._stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) self._stop_all_button.name = 'Stop_All_Clips_Button' self._session.set_stop_all_clips_button(self._stop_all_button) self._session.set_stop_track_clip_buttons( tuple(self._track_stop_buttons)) self._session.set_stop_clip_value(0) self._session.set_stop_clip_triggered_value(2) self._button_rows = [] for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(self._scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53)) button.name = str(track_index) + '_Clip_' + str( scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(5) clip_slot.set_started_value(1) clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) self._matrix.add_row(tuple(button_row)) self._button_rows.append(button_row) self._session.set_slot_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = ShiftableZoomingComponent( self._session, tuple(self._track_stop_buttons)) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(self._matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_nav_buttons(self._up_button, self._down_button, self._left_button, self._right_button) self._session_zoom.set_scene_bank_buttons( tuple(self._scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(self, 8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) master_select_button.name = 'Master_Select_Button' self._mixer.master_strip().set_select_button(master_select_button) self._mixer.selected_strip().name = 'Selected_Channel_Strip' select_buttons = [] arm_buttons = [] solo_buttons = [] mute_buttons = [] sliders = [] for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) solo_buttons.append(solo_button) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) mute_buttons.append(mute_button) solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) select_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) select_buttons[-1].name = str(track) + '_Select_Button' arm_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) arm_buttons[-1].name = str(track) + '_Arm_Button' sliders.append(SliderElement(MIDI_CC_TYPE, track, 7)) sliders[-1].name = str(track) + '_Volume_Control' self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) self._prehear_control = EncoderElement( MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) self._crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' self._prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_shift_button(self._shift_button) self._mixer.set_crossfader_control(self._crossfader) self._mixer.set_prehear_volume_control(self._prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) self._slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) self._slider_modes.name = 'Slider_Modes' self._matrix_modes = MatrixModesComponent( self._matrix, self._session, self._session_zoom, tuple(self._track_stop_buttons), self) self._matrix_modes.name = 'Matrix_Modes' self._sequencer = StepSequencerComponent( self, self._session, self._matrix, tuple(self._track_stop_buttons)) self._sequencer.set_bank_buttons(tuple(select_buttons)) self._sequencer.set_nav_buttons(self._up_button, self._down_button, self._left_button, self._right_button) self._sequencer.set_button_matrix(self._matrix) self._sequencer.set_follow_button(master_select_button) self._sequencer.set_velocity_buttons(tuple(arm_buttons)) self._sequencer.set_shift_button(self._shift_button) self._sequencer.set_lane_mute_buttons(tuple( self._scene_launch_buttons)) self._sequencer.set_loop_start_buttons(tuple(mute_buttons)) self._sequencer.set_loop_length_buttons(tuple(solo_buttons)) self._shift_modes = ShiftableSelectorComponent( self, tuple(select_buttons), master_select_button, tuple(self._track_stop_buttons), self._stop_all_button, tuple(mute_buttons), tuple(solo_buttons), tuple(arm_buttons), tuple(self._scene_launch_buttons), self._matrix, self._session, self._session_zoom, self._mixer, self._slider_modes, self._matrix_modes, self._sequencer) self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button) def _setup_custom_components(self): self._setup_device_and_transport_control() self._setup_global_control() def _setup_device_and_transport_control(self): is_momentary = True device_bank_buttons = [] device_param_controls = [] bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Metronome_Button') for index in range(8): device_bank_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 58 + index)) device_bank_buttons[-1].name = bank_button_labels[index] ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 24 + index) ringed_encoder = RingedEncoderElement( MIDI_CC_TYPE, 0, 16 + index, Live.MidiMap.MapMode.absolute) ringed_encoder.set_ring_mode_button(ring_mode_button) ringed_encoder.set_feedback_delay(-1) ringed_encoder.name = 'Device_Control_' + str(index) ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button' device_param_controls.append(ringed_encoder) self._device = ShiftableDeviceComponent() self._device.name = 'Device_Component' self._device.set_bank_buttons(tuple(device_bank_buttons)) self._device.set_shift_button(self._shift_button) self._device.set_parameter_controls(tuple(device_param_controls)) self._device.set_on_off_button(device_bank_buttons[1]) self.set_device_component(self._device) detail_view_toggler = DetailViewCntrlComponent() detail_view_toggler.name = 'Detail_View_Control' detail_view_toggler.set_shift_button(self._shift_button) detail_view_toggler.set_device_clip_toggle_button( device_bank_buttons[0]) detail_view_toggler.set_detail_toggle_button(device_bank_buttons[4]) detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3]) transport = ShiftableTransportComponent() transport.name = 'Transport' play_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 91) stop_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 92) record_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 93) nudge_up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 100) nudge_down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 101) tap_tempo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99) play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' record_button.name = 'Record_Button' nudge_up_button.name = 'Nudge_Up_button' nudge_down_button.name = 'Nudge_Down_button' tap_tempo_button.name = 'Tap_Tempo_Button' transport.set_shift_button(self._shift_button) transport.set_play_button(play_button) transport.set_stop_button(stop_button) transport.set_record_button(record_button) transport.set_nudge_buttons(nudge_up_button, nudge_down_button) transport.set_undo_button(nudge_down_button) transport.set_redo_button(nudge_up_button) transport.set_tap_tempo_button(tap_tempo_button) self._device.set_lock_button(tap_tempo_button) transport.set_quant_toggle_button(device_bank_buttons[5]) transport.set_overdub_button(device_bank_buttons[6]) transport.set_metronome_button(device_bank_buttons[7]) transport.set_tempo_encoder(self._prehear_control) bank_button_translator = ShiftTranslatorComponent() bank_button_translator.set_controls_to_translate( tuple(device_bank_buttons)) bank_button_translator.set_shift_button(self._shift_button) def _setup_global_control(self): is_momentary = True self._global_bank_buttons = [] self._global_param_controls = [] for index in range(8): ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 56 + index) ringed_encoder = RingedEncoderElement( MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute) ringed_encoder.name = 'Track_Control_' + str(index) ringed_encoder.set_feedback_delay(-1) ring_button.name = ringed_encoder.name + '_Ring_Mode_Button' ringed_encoder.set_ring_mode_button(ring_button) self._global_param_controls.append(ringed_encoder) self._global_bank_buttons = [] global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button') for index in range(4): self._global_bank_buttons.append( ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87 + index)) self._global_bank_buttons[-1].name = global_bank_labels[index] self._encoder_modes = EncModeSelectorComponent(self._mixer) self._encoder_modes.name = 'Track_Control_Modes' self._encoder_modes.set_controls(tuple(self._global_param_controls)) self._encoder_device_modes = EncoderDeviceComponent( self._mixer, self._device, self) self._encoder_device_modes.name = 'Alt_Device_Control_Modes' self._encoder_eq_modes = EncoderEQComponent(self._mixer, self) self._encoder_eq_modes.name = 'EQ_Control_Modes' global_translation_selector = ChannelTranslationSelector() global_translation_selector.name = 'Global_Translations' global_translation_selector.set_controls_to_translate( tuple(self._global_param_controls)) global_translation_selector.set_mode_buttons( tuple(self._global_bank_buttons)) encoder_user_modes = EncoderUserModesComponent( self, self._encoder_modes, tuple(self._global_param_controls), tuple(self._global_bank_buttons), self._mixer, self._device, self._encoder_device_modes, self._encoder_eq_modes) encoder_user_modes.name = 'Encoder_User_Modes' self._encoder_shift_modes = ShiftableEncoderSelectorComponent( self, tuple(self._global_bank_buttons), encoder_user_modes, self._encoder_modes, self._encoder_eq_modes, self._encoder_device_modes) self._encoder_shift_modes.name = 'Encoder_Shift_Modes' self._encoder_shift_modes.set_mode_toggle(self._shift_button) def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) return None def _on_track_offset_changed(self): self._matrix_modes._on_track_offset_changed() def _product_model_id_byte(self): return 115
class SubSelectorComponent(ModeSelectorComponent): """ Class that handles different mixer modes """ def __init__(self, matrix, side_buttons, session): assert (matrix, ButtonMatrixElement) assert matrix.width() == 8 and matrix.height() == 8 assert isinstance(side_buttons, tuple) assert len(side_buttons) == 8 assert isinstance(session, SessionComponent) ModeSelectorComponent.__init__(self) self._session = session self._mixer = SpecialMixerComponent(matrix.width()) self._matrix = matrix self._sliders = [] self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_strip' self._mixer.selected_strip().name = 'Selected_Channel_strip' for column in range(matrix.width()): self._mixer.channel_strip( column).name = 'Channel_Strip_' + str(column) self._sliders.append( PreciseButtonSliderElement( tuple([ matrix.get_button(column, 7 - row) for row in range(8) ]))) self._sliders[-1].name = 'Button_Slider_' + str(column) self._side_buttons = side_buttons[4:] self._update_callback = None self._session.set_mixer(self._mixer) self.set_modes_buttons(side_buttons[:4]) def disconnect(self): for button in self._modes_buttons: button.remove_value_listener(self._mode_value) self._session = None self._mixer = None for slider in self._sliders: slider.release_parameter() slider.set_disabled(True) self._sliders = None self._matrix = None self._side_buttons = None self._update_callback = None ModeSelectorComponent.disconnect(self) def set_update_callback(self, callback): assert dir(callback).count('im_func') is 1 self._update_callback = callback def set_modes_buttons(self, buttons): assert buttons == None or isinstance( buttons, tuple) or len(buttons) == self.number_of_modes() identify_sender = True for button in self._modes_buttons: button.remove_value_listener(self._mode_value) self._modes_buttons = [] if buttons != None: for button in buttons: assert isinstance(button, ButtonElement) self._modes_buttons.append(button) button.add_value_listener(self._mode_value, identify_sender) def set_mode(self, mode): assert isinstance(mode, int) assert mode in range(-1, self.number_of_modes()) if ((self._mode_index != mode) or (mode == -1)): self._mode_index = mode self.update() def mode(self): result = 0 if self.is_enabled(): result = self._mode_index + 1 return result def number_of_modes(self): return 4 def on_enabled_changed(self): enabled = self.is_enabled() for index in range(self._matrix.width()): self._sliders[index].set_disabled(not enabled) self._mixer.set_enabled(enabled) self.set_mode(-1) def release_controls(self): for track in range(self._matrix.width()): for row in range(self._matrix.height()): self._matrix.get_button(track, row).set_on_off_values(127, LED_OFF) strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_send_controls((None, None)) strip.set_pan_control(None) strip.set_volume_control(None) self._session.set_stop_track_clip_buttons(None) self._mixer.set_global_buttons(None, None, None) self._session.set_stop_all_clips_button(None) def update(self): assert (self._modes_buttons != None) if self.is_enabled(): if self._modes_buttons != None: for index in range(len(self._modes_buttons)): self._modes_buttons[index].set_on_off_values( GREEN_FULL, GREEN_THIRD) if index == self._mode_index: self._modes_buttons[index].turn_on() else: self._modes_buttons[index].turn_off() for button in self._side_buttons: button.set_on_off_values(127, LED_OFF) button.turn_off() for index in range(self._matrix.width()): self._sliders[index].set_disabled(self._mode_index == -1) self._mixer.set_allow_update(False) self._session.set_allow_update(False) if self._mode_index == -1: self._setup_mixer_overview() elif self._mode_index == 0: self._setup_volume_mode() elif self._mode_index == 1: self._setup_pan_mode() elif self._mode_index == 2: self._setup_send1_mode() elif self._mode_index == 3: self._setup_send2_mode() else: assert False if self._update_callback != None: self._update_callback() self._mixer.set_allow_update(True) self._session.set_allow_update(True) else: self.release_controls() def _setup_mixer_overview(self): trkon_index = 5 stop_buttons = [] for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_send_controls((None, None)) strip.set_pan_control(None) strip.set_volume_control(None) self._sliders[track].release_parameter() for row in range(self._matrix.height()): full_value = GREEN_THIRD third_value = GREEN_FULL if row == trkon_index: full_value = AMBER_FULL third_value = AMBER_THIRD elif row > 3: full_value = RED_FULL third_value = RED_THIRD self._matrix.get_button(track, row).set_on_off_values( full_value, third_value) strip.set_default_buttons(self._matrix.get_button(track, 0), self._matrix.get_button(track, 1), self._matrix.get_button(track, 2), self._matrix.get_button(track, 3)) stop_buttons.append(self._matrix.get_button(track, 4)) strip.set_mute_button(self._matrix.get_button(track, 5)) strip.set_solo_button(self._matrix.get_button(track, 6)) strip.set_arm_button(self._matrix.get_button(track, 7)) for button in self._side_buttons: if list(self._side_buttons).index(button) == trkon_index - 4: button.set_on_off_values(AMBER_FULL, AMBER_THIRD) else: button.set_on_off_values(RED_FULL, RED_THIRD) button.set_force_next_value() button.turn_off() self._session.set_stop_track_clip_buttons(tuple(stop_buttons)) self._session.set_stop_all_clips_button(self._side_buttons[0]) self._mixer.set_global_buttons(self._side_buttons[3], self._side_buttons[2], self._side_buttons[1]) def _setup_volume_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_send_controls((None, None)) strip.set_pan_control(None) for row in range(self._matrix.height()): self._matrix.get_button(track, row).set_on_off_values( GREEN_FULL, LED_OFF) self._sliders[track].set_mode(SLIDER_MODE_VOLUME) self._sliders[track].set_value_map(VOL_VALUE_MAP) strip.set_volume_control(self._sliders[track]) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None) def _setup_pan_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_send_controls((None, None)) strip.set_volume_control(None) for row in range(self._matrix.height()): self._matrix.get_button(track, row).set_on_off_values( AMBER_FULL, LED_OFF) self._sliders[track].set_mode(SLIDER_MODE_PAN) self._sliders[track].set_value_map(PAN_VALUE_MAP) strip.set_pan_control(self._sliders[track]) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None) def _setup_send1_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_volume_control(None) strip.set_pan_control(None) for row in range(self._matrix.height()): self._matrix.get_button(track, row).set_on_off_values( RED_FULL, LED_OFF) self._sliders[track].set_mode(SLIDER_MODE_VOLUME) self._sliders[track].set_value_map(SEND_VALUE_MAP) strip.set_send_controls((self._sliders[track], None)) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None) def _setup_send2_mode(self): for track in range(self._matrix.width()): strip = self._mixer.channel_strip(track) strip.set_default_buttons(None, None, None, None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) strip.set_volume_control(None) strip.set_pan_control(None) for row in range(self._matrix.height()): self._matrix.get_button(track, row).set_on_off_values( RED_FULL, LED_OFF) self._sliders[track].set_mode(SLIDER_MODE_VOLUME) self._sliders[track].set_value_map(SEND_VALUE_MAP) strip.set_send_controls((None, self._sliders[track])) self._session.set_stop_track_clip_buttons(None) self._session.set_stop_all_clips_button(None) self._mixer.set_global_buttons(None, None, None)
def _setup_mixer_control(self): is_momentary = True self._num_tracks = (7) #A mixer is one-dimensional; global mixer mixer = SpecialMixerComponent(7, 0, True, False) mixer.name = 'Mixer' self._mixer = mixer mixer.set_track_offset( 0) #Sets start point for mixer strip (offset from left) for index in range(7): mixer.channel_strip(index).set_volume_control(self._fader[index]) for index in range(7): mixer.channel_strip( index).name = 'Mixer_ChannelStrip_' + str(index) mixer.track_eq(index).name = 'Mixer_EQ_' + str(index) mixer.channel_strip(index)._invert_mute_feedback = True self.song().view.selected_track = 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