Exemple #1
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 = 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
Exemple #3
0
 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
Exemple #4
0
    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
Exemple #5
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 = 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..."""
Exemple #8
0
    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")
Exemple #9
0
    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)
Exemple #10
0
    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))
Exemple #11
0
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()
Exemple #12
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)
Exemple #13
0
 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
Exemple #14
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 = 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)
Exemple #15
0
    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))
Exemple #17
0
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)
Exemple #18
0
    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))
Exemple #19
0
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
Exemple #20
0
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
Exemple #21
0
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)
    
Exemple #23
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)