def _setup_mixer_control(self): is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant num_tracks = 7 # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent(num_tracks, 0) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track mixer.selected_strip().set_mute_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 64)) #mixer.selected_strip().set_solo_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 44)) mixer.selected_strip().set_arm_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 72)) track_select_notes = [65, 73, 66, 74, 67, 75, 68, 76] #more note numbers need to be added if num_scenes is increased slider_select_notes = [23, 22, 15, 14, 5, 7, 6, 4] pan_select_notes = [21, 20, 13, 12, 3, 1, 0, 2] master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 4) master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 76) prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 26, Live.MidiMap.MapMode.absolute) crossfader = SliderElement(MIDI_CC_TYPE, 0, 24) for index in range(num_tracks): mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, track_select_notes[index])) mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL, slider_select_notes[index])) mixer.channel_strip(index).set_pan_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, pan_select_notes[index], Live.MidiMap.MapMode.absolute)) crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' master_select_button.name = 'Master_Select_Button' prehear_control.name = 'Prehear_Volume_Control' mixer.set_crossfader_control(crossfader) mixer.set_prehear_volume_control(prehear_control) mixer.master_strip().set_volume_control(master_volume_control) mixer.master_strip().set_select_button(master_select_button)
def _setup_mixer_control(self): is_momentary = True #mixer = MixerComponent(8) mixer = MixerComponent(1) #for track in range(8): # strip = mixer.channel_strip(track) # strip.set_volume_control(SliderElement(MIDI_CC_TYPE, track, 7)) # strip.set_arm_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) # strip.set_solo_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)) # strip.set_mute_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50)) # #strip.set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) # strip.set_shift_button(self._shift_button) # strip.set_invert_mute_feedback(True) """ WAC addition....................................""" mixer.selected_strip().set_mute_button(SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[9])) mixer.selected_strip().set_solo_button(SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[13])) mixer.set_select_buttons(SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[15]), SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[14])) send_faders = [] NUM_CONTROLLABLE_SENDS = 4 for index in range(NUM_CONTROLLABLE_SENDS): send_faders.append(SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[index + 2])) mixer.selected_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[0])) mixer.selected_strip().set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[1])) mixer.selected_strip().set_send_controls(tuple(send_faders)) """------------------------------------------------""" #mixer.set_crossfader_control(SliderElement(MIDI_CC_TYPE, 0, 15)) #mixer.set_prehear_volume_control(EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)) mixer.set_prehear_volume_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[6], Live.MidiMap.MapMode.absolute)) #mixer.master_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, 0, 14)) mixer.master_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[7])) #mixer.master_strip().set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80)) return mixer
def _setup_mixer_control(self): is_momentary = True mixer = MixerComponent(1) mixer.selected_strip().set_mute_button( SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[9])) mixer.selected_strip().set_solo_button( SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[13])) mixer.set_select_buttons( SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[15]), SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[14])) send_faders = [] NUM_CONTROLLABLE_SENDS = 4 for index in range(NUM_CONTROLLABLE_SENDS): send_faders.append( SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[index + 2])) mixer.selected_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[0])) mixer.selected_strip().set_pan_control( SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[1])) mixer.selected_strip().set_send_controls(tuple(send_faders)) mixer.set_prehear_volume_control( EncoderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[6], Live.MidiMap.MapMode.absolute)) mixer.master_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[7])) return mixer
def _setup_mixer_control(self): is_momentary = True mixer = MixerComponent(NUM_TRACKS, 2, with_eqs=True, with_filters=True) for track in range(NUM_TRACKS): strip = mixer.channel_strip(track) strip.set_volume_control(SliderElement(MIDI_CC_TYPE, track, 23)) strip.set_pan_control(EncoderElement(MIDI_CC_TYPE, track, 10, Live.MidiMap.MapMode.absolute)) strip.set_send_controls((EncoderElement(MIDI_CC_TYPE, track, 19, Live.MidiMap.MapMode.absolute), EncoderElement(MIDI_CC_TYPE, track, 20, Live.MidiMap.MapMode.absolute))) strip.set_solo_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 64)) strip.set_mute_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 63)) strip.set_crossfade_toggle(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 65)) eq = mixer.track_eq(track) eq.set_gain_controls(tuple([ EncoderElement(MIDI_CC_TYPE, track, (18 - index), Live.MidiMap.MapMode.absolute) for index in range(3) ])) eq.set_cut_buttons(tuple([ ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, (62 - index)) for index in range(3) ])) filter = mixer.track_filter(track) filter.set_filter_controls(EncoderElement(MIDI_CC_TYPE, track, 22, Live.MidiMap.MapMode.absolute), EncoderElement(MIDI_CC_TYPE, track, 21, Live.MidiMap.MapMode.absolute)) for ret_track in range(2): strip = mixer.return_strip(ret_track) strip.set_volume_control(SliderElement(MIDI_CC_TYPE, 12, (22 + ret_track))) strip.set_pan_control(EncoderElement(MIDI_CC_TYPE, 12, (20 + ret_track), Live.MidiMap.MapMode.absolute)) strip.set_mute_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, (78 + ret_track))) mixer.set_crossfader_control(SliderElement(MIDI_CC_TYPE, 12, 8)) mixer.set_prehear_volume_control(EncoderElement(MIDI_CC_TYPE, 12, 24, Live.MidiMap.MapMode.absolute)) mixer.master_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, 12, 7)) mixer.master_strip().set_pan_control(EncoderElement(MIDI_CC_TYPE, 12, 10, Live.MidiMap.MapMode.absolute)) return mixer
def _setup_mixer_control(self): is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant num_tracks = 7 # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent(num_tracks, 0) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track mixer.selected_strip().set_mute_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 64)) #mixer.selected_strip().set_solo_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 44)) mixer.selected_strip().set_arm_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 72)) track_select_notes = [65, 73, 66, 74, 67, 75, 68, 76] #more note numbers need to be added if num_scenes is increased slider_select_notes = [3, 2, 1, 0, 5, 4, 6, 7] #pan_select_notes = [21, 20, 13, 12, 3, 1, 0, 2] master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 7) #master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 76) #prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 26, Live.MidiMap.MapMode.absolute) #crossfader = SliderElement(MIDI_CC_TYPE, 0, 24) for index in range(num_tracks): #mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, track_select_notes[index])) mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL, slider_select_notes[index])) #mixer.channel_strip(index).set_pan_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, pan_select_notes[index], Live.MidiMap.MapMode.absolute)) #crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' #master_select_button.name = 'Master_Select_Button' #prehear_control.name = 'Prehear_Volume_Control' #mixer.set_crossfader_control(crossfader) #mixer.set_prehear_volume_control(prehear_control) mixer.master_strip().set_volume_control(master_volume_control)
def _setup_mixer_control(self): is_momentary = True mixer = MixerComponent(NUM_TRACKS, 2, with_eqs=True, with_filters=True) for track in range(NUM_TRACKS): strip = mixer.channel_strip(track) strip.set_volume_control(SliderElement(MIDI_CC_TYPE, track, 23)) strip.set_pan_control( EncoderElement(MIDI_CC_TYPE, track, 10, Live.MidiMap.MapMode.absolute)) strip.set_send_controls( (EncoderElement(MIDI_CC_TYPE, track, 19, Live.MidiMap.MapMode.absolute), EncoderElement(MIDI_CC_TYPE, track, 20, Live.MidiMap.MapMode.absolute))) strip.set_solo_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 64)) strip.set_mute_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 63)) strip.set_crossfade_toggle( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 65)) eq = mixer.track_eq(track) eq.set_gain_controls( tuple([ EncoderElement(MIDI_CC_TYPE, track, 18 - index, Live.MidiMap.MapMode.absolute) for index in range(3) ])) eq.set_cut_buttons( tuple([ ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 62 - index) for index in range(3) ])) filter = mixer.track_filter(track) filter.set_filter_controls( EncoderElement(MIDI_CC_TYPE, track, 22, Live.MidiMap.MapMode.absolute), EncoderElement(MIDI_CC_TYPE, track, 21, Live.MidiMap.MapMode.absolute)) for ret_track in range(2): strip = mixer.return_strip(ret_track) strip.set_volume_control( SliderElement(MIDI_CC_TYPE, 12, 22 + ret_track)) strip.set_pan_control( EncoderElement(MIDI_CC_TYPE, 12, 20 + ret_track, Live.MidiMap.MapMode.absolute)) strip.set_mute_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 78 + ret_track)) mixer.set_crossfader_control(SliderElement(MIDI_CC_TYPE, 12, 8)) mixer.set_prehear_volume_control( EncoderElement(MIDI_CC_TYPE, 12, 24, Live.MidiMap.MapMode.absolute)) mixer.master_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, 12, 7)) mixer.master_strip().set_pan_control( EncoderElement(MIDI_CC_TYPE, 12, 10, Live.MidiMap.MapMode.absolute)) return mixer
def _setup_mixer_control(self): is_momentary = True num_tracks = 7 #A mixer is one-dimensional; here we define the width in tracks - seven columns, which we will map to seven "white" notes """Here we set up the global mixer""" #Note that it is possible to have more than one mixer... global mixer #We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent( num_tracks, 2, with_eqs=True, with_filters=True ) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset( 0) #Sets start point for mixer strip (offset from left) 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 """set up the mixer buttons""" mixer.set_select_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 56), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 54)) #left, right track select mixer.master_strip().set_select_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 94)) #jump to the master track mixer.selected_strip().set_mute_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 42)) #sets the mute ("activate") button mixer.selected_strip().set_solo_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 44)) #sets the solo button mixer.selected_strip().set_arm_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 46)) #sets the record arm button """set up the mixer sliders""" mixer.selected_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, 14)) #sets the continuous controller for volume """note that we have split the mixer functions across two scripts, in order to have two session highlight boxes (one red, one yellow), so there are a few things which we are not doing here..."""
def _create_mixer_control(self): is_momentary = True num_tracks = 7 """Here we set up the global mixer""" global mixer mixer = MixerComponent(name='Mixer', num_tracks=num_tracks, is_enabled=False, num_returns=2) mixer.set_enabled(True) mixer.set_track_offset(0) self.song().view.selected_track = mixer.channel_strip(0)._track mixer.channel_strip(0) """set up the mixer buttons""" mixer.set_select_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 56), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 54)) mixer.master_strip().set_select_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 94)) mixer.selected_strip().set_mute_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 42)) mixer.selected_strip().set_solo_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 44)) mixer.selected_strip().set_arm_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 46)) """set up the mixer sliders""" mixer.selected_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, 14)) """note that we have split the mixer functions across two scripts, in order to have two session highlight boxes (one red, one yellow), so there are a few things which we are not doing here... """ self.log_message("Captain's log stardate 2")
def _setup_mixer_control(self): is_momentary = True """ Instantiate a Mixer Component """ global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent(mixer_num_tracks, 2, with_eqs=True, with_filters=True) # (num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset(0) # Sets start point for mixer strip (offset from left) 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 """ Buttons and Sliders association """ # Master channel mixer.master_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, midi_channel, midi_mixer_volume_master)) # sets the continuous controller for volume # Other channels, same size as mixer_num_tracks # Set volume control, solo and mute buttons for index in range(mixer_num_tracks): # launch_button assignment must match number of scenes mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, midi_channel, midi_mixer_volume_channels[index])) # sets the continuous controller for volume mixer.channel_strip(index).set_solo_button(ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_mixer_solo_channels[index])) # sets the solo button mixer.channel_strip(index).set_mute_button(ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_mixer_mute_channels[index])) # sets the mute ("activate") button """ Buttons to select track """ button_next_track = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_track_select_next) button_previous_track = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_track_select_previous) mixer.set_select_buttons(button_next_track, button_previous_track) """ Listeners """ # When selected track if changed self.song().view.add_selected_track_listener(self.on_track_selected)
def _setup_mixer_control(self): is_momentary = True num_tracks = 8 num_returns = 7 mixer = MixerComponent(num_tracks, num_returns) for track in range(num_tracks): strip = mixer.channel_strip(track) strip.set_volume_control( SliderElement(MIDI_CC_TYPE, 15, 54 - track)) strip.set_pan_control(SliderElement(MIDI_CC_TYPE, 15, 80 - track)) strip.set_mute_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 117 - track)) strip.set_invert_mute_feedback(True) for track in range(num_returns): strip = mixer.return_strip(track) strip.set_volume_control( SliderElement(MIDI_CC_TYPE, 15, 10 + track)) mixer.set_bank_buttons( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 108), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 109)) mixer.set_crossfader_control(SliderElement(MIDI_CC_TYPE, 15, 9)) mixer.master_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, 15, 46)) session = SessionComponent(0, 0) session.set_select_buttons( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 95), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 92)) session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 91))
class Alias8(ControlSurface): num_tracks = 8 knobs_top = [1, 2, 3, 4, 5, 6, 7, 8] knobs_bottom = [9, 10, 11, 12, 13, 14, 15, 16] faders = [17, 18, 19, 20, 21, 22, 23, 24] master_fader = 25 encoder = 42 buttons_top = [0, 1, 2, 3, 4, 5, 6, 7] buttons_bottom = [8, 9, 10, 11, 12, 13, 14, 15] def __init__(self, instance): super(Alias8, self).__init__(instance, False) with self.component_guard(): self._set_suppress_rebuild_requests(True) self.init_session() self.init_mixer() # Connect mixer to session. self.session.set_mixer(self.mixer) self.session.update() # New in Live 9: must explicitly activate session component. self.set_highlighting_session_component(self.session) self._set_suppress_rebuild_requests(False) def init_session(self): self.session = SessionComponent(self.num_tracks, 1) self.session.name = 'Alias 8 Session' self.session.update() # Connect the encoder to track scroller. def scroll_cb(value): if value == 1: self.session._horizontal_banking.scroll_down() elif value == 127: self.session._horizontal_banking.scroll_up() self.track_encoder = EncoderElement(MIDI_CC_TYPE, 0, self.encoder, Live.MidiMap.MapMode.absolute) self.track_encoder.add_value_listener(scroll_cb) def init_mixer(self): self.mixer = MixerComponent(self.num_tracks, 0) self.mixer.id = 'Mixer' self.song().view.selected_track = self.mixer.channel_strip(0)._track for i in range(self.num_tracks): self.mixer.channel_strip(i).set_volume_control( fader(self.faders[i])) self.mixer.channel_strip(i).set_solo_button( button(self.buttons_top[i], color=CYAN)) self.mixer.channel_strip(i).set_arm_button( button(self.buttons_bottom[i], color=RED)) self.mixer.channel_strip(i).set_pan_control( knob(self.knobs_bottom[i])) self.mixer.master_strip().set_volume_control(fader(self.master_fader)) self.mixer.update()
def _setup_mixer_control(self): is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant num_tracks = 4 # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent(num_tracks, 2, with_eqs=True, with_filters=False) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track #mute_notes = [1,5,9,13] #solo_notes = [2,6,10,14] #arm_notes = [3,7,11,15] track_select_notes = [38,39,40,41]#more note numbers need to be added if num_scenes is increased send_ccs = [2,6,10,14,1,5,9,13] pan_ccs = [3,7,11,15] slider_ccs = [4,8,12,16] for index in range(num_tracks): mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, track_select_notes[index])) mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHAN, slider_ccs[index])) mixer.channel_strip(index).set_pan_control(EncoderElement(MIDI_CC_TYPE, CHAN, pan_ccs[index], Live.MidiMap.MapMode.absolute)) #put send A and send B controllers into an array, which is then "tupled" for set_send_controls: send_controlers = [EncoderElement(MIDI_CC_TYPE, CHAN, send_ccs[index], Live.MidiMap.MapMode.absolute), EncoderElement(MIDI_CC_TYPE, CHAN, send_ccs[index+num_tracks], Live.MidiMap.MapMode.absolute)] mixer.channel_strip(index).set_send_controls(tuple(send_controlers)) crossfader = SliderElement(MIDI_CC_TYPE, CHAN, 28) master_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 32) returna_pan_control = SliderElement(MIDI_CC_TYPE, CHAN, 19) returna_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 20) returnb_pan_control = SliderElement(MIDI_CC_TYPE, CHAN, 23) returnb_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 24) master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 31) prehear_control = EncoderElement(MIDI_CC_TYPE, CHAN, 30, Live.MidiMap.MapMode.absolute) crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' returna_pan_control.name = 'ReturnA_Pan_Control' returna_volume_control.name = 'ReturnA_Volume_Control' returnb_pan_control.name = 'ReturnB_Pan_Control' returnb_volume_control.name = 'ReturnB_Volume_Control' master_select_button.name = 'Master_Select_Button' prehear_control.name = 'Prehear_Volume_Control' mixer.set_crossfader_control(crossfader) mixer.master_strip().set_volume_control(master_volume_control) mixer.master_strip().set_select_button(master_select_button) mixer.set_prehear_volume_control(prehear_control) mixer.return_strip(0).set_pan_control(returna_pan_control) mixer.return_strip(0).set_volume_control(returna_volume_control) mixer.return_strip(1).set_pan_control(returnb_pan_control) mixer.return_strip(1).set_volume_control(returnb_volume_control)
def _setup_mixer_control(self): is_momentary = True mixer = MixerComponent(1) mixer.selected_strip().set_mute_button(SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[9])) mixer.selected_strip().set_solo_button(SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[13])) mixer.set_select_buttons(SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[15]), SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KMK_PAD[14])) send_faders = [] NUM_CONTROLLABLE_SENDS = 4 for index in range(NUM_CONTROLLABLE_SENDS): send_faders.append(SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[index + 2])) mixer.selected_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[0])) mixer.selected_strip().set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[1])) mixer.selected_strip().set_send_controls(tuple(send_faders)) mixer.set_prehear_volume_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[6], Live.MidiMap.MapMode.absolute)) mixer.master_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[7])) return mixer
def _setup_mixer_control(self): is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant num_tracks = 8 # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent( num_tracks, 0, with_eqs=False, with_filters=False ) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset( 0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track master_volume_control = SliderElement(MIDI_CC_TYPE, CHANNEL, 9) for index in range(num_tracks): mixer.channel_strip(index).set_mute_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, (index + 19))) mixer.channel_strip(index).set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, (index + 1))) #mixer.channel_strip(index).set_pan_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, (index+10), Live.MidiMap.MapMode.absolute)) master_volume_control.name = 'Master_Volume_Control' mixer.master_strip().set_volume_control(master_volume_control)
def _setup_mixer_control(self): num_tracks = 7 global mixer mixer = MixerComponent(num_tracks) mixer.set_track_offset(0) self.song().view.selected_track = mixer.channel_strip(0)._track master_volume_fader = SliderElement(MIDI_CC_TYPE, CHANNEL, MASTER_FADER) mixer.master_strip().set_volume_control(master_volume_fader) for index in range(num_tracks): mixer.channel_strip(index).set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, FADERS[index])) mixer.channel_strip(index).set_mute_button( ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, TRACK_MUTE_BUTTONS[index])) mixer.channel_strip(index).set_select_button( ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, TRACK_SELECT_BUTTONS[index])) #mixer.channel_strip(index).set_send_controls(SliderElement(MIDI_CC_TYPE, CHANNEL, SEND_KNOBS[index])) '''for index in range(6):
def _setup_mixer_control(self): is_momentary = True num_tracks = 8 num_returns = 7 mixer = MixerComponent(num_tracks, num_returns) for track in range(num_tracks): strip = mixer.channel_strip(track) strip.set_volume_control(SliderElement(MIDI_CC_TYPE, 15, 54 - track)) strip.set_pan_control(SliderElement(MIDI_CC_TYPE, 15, 80 - track)) strip.set_mute_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 117 - track)) strip.set_invert_mute_feedback(True) for track in range(num_returns): strip = mixer.return_strip(track) strip.set_volume_control(SliderElement(MIDI_CC_TYPE, 15, 10 + track)) mixer.set_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 108), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 109)) mixer.set_crossfader_control(SliderElement(MIDI_CC_TYPE, 15, 9)) mixer.master_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, 15, 46)) session = SessionComponent(0, 0) session.set_select_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 95), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 92)) session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 91))
class midilooper(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._instance = c_instance self._has_slider_section = True self.log_message("Midilooper initializing...") # register_sender(self) self._session = SessionComponent(NUM_TRACKS, NUM_ROWS) self._session.name = 'Session_Control' self._mixer = MixerComponent(NUM_TRACKS, NUM_RETURNS) for track in range(NUM_TRACKS): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) # encoder = EncoderElement(MIDI_CC_TYPE, 0, 20 + track, Live.MidiMap.MapMode.absolute) control = SliderElement(MIDI_CC_TYPE, 0, 20+track) control.name = str(track) + '_Volume_Control' strip.set_volume_control(control) for track in range(NUM_RETURNS): strip = self._mixer.return_strip(track) control = SliderElement(MIDI_CC_TYPE, 0, 40+track) control.name = str(track) + '_Return_Control' strip.set_volume_control(control) strip = self._mixer.master_strip() strip.name = 'Master_Channel_Strip' control = SliderElement(MIDI_CC_TYPE, 0, 50) control.name = 'Master_Volume_Control' strip.set_volume_control(control) self._session.set_offsets(0, 0); self._session.set_mixer(self._mixer) for row in range(NUM_ROWS): scene = self._session.scene(row) for track in range(NUM_TRACKS): slot = scene.clip_slot(track) button = ButtonElement(True, MIDI_NOTE_TYPE, track, 36+row) slot.set_launch_button(button) self.set_highlighting_session_component(self._session) self.request_rebuild_midi_map() self.log_message("Midilooper initialized.") def disconnect(self): ControlSurface.disconnect(self)
def _setup_mixer_control(self): num_tracks = GRIDSIZE[0] # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent(num_tracks) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track master = mixer.master_strip() master.set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_USER, MASTER_VOLUME)) mixer.set_prehear_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_USER, PREHEAR)) for index in xrange(GRIDSIZE[0]): mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, MIX_FADERS[index])) # mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_INST, MIX_FADERS[index])) mixer.channel_strip(index).set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, PAN_CONTROLS[index])) mixer.channel_strip(index).set_arm_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, ARM_BUTTONS[index])) #sets the record arm button mixer.channel_strip(index).set_solo_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, SOLO_BUTTONS[index])) mixer.channel_strip(index).set_mute_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, MUTE_BUTTONS[index])) mixer.channel_strip(index).set_select_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, TRACK_SELECTS[index])) mixer.channel_strip(index).set_send_controls([SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][0]), SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][1]), SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][2]), SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][3])]) """TRANSPORT CONTROLS""" stop_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL_MIXER, STOP_BUTTON) play_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL_MIXER, PLAY_BUTTON) record_button = ButtonElement(False,MIDI_CC_TYPE,CHANNEL_MIXER,RECORD_BUTTON) overdub_button = ButtonElement(False,MIDI_CC_TYPE,CHANNEL_MIXER,OVERDUB_BUTTON) transport = TransportComponent() transport.TEMPO_TOP = 188 transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_overdub_button(overdub_button) transport.set_record_button(record_button) transport.set_seek_buttons(ButtonElement(False,MIDI_CC_TYPE,0,SEEK_LEFT),ButtonElement(False,MIDI_CC_TYPE,0,SEEK_RIGHT)) transport.set_tempo_control(SliderElement(MIDI_CC_TYPE, CHANNEL_USER, TEMPO)) transport.set_metronome_button(ButtonElement(False,MIDI_CC_TYPE,CHANNEL_USER, METRONOME)) transport.set_tap_tempo_button(ButtonElement(False,MIDI_CC_TYPE,CHANNEL_USER,TAP_TEMPO))
class MPK_SessionControl(ControlSurface): __module__ = __name__ __doc__ = "MPK Session Control Script" def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._setup_mixer_control() self._setup_transport_control() self._setup_session_control() self._setup_channel_strip_control() self.set_highlighting_session_component(self.session) # Sets up the control surface ('colored box') def _setup_session_control(self): num_tracks = 3 # 3 columns (tracks) num_scenes = 1 # 1 row (scenes) # a session highlight ("red box") will appear with any two non-zero values self.session = SessionComponent(num_tracks, num_scenes) # (track_offset, scene_offset) Sets the initial offset of the "red box" from top left self.session.set_offsets(0, 0) self.session.set_select_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_HIGH_C - 7), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_HIGH_C - 6)) # These calls control the actual movement of the box; however, we're just # using scene and track select to move around # self.session.set_scene_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 86), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 85)) # self.session.set_track_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 15), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 14)) # Launch current scene with top right pad self.session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, BANK_B[3])) # Stop all clips with bottom right pad self.session.set_stop_all_clips_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, BANK_B[7])) # First three pads launch clips in box clip_launch_notes = [BANK_B[0], BANK_B[1], BANK_B[2]] clip_select_notes = [ KEYBOARD_MID_C - 6, KEYBOARD_MID_C - 4, KEYBOARD_MID_C - 2 ] for tracks in range(num_tracks): self.session.scene(0).clip_slot(tracks).set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, clip_launch_notes[tracks])) self.session.scene(0).clip_slot(tracks).set_select_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, clip_select_notes[tracks])) self.session.scene(0).clip_slot(tracks).set_started_value(1) self.session.scene(0).clip_slot(tracks).set_stopped_value(0) # Bottom three pads stop current tracks in box track_stop_notes = [BANK_B[4], BANK_B[5], BANK_B[6]] # This looks unnecessary but I don't know the actual API call to to set the stop track button for the selected track stop_track_buttons = [] for tracks in range(num_tracks): stop_track_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, track_stop_notes[tracks])) self.session.set_stop_track_clip_buttons(tuple(stop_track_buttons)) #here we set up a mixer and channel strip(s) which move with the session self.session.set_mixer( self.mixer ) #bind the mixer to the session so that they move together selected_scene = self.song( ).view.selected_scene #this is from the Live API all_scenes = self.song().scenes index = list(all_scenes).index(selected_scene) self.session.set_offsets(0, index) #(track_offset, scene_offset) def _setup_transport_control(self): self.transport = TransportComponent() self.transport.set_stop_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_LOW_C)) self.transport.set_play_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 113)) self.transport.set_metronome_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 114)) self.transport.set_tap_tempo_button( ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 81)) def _setup_mixer_control(self): #set up the mixer self.mixer = MixerComponent( NUM_TRACKS, 2) #(num_tracks, num_returns, with_eqs, with_filters) self.mixer.set_track_offset( 0) #sets start point for mixer strip (offset from left) self.mixer.selected_strip().set_arm_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_HIGH_C)) self.mixer.set_select_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_HIGH_C - 2), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, KEYBOARD_HIGH_C - 4)) self.mixer.master_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[3])) #self.mixer.master_strip().set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[7])) #set the selected strip to the first track, so that we don't assign a button to arm the master track, which would cause an assertion error self.song().view.selected_track = self.mixer.channel_strip(0)._track self.mixer.selected_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[0])) #self.mixer.selected_strip().set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[4])) selected_track = self.song().view.selected_track all_tracks = ((self.song().tracks + self.song().return_tracks) + (self.song().master_track, )) currentTrackIndex = list(all_tracks).index(selected_track) if currentTrackIndex < len(all_tracks) - 1: self.mixer.channel_strip(currentTrackIndex + 1).set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[1])) #self.mixer.channel_strip(currentTrackIndex + 1).set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[5])) if currentTrackIndex < len(all_tracks) - 2: self.mixer.channel_strip(currentTrackIndex + 2).set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[2])) #self.mixer.channel_strip(currentTrackIndex + 2).set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[6])) def _setup_channel_strip_control(self): self.channelstrip = ChannelStripComponent() self.channelstrip.set_track(self.mixer.channel_strip(0)._track) def _on_selected_track_changed(self): """This is an override, to add special functionality (we want to move the session to the selected track, when it changes) Note that it is sometimes necessary to reload Live (not just the script) when making changes to this function""" ControlSurface._on_selected_track_changed( self ) # This will run component.on_selected_track_changed() for all components """here we set the mixer and session to the selected track, when the selected track changes""" selected_track = self.song( ).view.selected_track #this is how to get the currently selected track, using the Live API self.mixer.channel_strip(0).set_track(selected_track) all_tracks = ( (self.song().tracks + self.song().return_tracks) + (self.song().master_track, ) ) #this is from the MixerComponent's _next_track_value method index = list(all_tracks).index(selected_track) #and so is this self.session.set_offsets( index, self.session._scene_offset ) #(track_offset, scene_offset); we leave scene_offset unchanged, but set track_offset to the selected track. This allows us to jump the red box to the selected track. def _on_selected_scene_changed(self): """This is an override, to add special functionality (we want to move the session to the selected scene, when it changes)""" """When making changes to this function on the fly, it is sometimes necessary to reload Live (not just the script)...""" ControlSurface._on_selected_scene_changed( self ) # This will run component.on_selected_scene_changed() for all components """Here we set the mixer and session to the selected track, when the selected track changes""" selected_scene = self.song( ).view.selected_scene #this is how we get the currently selected scene, using the Live API all_scenes = self.song().scenes #then get all of the scenes index = list(all_scenes).index( selected_scene ) #then identify where the selected scene sits in relation to the full list self.session.set_offsets( self.session._track_offset, index ) #(track_offset, scene_offset) Set the session's scene offset to match the selected track (but make no change to the track offset) def disconnect(self): #clean things up on disconnect #create entry in log file self.log_message( time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "----------MPK SessionControl log closed----------") ControlSurface.disconnect(self) return None
class Tweaker(ControlSurface): __module__ = __name__ __doc__ = " Tweaker control surface script " def __init__(self, c_instance, *a, **k): super(Tweaker, self).__init__(c_instance, *a, **k) with self.component_guard(): self._update_linked_device_selection = None self._tweaker_version_check = '0.3' self.log_message("--------------= Tweaker Session " + str(self._tweaker_version_check) + " log opened =--------------") self._timer = 0 self.flash_status = 1 self._last_selected_strip_number = 0 self._device_selection_follows_track_selection = False #self._pad_translations = PAD_TRANSLATION self._linked_session = None self._mixer_offset = 0 self._nav_lock = True self._setup_controls() self._setup_transport_control() self._setup_device_control() self._setup_mixer_control() self._setup_session_control() self._setup_crossfader() self._setup_modes() self._setup_pads() self._setup_navigation_lock() self._setup_arrange_session_toggle() #self.assign_main_configuration() #self.request_rebuild_midi_map() #self._mixer._reassign_tracks() #this is to update rebuild the cf_assign closure, otherwise the colors aren't correct #self.schedule_message(30, self._detect_devices) self.show_message('Tweaker Control Surface Loaded') self.show_message('Tweaker Control Surface Loaded') #self._shift_value(0) #this updates the pads so that they transmit to Live on the assigned PAD_CHANNEL...also, lights shift button self.assign_main_configuration() #self.schedule_message(2, self._shift_value, 0) self.schedule_message(3, self._mixer._reassign_tracks) """script initialization methods""" def _setup_controls(self): is_momentary = True self._grid = [None for index in range(8)] for column in range(8): self._grid[column] = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, column + (row * 8) + 1, 'Grid_' + str(column) + '_' + str(row), self) for row in range(4)] self._button = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_BUTTONS[index], 'Button_' + str(index), self) for index in range(len(TWEAKER_BUTTONS))] self._nav = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_NAVS[index], 'Nav_' + str(index), self) for index in range(len(TWEAKER_NAVS))] self._encoder_button = [TweakerMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_ENCODER_BUTTONS[index], 'Encoder_Button_' + str(index), self) for index in range(len(TWEAKER_ENCODER_BUTTONS))] self._dial = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_DIALS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_DIALS))] self._fader = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_FADERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_FADERS))] self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute) self._encoder = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_ENCODERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_ENCODERS))] self._pad = [TweakerMonoButtonElement(False, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_PADS[index], 'Pad_' + str(index), self) for index in range(len(TWEAKER_PADS))] for index in range(4): self._pad[index].set_enabled(False) self._pad[index].set_channel(PAD_CHANNEL) self._pad[index].set_identifier(index + 4) self._pad[index+4].set_enabled(False) self._pad[index+4].set_channel(PAD_CHANNEL) self._pad[index+4].set_identifier(index) self._pad_pressure = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_PAD_PRESSURES[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_PADS))] for index in range(8): self._pad_pressure[index]._last_sent = 0 self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' for row in range(4): button_row = [] for column in range(7): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) self._send_midi(tuple([240,0,1,106,01,07,21,21,247])) #set all pots to walk mode self._send_midi(tuple([240, 0, 1, 106, 1, 6, 127 , 127, 25, 0, 15, 0, 9, PAD_SENSITIVITY, 247])) #set pads to sensitivity set in Map file def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_mixer_control(self): is_momentary = True self._num_tracks = (2) #A mixer is one-dimensional; self._mixer = MixerComponent(2, 0, False, False) self._mixer.name = 'Mixer' self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer) self._device_navigator = [None for index in range(2)] self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(2): self._mixer.channel_strip(index).set_volume_control(self._fader[index]) self._mixer.channel_strip(index)._on_cf_assign_changed = self._channelstrip_on_cf_assign_changed(self._mixer.channel_strip(index)) self._mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) #mixer.track_filter(index).name = 'Mixer_TrackFilter_' + str(index) self._mixer.channel_strip(index)._invert_mute_feedback = True self._mixer.channel_strip(index)._device_component = self._device[index] self._mixer.channel_strip(index).update = self._channelstrip_update(self._mixer.channel_strip(index)) self._mixer.channel_strip(index)._select_value = self._channelstrip_select_value(self._mixer.channel_strip(index), index) self._device_navigator[index] = DetailViewControllerComponent(self, self._mixer.channel_strip(index)) self._device_navigator[index].name = 'Device_Navigator_'+str(index) self._mixer.channel_strip(0).set_track = self._channelstrip_set_track(self._mixer.channel_strip(0), self._channelstrip1_cb) self._mixer.channel_strip(1).set_track = self._channelstrip_set_track(self._mixer.channel_strip(1), self._channelstrip2_cb) self.song().view.selected_track = self._mixer.channel_strip(0)._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error #self._mixer._reassign_tracks() def _setup_session_control(self): is_momentary = True num_tracks = NUM_TRACKS num_scenes = NUM_SCENES self._session = SessionComponent(num_tracks, num_scenes) self._session.name = "Session" self._session.set_offsets(0, 0) self._session.set_stop_track_clip_value(STOP_CLIP) self._scene = [None for index in range(3)] for row in range(num_scenes): self._scene[row] = self._session.scene(row) self._scene[row].name = 'Scene_' + str(row) for column in range(num_tracks): clip_slot = self._scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_' + str(row) clip_slot.set_triggered_to_play_value(CLIP_TRG_PLAY) clip_slot.set_triggered_to_record_value(CLIP_TRG_REC) clip_slot.set_stopped_value(CLIP_STOP) clip_slot.set_started_value(CLIP_STARTED) clip_slot.set_recording_value(CLIP_RECORDING) self._session._stop_track_value = self._session_stop_track_value(self._session) self._session._on_fired_slot_index_changed = self._session_on_fired_slot_index_changed(self._session) self._session._change_offsets = self._session_change_offsets(self._session) self._session.update = self._session_update(self._session) #self._session.add_offset_listener(self._update_navigation_view) self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) self._session_zoom = SessionZoomingComponent(self._session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_stopped_value(ZOOM_STOPPED) self._session_zoom.set_playing_value(ZOOM_PLAYING) self._session_zoom.set_selected_value(ZOOM_SELECTED) #self._session_zoom.set_enabled(True) def _setup_device_control(self): self._device = [None for index in range(2)] for index in range(2): self._device[index] = DeviceComponent() self._device[index].name = 'Device_Component_'+str(index) self._device[index].set_enabled(True) self._device[index]._number_of_parameter_banks = self._device_number_of_parameter_banks(self._device[index]) self._device[index]._assign_parameters = self._device_assign_parameters(self._device[index]) self._device[index]._device_banks = DEVICE_DICT self._device[index]._device_best_banks = DEVICE_BOB_DICT self._device[index]._device_bank_names = BANK_NAME_DICT def _setup_crossfader(self): self._mixer.set_crossfader_control(self._crossfader) def _setup_modes(self): self._pad_offset = PadOffsetComponent(self) self._pad_offset._set_protected_mode_index(0) self._pad_offset.set_enabled(False) def _setup_pads(self): for pad in self._pad_pressure: pad.add_value_listener(self._light_pad, True) def _setup_navigation_lock(self): if(self._encoder_button[0].value_has_listener(self._nav_lock_value)): self._encoder_button[0].remove_value_listener(self._nav_lock_value) self._encoder_button[0].add_value_listener(self._nav_lock_value) def _setup_arrange_session_toggle(self): if(self._nav[1].value_has_listener(self._arrange_session_value)): self._nav[1].remove_value_listener(self._arrange_session_value) self._nav[1].add_value_listener(self._arrange_session_value) """configuration methods""" def assign_main_configuration(self): for column in range(7): for row in range(3): self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row]) self._session.set_stop_track_clip_buttons(tuple([self._grid[index][3] for index in range(7)])) for row in range(3): self._scene[row].set_launch_button(self._grid[7][row]) self._device[0].set_parameter_controls(tuple([self._encoder[index+1] for index in range(3)])) self._device[0].set_enabled(True) self._device[1].set_parameter_controls(tuple([self._encoder[index+4] for index in range(3)])) self._device[1].set_enabled(True) for track in range(2): self._mixer.channel_strip(track).set_volume_control(self._fader[track]) self._mixer.channel_strip(track).set_solo_button(self._button[track*3]) self._button[track*3].set_on_off_values(SOLO, 0) self._mixer.channel_strip(track).set_arm_button(self._button[1 + (track*3)]) self._button[1 + (track*3)].set_on_off_values(ARM, 0) self._mixer.channel_strip(track).set_crossfade_toggle(self._button[2 + (track*3)]) self._mixer.master_strip().set_volume_control(self._dial[1]) self._mixer.set_prehear_volume_control(self._dial[0]) self._session.set_track_bank_buttons(self._nav[4], self._nav[3]) self._session.set_scene_bank_buttons(self._nav[2], self._nav[0]) self._session_zoom.set_zoom_button(self._grid[7][3]) self._session_zoom.set_nav_buttons(self._nav[0], self._nav[2], self._nav[3], self._nav[4]) self._session_zoom.set_button_matrix(self._matrix) self._device[0].set_on_off_button(self._encoder_button[1]) self._device_navigator[0].set_device_nav_buttons(self._encoder_button[2], self._encoder_button[3]) self._device[1].set_on_off_button(self._encoder_button[4]) self._device_navigator[1].set_device_nav_buttons(self._encoder_button[5], self._encoder_button[6]) for track in range(2): self._update_device(self._mixer.channel_strip(track)) #self._device.set_bank_nav_buttons(self._menu[0], self._menu[3]) self.assign_track_selector(self._encoder[0]) #for index in range(8): # self._pad[index].send_value(1, True) # self._pad[index].set_channel(1) # self._pad[index].set_identifier(index) # self._pad[index].set_enabled(False) #this has to happen for translate to work if not self._grid[7][3].value_has_listener(self._shift_value): self._grid[7][3].add_value_listener(self._shift_value) self._grid[7][3].send_value(127, True) self.request_rebuild_midi_map() """Tweaker custom methods""" def _shift_value(self, value): self._pad_offset.set_enabled(value>0) if value > 0: self._update_navigation_view() for pad in self._pad: pad.use_default_message() pad.set_enabled(True) self._pad_offset.set_mode_buttons(tuple(self._pad)) self.schedule_message(1, self._pad_offset.update) if self._session.is_enabled(): #self._update_navigation_view() #self.schedule_message(1, self._update_navigation_veiw) self._update_navigation_view() self._grid[7][3].send_value(SHIFT_ON) for track in range(2): self._mixer.channel_strip(track).set_crossfade_toggle(None) self._mixer.channel_strip(track).set_select_button(self._button[2 + (track*3)]) else: self._pad_offset.set_mode_buttons(None) for index in range(4): self._pad[index].set_enabled(False) self._pad[index].set_channel(PAD_CHANNEL) self._pad[index].set_identifier(index + 4 + (self._pad_offset._mode_index * 8)) self._pad[index+4].set_enabled(False) self._pad[index+4].set_channel(PAD_CHANNEL) self._pad[index+4].set_identifier(index + (self._pad_offset._mode_index * 8)) self._grid[7][3].send_value(SHIFT_OFF) for track in range(2): self._mixer.channel_strip(track).set_select_button(None) self._mixer.channel_strip(track).set_crossfade_toggle(self._button[2 + (track*3)]) def assign_track_selector(self, encoder): assert isinstance(encoder, EncoderElement) if not encoder.value_has_listener(self._track_selector_value): encoder.add_value_listener(self._track_selector_value) def deassign_track_selector(self, encoder): if encoder.value_has_listener(self._track_selector_value): encoder.remove_value_listener(self._track_selector_value) def _nav_lock_value(self, value): if value > 0: if self._nav_lock: self._mixer_offset = self._mixer_offset + self._session._track_offset self._mixer.set_track_offset(self._mixer_offset) else: if self._mixer_offset in range(self._session._track_offset, self._session._track_offset + 5): self._mixer_offset = self._mixer_offset - self._session._track_offset elif self._mixer_offset < self._session._track_offset: self._mixer_offset = 0 else: self._mixer_offset = min(self._session._track_offset+5, len(self._session.tracks_to_use())-2) self._mixer.set_track_offset(self._session._track_offset + self._mixer_offset) self._nav_lock = not self._nav_lock self._session.update() def _arrange_session_value(self, value): if value > 0: if (self.application().view.is_view_visible('Arranger')): self.application().view.show_view('Session') else: self.application().view.show_view('Arranger') def _track_selector_value(self, value): if(value is 1): if self._nav_lock: self._mixer_offset = min(self._mixer_offset + 1, min(NUM_TRACKS - 2, len(self._session.tracks_to_use())-self._session._track_offset-2)) else: self._mixer_offset = min(self._mixer_offset + 1, len(self._session.tracks_to_use())-2) elif(value is 127): self._mixer_offset = max(self._mixer_offset - 1, 0) if self._nav_lock: self._mixer.set_track_offset(self._session._track_offset + self._mixer_offset) #self._session.set_offsets(self._session._track_offset) ?? else: self._mixer.set_track_offset(self._mixer_offset) self._session.update() if self._mixer.channel_strip(self._last_selected_strip_number)._track != None: self.song().view.selected_track = self._mixer.channel_strip(self._last_selected_strip_number)._track if self._linked_session != None: if self._linked_session._is_linked(): self._linked_session._unlink() self._linked_session.set_offsets(self._mixer._track_offset, self._linked_session._scene_offset) self._linked_session._link() def _update_navigation_view(self): dif = self._mixer._track_offset - self._session._track_offset for index in range(7): #if (index + self._session._track_offset) in range(len(self._session.tracks_to_use())): if (index + self._session._track_offset) in range(0, len(self.song().visible_tracks)): self._grid[index][3].send_value(NAV_COLORS[int(index in range(dif, dif + 2))], True) elif (index + self._session._track_offset) in range(len(self.song().visible_tracks), len(self._session.tracks_to_use())): self._grid[index][3].send_value(RETURN_NAV_COLORS[int(index in range(dif, dif + 2))], True) else: self._grid[index][3].send_value(0, True) self._send_midi(tuple([240,0,1,106,01,07,21,21,247])) #set all pots to walk mode def _update_device(self, channelstrip): for control in channelstrip._device_component._parameter_controls: control.send_value(0, True) if channelstrip._device_component._on_off_button != None: channelstrip._device_component._on_off_button.turn_off() if not channelstrip._track is None: if not channelstrip._device_component._device in channelstrip._track.devices: track = channelstrip._track device_to_select = track.view.selected_device if (device_to_select == None) and (len(track.devices) > 0): device_to_select = track.devices[0] elif channelstrip._device_component and not type(channelstrip._device_component) is type(None): channelstrip._device_component.set_device(device_to_select) else: channelstrip._device_component.set_device(None) else: pass else: channelstrip._device_component.set_device(None) channelstrip._device_component._on_on_off_changed() def _light_pad(self, value, sender): if not self._pad_offset.is_enabled(): if value > sender._last_sent: if self._pad[self._pad_pressure.index(sender)]._last_sent_value < 1: self._pad[self._pad_pressure.index(sender)].send_value(127, True) else: self._pad[self._pad_pressure.index(sender)].send_value(0, True) sender._last_sent = value """called on timer""" def update_display(self): super(Tweaker, self).update_display() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if(self.flash_status > 0): for control in self.controls: if isinstance(control, TweakerMonoButtonElement): control.flash(self._timer) """m4l bridge""" def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' return ret def notification_to_bridge(self, name, value, sender): if(isinstance(sender, MonoEncoderElement2)): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if(self._shift_mode._mode_index < 2): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched +=1 def check_touch(self): if(self._shift_mode._mode_index < 2): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def handle_sysex(self, midi_bytes): pass """general functionality""" def disconnect(self): """clean things up on disconnect""" #self._update_linked_device_selection = None if self._session.offset_has_listener(self._update_navigation_view): self._session.remove_offset_listener(self._update_navigation_view) if(self._nav[1].value_has_listener(self._arrange_session_value)): self._nav[1].remove_value_listener(self._arrange_session_value) if(self._encoder_button[0].value_has_listener(self._nav_lock_value)): self._encoder_button[0].remove_value_listener(self._nav_lock_value) for pad in self._pad_pressure: if pad.value_has_listener(self._light_pad): pad.remove_value_listener(self._light_pad) if self._grid[7][3].value_has_listener(self._shift_value): self._grid[7][3].remove_value_listener(self._shift_value) if self._session._is_linked(): self._session._unlink() self.deassign_track_selector(self._encoder[0]) self.log_message("--------------= Tweaker Session " + str(self._tweaker_version_check) + " log closed =--------------") #Create entry in log file super(Tweaker, self).disconnect() return None def _get_num_tracks(self): return self.num_tracks def _on_selected_track_changed(self): super(Tweaker, self)._on_selected_track_changed() if self._session.is_enabled(): self._session.update() for index in range(2): self._update_device(self._mixer.channel_strip(index)) self._mixer.on_selected_track_changed() def connect_script_instances(self, instanciated_scripts): link = False for s in instanciated_scripts: if '_tweaker_version' in dir(s): if s._tweaker_version == self._tweaker_version_check: link = True break if link == True: if not self._session._is_linked(): self._session._link() """SessionComponent overrides""" def _session_update(self, session): def _update(): SessionComponent.update(session) if session.is_enabled(): self._update_navigation_view() return _update def _session_change_offsets(self, session): def _change_offsets(track_increment, scene_increment): offsets_changed = (track_increment != 0) or (scene_increment != 0) if offsets_changed: session._track_offset += track_increment session._scene_offset += scene_increment assert (session._track_offset >= 0) assert (session._scene_offset >= 0) if (session._mixer != None): if(self._nav_lock): if (session.track_offset() + self._mixer_offset) > (len(session.tracks_to_use())-2): self._mixer_offset = max(len(session.tracks_to_use()) - session._track_offset - 2, 0) session._mixer.set_track_offset(max(0, session.track_offset() + self._mixer_offset)) session._reassign_tracks() if offsets_changed: session._reassign_scenes() # this is replaced by notify_offset() in Live9 #for callback in session._offset_callbacks: # this is replaced by notify_offset() in Live9 # callback() session.notify_offset() self._update_navigation_view() if self._mixer.channel_strip(self._last_selected_strip_number)._track != None: self.song().view.selected_track = self._mixer.channel_strip(self._last_selected_strip_number)._track if ((session.width() > 0) and (session.height() > 0)): session._do_show_highlight() return _change_offsets def _session_on_fired_slot_index_changed(self, session): def _on_fired_slot_index_changed(index): tracks_to_use = tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) track_index = index + session.track_offset() if session.is_enabled() and session._stop_track_clip_buttons != None: if index < len(session._stop_track_clip_buttons): button = session._stop_track_clip_buttons[index] if button != None: if(track_index < len(tracks_to_use)) and (tracks_to_use[track_index].clip_slots) and (tracks_to_use[track_index].fired_slot_index == -2): button.send_value(session._stop_track_clip_value) #elif index in range(len(session.tracks_to_use())): # dif = self._mixer._track_offset - self._session._track_offset # button.send_value(NAV_COLORS[int(index in range(dif, dif + 2))], True) #else: # button.turn_off() else: self._update_navigation_view() return _on_fired_slot_index_changed def _session_stop_track_value(self, session): def _stop_track_value(value, sender): assert (session._stop_track_clip_buttons != None) assert (list(session._stop_track_clip_buttons).count(sender) == 1) assert (value in range(128)) if session.is_enabled(): if ((value is not 0) or (not sender.is_momentary())): tracks = session.tracks_to_use() track_index = (list(session._stop_track_clip_buttons).index(sender) + session.track_offset()) if (track_index in range(len(tracks))) and (tracks[track_index] in session.song().tracks): tracks[track_index].stop_all_clips() sender.send_value(3, True) self.schedule_message(10, self._update_navigation_view) return _stop_track_value """ChannelStripComponent overrides""" def _channelstrip_update(self, channelstrip): def _update(): ChannelStripComponent.update(channelstrip) self._update_device(channelstrip) return _update def _channelstrip_set_track(self, channelstrip, cb): def _set_track(track): assert ((track == None) or isinstance(track, Live.Track.Track)) if channelstrip._track != None and isinstance(channelstrip._track, Live.Track.Track): if channelstrip._track.devices_has_listener(cb): channelstrip._track.remove_devices_listener(cb) if (track != None): track.add_devices_listener(cb) ChannelStripComponent.set_track(channelstrip, track) return _set_track def _channelstrip_select_value(self, channelstrip, index): def _select_value(value): ChannelStripComponent._select_value(channelstrip, value) self._last_selected_strip_number = index return _select_value def _channelstrip_on_cf_assign_changed(self, channel_strip): def _on_cf_assign_changed(): if (channel_strip.is_enabled() and (channel_strip._crossfade_toggle != None)): if (channel_strip._track != None) and (channel_strip._track in chain(self.song().tracks, self.song().return_tracks)): if channel_strip._track.mixer_device.crossfade_assign == 1: #modified channel_strip._crossfade_toggle.turn_off() elif channel_strip._track.mixer_device.crossfade_assign == 0: channel_strip._crossfade_toggle.send_value(CROSSFADE_A) else: channel_strip._crossfade_toggle.send_value(CROSSFADE_B) return _on_cf_assign_changed def _channelstrip1_cb(self): self._on_selected_track_changed() def _channelstrip2_cb(self): self._on_selected_track_changed() """MixerComponent overrides""" def _mixer_tracks_to_use(self, mixer): def tracks_to_use(): return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) return tracks_to_use """SessionComponent overrides""" def _device_number_of_parameter_banks(self, device): def _number_of_parameter_banks(): return number_of_parameter_banks(device._device) #added return _number_of_parameter_banks def _device_assign_parameters(self, device): def _assign_parameters(): assert device.is_enabled() assert (device._device != None) assert (device._parameter_controls != None) device._bank_name = ('Bank ' + str(device._bank_index + 1)) #added if (device._device.class_name in device._device_banks.keys()): #modified assert (device._device.class_name in device._device_best_banks.keys()) banks = device._device_banks[device._device.class_name] bank = None if (not device._is_banking_enabled()): banks = device._device_best_banks[device._device.class_name] device._bank_name = 'Best of Parameters' #added if (len(banks) > device._bank_index): bank = banks[device._bank_index] if device._is_banking_enabled(): #added if device._device.class_name in device._device_bank_names.keys(): #added device._bank_name[device._bank_index] = device._device_bank_names[device._device.class_name] #added *recheck assert ((bank == None) or (len(bank) >= len(device._parameter_controls))) for index in range(len(device._parameter_controls)): parameter = None if (bank != None): parameter = get_parameter_by_name(device._device, bank[index]) if (parameter != None): device._parameter_controls[index].connect_to(parameter) else: device._parameter_controls[index].release_parameter() else: parameters = device._device_parameters_to_map() num_controls = len(device._parameter_controls) index = (device._bank_index * num_controls) for control in device._parameter_controls: if (index < len(parameters)): control.connect_to(parameters[index]) else: control.release_parameter() index += 1 return _assign_parameters
class ControlMI(ControlSurface): __module__ = __name__ __doc__ = " ControlMI 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("--------------= ControlMI log opened =--------------") with self.component_guard(): # OBJECTS self.session = None self.mixer = None self.view = None self.device = None self.transport = None # INITIALIZE MIXER, SESSIONS self._setup_session_control() # Setup the session object self._setup_mixer_control() # Setup the mixer object 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_initial_mode() self.set_device_component( self.device) # Bind device to control surface- 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 ##############################") self.session = SessionComponent(num_tracks, num_scenes) self.session.set_offsets(0, 0) self.session.set_track_bank_buttons( ButtonElement(False, MIDI_CC_TYPE, data_channel, session_right), ButtonElement(False, MIDI_CC_TYPE, data_channel, session_left)) def _setup_mixer_control(self): self.mixer = MixerComponent(num_tracks, 0, False, False) self.mixer.name = 'Mixer' self.mixer.set_track_offset(0) def _setup_device_control(self): self.device = DeviceComponent() self.device.name = 'Device_Component' def _setup_transport_control(self): self.transport = TransportComponent(self) def _clear_controls(self): 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) strip.set_select_button(None) # TRANSPORT self.transport.set_stop_button(None) self.transport.set_play_button(None) self.transport.set_record_button(None) self.log_message("Controls Cleared") def _set_initial_mode(self): is_momentary = True ### MIXER for index in range(num_tracks): strip = self.mixer.channel_strip(index) strip.name = 'Mixer_ChannelStrip_' + str(index) strip.set_volume_control( SliderElement(MIDI_CC_TYPE, data_channel, mixer_volume_cc[index])) strip._invert_mute_feedback = True self.mixer.master_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, data_channel, mixer_master_cc)) self.transport.set_stop_button( ButtonElement(False, MIDI_CC_TYPE, data_channel, transport_stop_cc)) self.transport.set_play_button( ButtonElement(False, MIDI_CC_TYPE, data_channel, transport_play_cc)) self.transport.set_record_button( ButtonElement(False, MIDI_CC_TYPE, data_channel, transport_record_cc)) self.log("color: " + str(self.session.tracks_to_use()[0].color)) self.log("color: " + str(self.session.tracks_to_use()[1].color)) self.log("color: " + str(self.session.tracks_to_use()[2].color)) self.log("color: " + str(self.session.tracks_to_use()[3].color)) self._send_midi([0x09, 0x09, 0x09, 0x09]) def disconnect(self): """clean things up on disconnect""" self.log("--------------= ControlMI log closed =--------------") self._clear_controls() self.session = None self.mixer = None self.view = None self.device = None self.transport = None self.set_device_component(None) ControlSurface.disconnect(self) return None def log(self, message): self.log_message( time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + message)
class VoidMaschine(ControlSurface): """ Originally Created on Nov 7, 2010 :: Matt Howell Thanks to Hanz Petrov, Native Instruments, Ableton, Liine """ def __init__(self, c_instance): """ Constructor """ ControlSurface.__init__(self, c_instance) self.name = 'VoidMaschine' self.log_message(self.name + " opened =-- @ "+ time.strftime("%d.%m.%Y %H:%M:%S", time.localtime())) self.set_suppress_rebuild_requests(True) self._suppress_session_highlight = False self._suppress_send_midi = True self._suggested_input_port = MASCHINE_DEVICE_PORT_NAME self._suggested_output_port = MASCHINE_DEVICE_PORT_NAME self._shift_button = None self.transport = TransportComponent() self.transport.name = 'Transport' self.session = None self.session_zoom = None self.mixer = None self.back_to_arranger_button = None self.is_momentary = True self.bpmBeatTime = 0 self.lastBeat = 0 self._setup_transport_control() self._session = VoidSessionComponent(c_instance) self._session.name = 'Session_Control' self._setup_mixer_control() #self._session_zoom = SessionZoomingComponent(self._session) #self._session_zoom.name = 'Session_Overview' #self._session_zoom.set_button_matrix(self._session._matrix) self._set_back_to_arranger_button(ButtonElement(True, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_BACK_TO_ARRANGER)) self.set_suppress_rebuild_requests(False) self._display = PhysicalDisplayElement(56, 8) self._void_message() self._register_timer_callback(self.update_controller) self._register_timer_callback(self.updateTempo) self._register_timer_callback(self.onTempoChange) def _void_message(self): self.sendScreenSysex(self.translateString((SYSEX_SCREEN_BUFFER_15 + 'VoidMaschine' + SYSEX_SCREEN_BUFFER_15)), 1) self.sendScreenSysex(self.translateString(('Voidrunner.com' + SYSEX_SCREEN_BUFFER_15 + ' maschine/ableton')), 2) def _setup_mixer_control(self): self.mixer = MixerComponent(0, 0, with_eqs=False, with_filters=False) master_volume_control = EncoderElement(MIDI_CC_TYPE, MIXER_CHANNEL, MASTER_VOLUME, Live.MidiMap.MapMode.absolute) booth_volume_control = EncoderElement(MIDI_CC_TYPE, MIXER_CHANNEL, MASTER_BOOTH, Live.MidiMap.MapMode.absolute) self.mixer.set_prehear_volume_control(booth_volume_control) self.mixer.master_strip().set_volume_control(master_volume_control) def _setup_transport_control(self): play_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_PLAY) stop_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_STOP) record_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_RECORD) seek_ffwd_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_SEEK_FFWD) seek_rwd_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_SEEK_RWD) tap_tempo_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_TAP_TEMPO) tempo_control = EncoderElement(MIDI_CC_TYPE, TRANSPORT_CHANNEL, TRANSPORT_COARSE_TEMPO, Live.MidiMap.MapMode.absolute) play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' record_button.name = 'Record_Button' seek_ffwd_button.name = 'Seek_FFWD_Button' seek_rwd_button.name = 'Seek_RWD_Button' tap_tempo_button.name = 'Tap_Tempo_Button' self.transport.set_play_button(play_button) self.transport.set_stop_button(stop_button) self.transport.set_record_button(record_button) self.transport.set_tap_tempo_button(tap_tempo_button) self.transport.set_tempo_control(tempo_control) self.transport.set_seek_buttons(seek_ffwd_button, seek_rwd_button) def _set_back_to_arranger_button(self, button): button.add_value_listener(self.back_to_arranger) self.back_to_arranger_button = button def disconnect(self): self.send_midi((240, 0, 66, 89, 69, 247)) #goodbye message in sysex stream def send_midi(self, midi_event_bytes): """ Use this function to send MIDI events through Live to the _real_ MIDI devices that this script is assigned to. """ assert isinstance(midi_event_bytes, tuple) self._send_midi(midi_event_bytes) return True def translateString(self, text): """ Convert a string into a sysex safe string """ result = () length = len(text) for i in range(0, length): charCode = ord(text[i]) if (charCode < 32): charCode = 32 elif (charCode > 127): charCode = 127 result = (result + (charCode,)) return result def sendScreenSysex(self, data, line=1): """ Data must be a tuple of bytes, remember only 7-bit data is allowed for sysex """ if not data: pass if(line==1): self._send_midi(((SYSEX_SCREEN_BEGIN_LINE_1 + data) + SYSEX_SCREEN_END)) else: if(line==2): self._send_midi(((SYSEX_SCREEN_BEGIN_LINE_2 + data) + SYSEX_SCREEN_END)) def send_value(self, msg_type, channel, id, value, force_send = False): assert (value != None) assert isinstance(value, int) assert (value in range(128)) data_byte1 = id data_byte2 = value status_byte = channel if (msg_type == MIDI_NOTE_TYPE): status_byte += MIDI_NOTE_ON_STATUS elif (msg_type == MIDI_CC_TYPE): status_byte += MIDI_CC_STATUS else: assert False self._send_midi((status_byte, data_byte1, data_byte2)) def back_to_arranger(self, *args, **kwargs): self.song().back_to_arranger = False def update_controller(self): """ controller event loop this may also update every 100 miliseconds. decoupling the data updates from live and the controller communication may help keep latency to a minimum. """ def onTempoChange(self): self.bpmBeatTime = self.song().get_current_beats_song_time() def updateTempo(self): if self.song().is_playing: if (self.bpmBeatTime.beats > self.lastBeat): self.updateBPMLightOff() else: self.updateBPMLightOn() def updateBPMLightOn(self): self.transport._play_button.turn_on() #self.send_value(MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_TEMPO, MASCHINE_DISPLAY_BPM) def updateBPMLightOff(self): self.transport._play_button.turn_off() #self.send_value(MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_TEMPO, 0)
def _setup_mixer_control(self): is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant num_tracks = 4 # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent( num_tracks, 2, with_eqs=True, with_filters=False ) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset( 0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track #mute_notes = [1,5,9,13] #solo_notes = [2,6,10,14] #arm_notes = [3,7,11,15] track_select_notes = [ 38, 39, 40, 41 ] #more note numbers need to be added if num_scenes is increased send_ccs = [2, 6, 10, 14, 1, 5, 9, 13] pan_ccs = [3, 7, 11, 15] slider_ccs = [4, 8, 12, 16] for index in range(num_tracks): mixer.channel_strip(index).set_select_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, track_select_notes[index])) mixer.channel_strip(index).set_volume_control( SliderElement(MIDI_CC_TYPE, CHAN, slider_ccs[index])) mixer.channel_strip(index).set_pan_control( EncoderElement(MIDI_CC_TYPE, CHAN, pan_ccs[index], Live.MidiMap.MapMode.absolute)) #put send A and send B controllers into an array, which is then "tupled" for set_send_controls: send_controlers = [ EncoderElement(MIDI_CC_TYPE, CHAN, send_ccs[index], Live.MidiMap.MapMode.absolute), EncoderElement(MIDI_CC_TYPE, CHAN, send_ccs[index + num_tracks], Live.MidiMap.MapMode.absolute) ] mixer.channel_strip(index).set_send_controls( tuple(send_controlers)) crossfader = SliderElement(MIDI_CC_TYPE, CHAN, 28) master_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 32) returna_pan_control = SliderElement(MIDI_CC_TYPE, CHAN, 19) returna_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 20) returnb_pan_control = SliderElement(MIDI_CC_TYPE, CHAN, 23) returnb_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 24) master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 31) prehear_control = EncoderElement(MIDI_CC_TYPE, CHAN, 30, Live.MidiMap.MapMode.absolute) crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' returna_pan_control.name = 'ReturnA_Pan_Control' returna_volume_control.name = 'ReturnA_Volume_Control' returnb_pan_control.name = 'ReturnB_Pan_Control' returnb_volume_control.name = 'ReturnB_Volume_Control' master_select_button.name = 'Master_Select_Button' prehear_control.name = 'Prehear_Volume_Control' mixer.set_crossfader_control(crossfader) mixer.master_strip().set_volume_control(master_volume_control) mixer.master_strip().set_select_button(master_select_button) mixer.set_prehear_volume_control(prehear_control) mixer.return_strip(0).set_pan_control(returna_pan_control) mixer.return_strip(0).set_volume_control(returna_volume_control) mixer.return_strip(1).set_pan_control(returnb_pan_control) mixer.return_strip(1).set_volume_control(returnb_volume_control)