Example #1
0
	def _setup_mixer_control(self):
		is_momentary = True
		self._num_tracks = (7) #A mixer is one-dimensional; 
		global mixer
		mixer = SpecialMixerComponent(7, 0, True, False)
		mixer.name = 'Mixer'
		self._mixer = mixer
		mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
		for index in range(7):
			mixer.channel_strip(index).set_volume_control(self._fader[index])
		for index in range(7):
			mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index)
			mixer.track_eq(index).name = 'Mixer_EQ_' + str(index)
			mixer.channel_strip(index)._invert_mute_feedback = True
		self.song().view.selected_track = mixer.channel_strip(0)._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error
Example #2
0
    def _init_mixer(self):
        make_button = partial(make_launch_control_button, channel=8)
        make_encoder = partial(make_launch_control_encoder, channel=8)
        bottom_encoders, top_encoders = make_all_encoders("Mixer", make_encoder)
        pan_volume_layer = Layer(
            volume_controls=ButtonMatrixElement(rows=[bottom_encoders]),
            pan_controls=ButtonMatrixElement(rows=[top_encoders]),
        )
        sends_layer = Layer(sends_controls=ButtonMatrixElement(rows=[bottom_encoders, top_encoders]))
        modes_layer = Layer(
            pan_volume_button=make_button(114, "Pan_Volume_Mode_Button"),
            sends_button=make_button(115, "Sends_Mode_Button"),
        )
        self._mixer = SpecialMixerComponent(8, modes_layer, pan_volume_layer, sends_layer)
        self._mixer.name = "Mixer"
        self._mixer.selected_strip().name = "Selected_Channel_Strip"
        self._mixer.master_strip().name = "Master_Channel_Strip"
        self._mixer_track_nav_layer = Layer(
            track_bank_left_button=make_button(116, "Mixer_Track_Left_Button"),
            track_bank_right_button=make_button(117, "Mixer_Track_Right_Button"),
        )
        for index in xrange(8):
            strip = self._mixer.channel_strip(index)
            strip.name = "Channel_Strip_" + str(index)
            strip.empty_color = Colors.LED_OFF
            strip.set_invert_mute_feedback(True)
            mute_button = make_button(pad_identifiers[index], "Track_Mute_Button_" + str(index), is_pad=True)
            mute_button.set_on_off_values(Colors.AMBER_FULL, Colors.AMBER_THIRD)
            strip.set_mute_button(mute_button)

        self._on_selected_send_index.subject = self._mixer
        self._on_selected_mixer_mode.subject = self._mixer
    def __init__(self, matrix, side_buttons, session):
        raise isinstance(matrix, ButtonMatrixElement) or AssertionError
        raise matrix.width() == 8 and matrix.height() == 8 or AssertionError
        raise isinstance(side_buttons, tuple) or AssertionError
        raise len(side_buttons) == 8 or AssertionError
        raise isinstance(session, SessionComponent) or AssertionError
        ModeSelectorComponent.__init__(self)
        self._session = session
        self._mixer = SpecialMixerComponent(matrix.width())
        self._matrix = matrix
        self._sliders = []
        self._mixer.name = "Mixer"
        self._mixer.master_strip().name = "Master_Channel_strip"
        self._mixer.selected_strip().name = "Selected_Channel_strip"
        for column in range(matrix.width()):
            self._mixer.channel_strip(column).name = "Channel_Strip_" + str(column)
            self._sliders.append(
                PreciseButtonSliderElement(tuple([matrix.get_button(column, 7 - row) for row in range(8)]))
            )
            self._sliders[-1].name = "Button_Slider_" + str(column)

        self._side_buttons = side_buttons[4:]
        self._update_callback = None
        self._session.set_mixer(self._mixer)
        self.set_modes_buttons(side_buttons[:4])
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            is_momentary = True
            self._suggested_input_port = 'Oxygen'
            self._suggested_output_port = 'Oxygen'
            self._has_slider_section = True
            self._device_selection_follows_track_selection = True
            self._shift_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 57)
            self._shift_button.add_value_listener(self._shift_value)
            self._mixer = SpecialMixerComponent(NUM_TRACKS)
            self._mute_solo_buttons = []
            self._track_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 111)
            self._track_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 110)
            self._master_slider = SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 41)
            for index in range(NUM_TRACKS):
                self._mute_solo_buttons.append(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 49 + index))
                self._mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 33 + index))

            self._shift_value(0)
            self._mixer.master_strip().set_volume_control(self._master_slider)
            self._mixer.selected_strip().set_volume_control(None)
            device = DeviceComponent()
            device.set_parameter_controls(tuple([ EncoderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 17 + index, Live.MidiMap.MapMode.absolute) for index in range(8) ]))
            self.set_device_component(device)
            ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 115)
            rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 114)
            loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 113)
            transport = TransportComponent()
            transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 116))
            transport.set_play_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 117))
            transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 118))
            session = SessionComponent(0, 0)
            transport_view_modes = TransportViewModeSelector(transport, session, ffwd_button, rwd_button, loop_button)
        return
    def _setup_mixer(self):
        mute_solo_flip_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 34)
        self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 37)
        self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 38)
        self._strip_buttons = []
        mute_solo_flip_button.name = 'Mute_Solo_Flip_Button'
        self._next_nav_button.name = 'Next_Track_Button'
        self._prev_nav_button.name = 'Prev_Track_Button'
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button)
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.master_strip().set_volume_control(self._master_slider)
        self._sliders = []
        for index in range(8):
            strip = self._mixer.channel_strip(index)
            strip.name = 'Channel_Strip_' + str(index)
            strip.set_invert_mute_feedback(True)
            self._sliders.append(SliderElement(MIDI_CC_TYPE, 0, index))
            self._sliders[-1].name = str(index) + '_Volume_Control'
            self._sliders[-1].set_feedback_delay(-1)
            self._sliders[-1].add_value_listener(self._slider_value, identify_sender=True)
            strip.set_volume_control(self._sliders[-1])
            self._strip_buttons.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + index))
            self._strip_buttons[-1].name = str(index) + '_Mute_Button'
            self._strip_buttons[-1].add_value_listener(self._mixer_button_value, identify_sender=True)

        self._mixer.master_strip().set_mute_button(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 17))
        self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)
Example #6
0
	def _setup_mixer_control(self):
		is_momentary = True
		self._mixer = SpecialMixerComponent(8)
		self._mixer.name = 'Mixer'
		self._mixer.master_strip().name = 'Master_Channel_Strip'
		self._mixer.selected_strip().name = 'Selected_Channel_Strip'
		self._solo_buttons = []
		for track in range(8):
			strip = self._mixer.channel_strip(track)
			strip.name = 'Channel_Strip_' + str(track)
			solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, self)
			self._solo_buttons.append(solo_button)
			mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)
			solo_button.name = str(track) + '_Solo_Button'
			mute_button.name = str(track) + '_Mute_Button'
			strip.set_solo_button(solo_button)
			strip.set_mute_button(mute_button)
			strip.set_shift_button(self._shift_button)
			strip.set_invert_mute_feedback(True)
		master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
		prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
		master_volume_control.name = 'Master_Volume_Control'
		prehear_control.name = 'Prehear_Volume_Control'
		self._mixer.set_prehear_volume_control(prehear_control)
		self._mixer.master_strip().set_volume_control(master_volume_control)
    def _setup_mixer_control(self):
        self.mixer = SpecialMixerComponent(self.num_tracks, self)
        self.mixer.name = 'Mixer'
        self.mixer.set_track_offset(0)
        self.mixer.set_select_buttons(self.button(PAD_CHANNEL, TRACK_RIGHT), self.button(PAD_CHANNEL, TRACK_LEFT))
        self.mixer.set_crossfader_control(self.slider(SLIDER_CHANNEL, CROSSFADER))
        for index in range(4):
            self.mixer.channel_strip(index).set_volume_control(self.slider(SLIDER_CHANNEL, TRACK_VOL[index]))

        self.num_o_tracks = self.song().visible_tracks
        if self.num_o_tracks != None:
            index_count = -1
            index_table = []
            for index in self.song().visible_tracks:
                index_count += 1
                if index.has_midi_output != True:
                    index_table.append(index_count)
                else:
                    None

            if index_table != None:
                for index in range(len(index_table)):
                    x = index_table[index]
                    if x > 3:
                        None
                    else:
                        None
 def _setup_mixer_control(self):
     
     self.mixer = SpecialMixerComponent(self.box_width, self) # get a local mixer object ready
     self.mixer.name = 'Mixer' # name
     self.mixer.set_track_offset(self.gutter)  # gutter ----marwei
     # compare width with track vol count to qualify -- put somewhere else 
     for index in range(self.box_width): # @marwei must kill this style and count
         self.mixer.channel_strip(index).set_volume_control(self.slider(midi_channel, track_volume[index]))
         
Example #9
0
    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(self, 8) #added self for parent
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80)
        master_select_button.name = 'Master_Select_Button'
        self._mixer.master_strip().set_select_button(master_select_button) #set in ShiftableSelectorComponent instead if used for Note Mode
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        select_buttons = [] #added
        arm_buttons = [] #added
        sliders = [] #added     
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            #volume_control = SliderElement(MIDI_CC_TYPE, track, 7) #set in ShiftableSelectorComponent instead
            #arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) #see below
            solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)
            solo_button.name = str(track) + '_Solo_Button'
            strip.set_solo_button(solo_button)

            if track < 4:
              mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50)
              mute_button.name = str(track) + '_Mute_Button'
              strip.set_mute_button(mute_button)
              strip.set_invert_mute_feedback(True)

            strip.set_shift_button(self._shift_button)
            select_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) #added
            select_buttons[-1].name = str(track) + '_Select_Button' #added            
            #strip.set_select_button(select_buttons[-1]) #added 
            arm_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) #added
            arm_buttons[-1].name = str(track) + '_Arm_Button' #added
            sliders.append(SliderElement(MIDI_CC_TYPE, track, 7)) #added
            sliders[-1].name = str(track) + '_Volume_Control' #added

        self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        self._prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
        self._crossfader.name = 'Crossfader' #not used in APC20
        master_volume_control.name = 'Master_Volume_Control'
        self._prehear_control.name = 'Prehear_Volume_Control'
        self._mixer.set_shift_button(self._shift_button) #added for shifting prehear
        self._mixer.set_crossfader_control(self._crossfader) #not used in APC20
        self._mixer.set_prehear_volume_control(self._prehear_control) #functionality overridden in SpecialMixerComponent
        self._mixer.master_strip().set_volume_control(master_volume_control)
        self._slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) #added from APC20 script
        self._slider_modes.name = 'Slider_Modes' #added from APC20 script
        matrix_modes = MatrixModesComponent(self._matrix, self._session, self._session_zoom, tuple(self._track_stop_buttons), self) #added new
        matrix_modes.name = 'Matrix_Modes' #added new
        # Original method args for ShiftableSelectorComponent: (self, select_buttons, master_button, arm_buttons, matrix, session, zooming, mixer, transport, slider_modes, mode_callback)
        #self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message)
        self._shift_modes = ShiftableSelectorComponent(self, tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, self._slider_modes, matrix_modes) #, self._send_introduction_message) #also added self for _parent
        self._shift_modes.name = 'Shift_Modes'
        self._shift_modes.set_mode_toggle(self._shift_button)
Example #10
0
	def _setup_mixer_control(self):
		global mixer
		is_momentary = True
		self._num_tracks = 7
		mixer = SpecialMixerComponent(7, 0, True, False)
		mixer.name = 'Mixer'
		self._mixer = mixer
		for index in range(7):
			mixer.channel_strip(index).set_volume_control(self._fader[index])

		for index in range(7):
			mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index)
			mixer.track_eq(index).name = 'Mixer_EQ_' + str(index)
			mixer.channel_strip(index)._invert_mute_feedback = True

		self.song().view.selected_track = mixer.channel_strip(0)._track
 def _setup_mixer_control(self):
     is_momentary = True
     
     ## Quirksmode
     self.arm_buttons = []
     
     self._mixer = SpecialMixerComponent(self, 8) #added self for parent
     self._mixer.name = 'Mixer'
     self._mixer.master_strip().name = 'Master_Channel_Strip'
     self._mixer.selected_strip().name = 'Selected_Channel_Strip'
     for track in range(8):
         self.strip = self._mixer.channel_strip(track)
         self.strip.name = 'Channel_Strip_' + str(track)
         volume_control = SliderElement(MIDI_CC_TYPE, track, 7)
         arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)
         solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)
         mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50)
         select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)
         volume_control.name = str(track) + '_Volume_Control'
         arm_button.name = str(track) + '_Arm_Button'
         solo_button.name = str(track) + '_Solo_Button'
         mute_button.name = str(track) + '_Mute_Button'
         select_button.name = str(track) + '_Select_Button'
         self.strip.set_volume_control(volume_control)
         
         ##Quirksmode
         self.arm_buttons.append(arm_button)
         
         self.strip.set_arm_button(arm_button)
         self.strip.set_solo_button(solo_button)
         self.strip.set_mute_button(mute_button)
         self.strip.set_select_button(select_button)
         self.strip.set_shift_button(self._shift_button)
         self.strip.set_invert_mute_feedback(True)
     crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
     
     
     master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
     master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80)
     ##self._prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
     crossfader.name = 'Crossfader'
     master_volume_control.name = 'Master_Volume_Control'
     master_select_button.name = 'Master_Select_Button'
     ##self._prehear_control.name = 'Prehear_Volume_Control'
     self._mixer.set_crossfader_control(crossfader)
     ##self._mixer.set_prehear_volume_control(self._prehear_control)
     self._mixer.master_strip().set_volume_control(master_volume_control)
     self._mixer.master_strip().set_select_button(master_select_button)
    def __init__(self, matrix, side_buttons, session):
        assert isinstance(matrix, ButtonMatrixElement)
        assert ((matrix.width() == 8) and (matrix.height() == 8))
        assert isinstance(side_buttons, tuple)
        assert (len(side_buttons) == 8)
        assert isinstance(session, SessionComponent)
        ModeSelectorComponent.__init__(self)
        self._session = session
        self._mixer = SpecialMixerComponent(matrix.width())
        self._matrix = matrix
        self._sliders = []
        for column in range(8):
            self._sliders.append(PreciseButtonSliderElement(tuple([ matrix.get_button(column, (7 - row)) for row in range(8) ])))

        self._side_buttons = side_buttons[4:]
        self._update_callback = None
        self._session.set_mixer(self._mixer)
        self.set_modes_buttons(side_buttons[:4])
Example #13
0
    def _setup_mixer(self):
        mute_solo_flip_button = make_button(59, 'Master_Button')
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.master_strip().set_volume_control(self._master_slider)
        self._sliders = []
        self._strip_buttons = []
        for index in range(8):
            strip = self._mixer.channel_strip(index)
            strip.name = 'Channel_Strip_' + str(index)
            strip.set_invert_mute_feedback(True)
            self._sliders.append(make_slider(41 + index, 'Volume_Control_%d' % index))
            strip.set_volume_control(self._sliders[-1])
            self._strip_buttons.append(make_button(51 + index, 'Mute_Button_%d' % index))

        self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)
Example #14
0
	def _setup_mixer_control(self):
		is_momentary = True
		self._mixer = SpecialMixerComponent(8)
		self._mixer.name = 'Mixer'
		self._mixer.master_strip().name = 'Master_Channel_Strip'
		self._mixer.selected_strip().name = 'Selected_Channel_Strip'
		self._solo_buttons = []	# added a
		self._select_buttons = []	# added a
		for track in range(8):
			strip = self._mixer.channel_strip(track)
			strip.name = 'Channel_Strip_' + str(track)
			volume_control = MonoEncoderElement2(MIDI_CC_TYPE, track, 7, Live.MidiMap.MapMode.absolute, 'Slider_' + str(track), track, self)
			arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)
			solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, self)
			self._solo_buttons.append(solo_button)	# added a
			mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)
			select_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51, self)
			self._select_buttons.append(select_button)	# added a
			#volume_control.name = str(track) + '_Volume_Control'
			arm_button.name = str(track) + '_Arm_Button'
			solo_button.name = str(track) + '_Solo_Button'
			mute_button.name = str(track) + '_Mute_Button'
			select_button.name = str(track) + '_Select_Button'
			strip.set_volume_control(volume_control)
			strip.set_arm_button(arm_button)
			strip.set_solo_button(solo_button)
			strip.set_mute_button(mute_button)
			strip.set_select_button(select_button)
			strip.set_shift_button(self._shift_button)
			strip.set_invert_mute_feedback(True)
		crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
		master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
		master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80)
		self._master_select_button = master_select_button
		prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
		crossfader.name = 'Crossfader'
		master_volume_control.name = 'Master_Volume_Control'
		master_select_button.name = 'Master_Select_Button'
		prehear_control.name = 'Prehear_Volume_Control'
		self._mixer.set_crossfader_control(crossfader)
		self._mixer.set_prehear_volume_control(prehear_control)
		self._mixer.master_strip().set_volume_control(master_volume_control)
		self._mixer.master_strip().set_select_button(master_select_button)
Example #15
0
    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = "Mixer"
        self._mixer.master_strip().name = "Master_Channel_Strip"
        self._mixer.selected_strip().name = "Selected_Channel_Strip"
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = "Channel_Strip_" + str(track)
            volume_control = SliderElement(MIDI_CC_TYPE, track, 7)
            arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)
            solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)
            mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50)
            select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)
            volume_control.name = str(track) + "_Volume_Control"
            arm_button.name = str(track) + "_Arm_Button"
            solo_button.name = str(track) + "_Solo_Button"
            mute_button.name = str(track) + "_Mute_Button"
            select_button.name = str(track) + "_Select_Button"
            strip.set_volume_control(volume_control)
            strip.set_arm_button(arm_button)
            strip.set_solo_button(solo_button)
            strip.set_mute_button(mute_button)
            strip.set_select_button(select_button)
            strip.set_shift_button(self._shift_button)
            strip.set_invert_mute_feedback(True)
        crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80)
        self.prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)

        self._mixer.set_shift_button(self._shift_button)  # added for shifting prehear

        crossfader.name = "Crossfader"
        master_volume_control.name = "Master_Volume_Control"
        master_select_button.name = "Master_Select_Button"
        self.prehear_control.name = "Prehear_Volume_Control"
        self._mixer.set_crossfader_control(crossfader)
        self._mixer.set_prehear_volume_control(self.prehear_control)
        self._mixer.master_strip().set_volume_control(master_volume_control)
        self._mixer.master_strip().set_select_button(master_select_button)
    def _setup_mixer(self):
        self._next_nav_button = make_button(103, "Next_Track_Button")
        self._prev_nav_button = make_button(102, "Prev_Track_Button")
        mute_solo_flip_button = make_button(59, "Master_Button")
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = "Mixer"
        self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button)
        self._mixer.selected_strip().name = "Selected_Channel_Strip"
        self._mixer.master_strip().name = "Master_Channel_Strip"
        self._mixer.master_strip().set_volume_control(self._master_slider)
        self._sliders = []
        self._strip_buttons = []
        for index in range(8):
            strip = self._mixer.channel_strip(index)
            strip.name = "Channel_Strip_" + str(index)
            strip.set_invert_mute_feedback(True)
            self._sliders.append(make_slider(41 + index, "Volume_Control_%d" % index))
            strip.set_volume_control(self._sliders[-1])
            self._strip_buttons.append(make_button(51 + index, "Mute_Button_%d" % index))

        self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)
Example #17
0
 def _setup_mixer_control(self):
     is_momentary = True
     self._mixer = SpecialMixerComponent(8)
     self._mixer.name = 'Mixer'
     self._mixer.master_strip().name = 'Master_Channel_Strip'
     self._mixer.master_strip().set_select_button(self._note_map[MASTERSEL])
     self._mixer.selected_strip().name = 'Selected_Channel_Strip'
     self._mixer.set_select_buttons(self._note_map[TRACKRIGHT], self._note_map[TRACKLEFT])
     self._mixer.set_crossfader_control(self._ctrl_map[CROSSFADER])
     self._mixer.set_prehear_volume_control(self._ctrl_map[CUELEVEL])
     self._mixer.master_strip().set_volume_control(self._ctrl_map[MASTERVOLUME])
     for track in range(8):
         strip = self._mixer.channel_strip(track)
         strip.name = 'Channel_Strip_' + str(track)
         strip.set_arm_button(self._note_map[TRACKREC[track]])
         strip.set_solo_button(self._note_map[TRACKSOLO[track]])
         strip.set_mute_button(self._note_map[TRACKMUTE[track]])
         strip.set_select_button(self._note_map[TRACKSEL[track]])
         strip.set_volume_control(self._ctrl_map[TRACKVOL[track]])
         strip.set_pan_control(self._ctrl_map[TRACKPAN[track]])
         strip.set_send_controls((self._ctrl_map[TRACKSENDA[track]], self._ctrl_map[TRACKSENDB[track]], self._ctrl_map[TRACKSENDC[track]]))
         strip.set_invert_mute_feedback(True)
	def __init__(self, matrix, side_buttons, session):
		assert isinstance(matrix, ButtonMatrixElement)
		assert ((matrix.width() == 8) and (matrix.height() == 8))
		assert isinstance(side_buttons, tuple)
		assert (len(side_buttons) == 8)
		assert isinstance(session, SessionComponent)
		ModeSelectorComponent.__init__(self)
		self._session = session
		self._mixer = SpecialMixerComponent(len(self.song().tracks))
		self._matrix = matrix
		self._mixer.name = "Mixer"
		self._mixer.master_strip().name = "Master_Channel_strip"
		self._mixer.selected_strip().name = "Selected_Channel_strip"
		for column in range(len(self.song().tracks)):
			button_index = 0
			if self.song().tracks[column].is_foldable:
				if button_index < GROUPS_CONSIDERED:
					self._mixer.channel_strip(column).name = ("Channel_Strip_" + str(column))
					button_index = button_index + 1
		self._side_buttons = side_buttons[5:]
		self._update_callback = None
		self._session.set_mixer(self._mixer)
Example #19
0
 def _setup_mixer_control(self):
     is_momentary = True
     self._mixer = SpecialMixerComponent(NUM_TRACKS)
     self._mixer.set_serato_interface(self._serato_interface)
     self._mixer.master_strip().set_serato_interface(self._serato_interface)
     self._track_arm_buttons = []
     self._track_solo_buttons = []
     self._track_mute_buttons = []
     self._track_select_buttons = []
     self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
     for track in range(NUM_TRACKS):
         strip = self._mixer.channel_strip(track)
         strip.set_serato_interface(self._serato_interface)
         self._track_arm_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
         self._track_solo_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
         self._track_mute_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
         self._track_select_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
         strip.set_arm_button(self._track_arm_buttons[-1])
         strip.set_solo_button(self._track_solo_buttons[-1])
         strip.set_mute_button(self._track_mute_buttons[-1])
         strip.set_select_button(self._track_select_buttons[-1])
         strip.set_shift_button(self._shift_button)
	def __init__(self, matrix, side_buttons, session, skin):
		assert isinstance(matrix, ButtonMatrixElement)
		assert ((matrix.width() == 8) and (matrix.height() == 8))
		assert isinstance(side_buttons, tuple)
		assert (len(side_buttons) == 8)
		assert isinstance(session, SessionComponent)
		ModeSelectorComponent.__init__(self)
		self._skin = skin
		self._session = session
		self._mixer = SpecialMixerComponent(matrix.width())
		self._matrix = matrix
		self._sliders = []
		self._mixer.name = 'Mixer'
		self._mixer.master_strip().name = 'Master_Channel_strip'
		self._mixer.selected_strip().name = 'Selected_Channel_strip'
		for column in range(matrix.width()):
			self._mixer.channel_strip(column).name = 'Channel_Strip_' + str(column)
			self._sliders.append(PreciseButtonSliderElement(tuple([matrix.get_button(column, 7 - row) for row in range(8)])))
			self._sliders[-1].name = 'Button_Slider_' + str(column)

		self._side_buttons = side_buttons[4:]
		self._update_callback = None
		self._session.set_mixer(self._mixer)
		self.set_modes_buttons(side_buttons[:4])
Example #21
0
    def _init_session(self):
        make_button = partial(make_launch_control_button, channel=9)
        make_encoder = partial(make_launch_control_encoder, channel=9)
        bottom_encoders, top_encoders = make_all_encoders('Session_Mixer', make_encoder)
        pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders]))
        self._session_mixer = SpecialMixerComponent(8, Layer(), pan_volume_layer, Layer())
        self._session_mixer.set_enabled(False)
        self._session_mixer.name = 'Session_Mixer'
        clip_launch_buttons = [ make_button(identifier, 'Clip_Launch_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ]
        self._session = SpecialSessionComponent(num_tracks=8, num_scenes=0, name='Session')
        self._session.set_enabled(False)
        self._session.set_mixer(self._session_mixer)
        self._session_layer = Layer(track_bank_left_button=make_button(116, 'Track_Bank_Left_Button'), track_bank_right_button=make_button(117, 'Track_Bank_Right_Button'), select_prev_button=make_button(114, 'Scene_Bank_Up_Button'), select_next_button=make_button(115, 'Scene_Bank_Down_Button'), clip_launch_buttons=ButtonMatrixElement(rows=[clip_launch_buttons]))
        scene = self._session.selected_scene()
        for index in range(8):
            clip_slot = scene.clip_slot(index)
            clip_slot.set_triggered_to_play_value(Colors.GREEN_BLINK)
            clip_slot.set_triggered_to_record_value(Colors.RED_BLINK)
            clip_slot.set_stopped_value(Colors.AMBER_FULL)
            clip_slot.set_started_value(Colors.GREEN_FULL)
            clip_slot.set_recording_value(Colors.RED_FULL)
            clip_slot.name = 'Selected_Clip_Slot_' + str(index)

        self._on_track_offset.subject = self._session
Example #22
0
    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(self, 8)  #added self for parent
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                             80)
        master_select_button.name = 'Master_Select_Button'
        self._mixer.master_strip().set_select_button(
            master_select_button
        )  #set in ShiftableSelectorComponent instead if used for Note Mode
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        select_buttons = []  #added
        arm_buttons = []  #added
        sliders = []  #added
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            #volume_control = SliderElement(MIDI_CC_TYPE, track, 7) #set in ShiftableSelectorComponent instead
            #arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) #see below
            solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        49)
            solo_button.name = str(track) + '_Solo_Button'
            strip.set_solo_button(solo_button)

            if track < 4:
                mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                            track, 50)
                mute_button.name = str(track) + '_Mute_Button'
                strip.set_mute_button(mute_button)
                strip.set_invert_mute_feedback(True)

            strip.set_shift_button(self._shift_button)
            select_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51))  #added
            select_buttons[-1].name = str(track) + '_Select_Button'  #added
            #strip.set_select_button(select_buttons[-1]) #added
            arm_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48))  #added
            arm_buttons[-1].name = str(track) + '_Arm_Button'  #added
            sliders.append(SliderElement(MIDI_CC_TYPE, track, 7))  #added
            sliders[-1].name = str(track) + '_Volume_Control'  #added

        self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        self._prehear_control = EncoderElement(
            MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
        self._crossfader.name = 'Crossfader'  #not used in APC20
        master_volume_control.name = 'Master_Volume_Control'
        self._prehear_control.name = 'Prehear_Volume_Control'
        self._mixer.set_shift_button(
            self._shift_button)  #added for shifting prehear
        self._mixer.set_crossfader_control(
            self._crossfader)  #not used in APC20
        self._mixer.set_prehear_volume_control(
            self._prehear_control
        )  #functionality overridden in SpecialMixerComponent
        self._mixer.master_strip().set_volume_control(master_volume_control)
        self._slider_modes = SliderModesComponent(
            self._mixer, tuple(sliders))  #added from APC20 script
        self._slider_modes.name = 'Slider_Modes'  #added from APC20 script
        matrix_modes = MatrixModesComponent(self._matrix, self._session,
                                            self._session_zoom,
                                            tuple(self._track_stop_buttons),
                                            self)  #added new
        matrix_modes.name = 'Matrix_Modes'  #added new
        # Original method args for ShiftableSelectorComponent: (self, select_buttons, master_button, arm_buttons, matrix, session, zooming, mixer, transport, slider_modes, mode_callback)
        #self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message)
        self._shift_modes = ShiftableSelectorComponent(
            self, tuple(select_buttons), master_select_button,
            tuple(arm_buttons), self._matrix, self._session,
            self._session_zoom, self._mixer, self._slider_modes, matrix_modes
        )  #, self._send_introduction_message) #also added self for _parent
        self._shift_modes.name = 'Shift_Modes'
        self._shift_modes.set_mode_toggle(self._shift_button)
class Launchkey(ControlSurface):
    """ Script for Novation's Launchkey 25/49/61 keyboards """

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = "Launchkey InControl"
            self._suggested_output_port = "Launchkey InControl"
            self._has_sliders = True
            self._current_midi_map = None
            self._master_slider = make_slider(7, "Master_Volume_Control")
            self._modes_buttons = []
            for index in range(3):
                button = ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, 0, 13 + index)
                self._modes_buttons.append(button)
                self._modes_buttons[-1].add_value_listener(self._dummy_listener)

            self._setup_mixer()
            self._setup_session()
            self._setup_transport()
            self._setup_device()
            for component in self.components:
                component.set_enabled(False)

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self.schedule_message(2, self._send_midi, LIVE_MODE_ON)
        self.schedule_message(3, self._send_midi, SIZE_QUERY)

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:11] == SIZE_RESPONSE:
            self._has_sliders = midi_bytes[11] != 48
            self._send_midi(LED_FLASHING_ON)
            self._update_mixer_offset()
            for control in self.controls:
                if isinstance(control, InputControlElement):
                    control.clear_send_cache()

            for component in self.components:
                component.set_enabled(True)

            if self._has_sliders:
                self._mixer.master_strip().set_volume_control(self._master_slider)
                self._mixer.update()
            else:
                self._mixer.master_strip().set_volume_control(None)
                for index in range(len(self._sliders)):
                    self._mixer.channel_strip(index).set_volume_control(None)
                    self._mixer.channel_strip(index).set_mute_button(None)
                    slider = self._sliders[index]
                    slider.release_parameter()

                self._mixer.selected_strip().set_volume_control(self._master_slider)
            self.request_rebuild_midi_map()

    def disconnect(self):
        ControlSurface.disconnect(self)
        for button in self._modes_buttons:
            if button.value_has_listener(self._dummy_listener):
                button.remove_value_listener(self._dummy_listener)

        self._modes_buttons = None
        self._encoders = None
        self._sliders = None
        self._strip_buttons = None
        self._master_slider = None
        self._current_midi_map = None
        self._transport_view_modes = None
        self._send_midi(LED_FLASHING_OFF)
        self._send_midi(LIVE_MODE_OFF)

    def build_midi_map(self, midi_map_handle):
        self._current_midi_map = midi_map_handle
        ControlSurface.build_midi_map(self, midi_map_handle)

    def _setup_mixer(self):
        self._next_nav_button = make_button(103, "Next_Track_Button")
        self._prev_nav_button = make_button(102, "Prev_Track_Button")
        mute_solo_flip_button = make_button(59, "Master_Button")
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = "Mixer"
        self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button)
        self._mixer.selected_strip().name = "Selected_Channel_Strip"
        self._mixer.master_strip().name = "Master_Channel_Strip"
        self._mixer.master_strip().set_volume_control(self._master_slider)
        self._sliders = []
        self._strip_buttons = []
        for index in range(8):
            strip = self._mixer.channel_strip(index)
            strip.name = "Channel_Strip_" + str(index)
            strip.set_invert_mute_feedback(True)
            self._sliders.append(make_slider(41 + index, "Volume_Control_%d" % index))
            strip.set_volume_control(self._sliders[-1])
            self._strip_buttons.append(make_button(51 + index, "Mute_Button_%d" % index))

        self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)

    def _setup_session(self):
        scene_launch_button = make_configurable_button(104, "Scene_Launch_Button")
        scene_stop_button = make_configurable_button(120, "Scene_Stop_Button")
        self._session = SpecialSessionComponent(8, 0)
        self._session.name = "Session_Control"
        self._session.selected_scene().name = "Selected_Scene"
        self._session.selected_scene().set_launch_button(scene_launch_button)
        self._session.selected_scene().set_triggered_value(GREEN_BLINK)
        self._session.set_stop_all_clips_button(scene_stop_button)
        scene_stop_button.set_on_off_values(AMBER_FULL, LED_OFF)
        self._session.set_mixer(self._mixer)
        self._session.set_track_banking_increment(8)
        self._session.set_stop_track_clip_value(GREEN_BLINK)
        clip_launch_buttons = []
        clip_stop_buttons = []
        for index in range(8):
            clip_launch_buttons.append(make_configurable_button(96 + index, "Clip_Launch_%d" % index))
            clip_stop_buttons.append(make_configurable_button(112 + index, "Clip_Stop_%d" % index))
            clip_slot = self._session.selected_scene().clip_slot(index)
            clip_slot.set_triggered_to_play_value(GREEN_BLINK)
            clip_slot.set_triggered_to_record_value(RED_BLINK)
            clip_slot.set_stopped_value(AMBER_FULL)
            clip_slot.set_started_value(GREEN_FULL)
            clip_slot.set_recording_value(RED_FULL)
            clip_slot.set_launch_button(clip_launch_buttons[-1])
            clip_slot.name = "Selected_Clip_Slot_" + str(index)

        self._session.set_stop_track_clip_buttons(tuple(clip_stop_buttons))

    def _setup_transport(self):
        rwd_button = make_button(112, "Rwd_Button")
        ffwd_button = make_button(113, "FFwd_Button")
        stop_button = make_button(114, "Stop_Button")
        play_button = make_button(115, "Play_Button")
        loop_button = make_button(116, "Loop_Button")
        rec_button = make_button(117, "Record_Button")
        transport = TransportComponent()
        transport.name = "Transport"
        transport.set_stop_button(stop_button)
        transport.set_play_button(play_button)
        transport.set_record_button(rec_button)
        transport.set_loop_button(loop_button)
        self._transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button)
        self._transport_view_modes.name = "Transport_View_Modes"

    def _setup_device(self):
        encoders = [make_encoder(21 + index, "Device_Control_%d" % index) for index in xrange(8)]
        self._encoders = tuple(encoders)
        device = DeviceComponent()
        device.name = "Device_Component"
        self.set_device_component(device)
        device.set_parameter_controls(self._encoders)

    def _dummy_listener(self, value):
        pass

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._update_mixer_offset()

    def _update_mixer_offset(self):
        all_tracks = self._session.tracks_to_use()
        selected_track = self.song().view.selected_track
        num_strips = self._session.width()
        if selected_track in all_tracks:
            track_index = list(all_tracks).index(selected_track)
            new_offset = track_index - track_index % num_strips
            self._session.set_offsets(new_offset, self._session.scene_offset())
class Axiom_AIR_25_49_61(ControlSurface):
    """ Script for the M-Audio Axiom A.I.R. 25, 49 and 61 """
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self._alt_device_component = None
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = 'HyperControl'
            self._suggested_output_port = 'HyperControl'
            self._single_fader_button_modes = None
            self._has_faders = True
            self._display_reset_delay = -1
            self._hc_byte = HC_BYTE
            self._waiting_for_first_response = True
            self._setup_controls()
            self._setup_displays()
            self._setup_mixer()
            self._setup_session()
            self._setup_transport()
            self._setup_device()
            self._setup_modes()
            self._drum_group_midi_button = None
            self._drum_group_hyper_button = None
            for component in self.components:
                component.set_enabled(False)

    def disconnect(self):
        self._scheduled_messages = []
        for encoder in self._encoders:
            encoder.remove_value_listener(self._encoder_value)

        for fader in self._faders:
            fader.remove_value_listener(self._fader_value)

        for fader_button in self._fader_buttons:
            fader_button.remove_value_listener(self._fader_button_value)

        self._master_fader.remove_value_listener(self._fader_value)
        self._master_fader_button.remove_value_listener(
            self._fader_button_value)
        self._select_button.remove_value_listener(self._select_button_value)
        self._identify_button.remove_value_listener(self._identify_value)
        self._fader_group_midi_button.remove_value_listener(
            self._midi_button_value)
        self._fader_group_mix_button.remove_value_listener(
            self._hyper_button_value)
        self._fader_group_fx_button.remove_value_listener(
            self._hyper_button_value)
        self._encoder_group_midi_button.remove_value_listener(
            self._midi_button_value)
        self._encoder_group_mix_button.remove_value_listener(
            self._hyper_button_value)
        self._encoder_group_fx_button.remove_value_listener(
            self._hyper_button_value)
        if self._drum_group_midi_button != None:
            self._drum_group_midi_button.remove_value_listener(
                self._midi_button_value)
        if self._drum_group_hyper_button != None:
            self._drum_group_hyper_button.remove_value_listener(
                self._hyper_button_value)
        self._alt_device_component = None
        self._name_display = None
        self._value_display = None
        self._bank_display = None
        self._pad_display = None
        self._name_display_data_source = None
        self._value_display_data_source = None
        self._bank_display_data_source = None
        self._pad_display_data_source = None
        self._select_button = None
        self._left_button = None
        self._right_button = None
        self._up_button = None
        self._down_button = None
        self._loop_button = None
        self._ffwd_button = None
        self._rwd_button = None
        self._play_button = None
        self._stop_button = None
        self._rec_button = None
        self._master_fader_button = None
        self._fader_buttons = None
        self._faders = None
        self._encoders = None
        self._drum_pads = None
        self._identify_button = None
        self._main_group_hyper_button = None
        self._main_group_track_button = None
        self._main_group_fx_button = None
        self._encoder_group_midi_button = None
        self._encoder_group_mix_button = None
        self._encoder_group_fx_button = None
        self._fader_group_mode_button = None
        self._fader_group_midi_button = None
        self._fader_group_mix_button = None
        self._fader_group_fx_button = None
        self._drum_group_midi_button = None
        self._drum_group_roll_button = None
        self._drum_group_hyper_button = None
        self._mixer_for_encoders = None
        self._mixer_for_faders = None
        self._device_for_encoders = None
        self._device_for_faders = None
        self._transport = None
        self._session = None
        ControlSurface.disconnect(self)
        self._send_midi(SYSEX_START + DISABLE_HYPERCONTROL)

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self.schedule_message(5, self._send_midi, IDENTITY_REQUEST)

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:10] == AXIOM_AIR_RESPONSE:
            if midi_bytes[12:15] < AXIOM_REV4_RESPONSE:
                self.schedule_message(1, self._send_midi,
                                      SYSEX_START + ENGAGE_HYPERCONTROL)
                self.schedule_message(2, self._send_midi,
                                      SYSEX_START + CLEAR_ALL)
                self.schedule_message(3, self._name_display.display_message,
                                      'Firmware')
                self.schedule_message(13, self._name_display.display_message,
                                      'Update')
                self.schedule_message(23, self._name_display.display_message,
                                      'Required')
                self.schedule_message(33, self._send_midi,
                                      SYSEX_START + DISABLE_HYPERCONTROL)
            elif midi_bytes[12:15] >= AXIOM_REV4_RESPONSE:
                if self._waiting_for_first_response == True:
                    self._waiting_for_first_response = False
                    self._has_faders = midi_bytes[10] != 50
                    self.schedule_message(1, self._send_midi,
                                          SYSEX_START + ENGAGE_HYPERCONTROL)
                    self.schedule_message(2, self._send_midi,
                                          SYSEX_START + SPECIAL_HYPERCONTROL)
                    self.schedule_message(3, self._complete_setup)
                else:
                    self._display_reset_delay = 0
        elif midi_bytes[0:8] == REQUEST_HYPERCONTROL:
            self.schedule_message(5, self._send_midi, IDENTITY_REQUEST)

    def update_display(self):
        ControlSurface.update_display(self)
        if self._display_reset_delay >= 0:
            self._display_reset_delay -= 1
            if self._display_reset_delay == -1:
                self._set_displays_to_default()

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._display_reset_delay = 0

    def restore_bank(self, bank_index):
        ControlSurface.restore_bank(self, bank_index)
        if self._alt_device_component != None:
            self._alt_device_component.restore_bank(bank_index)

    def set_appointed_device(self, device):
        ControlSurface.set_appointed_device(self, device)
        with self.component_guard():
            if self._alt_device_component != None:
                self._alt_device_component.set_device(device)

    def set_alt_device_component(self, device_component):
        self._alt_device_component = device_component

    def _update_device_selection(self):
        track = self.song().view.selected_track
        device_to_select = track.view.selected_device
        if device_to_select == None and len(track.devices) > 0:
            device_to_select = track.devices[0]
        if device_to_select != None:
            self.song().view.select_device(device_to_select)
        self._device_component.set_device(device_to_select)
        if self._alt_device_component != None:
            self._alt_device_component.set_device(device_to_select)

    def _setup_controls(self):
        self._left_button = create_button(99, 'Left_Button')
        self._right_button = create_button(100, 'Right_Button')
        self._up_button = create_button(101, 'Up_Button')
        self._down_button = create_button(102, 'Down_Button')
        self._loop_button = create_button(113, 'Loop_Button')
        self._rwd_button = create_button(114, 'Rwd_Button')
        self._ffwd_button = create_button(115, 'FFwd_Button')
        self._stop_button = create_button(116, 'Stop_Button')
        self._play_button = create_button(117, 'Play_Button')
        self._rec_button = create_button(118, 'Record_Button')
        self._select_button = ConfigurableButtonElement(
            IS_MOMENTARY, MIDI_CC_TYPE, GLOBAL_CHANNEL, 98)
        self._select_button.name = 'Select_Button'
        self._select_button.add_value_listener(self._select_button_value)
        self._main_group_hyper_button = create_configurable_button(
            104, 'Fader_Group_HyperControl_Button', 2, 14)
        self._main_group_track_button = create_configurable_button(
            105, 'Main_Group_Track_Button', 2, 11)
        self._main_group_fx_button = create_configurable_button(
            106, 'Main_Group_Inst_FX_Button', 2, 11)
        self._identify_button = create_configurable_button(
            97, 'Identify_Button', 2, 16)
        self._identify_button.add_value_listener(self._identify_value)
        self._fader_buttons = []
        for index in range(8):
            self._fader_buttons.append(
                create_configurable_button(49 + index,
                                           'Fader_Button_%d' % index))
            self._fader_buttons[-1].add_value_listener(
                self._fader_button_value, identify_sender=True)

        self._faders = []
        for index in range(8):
            self._faders.append(create_slider(33 + index, 'Fader_%d' % index))
            self._faders[-1].add_value_listener(self._fader_value,
                                                identify_sender=True)

        self._master_fader_button = create_configurable_button(
            57, 'Master_Fader_Button')
        self._master_fader_button.add_value_listener(self._fader_button_value,
                                                     identify_sender=True)
        self._master_fader = create_slider(41, 'Master_Fader')
        self._master_fader.add_value_listener(self._fader_value,
                                              identify_sender=True)
        self._fader_group_mode_button = create_configurable_button(
            61, 'Fader_Group_Mode_Button')
        self._fader_group_midi_button = create_configurable_button(
            60, 'Fader_Group_MIDI_Button')
        self._fader_group_midi_button.add_value_listener(
            self._midi_button_value, identify_sender=True)
        self._fader_group_mix_button = create_configurable_button(
            58, 'Fader_Group_Mix_Button', 0, 1)
        self._fader_group_mix_button.add_value_listener(
            self._hyper_button_value, identify_sender=True)
        self._fader_group_fx_button = create_configurable_button(
            59, 'Fader_Group_Inst_FX_Button', 0, -1)
        self._fader_group_fx_button.add_value_listener(
            self._hyper_button_value, identify_sender=True)
        self._encoders = []
        for index in range(8):
            self._encoders.append(
                create_encoder(17 + index, 'Encoder_%d' % index))
            self._encoders[-1].add_value_listener(self._encoder_value,
                                                  identify_sender=True)

        self._encoder_group_midi_button = create_configurable_button(
            27, 'Encoder_Group_MIDI_Button', 0, 72)
        self._encoder_group_midi_button.add_value_listener(
            self._midi_button_value, identify_sender=True)
        self._encoder_group_mix_button = create_configurable_button(
            25, 'Encoder_Group_Mix_Button', 0, 72)
        self._encoder_group_mix_button.add_value_listener(
            self._hyper_button_value, identify_sender=True)
        self._encoder_group_fx_button = create_configurable_button(
            26, 'Encoder_Group_Inst_FX_Button', 0, 72)
        self._encoder_group_fx_button.add_value_listener(
            self._hyper_button_value, identify_sender=True)

    def _setup_drum_pads(self):
        self._drum_pads = []
        num_pads = 12 if self._has_faders else 16
        for index in range(8):
            self._drum_pads.append(
                create_configurable_button(81 + index, 'Pad_%d' % index, 0, 0,
                                           MIDI_CC_TYPE))

        for index in range(num_pads - 8):
            self._drum_pads.append(
                ConfigurableButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE,
                                          GLOBAL_CHANNEL - 1, 81 + index,
                                          GLOBAL_SEND_CHANNEL, 8,
                                          MIDI_CC_TYPE))
            self._drum_pads[-1].name = 'Pad_' + str(index + 8)

        self._drum_group_midi_button = create_configurable_button(
            91, 'Drum_Group_MIDI_Button', 2, -2)
        self._drum_group_midi_button.add_value_listener(
            self._midi_button_value, identify_sender=True)
        self._drum_group_roll_button = create_configurable_button(
            90, 'Drum_Group_Roll_Button', -1)
        self._drum_group_hyper_button = create_configurable_button(
            89, 'Drum_Group_HyperControl_Button', 2, 2)
        self._drum_group_hyper_button.add_value_listener(
            self._hyper_button_value, identify_sender=True)

    def _setup_displays(self):
        self._name_display = PhysicalDisplayElement(12, 1)
        self._name_display.name = 'Name_Display'
        self._name_display.set_message_parts(SYSEX_START + (21, ), (0, 247))
        self._name_display.set_clear_all_message(CLEAR_NAME)
        self._name_display_data_source = DisplayDataSource()
        self._name_display.segment(0).set_data_source(
            self._name_display_data_source)
        self._value_display = NumericalDisplayElement(3, 1)
        self._value_display.name = 'Value_Display'
        self._value_display.set_message_parts(SYSEX_START + (20, 48), (0, 247))
        self._value_display.set_clear_all_message(CLEAR_VALUE)
        self._value_display_data_source = DisplayDataSource()
        self._value_display.segment(0).set_data_source(
            self._value_display_data_source)
        self._bank_display = NumericalDisplayElement(3, 1)
        self._bank_display.name = 'Bank_Display'
        self._bank_display.set_message_parts(SYSEX_START + (19, ), (0, 247))
        self._bank_display.set_clear_all_message(CLEAR_BANK)
        self._bank_display_data_source = DisplayDataSource()
        self._bank_display.segment(0).set_data_source(
            self._bank_display_data_source)
        self._pad_display = NumericalDisplayElement(2, 1)
        self._pad_display.name = 'Pad_Display'
        self._pad_display.set_message_parts(SYSEX_START + (18, ), (0, 247))
        self._pad_display.set_clear_all_message(CLEAR_PAD)
        self._pad_display_data_source = DisplayDataSource()
        self._pad_display.segment(0).set_data_source(
            self._pad_display_data_source)

    def _setup_mixer(self):
        self._mixer_for_encoders = SpecialMixerComponent(
            self._name_display, self._value_display, 8)
        self._mixer_for_encoders.name = 'Mixer_for_encoders'
        self._mixer_for_faders = SpecialMixerComponent(self._name_display,
                                                       self._value_display, 8)
        self._mixer_for_faders.name = 'Mixer_for_faders'

    def _setup_session(self):
        self._session = SpecialSessionComponent(8, 0)
        self._session.name = 'Session_Control'
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.set_mixer(self._mixer_for_encoders)
        self._session.set_alt_mixer(self._mixer_for_faders)
        self._session.add_offset_listener(self._update_bank_value)

    def _setup_transport(self):
        self._transport = TransportComponent()
        self._transport.name = 'Transport'
        self._transport.set_stop_button(self._stop_button)
        self._transport.set_play_button(self._play_button)
        self._transport.set_record_button(self._rec_button)
        transport_view_modes = TransportViewModeSelector(
            self._transport, self._session, self._ffwd_button,
            self._rwd_button, self._loop_button)
        transport_view_modes.name = 'Transport_View_Modes'

    def _setup_device(self):
        self._device_for_encoders = BestBankDeviceComponent()
        self._device_for_encoders.name = 'Device_Component_for_encoders'
        self._device_for_faders = BestBankDeviceComponent()
        self._device_for_faders.name = 'Device_Component_for_faders'
        self.set_device_component(self._device_for_encoders)
        self.set_alt_device_component(self._device_for_faders)
        self._device_nav = DeviceNavComponent()
        self._device_nav.name = 'Device_Nav_Component'

    def _setup_modes(self):
        self._fader_button_modes = FaderButtonModeSelector(
            self._mixer_for_faders, tuple(self._fader_buttons))
        self._fader_button_modes.name = 'Fader_Button_Modes'
        self._fader_button_modes.set_mode_toggle(self._fader_group_mode_button)
        self._fader_modes = FaderModeSelector(self._mixer_for_faders,
                                              self._device_for_faders,
                                              tuple(self._faders),
                                              self._fader_button_modes,
                                              self._master_fader_button)
        self._fader_modes.name = 'Fader_Modes'
        self._fader_modes.set_mode_buttons(
            (self._fader_group_mix_button, self._fader_group_fx_button))
        self._encoder_modes = EncoderModeSelector(self._mixer_for_encoders,
                                                  self._device_for_encoders,
                                                  tuple(self._encoders))
        self._encoder_modes.name = 'Encoder_Modes'
        self._encoder_modes.set_mode_buttons(
            (self._encoder_group_mix_button, self._encoder_group_fx_button))
        main_modes = MainModeSelector(self._device_for_encoders,
                                      self._device_for_faders, self._session,
                                      self._mixer_for_faders, self._device_nav,
                                      self._up_button, self._down_button,
                                      self._left_button, self._right_button,
                                      self._select_button)
        main_modes.name = 'Main_Modes'
        main_modes.set_mode_buttons(
            (self._main_group_track_button, self._main_group_fx_button))

    def _setup_master_fader(self):
        if self._has_faders:
            self._mixer_for_encoders.master_strip().set_volume_control(
                self._master_fader)
        else:
            self._mixer_for_encoders.selected_strip().set_volume_control(
                self._master_fader)

    def _setup_single_fader_button_modes(self):
        self._single_fader_button_modes = SingleFaderButtonModeSelector(
            self._mixer_for_encoders, self._fader_group_midi_button)
        self._single_fader_button_modes.name = 'Single_Fader_Button_Modes'
        self._single_fader_button_modes.set_mode_toggle(
            self._fader_group_mode_button)

    def _complete_setup(self):
        self._setup_drum_pads()
        self._set_drum_pads_to_hc()
        self._setup_master_fader()
        if not self._has_faders:
            self._setup_single_fader_button_modes()
        for control in self.controls:
            if isinstance(control, InputControlElement):
                control.clear_send_cache()

        for component in self.components:
            component.set_enabled(True)

        self._fader_group_midi_button.send_value(LED_OFF, True)
        self._encoder_group_midi_button.send_value(LED_OFF, True)
        self._main_group_hyper_button.send_value(AMB_FULL, True)
        self.request_rebuild_midi_map()
        self._on_selected_track_changed()
        self.schedule_message(1, self._show_startup_message)

    def _show_startup_message(self):
        self._send_midi(SYSEX_START + CLEAR_ALL)
        self._name_display.display_message('Ableton Live')
        self._display_reset_delay = INITIAL_DISPLAY_DELAY

    def _select_button_value(self, value):
        self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _identify_value(self, value):
        for encoder in self._encoders:
            encoder.set_identify_mode(value > 0)

        for fader in self._faders:
            fader.set_identify_mode(value > 0)

        self._master_fader.set_identify_mode(value > 0)
        self._display_reset_delay = 0
        self._identify_button.turn_on(
        ) if value > 0 else self._identify_button.turn_off()

    def _midi_button_value(self, value, sender):
        if value > 0:
            if sender is self._drum_group_midi_button:
                hc_byte = self._hc_byte ^ PADS
                if hc_byte != self._hc_byte:
                    self._hc_byte = hc_byte
                    self._drum_group_hyper_button.send_value(LED_OFF, True)
                    self.schedule_message(
                        1, self._send_midi,
                        SYSEX_START + (32, self._hc_byte, 247))
            elif sender is self._encoder_group_midi_button:
                hc_byte = self._hc_byte ^ ENCODERS
                if hc_byte != self._hc_byte:
                    self._hc_byte = hc_byte
                    self._encoder_group_mix_button.send_value(LED_OFF, True)
                    self._encoder_group_fx_button.send_value(LED_OFF, True)
                    if self._encoder_modes.mode_index < 3:
                        self._encoder_modes.set_enabled(False)
                    self.schedule_message(
                        1, self._send_midi,
                        SYSEX_START + (32, self._hc_byte, 247))
            elif sender is self._fader_group_midi_button:
                if self._has_faders:
                    hc_byte = self._hc_byte ^ FADERS
                    if hc_byte != self._hc_byte:
                        self._hc_byte = hc_byte
                        self._fader_group_mix_button.send_value(LED_OFF, True)
                        self._fader_group_fx_button.send_value(LED_OFF, True)
                        self._fader_group_mode_button.send_value(LED_OFF, True)
                        if self._fader_modes.mode_index < 2:
                            self._fader_modes.set_enabled(False)
                            self._fader_button_modes.set_enabled(False)
                        self.schedule_message(
                            1, self._send_midi,
                            SYSEX_START + (32, self._hc_byte, 247))
                else:
                    self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _hyper_button_value(self, value, sender):
        if value > 0:
            if sender is self._drum_group_hyper_button:
                if self._hc_byte | PADS != self._hc_byte:
                    self._hc_byte = self._hc_byte | PADS
                    self._send_midi(SYSEX_START + (32, self._hc_byte, 247))
                    self.schedule_message(1, self._set_drum_pads_to_hc)
            elif sender is self._encoder_group_fx_button or sender is self._encoder_group_mix_button:
                if self._hc_byte | ENCODERS != self._hc_byte:
                    self._hc_byte = self._hc_byte | ENCODERS
                    self._send_midi(SYSEX_START + (32, self._hc_byte, 247))
                    self._encoder_group_midi_button.turn_off()
                    if sender is self._encoder_group_fx_button:
                        self._encoder_modes.set_enabled(True)
                        self._display_reset_delay = 0
                        return
                    else:
                        self.schedule_message(1,
                                              self._encoder_modes.set_enabled,
                                              True)
                        self.schedule_message(1, self._encoder_modes.update)
                        self._display_reset_delay = 2
                        return
            elif sender is self._fader_group_fx_button or sender is self._fader_group_mix_button:
                if self._hc_byte | FADERS != self._hc_byte:
                    self._hc_byte = self._hc_byte | FADERS
                    self._send_midi(SYSEX_START + (32, self._hc_byte, 247))
                    self._fader_group_midi_button.turn_off()
                    self._fader_button_modes.set_enabled(True)
                    if sender is self._fader_group_fx_button:
                        self._fader_modes.set_enabled(True)
                        self._fader_button_modes.set_enabled(True)
                        self._display_reset_delay = 0
                        return
                    else:
                        self.schedule_message(1, self._fader_modes.set_enabled,
                                              True)
                        self.schedule_message(1, self._fader_modes.update)
                        self.schedule_message(
                            1, self._fader_button_modes.set_enabled, True)
                        self.schedule_message(1,
                                              self._fader_button_modes.update)
                        self._display_reset_delay = 2
                        return
            self._display_reset_delay = 0

    def _set_drum_pads_to_hc(self):
        self._drum_group_midi_button.send_value(LED_OFF, True)
        self._drum_group_hyper_button.send_value(RED_FULL, True)
        for index in range(len(self._drum_pads)):
            self._drum_pads[index].send_value(RED_LOW, True)

    def _fader_button_value(self, value, sender):
        self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _fader_value(self, value, sender):
        param = sender.mapped_parameter()
        if param != None:
            param_range = param.max - param.min
            if param.name == 'Track Volume':
                if sender == self._master_fader:
                    if self._has_faders:
                        name_string = 'Master  Vol'
                    else:
                        name_string = self._mixer_for_faders.selected_strip(
                        ).track_name_data_source().display_string() + '   Vol'
                else:
                    name_string = self._mixer_for_faders.channel_strip(
                        self._faders.index(sender)).track_name_data_source(
                        ).display_string() + '   Vol'
            else:
                name_string = param.name
                value = int((param.value - param.min) / param_range * 127)
            value_string = str(value)
        else:
            name_string = '<unmapped>'
            value_string = None
            self.schedule_message(1, self._set_value_string)
        self._set_name_string(name_string)
        self._set_value_string(value_string)

    def _encoder_value(self, value, sender):
        param = sender.mapped_parameter()
        if param != None:
            param_range = param.max - param.min
            if param.name == 'Track Volume':
                name_string = self._mixer_for_encoders.channel_strip(
                    self._encoders.index(sender)).track_name_data_source(
                    ).display_string() + '   Vol'
                value = int((param.value - param.min) / param_range * 127)
            elif param.name == 'Track Panning':
                name_string = self._mixer_for_encoders.channel_strip(
                    self._encoders.index(sender)).track_name_data_source(
                    ).display_string() + '   Pan'
                value = int(param.value / param_range * 127)
                if value < 0:
                    name_string += '  L'
                elif value > 0:
                    name_string += '  R'
                else:
                    name_string += '  C'
            else:
                name_string = param.name
                value = int((param.value - param.min) / param_range * 127)
            value_string = str(value)
        else:
            name_string = '<unmapped>'
            value_string = None
            self.schedule_message(1, self._set_value_string)
        self._set_name_string(name_string)
        self._set_value_string(value_string)

    def _set_displays_to_default(self):
        self._name_display.segment(0).set_data_source(
            self._mixer_for_encoders.selected_strip().track_name_data_source())
        self._name_display.update()
        self._update_bank_value()
        self._set_value_string(None)
        self._send_midi(SYSEX_START + LCD_HC_DEFAULT)

    def _set_name_string(self, name_string):
        self._name_display.segment(0).set_data_source(
            self._name_display_data_source)
        self._name_display_data_source.set_display_string(name_string)
        self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _set_value_string(self, value_string=None):
        if value_string != None:
            self._value_display_data_source.set_display_string(value_string)
        else:
            self._value_display.reset()

    def _set_bank_string(self, bank_string=None):
        if bank_string != None:
            self._bank_display_data_source.set_display_string(bank_string)
        else:
            self._bank_display.reset()

    def _update_bank_value(self):
        bank = (self._session.track_offset() + 1) / self._session.width() + 1
        self._set_bank_string(str(bank))

    def _install_mapping(self, midi_map_handle, control, parameter,
                         feedback_delay, feedback_map):
        if not self._in_build_midi_map:
            raise AssertionError
            raise midi_map_handle != None or AssertionError
            raise control != None and parameter != None or AssertionError
            raise isinstance(
                parameter,
                Live.DeviceParameter.DeviceParameter) or AssertionError
            raise isinstance(control, InputControlElement) or AssertionError
            raise isinstance(feedback_delay, int) or AssertionError
            if not isinstance(feedback_map, tuple):
                raise AssertionError
                success = False
                feedback_rule = None
                feedback_rule = control.message_type(
                ) is MIDI_NOTE_TYPE and Live.MidiMap.NoteFeedbackRule()
                feedback_rule.note_no = 0
                feedback_rule.vel_map = (0, )
            elif control.message_type() is MIDI_CC_TYPE:
                feedback_rule = Live.MidiMap.CCFeedbackRule()
                feedback_rule.cc_no = 0
                feedback_rule.cc_value_map = (0, )
            elif control.message_type() is MIDI_PB_TYPE:
                feedback_rule = Live.MidiMap.PitchBendFeedbackRule()
                feedback_rule.value_pair_map = feedback_map
            raise feedback_rule != None or AssertionError
            feedback_rule.channel = control.message_channel()
            feedback_rule.delay_in_ms = feedback_delay
            success = control.message_type(
            ) is MIDI_NOTE_TYPE and Live.MidiMap.map_midi_note_with_feedback_map(
                midi_map_handle, parameter, control.message_channel(),
                control.message_identifier(), feedback_rule)
        elif control.message_type() is MIDI_CC_TYPE:
            success = Live.MidiMap.map_midi_cc_with_feedback_map(
                midi_map_handle, parameter, control.message_channel(),
                control.message_identifier(), control.message_map_mode(),
                feedback_rule, not control.needs_takeover())
        elif control.message_type() is MIDI_PB_TYPE:
            success = Live.MidiMap.map_midi_pitchbend_with_feedback_map(
                midi_map_handle, parameter, control.message_channel(),
                feedback_rule, not control.needs_takeover())
        return success
Example #25
0
class Generic(ControlSurface):
    __doc__ = " Script for FCB1010 in APC emulation mode "

    _active_instances = []

    def _combine_active_instances():
        track_offset = 0
        scene_offset = 0
        for instance in Generic._active_instances:
            instance._activate_combination_mode(track_offset, scene_offset)
            track_offset += instance._session.width()

    _combine_active_instances = staticmethod(_combine_active_instances)

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            self._note_map_scenes = []
            self._note_map_buttons = []
            self._ctrl_map_sliders = []
            self._note_map_trk_stop_buttons = []
            self._note_map_trk_sel_buttons = []
            self._note_map_trk_mute_buttons = []
            self._note_map_trk_solo_buttons = []
            self._note_map_trk_rec_buttons = []
            self._ctrl_map_trk_volume = []
            self._ctrl_map_trk_pan = []
            self._ctrl_map_senda = []
            self._ctrl_map_sendb = []
            self._ctrl_map_sendc = []
            self._note_map_bank_buttons = []
            self._ctrl_map_parameter = []
            self._load_MIDI_map()
            self._session = None
            self._session_zoom = None
            self._mixer = None
            self._setup_session_control()
            self._setup_mixer_control()
            self._session.set_mixer(self._mixer)
            self._setup_device_and_transport_control()
            self.set_highlighting_session_component(self._session)
        self._pads = []
        self._load_pad_translations()
        self._do_combine()

    def disconnect(self):
        self._note_map_scenes = None
        self._note_map_buttons = None
        self._ctrl_map_sliders = None
        self._note_map_trk_stop_buttons = None
        self._note_map_trk_sel_buttons = None
        self._note_map_trk_mute_buttons = None
        self._note_map_trk_solo_buttons = None
        self._note_map_trk_rec_buttons = None
        self._ctrl_map_trk_volume = None
        self._ctrl_map_trk_pan = None
        self._ctrl_map_senda = None
        self._ctrl_map_sendb = None
        self._ctrl_map_sendc = None
        self._note_map_bank_buttons = None
        self._ctrl_map_parameter = None
        self._pads = None
        self._do_uncombine()
        self._shift_button = None
        self._session = None
        self._session_zoom = None
        self._mixer = None
        ControlSurface.disconnect(self)

    def _do_combine(self):
        if self not in Generic._active_instances:
            Generic._active_instances.append(self)
            Generic._combine_active_instances()

    def _do_uncombine(self):
        if ((self in Generic._active_instances)
                and Generic._active_instances.remove(self)):
            self._session.unlink()
            Generic._combine_active_instances()

    def _activate_combination_mode(self, track_offset, scene_offset):
        if TRACK_OFFSET != -1:
            track_offset = TRACK_OFFSET
        if SCENE_OFFSET != -1:
            scene_offset = SCENE_OFFSET
        self._session.link_with_track_offset(track_offset, scene_offset)

    def _setup_session_control(self):
        is_momentary = True
        self._session = SpecialSessionComponent(TRACK_NUMBER, MATRIX_DEPTH)
        self._session.name = 'Session_Control'
        self._session.set_track_bank_buttons(self._note_map_buttons[25],
                                             self._note_map_buttons[24])
        self._session.set_scene_bank_buttons(self._note_map_buttons[27],
                                             self._note_map_buttons[26])
        self._session.set_select_buttons(self._note_map_buttons[34],
                                         self._note_map_buttons[35])
        self._scene_launch_buttons = [
            self._note_map_scenes[index] for index in range(MATRIX_DEPTH)
        ]
        self._track_stop_buttons = [
            self._note_map_trk_stop_buttons[index]
            for index in range(TRACK_NUMBER)
        ]
        self._session.set_stop_all_clips_button(self._note_map_buttons[38])
        self._session.set_stop_track_clip_buttons(
            tuple(self._track_stop_buttons))
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(
            self._note_map_buttons[36])
        self._session.set_slot_launch_button(self._note_map_buttons[37])
        for scene_index in range(MATRIX_DEPTH):
            scene = self._session.scene(scene_index)
            scene.name = 'Scene_' + str(scene_index)
            button_row = []
            scene.set_launch_button(self._scene_launch_buttons[scene_index])
            scene.set_triggered_value(2)
            for track_index in range(TRACK_NUMBER):
                if (CLIPNOTEMAP[scene_index][track_index] == -1):
                    button = None
                else:
                    button = ButtonElement(
                        is_momentary,
                        CLIPNOTEMAP_TYPE[scene_index][track_index],
                        CLIPNOTEMAP_CH[scene_index][track_index],
                        CLIPNOTEMAP[scene_index][track_index])
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                    scene_index)
                clip_slot.set_launch_button(button)
        self._session_zoom = SpecialZoomingComponent(self._session)
        self._session_zoom.name = 'Session_Overview'
        self._session_zoom.set_nav_buttons(self._note_map_buttons[28],
                                           self._note_map_buttons[29],
                                           self._note_map_buttons[30],
                                           self._note_map_buttons[31])

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(TRACK_NUMBER)
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.master_strip().set_select_button(
            self._note_map_buttons[39])
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.set_select_buttons(self._note_map_buttons[33],
                                       self._note_map_buttons[32])
        self._mixer.set_crossfader_control(self._ctrl_map_sliders[2])
        self._mixer.set_prehear_volume_control(self._ctrl_map_sliders[1])
        self._mixer.master_strip().set_volume_control(
            self._ctrl_map_sliders[0])
        for track in range(TRACK_NUMBER):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            strip.set_arm_button(self._note_map_trk_rec_buttons[track])
            strip.set_solo_button(self._note_map_trk_solo_buttons[track])
            strip.set_mute_button(self._note_map_trk_mute_buttons[track])
            strip.set_select_button(self._note_map_trk_sel_buttons[track])
            strip.set_volume_control(self._ctrl_map_trk_volume[track])
            strip.set_pan_control(self._ctrl_map_trk_pan[track])
            strip.set_send_controls(
                (self._ctrl_map_senda[track], self._ctrl_map_sendb[track],
                 self._ctrl_map_sendc[track]))
            strip.set_invert_mute_feedback(True)

    def _setup_device_and_transport_control(self):
        is_momentary = True
        self._device = DeviceComponent()
        self._device.name = 'Device_Component'
        device_bank_buttons = []
        device_param_controls = []
        for index in range(PARAMS_NUMBER):
            device_param_controls.append(self._ctrl_map_parameter[index])
        for index in range(BANKS_NUMBER):
            device_bank_buttons.append(self._note_map_bank_buttons[index])
        if None not in device_bank_buttons:
            self._device.set_bank_buttons(tuple(device_bank_buttons))
        if None not in device_param_controls:
            self._device.set_parameter_controls(tuple(device_param_controls))
        self._device.set_on_off_button(self._note_map_buttons[17])
        self._device.set_bank_nav_buttons(self._note_map_buttons[20],
                                          self._note_map_buttons[21])
        self._device.set_lock_button(self._note_map_buttons[16])
        self.set_device_component(self._device)

        detail_view_toggler = DetailViewControllerComponent()
        detail_view_toggler.name = 'Detail_View_Control'
        detail_view_toggler.set_device_clip_toggle_button(
            self._note_map_buttons[15])
        detail_view_toggler.set_detail_toggle_button(
            self._note_map_buttons[14])
        detail_view_toggler.set_device_nav_buttons(self._note_map_buttons[18],
                                                   self._note_map_buttons[19])

        transport = SpecialTransportComponent()
        transport.name = 'Transport'
        transport.set_play_button(self._note_map_buttons[0])
        transport.set_stop_button(self._note_map_buttons[1])
        transport.set_record_button(self._note_map_buttons[2])
        transport.set_nudge_buttons(self._note_map_buttons[4],
                                    self._note_map_buttons[5])
        transport.set_undo_button(self._note_map_buttons[6])
        transport.set_redo_button(self._note_map_buttons[7])
        transport.set_tap_tempo_button(self._note_map_buttons[3])
        transport.set_quant_toggle_button(self._note_map_buttons[13])
        transport.set_overdub_button(self._note_map_buttons[11])
        transport.set_metronome_button(self._note_map_buttons[12])
        transport.set_tempo_control(self._ctrl_map_sliders[3])
        transport.set_loop_button(self._note_map_buttons[8])
        transport.set_seek_buttons(self._note_map_buttons[22],
                                   self._note_map_buttons[23])
        transport.set_punch_buttons(self._note_map_buttons[9],
                                    self._note_map_buttons[10])

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        track = self.song().view.selected_track
        device_to_select = track.view.selected_device
        if device_to_select == None and len(track.devices) > 0:
            device_to_select = track.devices[0]
        if device_to_select != None:
            self.song().view.select_device(device_to_select)
        self._device_component.set_device(device_to_select)

    def _load_pad_translations(self):
        if -1 not in DRUM_PADS:
            pad = []
            for row in range(PAD_Y_NUMBER):
                for col in range(PAD_X_NUMBER):
                    pad = (
                        col,
                        row,
                        DRUM_PADS[row * 4 + col],
                        PADCHANNEL,
                    )
                    self._pads.append(pad)
            self.set_pad_translations(tuple(self._pads))

    def _load_MIDI_map(self):
        is_momentary = True
        # SCENELAUNCH Buttons
        for scene_id in range(MATRIX_DEPTH):
            if (SCENELAUNCH[scene_id] == -1):
                button = None
            else:
                button = ButtonElement(is_momentary,
                                       SCENELAUNCH_TYPE[scene_id],
                                       SCENELAUNCH_CH[scene_id],
                                       SCENELAUNCH[scene_id])
                button.name = 'Scene_' + str(scene_id)
            self._note_map_scenes.append(button)
        # BUTTON_VECTOR Buttons
        for button_id in range(NUMBER_BUTTONS):
            if (BUTTON_VECTOR[button_id] == -1):
                button = None
            else:
                button = ButtonElement(is_momentary,
                                       BUTTON_VECTOR_TYPE[button_id],
                                       BUTTON_VECTOR_CH[button_id],
                                       BUTTON_VECTOR[button_id])
                button.name = 'Global_Button_' + str(button_id)
            self._note_map_buttons.append(button)
        # SLIDER_VECTOR Sliders
        for slider_id in range(NUMBER_SLIDERS):
            if (SLIDER_VECTOR[slider_id] == -1):
                control = None
            else:
                control = SliderElement(MIDI_CC_TYPE,
                                        SLIDER_VECTOR_CH[slider_id],
                                        SLIDER_VECTOR[slider_id])
                control.name = 'Global_Slider_' + str(slider_id)
            self._ctrl_map_sliders.append(control)
        # TRACKSTOP Buttons
        for track_id in range(TRACK_NUMBER):
            if (TRACKSTOP[track_id] == -1):
                button = None
            else:
                button = ButtonElement(is_momentary, TRACKSTOP_TYPE[track_id],
                                       TRACKSTOP_CH[track_id],
                                       TRACKSTOP[track_id])
                button.name = 'Trk_Stop_Button_' + str(track_id)
            self._note_map_trk_stop_buttons.append(button)
        # TRACKSEL Buttons
        for track_id in range(TRACK_NUMBER):
            if (TRACKSEL[track_id] == -1):
                button = None
            else:
                button = ButtonElement(is_momentary, TRACKSEL_TYPE[track_id],
                                       TRACKSEL_CH[track_id],
                                       TRACKSEL[track_id])
                button.name = 'Trk_Sel_Button_' + str(track_id)
            self._note_map_trk_sel_buttons.append(button)
        # TRACKMUTE Buttons
        for track_id in range(TRACK_NUMBER):
            if (TRACKMUTE[track_id] == -1):
                button = None
            else:
                button = ButtonElement(is_momentary, TRACKMUTE_TYPE[track_id],
                                       TRACKMUTE_CH[track_id],
                                       TRACKMUTE[track_id])
                button.name = 'Trk_Mute_Button_' + str(track_id)
            self._note_map_trk_mute_buttons.append(button)
        # TRACKSOLO Buttons
        for track_id in range(TRACK_NUMBER):
            if (TRACKSOLO[track_id] == -1):
                button = None
            else:
                button = ButtonElement(is_momentary, TRACKSOLO_TYPE[track_id],
                                       TRACKSOLO_CH[track_id],
                                       TRACKSOLO[track_id])
                button.name = 'Trk_Solo_Button_' + str(track_id)
            self._note_map_trk_solo_buttons.append(button)
        # TRACKREC Buttons
        for track_id in range(TRACK_NUMBER):
            if (TRACKREC[track_id] == -1):
                button = None
            else:
                button = ButtonElement(is_momentary, TRACKREC_TYPE[track_id],
                                       TRACKREC_CH[track_id],
                                       TRACKREC[track_id])
                button.name = 'Trk_Rec_Button_' + str(track_id)
            self._note_map_trk_rec_buttons.append(button)
        # TRACKVOL Sliders
        for track_id in range(TRACK_NUMBER):
            if (TRACKVOL[track_id] == -1):
                control = None
            else:
                control = SliderElement(MIDI_CC_TYPE, TRACKVOL_CH[track_id],
                                        TRACKVOL[track_id])
                control.name = 'Trk_Vol_Slider_' + str(track_id)
            self._ctrl_map_trk_volume.append(control)
        # TRACKPAN Sliders
        for track_id in range(TRACK_NUMBER):
            if (TRACKPAN[track_id] == -1):
                control = None
            else:
                control = SliderElement(MIDI_CC_TYPE, TRACKPAN_CH[track_id],
                                        TRACKPAN[track_id])
                control.name = 'Trk_Pan_Slider_' + str(track_id)
            self._ctrl_map_trk_pan.append(control)
        # TRACKSENDA Sliders
        for track_id in range(TRACK_NUMBER):
            if (TRACKSENDA[track_id] == -1):
                control = None
            else:
                control = SliderElement(MIDI_CC_TYPE, TRACKSENDA_CH[track_id],
                                        TRACKSENDA[track_id])
                control.name = 'Trk_SendA_Slider_' + str(track_id)
            self._ctrl_map_senda.append(control)
        # TRACKSENDB Sliders
        for track_id in range(TRACK_NUMBER):
            if (TRACKSENDB[track_id] == -1):
                control = None
            else:
                control = SliderElement(MIDI_CC_TYPE, TRACKSENDB_CH[track_id],
                                        TRACKSENDB[track_id])
                control.name = 'Trk_SendB_Slider_' + str(track_id)
            self._ctrl_map_sendb.append(control)
        # TRACKSENDC Sliders
        for track_id in range(TRACK_NUMBER):
            if (TRACKSENDC[track_id] == -1):
                control = None
            else:
                control = SliderElement(MIDI_CC_TYPE, TRACKSENDC_CH[track_id],
                                        TRACKSENDC[track_id])
                control.name = 'Trk_SendC_Slider_' + str(track_id)
            self._ctrl_map_sendc.append(control)
        # DEVICEBANK Buttons
        for bank_id in range(BANKS_NUMBER):
            if (DEVICEBANK[bank_id] == -1):
                button = None
            else:
                button = ButtonElement(is_momentary, DEVICEBANK_TYPE[bank_id],
                                       DEVICEBANK_CH[bank_id],
                                       DEVICEBANK[bank_id])
                button.name = 'Bank_Button_' + str(bank_id)
            self._note_map_bank_buttons.append(button)
        # PARAMCONTROL Sliders
        for param_id in range(PARAMS_NUMBER):
            if (PARAMCONTROL[param_id] == -1):
                control = None
            else:
                control = SliderElement(MIDI_CC_TYPE,
                                        PARAMCONTROL_CH[param_id],
                                        PARAMCONTROL[param_id])
                control.name = 'Slider_Param_' + str(param_id)
            self._ctrl_map_parameter.append(control)
class Midi_Fighter_Twister(ControlSurface):
    __doc__ = " Script for Midi_Fighter_Twister in APC emulation mode "

    _active_instances = []

    def _combine_active_instances():
        track_offset = 0
        scene_offset = 0
        for instance in Midi_Fighter_Twister._active_instances:
            instance._activate_combination_mode(track_offset, scene_offset)
            track_offset += instance._session.width()

    _combine_active_instances = staticmethod(_combine_active_instances)

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        #self.set_suppress_rebuild_requests(True)
        with self.component_guard():
            self._note_map = []
            self._ctrl_map = []
            self._shift_encoder_map = []
            self._shift_bank_map = []
            self._load_MIDI_map()
            self._session = None
            self._session_zoom = None
            self._mixer = None
            self._setup_session_control()
            self._setup_mixer_control()
            self._session.set_mixer(self._mixer)
            self._setup_device_and_transport_control()
            self.set_highlighting_session_component(self._session)
            #self.set_suppress_rebuild_requests(False)
        self._pads = []
        self._load_pad_translations()
        self._do_combine()

    def disconnect(self):
        self._note_map = None
        self._ctrl_map = None
        self._shift_encoder_map = None
        self._shift_bank_map = None
        self._pads = None
        self._do_uncombine()
        self._shift_button = None
        self._session = None
        self._session_zoom = None
        self._mixer = None
        self._device = None
        ControlSurface.disconnect(self)

    def _do_combine(self):
        if self not in Midi_Fighter_Twister._active_instances:
            Midi_Fighter_Twister._active_instances.append(self)
            Midi_Fighter_Twister._combine_active_instances()

    def _do_uncombine(self):
        if ((self in Midi_Fighter_Twister._active_instances)
                and Midi_Fighter_Twister._active_instances.remove(self)):
            self._session.unlink()
            Midi_Fighter_Twister._combine_active_instances()

    def _activate_combination_mode(self, track_offset, scene_offset):
        if TRACK_OFFSET != -1:
            track_offset = TRACK_OFFSET
        if SCENE_OFFSET != -1:
            scene_offset = SCENE_OFFSET
        self._session.link_with_track_offset(track_offset, scene_offset)

    def _setup_session_control(self):
        is_momentary = True
        # sessionRight = ButtonElement(is_momentary, 1, 3, 11)
        # sessionLeft = ButtonElement(is_momentary, 1, 3, 8)
        self._session = SpecialSessionComponent(4, 4)
        self._session.name = 'Session_Control'
        self._session.set_track_bank_buttons(
            self._shift_bank_map[SESSIONRIGHT],
            self._shift_bank_map[SESSIONLEFT])
        # self._session.set_track_bank_buttons(sessionRight, sessionLeft)
        self._session.set_scene_bank_buttons(self._note_map[SESSIONDOWN],
                                             self._note_map[SESSIONUP])
        self._session.set_select_buttons(self._note_map[SCENEDN],
                                         self._note_map[SCENEUP])
        self._scene_launch_buttons = [
            self._note_map[SCENELAUNCH[index]] for index in range(4)
        ]
        self._track_stop_buttons = [
            self._note_map[TRACKSTOP[index]] for index in range(4)
        ]
        self._session.set_stop_all_clips_button(self._note_map[STOPALLCLIPS])
        self._session.set_stop_track_clip_buttons(
            tuple(self._track_stop_buttons))
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(
            self._note_map[SELSCENELAUNCH])
        self._session.set_slot_launch_button(self._note_map[SELCLIPLAUNCH])
        for scene_index in range(4):
            scene = self._session.scene(scene_index)
            scene.name = 'Scene_' + str(scene_index)
            button_row = []
            scene.set_launch_button(self._scene_launch_buttons[scene_index])
            scene.set_triggered_value(2)
            for track_index in range(4):
                button = self._note_map[CLIPNOTEMAP[scene_index][track_index]]
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                    scene_index)
                clip_slot.set_launch_button(button)
        self._session_zoom = SpecialZoomingComponent(self._session)
        self._session_zoom.name = 'Session_Overview'
        self._session_zoom.set_nav_buttons(self._note_map[ZOOMUP],
                                           self._note_map[ZOOMDOWN],
                                           self._note_map[ZOOMLEFT],
                                           self._note_map[ZOOMRIGHT])

    def _setup_mixer_control(self):
        is_momentary = True
        MasterVol = ButtonElement(is_momentary, 1, 4, 3)
        self._mixer = SpecialMixerComponent(4)
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.master_strip().set_select_button(self._note_map[MASTERSEL])
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.set_select_buttons(self._note_map[TRACKRIGHT],
                                       self._note_map[TRACKLEFT])
        self._mixer.set_crossfader_control(self._ctrl_map[CROSSFADER])
        self._mixer.set_prehear_volume_control(self._ctrl_map[CUELEVEL])
        self._mixer.master_strip().set_volume_control(
            self._shift_encoder_map[MASTERVOLUME])
        for track in range(4):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            strip.set_arm_button(self._note_map[TRACKREC[track]])
            strip.set_solo_button(self._note_map[TRACKSOLO[track]])
            strip.set_mute_button(self._note_map[TRACKMUTE[track]])
            strip.set_select_button(self._note_map[TRACKSEL[track]])
            strip.set_volume_control(self._ctrl_map[TRACKVOL[track]])
            strip.set_pan_control(self._ctrl_map[TRACKPAN[track]])
            strip.set_send_controls((self._ctrl_map[TRACKSENDA[track]],
                                     self._ctrl_map[TRACKSENDB[track]],
                                     self._ctrl_map[TRACKSENDC[track]]))
            strip.set_invert_mute_feedback(True)

# have right side btns act as device next/prev & toggle on/off?

    def _setup_device_and_transport_control(self):
        is_momentary = True
        # self._device = DeviceComponent()
        # self._device.name = 'Device_Component'
        # uses BestBankDeviceComponent as pseudo for Device_Component
        self._device = BestBankDeviceComponent(
            device_selection_follows_track_selection=True)
        self._device.name = u'Device_Component'
        # device_bank_buttons = []
        device_param_controls = []
        # Accounts for mappings on top two rows of MFT
        for index in range(16):  # handles all 16 encoder knobs
            device_param_controls.append(self._ctrl_map[PARAMCONTROL[index]])
        for index in range(4):  # 1st row, shift encoder hold
            device_param_controls.append(
                self._shift_encoder_map[PARAMCONTROL[index]])
        for index in range(6):  # 2nd row & left-half of 3rd row, CC hold
            device_param_controls.append(self._note_map[PARAMCONTROL[index +
                                                                     4]])
        #  Accounts for mappings on third row of MFT
        # for index in range(4):
        #     device_param_controls.append(self._shift_encoder_map[PARAMCONTROL[index + 8]])
        #     device_bank_buttons.append(self._note_map[DEVICEBANK[index]])
        # if None not in device_bank_buttons:
        #     self._device.set_bank_buttons(tuple(device_bank_buttons))
        if None not in device_param_controls:
            self._device.set_parameter_controls(tuple(device_param_controls))
        self._device.set_on_off_button(self._shift_bank_map[DEVICEONOFF])
        # self._device.set_bank_nav_buttons(self._shift_bank_map[DEVICEBANKNAVLEFT], self._shift_bank_map[DEVICEBANKNAVRIGHT])
        self._device.set_bank_nav_buttons(self._note_map[DEVICEBANKNAVLEFT],
                                          self._note_map[DEVICEBANKNAVRIGHT])
        self._device.set_lock_button(self._note_map[DEVICELOCK])
        self.set_device_component(self._device)

        detail_view_toggler = DetailViewControllerComponent()
        detail_view_toggler.name = 'Detail_View_Control'
        detail_view_toggler.set_device_clip_toggle_button(
            self._shift_bank_map[CLIPTRACKVIEW])
        detail_view_toggler.set_detail_toggle_button(
            self._shift_bank_map[DETAILVIEW])
        # detail_view_toggler.set_device_nav_buttons(self._note_map[DEVICENAVLEFT], self._note_map[DEVICENAVRIGHT] )
        detail_view_toggler.set_device_nav_buttons(
            self._shift_bank_map[DEVICENAVLEFT],
            self._shift_bank_map[DEVICENAVRIGHT])

        transport = SpecialTransportComponent()
        transport.name = 'Transport'
        transport.set_play_button(self._note_map[PLAY])
        transport.set_stop_button(self._note_map[STOP])
        transport.set_record_button(self._note_map[REC])
        transport.set_nudge_buttons(self._note_map[NUDGEUP],
                                    self._note_map[NUDGEDOWN])
        transport.set_undo_button(self._shift_bank_map[UNDO])
        transport.set_redo_button(self._note_map[REDO])
        transport.set_tap_tempo_button(self._note_map[TAPTEMPO])
        transport.set_quant_toggle_button(self._note_map[RECQUANT])
        transport.set_overdub_button(self._note_map[OVERDUB])
        transport.set_metronome_button(self._note_map[METRONOME])
        transport.set_tempo_control(self._ctrl_map[TEMPOCONTROL])
        transport.set_loop_button(self._note_map[LOOP])
        transport.set_seek_buttons(self._note_map[SEEKFWD],
                                   self._note_map[SEEKRWD])
        transport.set_punch_buttons(self._note_map[PUNCHIN],
                                    self._note_map[PUNCHOUT])
        ##transport.set_song_position_control(self._ctrl_map[SONGPOSITION]) #still not implemented as of Live 8.1.6

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        # From Axiom_AIR_25_49_61.py line 202
        track = self.song().view.selected_track
        device_to_select = track.view.selected_device
        if device_to_select == None and len(track.devices) > 0:
            device_to_select = track.devices[0]
        if device_to_select != None:
            self.song().view.select_device(device_to_select)
        self._device_component.set_device(device_to_select)

        # BEGIN update(self) FROM EncoderModeSelector.py
        #
        # todo: Move this block to a file where 'self._ctrl_map[PARAMCONTROL[index]]'
        # is accessible (MFT see line 164 for example)
        # if self.is_enabled():
        #     self._device.set_allow_update(False)
        # self._mixer.set_allow_update(False)
        # self._device.set_parameter_controls(())
        # self._mixer.set_send_controls(())
        # for index in range(len(self._encoders)):
        # strip = self._mixer.channel_strip(index)
        # encoder = self._encoders[index]
        # strip.set_volume_control(None)
        # strip.set_pan_control(None)
        # encoder.release_parameter()
        # if self._mode_index == 0:
        # strip.set_volume_control(encoder)
        #     encoder.set_on_off_values(AMB_FULL, LED_OFF)
        # elif self._mode_index == 1:
        #     strip.set_pan_control(encoder)
        #     encoder.set_on_off_values(RED_FULL, LED_OFF)
        # elif self._mode_index == 2:
        #     encoder.set_on_off_values(GRN_FULL, LED_OFF)
        # elif self._mode_index == 3:
        #     encoder.set_on_off_values(RED_FULL, LED_OFF)

        # if self._mode_index == 0:
        #     self._modes_buttons[0].send_value(AMB_FULL, True)
        #     self._modes_buttons[1].send_value(LED_OFF, True)
        # elif self._mode_index == 1:
        #     self._modes_buttons[0].send_value(RED_FULL, True)
        #     self._modes_buttons[1].send_value(LED_OFF, True)
        # elif self._mode_index == 2:
        #     self._modes_buttons[0].send_value(GRN_FULL, True)
        #     self._modes_buttons[1].send_value(LED_OFF, True)
        #     self._mixer.set_send_controls(self._encoders)
        # elif self._mode_index == 3:
        #     self._modes_buttons[0].send_value(LED_OFF, True)
        #     self._modes_buttons[1].send_value(RED_FULL, True)
        # self._device.set_parameter_controls(self._encoders)
        # self._device.set_allow_update(True)
        #
        # END update(self) FROM EncoderModeSelector.py

    def _load_pad_translations(self):
        if -1 not in DRUM_PADS:
            pad = []
            for row in range(4):
                for col in range(4):
                    pad = (
                        col,
                        row,
                        DRUM_PADS[row * 4 + col],
                        PADCHANNEL,
                    )
                    self._pads.append(pad)
            self.set_pad_translations(tuple(self._pads))

    def _load_MIDI_map(self):
        is_momentary = True
        for note in range(128):
            button = ButtonElement(is_momentary, MESSAGETYPE, BUTTONCHANNEL,
                                   note)
            button.name = 'Note_' + str(note)
            self._note_map.append(button)  # CC Hold, CC Toggle
            shift_bank_button = ButtonElement(is_momentary, MESSAGETYPE,
                                              SHIFTBANKCHANNEL, note)
            shift_bank_button.name = 'Note_' + str(note)
            self._shift_bank_map.append(shift_bank_button)  # Shift Bank
            shift_encoder = ButtonElement(is_momentary, 1, ENCODERSHIFTCHANNEL,
                                          note)
            shift_encoder.name = 'Note_' + str(note)
            self._shift_encoder_map.append(shift_encoder)  # Shift Encoder Hold
        self._note_map.append(
            None)  #add None to the end of the list, selectable with [-1]
        self._shift_encoder_map.append(None)
        self._shift_bank_map.append(None)
        if MESSAGETYPE == MIDI_CC_TYPE and BUTTONCHANNEL == SLIDERCHANNEL:
            for ctrl in range(128):
                self._ctrl_map.append(None)
        else:
            for ctrl in range(128):
                control = SliderElement(MIDI_CC_TYPE, SLIDERCHANNEL, ctrl)
                control.name = 'Ctrl_' + str(ctrl)
                self._ctrl_map.append(control)  # Standard Encoder
            self._ctrl_map.append(None)
    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(self, 8)
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                             80)
        master_select_button.name = 'Master_Select_Button'
        self._mixer.master_strip().set_select_button(master_select_button)
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        select_buttons = []
        arm_buttons = []
        solo_buttons = []
        mute_buttons = []
        sliders = []
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        49)
            solo_buttons.append(solo_button)
            mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        50)
            mute_buttons.append(mute_button)
            solo_button.name = str(track) + '_Solo_Button'
            mute_button.name = str(track) + '_Mute_Button'
            strip.set_solo_button(solo_button)
            strip.set_mute_button(mute_button)
            strip.set_shift_button(self._shift_button)
            strip.set_invert_mute_feedback(True)
            select_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51))
            select_buttons[-1].name = str(track) + '_Select_Button'
            arm_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48))
            arm_buttons[-1].name = str(track) + '_Arm_Button'
            sliders.append(SliderElement(MIDI_CC_TYPE, track, 7))
            sliders[-1].name = str(track) + '_Volume_Control'

        self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        self._prehear_control = EncoderElement(
            MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
        self._crossfader.name = 'Crossfader'
        master_volume_control.name = 'Master_Volume_Control'
        self._prehear_control.name = 'Prehear_Volume_Control'
        self._mixer.set_shift_button(self._shift_button)
        self._mixer.set_crossfader_control(self._crossfader)
        self._mixer.set_prehear_volume_control(self._prehear_control)
        self._mixer.master_strip().set_volume_control(master_volume_control)
        self._slider_modes = SliderModesComponent(self._mixer, tuple(sliders))
        self._slider_modes.name = 'Slider_Modes'
        self._matrix_modes = MatrixModesComponent(
            self._matrix, self._session, self._session_zoom,
            tuple(self._track_stop_buttons), self)
        self._matrix_modes.name = 'Matrix_Modes'
        self._sequencer = StepSequencerComponent(
            self, self._session, self._matrix, tuple(self._track_stop_buttons))
        self._sequencer.set_bank_buttons(tuple(select_buttons))
        self._sequencer.set_nav_buttons(self._up_button, self._down_button,
                                        self._left_button, self._right_button)
        self._sequencer.set_button_matrix(self._matrix)
        self._sequencer.set_follow_button(master_select_button)
        self._sequencer.set_velocity_buttons(tuple(arm_buttons))
        self._sequencer.set_shift_button(self._shift_button)
        self._sequencer.set_lane_mute_buttons(tuple(
            self._scene_launch_buttons))
        self._sequencer.set_loop_start_buttons(tuple(mute_buttons))
        self._sequencer.set_loop_length_buttons(tuple(solo_buttons))
        self._shift_modes = ShiftableSelectorComponent(
            self, tuple(select_buttons), master_select_button,
            tuple(self._track_stop_buttons), self._stop_all_button,
            tuple(mute_buttons), tuple(solo_buttons), tuple(arm_buttons),
            tuple(self._scene_launch_buttons), self._matrix, self._session,
            self._session_zoom, self._mixer, self._slider_modes,
            self._matrix_modes, self._sequencer)
        self._shift_modes.name = 'Shift_Modes'
        self._shift_modes.set_mode_toggle(self._shift_button)
class Novation_Impulse(ControlSurface):
    """ Script for Novation's Impulse keyboards """

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = 'Impulse'
            self._suggested_output_port = 'Impulse'
            self._has_sliders = True
            self._current_midi_map = None
            self._display_reset_delay = -1
            self._shift_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 39)
            self._preview_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 41)
            self._master_slider = SliderElement(MIDI_CC_TYPE, 0, 8)
            self._shift_button.name = 'Shift_Button'
            self._master_slider.name = 'Master_Volume_Control'
            self._master_slider.add_value_listener(self._slider_value, identify_sender=True)
            self._preview_button.add_value_listener(self._preview_value)
            self._setup_mixer()
            self._setup_session()
            self._setup_transport()
            self._setup_device()
            self._setup_name_display()
            device_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1, 10)
            mixer_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1, 9)
            device_button.name = 'Encoder_Device_Mode'
            mixer_button.name = 'Encoder_Mixer_Mode'
            self._encoder_modes = EncoderModeSelector(self._device_component, self._mixer, self._next_bank_button, self._prev_bank_button, self._encoders)
            self._encoder_modes.set_device_mixer_buttons(device_button, mixer_button)
            self._string_to_display = None
            for component in self.components:
                component.set_enabled(False)

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self.schedule_message(3, self._send_midi, SYSEX_START + (6, 1, 1, 1, 247))

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:-2] == SYSEX_START + (7,) and midi_bytes[-2] != 0:
            self._has_sliders = midi_bytes[-2] != 25
            self.schedule_message(1, self._show_startup_message)
            for control in self.controls:
                if isinstance(control, InputControlElement):
                    control.clear_send_cache()

            for component in self.components:
                component.set_enabled(True)

            if self._has_sliders:
                self._mixer.master_strip().set_volume_control(self._master_slider)
                self._mixer.update()
            else:
                self._mixer.master_strip().set_volume_control(None)
                self._mixer.selected_strip().set_volume_control(self._master_slider)
                for index in range(len(self._sliders)):
                    self._mixer.channel_strip(index).set_volume_control(None)
                    slider = self._sliders[index]
                    slider.release_parameter()
                    if slider.value_has_listener(self._slider_value):
                        slider.remove_value_listener(self._slider_value)

            self._encoder_modes.set_provide_volume_mode(not self._has_sliders)
            self.request_rebuild_midi_map()

    def disconnect(self):
        self._name_display_data_source.set_display_string('  ')
        for encoder in self._encoders:
            encoder.remove_value_listener(self._encoder_value)

        self._master_slider.remove_value_listener(self._slider_value)
        if self._has_sliders:
            for slider in tuple(self._sliders):
                slider.remove_value_listener(self._slider_value)

        for button in self._strip_buttons:
            button.remove_value_listener(self._mixer_button_value)

        self._preview_button.remove_value_listener(self._preview_value)
        ControlSurface.disconnect(self)
        self._encoders = None
        self._sliders = None
        self._strip_buttons = None
        self._master_slider = None
        self._current_midi_map = None
        self._shift_button = None
        self._name_display = None
        self._prev_bank_button = None
        self._next_bank_button = None
        self._encoder_modes = None
        self._transport_view_modes = None
        self._send_midi(SYSEX_START + (6, 0, 0, 0, 247))

    def build_midi_map(self, midi_map_handle):
        self._current_midi_map = midi_map_handle
        ControlSurface.build_midi_map(self, midi_map_handle)

    def update_display(self):
        ControlSurface.update_display(self)
        if self._string_to_display != None:
            self._name_display_data_source.set_display_string(self._string_to_display)
            self._string_to_display = None
        if self._display_reset_delay >= 0:
            self._display_reset_delay -= 1
            if self._display_reset_delay == -1:
                self._show_current_track_name()

    def _setup_mixer(self):
        mute_solo_flip_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 34)
        self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 37)
        self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 38)
        self._strip_buttons = []
        mute_solo_flip_button.name = 'Mute_Solo_Flip_Button'
        self._next_nav_button.name = 'Next_Track_Button'
        self._prev_nav_button.name = 'Prev_Track_Button'
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button)
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.master_strip().set_volume_control(self._master_slider)
        self._sliders = []
        for index in range(8):
            strip = self._mixer.channel_strip(index)
            strip.name = 'Channel_Strip_' + str(index)
            strip.set_invert_mute_feedback(True)
            self._sliders.append(SliderElement(MIDI_CC_TYPE, 0, index))
            self._sliders[-1].name = str(index) + '_Volume_Control'
            self._sliders[-1].set_feedback_delay(-1)
            self._sliders[-1].add_value_listener(self._slider_value, identify_sender=True)
            strip.set_volume_control(self._sliders[-1])
            self._strip_buttons.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + index))
            self._strip_buttons[-1].name = str(index) + '_Mute_Button'
            self._strip_buttons[-1].add_value_listener(self._mixer_button_value, identify_sender=True)

        self._mixer.master_strip().set_mute_button(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 17))
        self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)

    def _setup_session(self):
        num_pads = len(PAD_TRANSLATIONS)
        self._track_left_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 36)
        self._track_right_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 35)
        self._session = SessionComponent(8, 0)
        self._session.name = 'Session_Control'
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.set_mixer(self._mixer)
        self._session.set_page_left_button(self._track_left_button)
        self._session.set_page_right_button(self._track_right_button)
        pads = []
        for index in range(num_pads):
            pads.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 60 + index))
            pads[-1].name = 'Pad_' + str(index)
            clip_slot = self._session.selected_scene().clip_slot(index)
            clip_slot.set_triggered_to_play_value(GREEN_BLINK)
            clip_slot.set_triggered_to_record_value(RED_BLINK)
            clip_slot.set_stopped_value(AMBER_FULL)
            clip_slot.set_started_value(GREEN_FULL)
            clip_slot.set_recording_value(RED_FULL)
            clip_slot.set_launch_button(pads[-1])
            clip_slot.name = str(index) + '_Selected_Clip_Slot'

    def _setup_transport(self):
        rwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 27)
        ffwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 28)
        stop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 29)
        play_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 30)
        loop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 31)
        rec_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 32)
        ffwd_button.name = 'FFwd_Button'
        rwd_button.name = 'Rwd_Button'
        loop_button.name = 'Loop_Button'
        play_button.name = 'Play_Button'
        stop_button.name = 'Stop_Button'
        rec_button.name = 'Record_Button'
        transport = ShiftableTransportComponent()
        transport.name = 'Transport'
        transport.set_stop_button(stop_button)
        transport.set_play_button(play_button)
        transport.set_record_button(rec_button)
        transport.set_shift_button(self._shift_button)
        self._transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button, loop_button)
        self._transport_view_modes.name = 'Transport_View_Modes'

    def _setup_device(self):
        encoders = []
        for index in range(8):
            encoders.append(PeekableEncoderElement(MIDI_CC_TYPE, 1, index, Live.MidiMap.MapMode.relative_binary_offset))
            encoders[-1].set_feedback_delay(-1)
            encoders[-1].add_value_listener(self._encoder_value, identify_sender=True)
            encoders[-1].name = 'Device_Control_' + str(index)

        self._encoders = tuple(encoders)
        self._prev_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 12)
        self._next_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 11)
        self._prev_bank_button.name = 'Device_Bank_Down_Button'
        self._next_bank_button.name = 'Device_Bank_Up_Button'
        device = DeviceComponent()
        device.name = 'Device_Component'
        self.set_device_component(device)
        device.set_parameter_controls(self._encoders)
        device.set_bank_nav_buttons(self._prev_bank_button, self._next_bank_button)

    def _setup_name_display(self):
        self._name_display = PhysicalDisplayElement(16, 1)
        self._name_display.name = 'Display'
        self._name_display.set_message_parts(SYSEX_START + (8,), (247,))
        self._name_display_data_source = DisplayDataSource()
        self._name_display.segment(0).set_data_source(self._name_display_data_source)

    def _encoder_value(self, value, sender):
        if not sender in self._encoders:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                display_string = self._device_component.is_enabled() and ' - '
                display_string = sender.mapped_parameter() != None and sender.mapped_parameter().name
            self._set_string_to_display(display_string)

    def _slider_value(self, value, sender):
        if not sender in tuple(self._sliders) + (self._master_slider,):
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                if self._mixer.is_enabled():
                    display_string = ' - '
                    if sender.mapped_parameter() != None:
                        master = self.song().master_track
                        tracks = self.song().tracks
                        returns = self.song().return_tracks
                        track = None
                        if sender == self._master_slider:
                            track = self._has_sliders and master
                        else:
                            track = self.song().view.selected_track
                    else:
                        track = self._mixer.channel_strip(self._sliders.index(sender))._track
                    display_string = track == master and 'Master'
                elif track in tracks:
                    display_string = str(list(tracks).index(track) + 1)
                elif track in returns:
                    display_string = str(chr(ord('A') + list(returns).index(track)))
                else:
                    raise False or AssertionError
                display_string += ' Volume'
            self._set_string_to_display(display_string)

    def _mixer_button_value(self, value, sender):
        if not value in range(128):
            raise AssertionError
            if self._mixer.is_enabled() and value > 0:
                strip = self._mixer.channel_strip(self._strip_buttons.index(sender))
                self._string_to_display = strip != None and None
                self._name_display.segment(0).set_data_source(strip.track_name_data_source())
                self._name_display.update()
                self._display_reset_delay = STANDARD_DISPLAY_DELAY
            else:
                self._set_string_to_display(' - ')

    def _preview_value(self, value):
        raise value in range(128) or AssertionError
        for encoder in self._encoders:
            encoder.set_peek_mode(value > 0)

    def _show_current_track_name(self):
        if self._name_display != None and self._mixer != None:
            self._string_to_display = None
            self._name_display.segment(0).set_data_source(self._mixer.selected_strip().track_name_data_source())
            self._name_display.update()

    def _show_startup_message(self):
        self._name_display.display_message('LIVE')
        self._display_reset_delay = INITIAL_DISPLAY_DELAY

    def _set_string_to_display(self, string_to_display):
        raise isinstance(string_to_display, (str, unicode)) or AssertionError
        self._name_display.segment(0).set_data_source(self._name_display_data_source)
        self._string_to_display = string_to_display
        self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._show_current_track_name()
        all_tracks = self._has_sliders or self._session.tracks_to_use()
        selected_track = self.song().view.selected_track
        num_strips = self._session.width()
        if selected_track in all_tracks:
            track_index = list(all_tracks).index(selected_track)
            new_offset = track_index - track_index % num_strips
            if not new_offset / num_strips == int(new_offset / num_strips):
                raise AssertionError
                self._session.set_offsets(new_offset, self._session.scene_offset())
Example #29
0
class SubSelectorComponent(ModeSelectorComponent):
    """ Class that handles different mixer modes """
    def __init__(self, matrix, side_buttons, session, control_surface):
        assert isinstance(matrix, ButtonMatrixElement)
        assert ((matrix.width() == 8) and (matrix.height() == 8))
        assert isinstance(side_buttons, tuple)
        assert (len(side_buttons) == 8)
        assert isinstance(session, SessionComponent)
        ModeSelectorComponent.__init__(self)
        self._control_surface = control_surface
        self._session = session
        self._mixer = SpecialMixerComponent(matrix.width())
        self._matrix = matrix
        self._sliders = []
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_strip'
        self._mixer.selected_strip().name = 'Selected_Channel_strip'
        for column in range(matrix.width()):
            self._mixer.channel_strip(
                column).name = 'Channel_Strip_' + str(column)
            self._sliders.append(
                PreciseButtonSliderElement(
                    tuple([
                        matrix.get_button(column, 7 - row) for row in range(8)
                    ])))
            self._sliders[-1].name = 'Button_Slider_' + str(column)

        self._side_buttons = side_buttons[4:]
        self._update_callback = None
        self._session.set_mixer(self._mixer)
        self.set_modes_buttons(side_buttons[:4])

    def disconnect(self):
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)

        self._session = None
        self._mixer = None
        for slider in self._sliders:
            slider.release_parameter()
            slider.set_disabled(True)

        self._sliders = None
        self._matrix = None
        self._side_buttons = None
        self._update_callback = None
        ModeSelectorComponent.disconnect(self)

    def set_update_callback(self, callback):
        assert (dir(callback).count("im_func") is 1)
        self._update_callback = callback

    def set_modes_buttons(self, buttons):
        assert ((buttons == None)
                or (isinstance(buttons, tuple) or
                    (len(buttons) == self.number_of_modes())))
        identify_sender = True
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)

        self._modes_buttons = []
        if buttons != None:
            for button in buttons:
                assert isinstance(button, ButtonElement)
                self._modes_buttons.append(button)
                button.add_value_listener(self._mode_value, identify_sender)

    def set_mode(self, mode):
        assert isinstance(mode, int)
        assert (mode in range(-1, self.number_of_modes()))
        if ((self._mode_index != mode) or (mode == -1)):
            self._mode_index = mode
            self.update()

    def mode(self):
        result = 0
        if self.is_enabled():
            result = self._mode_index + 1
        return result

    def number_of_modes(self):
        return 4

    def on_enabled_changed(self):
        enabled = self.is_enabled()
        for index in range(self._matrix.width()):
            self._sliders[index].set_disabled(not enabled)

        self._mixer.set_enabled(enabled)
        self.set_mode(-1)

    def release_controls(self):
        for track in range(self._matrix.width()):
            for row in range(self._matrix.height()):
                self._matrix.get_button(track, row).set_on_off_values(
                    127, "DefaultButton.Disabled")

            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_send_controls((None, None))
            strip.set_pan_control(None)
            strip.set_volume_control(None)

        self._session.set_stop_track_clip_buttons(None)
        self._mixer.set_global_buttons(None, None, None)
        self._session.set_stop_all_clips_button(None)

    def update(self):
        assert (self._modes_buttons != None)
        if self.is_enabled():
            if (self._modes_buttons != None):
                for index in range(len(self._modes_buttons)):
                    button = self._modes_buttons[index]
                    if index == 0:
                        button.set_on_off_values("Mixer.Volume")
                    elif index == 1:
                        button.set_on_off_values("Mixer.Pan")
                    elif index == 2:
                        button.set_on_off_values("Mixer.Sends")
                    elif index == 3:
                        button.set_on_off_values("Mixer.Sends")
                    elif index == 4:
                        button.set_on_off_values("Mixer.Stop")
                    elif index == 5:
                        button.set_on_off_values("Mixer.Mute")
                    elif index == 6:
                        button.set_on_off_values("Mixer.Solo")
                    elif index == 7:
                        button.set_on_off_values("Mixer.Arm")
                    if (index == self._mode_index):
                        button.turn_on()
                    else:
                        button.turn_off()

            for button in self._side_buttons:
                button.set_on_off_values(127, "DefaultButton.Disabled")
                button.turn_off()

            for index in range(self._matrix.width()):
                self._sliders[index].set_disabled((self._mode_index == -1))

            self._mixer.set_allow_update(False)
            self._session.set_allow_update(False)
            if self._mode_index == -1:
                self._setup_mixer_overview()
            elif self._mode_index == 0:
                self._setup_volume_mode()
            elif self._mode_index == 1:
                self._setup_pan_mode()
            elif self._mode_index == 2:
                self._setup_send1_mode()
            elif self._mode_index == 3:
                self._setup_send2_mode()
            else:
                assert False
            if (self._update_callback != None):
                self._update_callback()
            self._mixer.set_allow_update(True)
            self._session.set_allow_update(True)
        #else:
        #self.release_controls()

    def _setup_mixer_overview(self):
        stop_buttons = []
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_send_controls((None, None))
            strip.set_pan_control(None)
            strip.set_volume_control(None)
            self._sliders[track].release_parameter()
            for row in range(self._matrix.height()):
                if row == 0:
                    self._matrix.get_button(
                        track, row).set_on_off_values("Mixer.Volume")
                elif row == 1:
                    self._matrix.get_button(track,
                                            row).set_on_off_values("Mixer.Pan")
                elif row == 2:
                    self._matrix.get_button(
                        track, row).set_on_off_values("Mixer.Sends")
                elif row == 3:
                    self._matrix.get_button(
                        track, row).set_on_off_values("Mixer.Sends")
                elif row == 4:
                    self._matrix.get_button(
                        track, row).set_on_off_values("Mixer.Stop")
                elif row == 5:
                    self._matrix.get_button(
                        track, row).set_on_off_values("Mixer.Mute")
                elif row == 6:
                    self._matrix.get_button(
                        track, row).set_on_off_values("Mixer.Solo")
                elif row == 7:
                    self._matrix.get_button(track,
                                            row).set_on_off_values("Mixer.Arm")

            strip.set_default_buttons(self._matrix.get_button(track, 0),
                                      self._matrix.get_button(track, 1),
                                      self._matrix.get_button(track, 2),
                                      self._matrix.get_button(track, 3))
            stop_buttons.append(self._matrix.get_button(track, 4))
            strip.set_mute_button(self._matrix.get_button(track, 5))
            strip.set_solo_button(self._matrix.get_button(track, 6))
            strip.set_arm_button(self._matrix.get_button(track, 7))

        for button in self._side_buttons:
            if row == 0:
                button.set_on_off_values("Mixer.Volume")
            elif row == 1:
                button.set_on_off_values("Mixer.Pan")
            elif row == 2:
                button.set_on_off_values("Mixer.Sends")
            elif row == 3:
                button.set_on_off_values("Mixer.Sends")
            elif row == 4:
                button.set_on_off_values("Mixer.Stop")
            elif row == 5:
                button.set_on_off_values("Mixer.Mute")
            elif row == 6:
                button.set_on_off_values("Mixer.Solo")
            elif row == 7:
                button.set_on_off_values("Mixer.Arm")
            button.force_next_send()
            button.turn_on()

        self._session.set_stop_track_clip_buttons(tuple(stop_buttons))
        self._session.set_stop_all_clips_button(self._side_buttons[0])
        self._mixer.set_global_buttons(self._side_buttons[3],
                                       self._side_buttons[2],
                                       self._side_buttons[1])

    def _setup_volume_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_send_controls((None, None))
            strip.set_pan_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(
                    track, row).set_on_off_values("Mixer.VolumeSlider")

            self._sliders[track].set_mode(SLIDER_MODE_VOLUME)
            self._sliders[track].set_value_map(VOL_VALUE_MAP)
            strip.set_volume_control(self._sliders[track])

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)

    def _setup_pan_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_send_controls((None, None))
            strip.set_volume_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(
                    track, row).set_on_off_values("Mixer.PanSlider")

            self._sliders[track].set_mode(SLIDER_MODE_PAN)
            self._sliders[track].set_value_map(PAN_VALUE_MAP)
            strip.set_pan_control(self._sliders[track])

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)

    def _setup_send1_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_volume_control(None)
            strip.set_pan_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(
                    track, row).set_on_off_values("Mixer.SendsSlider")

            self._sliders[track].set_mode(SLIDER_MODE_VOLUME)
            self._sliders[track].set_value_map(SEND_VALUE_MAP)
            strip.set_send_controls((self._sliders[track], None))

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)

    def _setup_send2_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_volume_control(None)
            strip.set_pan_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(
                    track, row).set_on_off_values("Mixer.SendsSlider")

            self._sliders[track].set_mode(SLIDER_MODE_VOLUME)
            self._sliders[track].set_value_map(SEND_VALUE_MAP)
            strip.set_send_controls((None, self._sliders[track]))

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)
Example #30
0
class LaunchControl(ControlSurface):

    def __init__(self, c_instance):
        super(LaunchControl, self).__init__(c_instance)
        with self.component_guard():
            self._device_selection_follows_track_selection = True
            self._init_mixer()
            self._init_session()
            self._init_device()
            self._init_modes()
            self._refresh_state_task = self._tasks.add(Task.sequence(Task.delay(3), Task.run(self._do_refresh_state)))
            self._refresh_state_task.kill()
        self.log_message('Launch Control script loaded')

    def disconnect(self):
        super(LaunchControl, self).disconnect()
        for channel in xrange(16):
            self._send_midi((CC_STATUS + channel, 0, 0))

    def refresh_state(self):
        self._refresh_state_task.restart()

    def _do_refresh_state(self):
        self._send_current_mode()
        self._update_hardware()
        self.schedule_message(3, super(LaunchControl, self).refresh_state)

    def _update_hardware(self):
        for channel in xrange(8, 11):
            self._send_midi(Sysex.make_automatic_flashing_message(channel))

    def _send_current_mode(self):
        try:
            self._send_midi(MODE_SYSEX_MAP[self._modes.selected_mode])
        except KeyError:
            pass

    def _init_mixer(self):
        make_button = partial(make_launch_control_button, channel=8)
        make_encoder = partial(make_launch_control_encoder, channel=8)
        bottom_encoders, top_encoders = make_all_encoders('Mixer', make_encoder)
        pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders]))
        sends_layer = Layer(sends_controls=ButtonMatrixElement(rows=[bottom_encoders, top_encoders]))
        modes_layer = Layer(pan_volume_button=make_button(114, 'Pan_Volume_Mode_Button'), sends_button=make_button(115, 'Sends_Mode_Button'))
        self._mixer = SpecialMixerComponent(8, modes_layer, pan_volume_layer, sends_layer)
        self._mixer.set_enabled(False)
        self._mixer.name = 'Mixer'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer_track_nav_layer = Layer(track_bank_left_button=make_button(116, 'Mixer_Track_Left_Button'), track_bank_right_button=make_button(117, 'Mixer_Track_Right_Button'))
        for index in xrange(8):
            strip = self._mixer.channel_strip(index)
            strip.name = 'Channel_Strip_' + str(index)
            strip.empty_color = Colors.LED_OFF
            strip.set_invert_mute_feedback(True)
            mute_button = make_button(pad_identifiers[index], 'Track_Mute_Button_' + str(index), is_pad=True)
            mute_button.set_on_off_values(Colors.AMBER_FULL, Colors.AMBER_THIRD)
            strip.set_mute_button(mute_button)

        self._on_selected_send_index.subject = self._mixer
        self._on_selected_mixer_mode.subject = self._mixer

    def _init_session(self):
        make_button = partial(make_launch_control_button, channel=9)
        make_encoder = partial(make_launch_control_encoder, channel=9)
        bottom_encoders, top_encoders = make_all_encoders('Session_Mixer', make_encoder)
        pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders]))
        self._session_mixer = SpecialMixerComponent(8, Layer(), pan_volume_layer, Layer())
        self._session_mixer.set_enabled(False)
        self._session_mixer.name = 'Session_Mixer'
        clip_launch_buttons = [ make_button(identifier, 'Clip_Launch_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ]
        self._session = SpecialSessionComponent(num_tracks=8, num_scenes=0, name='Session')
        self._session.set_enabled(False)
        self._session.set_mixer(self._session_mixer)
        self._session_layer = Layer(track_bank_left_button=make_button(116, 'Track_Bank_Left_Button'), track_bank_right_button=make_button(117, 'Track_Bank_Right_Button'), select_prev_button=make_button(114, 'Scene_Bank_Up_Button'), select_next_button=make_button(115, 'Scene_Bank_Down_Button'), clip_launch_buttons=ButtonMatrixElement(rows=[clip_launch_buttons]))
        scene = self._session.selected_scene()
        for index in range(8):
            clip_slot = scene.clip_slot(index)
            clip_slot.set_triggered_to_play_value(Colors.GREEN_BLINK)
            clip_slot.set_triggered_to_record_value(Colors.RED_BLINK)
            clip_slot.set_stopped_value(Colors.AMBER_FULL)
            clip_slot.set_started_value(Colors.GREEN_FULL)
            clip_slot.set_recording_value(Colors.RED_FULL)
            clip_slot.name = 'Selected_Clip_Slot_' + str(index)

        self._on_track_offset.subject = self._session

    def _init_device(self):
        make_button = partial(make_launch_control_button, channel=10)
        make_encoder = partial(make_launch_control_encoder, channel=10)
        bottom_encoders, top_encoders = make_all_encoders('Device', make_encoder)
        parameter_controls = top_encoders[:4] + bottom_encoders[:4]
        bank_buttons = [ make_button(identifier, 'Device_Bank_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ]
        for button in bank_buttons:
            button.set_on_off_values(Colors.LED_ON, Colors.LED_OFF)

        self._device_bank_registry = DeviceBankRegistry()
        self._device = DeviceComponent(device_bank_registry=self._device_bank_registry, name='Device')
        self._device.set_enabled(False)
        self._device.layer = Layer(parameter_controls=ButtonMatrixElement(rows=[parameter_controls]), bank_buttons=ButtonMatrixElement(rows=[bank_buttons]))
        self.set_device_component(self._device)
        self._device_navigation = DeviceNavigationComponent()
        self._device_navigation.set_enabled(False)
        self._device_navigation.name = 'Device_Navigation'
        self._device_navigation.layer = Layer(next_device_button=make_button(115, 'Next_Device_Button'), previous_device_button=make_button(114, 'Prev_Device_Button'))
        self._view_control = ViewControlComponent()
        self._view_control.set_enabled(False)
        self._view_control.name = 'View_Control'
        self._view_control.layer = Layer(next_track_button=make_button(117, 'Device_Next_Track_Button'), prev_track_button=make_button(116, 'Device_Prev_Track_Button'))

    def _init_modes(self):
        self._modes = ModesComponent(is_root=True)
        self._modes.add_mode('mixer', [partial(self._session.set_mixer, self._mixer),
         LayerMode(self._session, self._mixer_track_nav_layer),
         self._mixer,
         self._session,
         self._show_controlled_tracks_message])
        self._modes.add_mode('session', [partial(self._session.set_mixer, self._session_mixer),
         LayerMode(self._session, self._session_layer),
         self._session_mixer,
         self._session,
         self._show_controlled_tracks_message])
        self._modes.add_mode('device', [self._device, self._device_navigation, self._view_control])
        self._modes.add_mode('user', None)
        self._modes.selected_mode = 'mixer'
        self._modes.layer = Layer(mixer_button=ButtonSysexControl(Sysex.MIXER_MODE), session_button=ButtonSysexControl(Sysex.SESSION_MODE), device_button=ButtonSysexControl(Sysex.DEVICE_MODE))

    @subject_slot('offset')
    def _on_track_offset(self):
        self._show_controlled_tracks_message()

    @subject_slot('selected_send_index')
    def _on_selected_send_index(self, index):
        self._show_controlled_sends_message()

    @subject_slot('selected_mixer_mode')
    def _on_selected_mixer_mode(self, mode):
        if mode == 'sends':
            self._show_controlled_sends_message()
        else:
            self.show_message('Controlling Pan and Volume')

    def _show_controlled_tracks_message(self):
        start = self._session.track_offset() + 1
        end = min(start + 8, len(self._session.tracks_to_use()))
        if start < end:
            self.show_message('Controlling Track %d to %d' % (start, end))
        else:
            self.show_message('Controlling Track %d' % start)

    def _show_controlled_sends_message(self):
        send_index = self._mixer.selected_send_index
        send_name1 = chr(ord('A') + send_index)
        if send_index + 1 < self._mixer.num_sends:
            send_name2 = chr(ord('A') + send_index + 1)
            self.show_message('Controlling Send %s and %s' % (send_name1, send_name2))
        else:
            self.show_message('Controlling Send %s' % send_name1)

    def handle_sysex(self, midi_bytes):
        super(LaunchControl, self).handle_sysex(midi_bytes)
        if self._is_user_mode_message(midi_bytes):
            self._modes.selected_mode = 'user'
            self.request_rebuild_midi_map()

    def _is_user_mode_message(self, midi_bytes):
        """
        True if midi_byes refer to a mode change, but none of the three
        predefined Live modes
        """
        return midi_bytes[:7] == Sysex.MODE_CHANGE_PREFIX and midi_bytes not in SYSEX_MODE_MAP
Example #31
0
class NanoKontrolShift(ControlSurface):
    __module__ = __name__
    __doc__ = " NanoKontrolShift controller script "

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self._suppress_session_highlight = True
        self._suppress_send_midi = True  # Turn off rebuild MIDI map until after we're done setting up
        self.log_message(
            time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) +
            "--------------= NanoKontrolShift log opened =--------------"
        )  # Writes message into Live's main log file. This is a ControlSurface method.
        with self.component_guard():
            # OBJECTS
            self.session = None  # session object
            self.mixer = None  # mixer object
            self.view = None  # clip/device view object
            self.device = None  # device object
            self.transport = None  # transport object
            # MODES
            self._shift_button = None
            self._shift_button_pressed = False
            self._alt_button = None
            self._alt_button_pressed = False
            self._ctrl_button = None
            self._ctrl_button_pressed = False
            # INITIALIZE MIXER, SESSIONS
            self._setup_session_control()  # Setup the session object
            self._setup_mixer_control()  # Setup the mixer object
            self._setup_view_control()  # Setup the clip/view toggler
            self.session.set_mixer(self.mixer)  # Bind mixer to session
            self._setup_device_control()  # Setup the device object
            self._setup_transport_control()  # Setup transport object
            self.set_device_component(
                self.device)  # Bind device to control surface
            # SET INITIAL SESSION/MIXER AND MODIFIERS BUTTONS
            self._set_modifiers_buttons()
            self.__update_matrix()
            self.set_highlighting_session_component(self.session)

            for component in self.components:
                component.set_enabled(True)

        # self._suppress_session_highlight = True
        self._suppress_send_midi = True  # Turn rebuild back on, once we're done setting up

    def _setup_session_control(self):
        self.show_message(
            "#################### SESSION: ON ##############################")
        is_momentary = True
        # CREATE SESSION, SET OFFSETS, BUTTONS NAVIGATION AND BUTTON MATRIX
        self.session = SessionComponent(num_tracks,
                                        num_scenes)  # (num_tracks, num_scenes)
        self.session.set_offsets(0, 0)
        # self.session.set_scene_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_down), ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_up))
        self.session.set_track_bank_buttons(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_right),
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, session_left)
        )  # (right_button, left_button) This moves the "red box" selection set left & right. We'll use the mixer track selection instead...

    def _setup_mixer_control(self):
        is_momentary = True
        # CREATE MIXER, SET OFFSET (SPECIALMIXERCOMPONENT USES SPECIALCHANNELSTRIP THAT ALLOWS US TO UNFOLD TRACKS WITH TRACK SELECT BUTTON)
        self.mixer = SpecialMixerComponent(
            num_tracks, 0, False,
            False)  # 4 tracks, 2 returns, no EQ, no filters
        self.mixer.name = 'Mixer'
        self.mixer.set_track_offset(
            0)  # Sets start point for mixer strip (offset from left)

    def _setup_view_control(self):
        # CREATES OBJECT SO WE CAN TOGGLE DEVICE/CLIP, LOCK DEVICE
        self.view = ViewTogglerComponent(num_tracks, self)

    def _setup_device_control(self):
        # CREATE DEVICE TO ASSIGN PARAMETERS BANK
        self.device = DeviceComponent()
        self.device.name = 'Device_Component'

    def _setup_transport_control(self):
        # CREATE TRANSPORT DEVICE
        self.transport = SpecialTransportComponent(self)

    def _on_selected_scene_changed(self):
        # ALLOWS TO GRAB THE FIRST DEVICE OF A SELECTED TRACK IF THERE'S ANY
        ControlSurface._on_selected_track_changed(self)
        track = self.song().view.selected_track
        if (track.devices is not None):
            self._ignore_track_selection = True
            device_to_select = track.devices[0]
            self.song().view.select_device(device_to_select)
            self._device_component.set_device(device_to_select)
        self._ignore_track_selection = False

    """                                 LED ON, OFF, FLASH WITH SESSION CLIPS                                             """

    # UPDATING BUTTONS FROM CLIP MATRIX IN NK AS SESSION MOVES
    def __update_matrix(self):
        for scene_index in range(num_scenes):
            scene = self.session.scene(scene_index)
            for track_index in range(num_tracks):
                clip_slot = scene.clip_slot(track_index)
                button = clip_slot._launch_button_value.subject
                value_to_send = -1
                if clip_slot._clip_slot != None:
                    if clip_slot.has_clip():
                        value_to_send = 127
                        if clip_slot._clip_slot.clip.is_triggered:
                            if clip_slot._clip_slot.clip.will_record_on_start:
                                value_to_send = clip_slot._triggered_to_record_value
                            else:
                                value_to_send = clip_slot._triggered_to_play_value
                        '''
                        elif clip_slot._clip_slot.clip.is_playing:
                            if clip_slot._clip_slot.clip.is_recording:
                                value_to_send = 127
                                #########      CLIPS PLAYING WILL FLASH
                                for i in range(2000):
                                    if i % 50 == 0:
                                        button.send_value(127)
                                    else:
                                        button.send_value(0)
                            else:
                                for i in range(2000):
                                    if i % 50 == 0:
                                        button.send_value(127)
                                    else:
                                        button.send_value(0)
                        '''
                    elif clip_slot._clip_slot.is_triggered:
                        if clip_slot._clip_slot.will_record_on_start:
                            value_to_send = clip_slot._triggered_to_record_value
                        else:
                            value_to_send = clip_slot._triggered_to_play_value
                    elif clip_slot._clip_slot.is_playing:
                        if clip_slot._clip_slot.is_recording:
                            value_to_send = clip_slot._recording_value
                        else:
                            value_to_send = clip_slot._started_value
                    elif clip_slot._clip_slot.controls_other_clips:
                        value_to_send = 0
                '''
                if value_to_send in range(128):
                    button.send_value(value_to_send)
                else:
                    button.turn_off()
                '''

    """                                 MODIFIERS, MODES, KEYS CONFIG                                             """

    # MODES ARE HERE: INITIALIZATIONS, DISCONNECTS BUTTONS, SLIDERS, ENCODERS
    def _clear_controls(self):
        # TURNING OFF ALL LEDS IN MATRIX
        self._turn_off_matrix()
        # SESSION
        resetsend_controls = []
        self.mixer.send_controls = []
        for scene_index in range(num_scenes):
            scene = self.session.scene(scene_index)
            scene.set_launch_button(None)
            for track_index in range(num_tracks):
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(None)
        self.session.set_stop_track_clip_buttons(None)
        self.session.set_stop_all_clips_button(None)
        # REMOVE LISTENER TO SESSION MOVES
        if self.session.offset_has_listener(self.__update_matrix):
            self.session.remove_offset_listener(self.__update_matrix)
        self.session.set_stop_all_clips_button(None)
        # MIXER
        self.mixer._set_send_nav(None, None)
        for track_index in range(num_tracks):
            strip = self.mixer.channel_strip(track_index)
            strip.set_solo_button(None)
            strip.set_mute_button(None)
            strip.set_arm_button(None)
            resetsend_controls.append(None)
            strip.set_select_button(None)
            for i in range(12):
                self.mixer.send_controls.append(None)
            strip.set_send_controls(tuple(self.mixer.send_controls))
        self.mixer.set_resetsend_buttons(tuple(resetsend_controls))
        # VIEW
        self.view.set_device_nav_buttons(None, None)
        detailclip_view_controls = []
        for track_index in range(num_tracks):
            detailclip_view_controls.append(None)
        self.view.set_buttons(tuple(detailclip_view_controls))
        # DEVICE PARAMETERS
        device_param_controls = []
        self.device.set_parameter_controls(tuple(device_param_controls))
        self.device.set_on_off_button(None)
        self.device.set_lock_button(None)
        # TRANSPORT
        self.transport.set_stop_button(None)
        self.transport.set_play_button(None)
        self.transport.set_record_button(None)
        self.transport._set_quant_toggle_button(None)
        self.transport.set_metronome_button(None)
        self.transport._set_tempo_buttons(None, None)

        self.log_message("Controls Cleared")

    def _set_normal_mode(self):
        is_momentary = True
        self.mixer._set_send_nav(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_up),
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_down))
        for index in range(num_tracks):
            strip = self.mixer.channel_strip(index)
            strip.name = 'Mixer_ChannelStrip_' + str(index)
            self.mixer._update_send_index(self.mixer.sends_index)
            strip.set_volume_control(
                SliderElement(MIDI_CC_TYPE, CHANNEL,
                              mixer_volumefader_cc[index]))
            self.mixer.send_controls[self.mixer.sends_index] = EncoderElement(
                MIDI_CC_TYPE, CHANNEL, mixer_sendknob_cc[index],
                Live.MidiMap.MapMode.absolute)
            strip.set_send_controls(tuple(self.mixer.send_controls))
            strip._invert_mute_feedback = True
        ### SET ARM, SOLO, MUTE
        for index in range(num_tracks):
            strip = self.mixer.channel_strip(index)
            strip.set_send_controls(tuple(self.mixer.send_controls))
            strip.set_solo_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                              track_solo_cc[index]))
            strip.set_mute_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                              track_mute_cc[index]))
            strip.set_arm_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                              track_arm_cc[index]))
            # self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_stop_cc))
            for i in range(12):
                self.mixer.send_controls.append(None)
            self.mixer.send_controls[self.mixer.sends_index] = EncoderElement(
                MIDI_CC_TYPE, CHANNEL, mixer_sendknob_cc[index],
                Live.MidiMap.MapMode.absolute)
            strip.set_send_controls(tuple(self.mixer.send_controls))
            strip._invert_mute_feedback = True
        self.mixer._update_send_index(self.mixer.sends_index)

    def _set_alt_mode(self):
        is_momentary = True
        self.mixer._set_send_nav(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_up),
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, send_down))
        stop_track_controls = []
        resetsend_controls = []
        button = None
        buttons = None
        # SET SESSION TRACKSTOP, TRACK SELECT, RESET SEND KNOB
        for index in range(num_tracks):
            strip = self.mixer.channel_strip(index)
            strip.set_select_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                              track_select_cc[index]))
            button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                   stop_track_cc[index])
            stop_track_controls.append(button)
            buttons = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                    track_resetsend_cc[index])
            resetsend_controls.append(buttons)
        self.session.set_stop_track_clip_buttons(tuple(stop_track_controls))
        self.mixer.set_resetsend_buttons(tuple(resetsend_controls))
        self.mixer._update_send_index(self.mixer.sends_index)

    def _set_ctrl_mode(self):
        # CLIP/DEVICE VIEW TOGGLE
        is_momentary = True
        self.view.set_device_nav_buttons(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, device_left_cc),
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                          device_right_cc))
        button = None
        detailclip_view_controls = []
        for index in range(num_tracks):
            button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL,
                                   detailclip_view_cc[index])
            detailclip_view_controls.append(button)
        self.view.set_buttons(tuple(detailclip_view_controls))
        # DEVICE ON/OFF, LOCK AND PARAMETERS
        device_param_controls = []
        onoff_control = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                      onoff_device_cc)
        setlock_control = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                                        lock_device_cc)
        for index in range(num_tracks):
            knob = None
            knob = EncoderElement(MIDI_CC_TYPE, CHANNEL,
                                  device_param_cc[index],
                                  Live.MidiMap.MapMode.absolute)
            device_param_controls.append(knob)
        if None not in device_param_controls:
            self.device.set_parameter_controls(tuple(device_param_controls))
        self.device.set_on_off_button(onoff_control)
        self.device.set_lock_button(setlock_control)
        # TRANSPORT
        # self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_stop_cc))
        # self.transport.set_play_button(ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, transport_play_cc))
        # self.transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, transport_record_cc))
        self.transport._set_quant_toggle_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                          transport_quantization_cc))
        self.transport.set_metronome_button(
            ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL,
                          transport_metronome_cc))
        self.transport._set_tempo_buttons(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                          transport_tempodown_cc),
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                          transport_tempoup_cc))
        # SESSION STOP ALL CLIPS AND SCENE LAUNCH
        self.session.set_stop_all_clips_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                          session_stopall_cc))
        for index in range(num_scenes):
            self.session.scene(index).set_launch_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL,
                              session_scenelaunch_cc[index]))

    def _set_modifiers_buttons(self):
        is_momentary = True
        self._shift_button = ButtonElement(not is_momentary, MIDI_CC_TYPE,
                                           CHANNEL, shift_mod)
        self._alt_button = ButtonElement(not is_momentary, MIDI_CC_TYPE,
                                         CHANNEL, alt_mod)
        self._ctrl_button = ButtonElement(not is_momentary, MIDI_CC_TYPE,
                                          CHANNEL, ctrl_mod)

        if (self._shift_button != None):
            self._shift_button.add_value_listener(self._shift_value)

        if (self._alt_button != None):
            self._alt_button.add_value_listener(self._alt_value)

        if (self._ctrl_button != None):
            self._ctrl_button.add_value_listener(self._ctrl_value)
        # INIT NORMAL MODE
        self._manage_modes(0)

    # MODIFIERS LISTENERS FUNCS ARE HERE
    def _shift_value(self, value):
        assert isinstance(value, int)
        assert isinstance(self._shift_button, ButtonElement)
        if value == 127:
            if self._shift_button_pressed is False:
                self._unpress_modes()
                self._shift_button_pressed = True
                self._manage_modes(0)

    def _alt_value(self, value):
        assert isinstance(value, int)
        assert isinstance(self._alt_button, ButtonElement)
        if value == 127:
            if self._alt_button_pressed is False:
                self._unpress_modes()
                self._alt_button_pressed = True
                self._manage_modes(2)

    def _ctrl_value(self, value):
        assert isinstance(value, int)
        assert isinstance(self._ctrl_button, ButtonElement)
        if value == 127:
            if self._ctrl_button_pressed is False:
                self._unpress_modes()
                self._ctrl_button_pressed = True
                self._manage_modes(3)

    def _manage_modes(self, mode_index):
        if mode_index == 0:
            self._clear_controls()
            self._set_normal_mode()
            # self._shift_button.turn_on()
            self._alt_button.turn_on()
            self._ctrl_button.turn_on()
            self.log_message("NORMAL ON")
        elif mode_index == 2:
            self._clear_controls()
            self._set_alt_mode()
            self._alt_button.turn_on()
            self._shift_button.turn_off()
            self._ctrl_button.turn_off()
            self.log_message("ALT ON")
        elif mode_index == 3:
            self._clear_controls()
            self._set_ctrl_mode()
            self._ctrl_button.turn_on()
            self._shift_button.turn_off()
            self._alt_button.turn_off()
            self.log_message("CTRL ON")

    def _unpress_modes(self):
        self._shift_button_pressed = False
        self._alt_button_pressed = False
        self._ctrl_button_pressed = False

    def _turn_off_matrix(self):
        for index in range(24):
            self._send_midi(tuple([176, index + 16, 0]))

    def disconnect(self):
        """clean things up on disconnect"""
        self.log_message(
            time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) +
            "--------------= NanoKontrolShift log closed =--------------"
        )  # Create entry in log file
        self._clear_controls()
        self.session = None
        self.mixer = None
        self.view = None
        self.device = None
        self.transport = None
        # MODES
        self._shift_button = None
        self._alt_button = None
        self._ctrl_button = None
        # SENDS
        self.send_button_up = None
        self.send_button_down = None
        self.send_controls = []
        self.send_reset = []

        self.set_device_component(None)
        ControlSurface.disconnect(self)
        return None
class SubSelectorComponent(ModeSelectorComponent):
    """ Class that handles different mixer modes """

    def __init__(self, matrix, side_buttons, session):
        raise isinstance(matrix, ButtonMatrixElement) or AssertionError
        raise matrix.width() == 8 and matrix.height() == 8 or AssertionError
        raise isinstance(side_buttons, tuple) or AssertionError
        raise len(side_buttons) == 8 or AssertionError
        raise isinstance(session, SessionComponent) or AssertionError
        ModeSelectorComponent.__init__(self)
        self._session = session
        self._mixer = SpecialMixerComponent(matrix.width())
        self._matrix = matrix
        self._sliders = []
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_strip'
        self._mixer.selected_strip().name = 'Selected_Channel_strip'
        for column in range(matrix.width()):
            self._mixer.channel_strip(column).name = 'Channel_Strip_' + str(column)
            self._sliders.append(PreciseButtonSliderElement(tuple([ matrix.get_button(column, 7 - row) for row in range(8) ])))
            self._sliders[-1].name = 'Button_Slider_' + str(column)

        self._side_buttons = side_buttons[4:]
        self._update_callback = None
        self._session.set_mixer(self._mixer)
        self.set_modes_buttons(side_buttons[:4])

    def disconnect(self):
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)

        self._session = None
        self._mixer = None
        for slider in self._sliders:
            slider.release_parameter()
            slider.set_disabled(True)

        self._sliders = None
        self._matrix = None
        self._side_buttons = None
        self._update_callback = None
        ModeSelectorComponent.disconnect(self)

    def set_update_callback(self, callback):
        raise dir(callback).count('im_func') is 1 or AssertionError
        self._update_callback = callback

    def set_modes_buttons(self, buttons):
        raise buttons == None or isinstance(buttons, tuple) or len(buttons) == self.number_of_modes() or AssertionError
        identify_sender = True
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)

        self._modes_buttons = []
        if buttons != None:
            for button in buttons:
                raise isinstance(button, ButtonElement) or AssertionError
                self._modes_buttons.append(button)
                button.add_value_listener(self._mode_value, identify_sender)

    def set_mode(self, mode):
        if not isinstance(mode, int):
            raise AssertionError
            raise mode in range(-1, self.number_of_modes()) or AssertionError
            self._mode_index = (self._mode_index != mode or mode == -1) and mode
            self.update()

    def mode(self):
        result = 0
        if self.is_enabled():
            result = self._mode_index + 1
        return result

    def number_of_modes(self):
        return 4

    def on_enabled_changed(self):
        enabled = self.is_enabled()
        for index in range(self._matrix.width()):
            self._sliders[index].set_disabled(not enabled)

        self._mixer.set_enabled(enabled)
        self.set_mode(-1)

    def release_controls(self):
        for track in range(self._matrix.width()):
            for row in range(self._matrix.height()):
                self._matrix.get_button(track, row).set_on_off_values(127, LED_OFF)

            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_send_controls((None, None))
            strip.set_pan_control(None)
            strip.set_volume_control(None)

        self._session.set_stop_track_clip_buttons(None)
        self._mixer.set_global_buttons(None, None, None)
        self._session.set_stop_all_clips_button(None)

    def update(self):
        super(SubSelectorComponent, self).update()
        if not self._modes_buttons != None:
            raise AssertionError
            if self.is_enabled():
                if self._modes_buttons != None:
                    for index in range(len(self._modes_buttons)):
                        self._modes_buttons[index].set_on_off_values(GREEN_FULL, GREEN_THIRD)
                        if index == self._mode_index:
                            self._modes_buttons[index].turn_on()
                        else:
                            self._modes_buttons[index].turn_off()

                for button in self._side_buttons:
                    button.set_on_off_values(127, LED_OFF)
                    button.turn_off()

                for index in range(self._matrix.width()):
                    self._sliders[index].set_disabled(self._mode_index == -1)

                self._mixer.set_allow_update(False)
                self._session.set_allow_update(False)
                if self._mode_index == -1:
                    self._setup_mixer_overview()
                elif self._mode_index == 0:
                    self._setup_volume_mode()
                elif self._mode_index == 1:
                    self._setup_pan_mode()
                elif self._mode_index == 2:
                    self._setup_send1_mode()
                elif self._mode_index == 3:
                    self._setup_send2_mode()
                else:
                    raise False or AssertionError
                self._update_callback != None and self._update_callback()
            self._mixer.set_allow_update(True)
            self._session.set_allow_update(True)
        else:
            self.release_controls()

    def _setup_mixer_overview(self):
        trkon_index = 5
        stop_buttons = []
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_send_controls((None, None))
            strip.set_pan_control(None)
            strip.set_volume_control(None)
            self._sliders[track].release_parameter()
            for row in range(self._matrix.height()):
                full_value = GREEN_THIRD
                third_value = GREEN_FULL
                if row == trkon_index:
                    full_value = AMBER_FULL
                    third_value = AMBER_THIRD
                elif row > 3:
                    full_value = RED_FULL
                    third_value = RED_THIRD
                self._matrix.get_button(track, row).set_on_off_values(full_value, third_value)

            strip.set_default_buttons(self._matrix.get_button(track, 0), self._matrix.get_button(track, 1), self._matrix.get_button(track, 2), self._matrix.get_button(track, 3))
            stop_buttons.append(self._matrix.get_button(track, 4))
            strip.set_mute_button(self._matrix.get_button(track, 5))
            strip.set_solo_button(self._matrix.get_button(track, 6))
            strip.set_arm_button(self._matrix.get_button(track, 7))

        for button in self._side_buttons:
            if list(self._side_buttons).index(button) == trkon_index - 4:
                button.set_on_off_values(AMBER_FULL, AMBER_THIRD)
            else:
                button.set_on_off_values(RED_FULL, RED_THIRD)
            button.set_force_next_value()
            button.turn_off()

        self._session.set_stop_track_clip_buttons(tuple(stop_buttons))
        self._session.set_stop_all_clips_button(self._side_buttons[0])
        self._mixer.set_global_buttons(self._side_buttons[3], self._side_buttons[2], self._side_buttons[1])

    def _setup_volume_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_send_controls((None, None))
            strip.set_pan_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(track, row).set_on_off_values(GREEN_FULL, LED_OFF)

            self._sliders[track].set_mode(SLIDER_MODE_VOLUME)
            self._sliders[track].set_value_map(VOL_VALUE_MAP)
            strip.set_volume_control(self._sliders[track])

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)

    def _setup_pan_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_send_controls((None, None))
            strip.set_volume_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(track, row).set_on_off_values(AMBER_FULL, LED_OFF)

            self._sliders[track].set_mode(SLIDER_MODE_PAN)
            self._sliders[track].set_value_map(PAN_VALUE_MAP)
            strip.set_pan_control(self._sliders[track])

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)

    def _setup_send1_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_volume_control(None)
            strip.set_pan_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(track, row).set_on_off_values(RED_FULL, LED_OFF)

            self._sliders[track].set_mode(SLIDER_MODE_VOLUME)
            self._sliders[track].set_value_map(SEND_VALUE_MAP)
            strip.set_send_controls((self._sliders[track], None))

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)

    def _setup_send2_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_volume_control(None)
            strip.set_pan_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(track, row).set_on_off_values(RED_FULL, LED_OFF)

            self._sliders[track].set_mode(SLIDER_MODE_VOLUME)
            self._sliders[track].set_value_map(SEND_VALUE_MAP)
            strip.set_send_controls((None, self._sliders[track]))

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)
class Serato(ControlSurface):
    def __init__(self, c_instance):
        publish_in_cs_list = True
        ControlSurface.__init__(self, c_instance, not publish_in_cs_list)
        self._device_selection_follows_track_selection = True
        with self.component_guard():
            self._matrix = None
            self._session = None
            self._mixer = None
            self._device = None
            self._scene_launch_buttons = None
            self._track_arm_buttons = None
            self._track_solo_buttons = None
            self._track_mute_buttons = None
            self._track_stop_buttons = None
            self._track_select_buttons = None
            self._device_on_off_button = None
            self._shift_button = None
            self._serato_interface = PySCAClipControl()
            self._serato_interface.PySCA_InitializeClipControl()
            self._setup_session_control()
            self._setup_mixer_control()
            self._setup_device_control()
            self._session.set_mixer(self._mixer)
            self.set_highlighting_session_component(self._session)

    def disconnect(self):
        ControlSurface.disconnect(self)
        self._serato_interface.PySCA_DeinitializeClipControl()
        self._serato_interface = None

    def connect_script_instances(self, instanciated_scripts):
        """ Called by the Application as soon as all scripts are initialized.
            You can connect yourself to other running scripts here, as we do it
            connect the extension modules (MackieControlXTs).
        """
        for control_surface in self._control_surfaces():
            control_surface_session = control_surface.highlighting_session_component(
            )
            if control_surface_session:
                self._session.sync_to(control_surface_session)
                self._on_track_list_changed()
                break

    def build_midi_map(self, midi_map_handle):
        pass

    def update_display(self):
        ControlSurface.update_display(self)
        while self._serato_interface.PySCA_HasIncomingEvent():
            new_event = self._serato_interface.PySCA_GetIncomingEvent()
            if not self._handle_session_event(new_event):
                if not self._handle_mixer_event(new_event):
                    if not self._handle_device_event(new_event):
                        print 'Unhandled Event: ' + str(new_event)

    def _setup_session_control(self):
        is_momentary = True
        self._session = SpecialSessionComponent(NUM_TRACKS, NUM_SCENES)
        self._session.set_serato_interface(self._serato_interface)
        self._matrix = ButtonMatrixElement()
        self._scene_launch_buttons = [
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
            for index in range(NUM_SCENES)
        ]
        self._track_stop_buttons = [
            ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)
            for index in range(NUM_TRACKS)
        ]
        stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
        self._session.set_stop_all_clips_button(stop_all_button)
        self._session.set_stop_track_clip_buttons(
            tuple(self._track_stop_buttons))
        for scene_index in range(NUM_SCENES):
            scene = self._session.scene(scene_index)
            button_row = []
            scene.set_launch_button(self._scene_launch_buttons[scene_index])
            scene.set_index(scene_index)
            scene.set_serato_interface(self._serato_interface)
            for track_index in range(NUM_TRACKS):
                button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(button)
                clip_slot.set_serato_interface(self._serato_interface)

            self._matrix.add_row(tuple(button_row))

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(NUM_TRACKS)
        self._mixer.set_serato_interface(self._serato_interface)
        self._mixer.master_strip().set_serato_interface(self._serato_interface)
        self._track_arm_buttons = []
        self._track_solo_buttons = []
        self._track_mute_buttons = []
        self._track_select_buttons = []
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
        for track in range(NUM_TRACKS):
            strip = self._mixer.channel_strip(track)
            strip.set_serato_interface(self._serato_interface)
            self._track_arm_buttons.append(
                ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_solo_buttons.append(
                ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_mute_buttons.append(
                ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_select_buttons.append(
                ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            strip.set_arm_button(self._track_arm_buttons[-1])
            strip.set_solo_button(self._track_solo_buttons[-1])
            strip.set_mute_button(self._track_mute_buttons[-1])
            strip.set_select_button(self._track_select_buttons[-1])
            strip.set_shift_button(self._shift_button)

    def _setup_device_control(self):
        is_momentary = True
        self._device_on_off_button = ButtonElement(not is_momentary,
                                                   MIDI_NOTE_TYPE, 0, 0)
        self._device = SpecialDeviceComponent()
        self._device.set_serato_interface(self._serato_interface)
        self._device.set_parameter_controls(
            tuple([
                SliderElement(MIDI_CC_TYPE, 0, 0)
                for index in range(NUM_PARAMS)
            ]))
        self._device.set_on_off_button(self._device_on_off_button)
        self.set_device_component(self._device)

    def _handle_session_event(self, event):
        result = False
        if event.type in CLIP_EVENTS:
            value = 127 * int(event.type == libInterprocessCommsAPIPython.
                              kAbletonClipControlEventClipPlayedDown)
            track_index = event.key1 - 1
            scene_index = event.key2 - 1
            if track_index in range(NUM_TRACKS) and scene_index in range(
                    NUM_SCENES):
                self._matrix.get_button(track_index,
                                        scene_index).receive_value(value)
            result = True
        elif event.type in SCENE_EVENTS:
            value = 127 * int(event.type == libInterprocessCommsAPIPython.
                              kAbletonClipControlEventScenePlayedDown)
            scene_index = event.key1 - 1
            if scene_index in range(NUM_SCENES):
                self._scene_launch_buttons[scene_index].receive_value(value)
            result = True
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixSizeChanged:
            new_width = event.key1
            new_height = event.key2
            self._session.set_size(new_width, new_height)
            result = True
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixOffsetChanged:
            x_increment = event.key1
            y_increment = event.key2
            self._session.move_by(x_increment, y_increment)
            result = True
        return result

    def _handle_mixer_event(self, event):
        result = True
        track_index = event.key1 - 1
        value = event.key2
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackMasterGainChange:
            self._mixer.master_strip().set_track_volume(fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackStopped:
            self.song().stop_all_clips()
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackSelect:
            self.song().view.selected_track = self.song().master_track
        else:
            result = track_index in range(
                NUM_TRACKS) and self._handle_strip_event(event)
        return result

    def _handle_strip_event(self, event):
        result = True
        track_index = event.key1 - 1
        value = event.key2
        if value == 0:
            self._shift_button.receive_value(127)
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSolo:
            self._track_solo_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackRecord:
            self._track_arm_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackActive:
            self._track_mute_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackStopped:
            self._track_stop_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSelect:
            self._track_select_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackGainChange:
            self._mixer.channel_strip(track_index).set_track_volume(
                fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendAChange:
            self._mixer.channel_strip(track_index).set_send(
                0, fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendBChange:
            self._mixer.channel_strip(track_index).set_send(
                1, fixed_value(value))
        else:
            result = False
        self._shift_button.receive_value(0)
        return result

    def _handle_device_event(self, event):
        result = True
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceValueChanged:
            self._device.set_parameter_value(event.key1 - 1,
                                             fixed_value(event.key2))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceActivate:
            self._device_on_off_button.receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceFocusMove:
            self._move_device_focus(event.key1)
        else:
            result = False
        return result

    def _move_device_focus(self, increment):
        if not self.application().view.is_view_visible(
                'Detail') or not self.application().view.is_view_visible(
                    'Detail/DeviceChain'):
            self.application().view.show_view('Detail')
            self.application().view.show_view('Detail/DeviceChain')
        else:
            modifier_pressed = True
            direction = Live.Application.Application.View.NavDirection.left
            if increment > 0:
                direction = Live.Application.Application.View.NavDirection.right
            self.application().view.scroll_view(direction,
                                                'Detail/DeviceChain',
                                                not modifier_pressed)
Example #34
0
class LaunchControl(ControlSurface):

    def __init__(self, c_instance):
        super(LaunchControl, self).__init__(c_instance)
        with self.component_guard():
            self._device_selection_follows_track_selection = True
            self._init_mixer()
            self._init_session()
            self._init_device()
            self._init_modes()
            self._refresh_state_task = self._tasks.add(Task.sequence(Task.delay(3), Task.run(self._do_refresh_state)))
            self._refresh_state_task.kill()
        self.log_message('Launch Control script loaded')

    def disconnect(self):
        super(LaunchControl, self).disconnect()
        for channel in xrange(16):
            self._send_midi((CC_STATUS + channel, 0, 0))

    def refresh_state(self):
        self._refresh_state_task.restart()

    def _do_refresh_state(self):
        self._send_current_mode()
        self._update_hardware()
        self.schedule_message(3, super(LaunchControl, self).refresh_state)

    def _update_hardware(self):
        for channel in xrange(8, 11):
            self._send_midi(Sysex.make_automatic_flashing_message(channel))

    def _send_current_mode(self):
        try:
            self._send_midi(MODE_SYSEX_MAP[self._modes.selected_mode])
        except KeyError:
            pass

    def _init_mixer(self):
        make_button = partial(make_launch_control_button, channel=8)
        make_encoder = partial(make_launch_control_encoder, channel=8)
        bottom_encoders, top_encoders = make_all_encoders('Mixer', make_encoder)
        pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders]))
        sends_layer = Layer(sends_controls=ButtonMatrixElement(rows=[bottom_encoders, top_encoders]))
        modes_layer = Layer(pan_volume_button=make_button(114, 'Pan_Volume_Mode_Button'), sends_button=make_button(115, 'Sends_Mode_Button'))
        self._mixer = SpecialMixerComponent(8, modes_layer, pan_volume_layer, sends_layer)
        self._mixer.set_enabled(False)
        self._mixer.name = 'Mixer'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer_track_nav_layer = Layer(track_bank_left_button=make_button(116, 'Mixer_Track_Left_Button'), track_bank_right_button=make_button(117, 'Mixer_Track_Right_Button'))
        for index in xrange(8):
            strip = self._mixer.channel_strip(index)
            strip.name = 'Channel_Strip_' + str(index)
            strip.empty_color = Colors.LED_OFF
            strip.set_invert_mute_feedback(True)
            mute_button = make_button(pad_identifiers[index], 'Track_Mute_Button_' + str(index), is_pad=True)
            mute_button.set_on_off_values(Colors.AMBER_FULL, Colors.AMBER_THIRD)
            strip.set_mute_button(mute_button)

        self._on_selected_send_index.subject = self._mixer
        self._on_selected_mixer_mode.subject = self._mixer

    def _init_session(self):
        make_button = partial(make_launch_control_button, channel=9)
        make_encoder = partial(make_launch_control_encoder, channel=9)
        bottom_encoders, top_encoders = make_all_encoders('Session_Mixer', make_encoder)
        pan_volume_layer = Layer(volume_controls=ButtonMatrixElement(rows=[bottom_encoders]), pan_controls=ButtonMatrixElement(rows=[top_encoders]))
        self._session_mixer = SpecialMixerComponent(8, Layer(), pan_volume_layer, Layer())
        self._session_mixer.set_enabled(False)
        self._session_mixer.name = 'Session_Mixer'
        clip_launch_buttons = [ make_button(identifier, 'Clip_Launch_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ]
        self._session = SpecialSessionComponent(num_tracks=8, num_scenes=0, name='Session')
        self._session.set_enabled(False)
        self._session.set_mixer(self._session_mixer)
        self._session_layer = Layer(track_bank_left_button=make_button(116, 'Track_Bank_Left_Button'), track_bank_right_button=make_button(117, 'Track_Bank_Right_Button'), select_prev_button=make_button(114, 'Scene_Bank_Up_Button'), select_next_button=make_button(115, 'Scene_Bank_Down_Button'), clip_launch_buttons=ButtonMatrixElement(rows=[clip_launch_buttons]))
        scene = self._session.selected_scene()
        for index in range(8):
            clip_slot = scene.clip_slot(index)
            clip_slot.set_triggered_to_play_value(Colors.GREEN_BLINK)
            clip_slot.set_triggered_to_record_value(Colors.RED_BLINK)
            clip_slot.set_stopped_value(Colors.AMBER_FULL)
            clip_slot.set_started_value(Colors.GREEN_FULL)
            clip_slot.set_recording_value(Colors.RED_FULL)
            clip_slot.name = 'Selected_Clip_Slot_' + str(index)

        self._on_track_offset.subject = self._session

    def _init_device(self):
        make_button = partial(make_launch_control_button, channel=10)
        make_encoder = partial(make_launch_control_encoder, channel=10)
        bottom_encoders, top_encoders = make_all_encoders('Device', make_encoder)
        parameter_controls = top_encoders[:4] + bottom_encoders[:4]
        bank_buttons = [ make_button(identifier, 'Device_Bank_Button_' + str(i), is_pad=True) for i, identifier in enumerate(pad_identifiers) ]
        for button in bank_buttons:
            button.set_on_off_values(Colors.LED_ON, Colors.LED_OFF)

        self._device_bank_registry = DeviceBankRegistry()
        self._device = DeviceComponent(device_bank_registry=self._device_bank_registry, name='Device')
        self._device.set_enabled(False)
        self._device.layer = Layer(parameter_controls=ButtonMatrixElement(rows=[parameter_controls]), bank_buttons=ButtonMatrixElement(rows=[bank_buttons]))
        self.set_device_component(self._device)
        self._device_navigation = DeviceNavigationComponent()
        self._device_navigation.set_enabled(False)
        self._device_navigation.name = 'Device_Navigation'
        self._device_navigation.layer = Layer(next_device_button=make_button(115, 'Next_Device_Button'), previous_device_button=make_button(114, 'Prev_Device_Button'))
        self._view_control = ViewControlComponent()
        self._view_control.set_enabled(False)
        self._view_control.name = 'View_Control'
        self._view_control.layer = Layer(next_track_button=make_button(117, 'Device_Next_Track_Button'), prev_track_button=make_button(116, 'Device_Prev_Track_Button'))

    def _init_modes(self):
        self._modes = ModesComponent(is_root=True)
        self._modes.add_mode('mixer', [partial(self._session.set_mixer, self._mixer),
         LayerMode(self._session, self._mixer_track_nav_layer),
         self._mixer,
         self._session,
         self._show_controlled_tracks_message])
        self._modes.add_mode('session', [partial(self._session.set_mixer, self._session_mixer),
         LayerMode(self._session, self._session_layer),
         self._session_mixer,
         self._session,
         self._show_controlled_tracks_message])
        self._modes.add_mode('device', [self._device, self._device_navigation, self._view_control])
        self._modes.add_mode('user', None)
        self._modes.selected_mode = 'mixer'
        self._modes.layer = Layer(mixer_button=ButtonSysexControl(Sysex.MIXER_MODE), session_button=ButtonSysexControl(Sysex.SESSION_MODE), device_button=ButtonSysexControl(Sysex.DEVICE_MODE))
        return

    @subject_slot('offset')
    def _on_track_offset(self):
        self._show_controlled_tracks_message()

    @subject_slot('selected_send_index')
    def _on_selected_send_index(self, index):
        self._show_controlled_sends_message()

    @subject_slot('selected_mixer_mode')
    def _on_selected_mixer_mode(self, mode):
        if mode == 'sends':
            self._show_controlled_sends_message()
        else:
            self.show_message('Controlling Pan and Volume')

    def _show_controlled_tracks_message(self):
        start = self._session.track_offset() + 1
        end = min(start + 8, len(self._session.tracks_to_use()))
        if start < end:
            self.show_message('Controlling Track %d to %d' % (start, end))
        else:
            self.show_message('Controlling Track %d' % start)

    def _show_controlled_sends_message(self):
        send_index = self._mixer.selected_send_index
        send_name1 = chr(ord('A') + send_index)
        if send_index + 1 < self._mixer.num_sends:
            send_name2 = chr(ord('A') + send_index + 1)
            self.show_message('Controlling Send %s and %s' % (send_name1, send_name2))
        else:
            self.show_message('Controlling Send %s' % send_name1)

    def handle_sysex(self, midi_bytes):
        super(LaunchControl, self).handle_sysex(midi_bytes)
        if self._is_user_mode_message(midi_bytes):
            self._modes.selected_mode = 'user'
            self.request_rebuild_midi_map()

    def _is_user_mode_message(self, midi_bytes):
        """
        True if midi_byes refer to a mode change, but none of the three
        predefined Live modes
        """
        return midi_bytes[:7] == Sysex.MODE_CHANGE_PREFIX and midi_bytes not in SYSEX_MODE_MAP
class Oxygen_3rd_Gen(ControlSurface):
    """ Script for the 3rd generation of M-Audio's Oxygen controllers """
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            is_momentary = True
            self._suggested_input_port = 'Oxygen'
            self._suggested_output_port = 'Oxygen'
            self._has_slider_section = True
            self._device_selection_follows_track_selection = True
            self._shift_button = ButtonElement(is_momentary, MIDI_CC_TYPE,
                                               GLOBAL_CHANNEL, 57)
            self._shift_button.add_value_listener(self._shift_value)
            self._mixer = SpecialMixerComponent(NUM_TRACKS)
            self._mute_solo_buttons = []
            self._track_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE,
                                                  GLOBAL_CHANNEL, 111)
            self._track_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE,
                                                    GLOBAL_CHANNEL, 110)
            self._master_slider = SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL,
                                                41)
            for index in range(NUM_TRACKS):
                self._mute_solo_buttons.append(
                    ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL,
                                  49 + index))
                self._mixer.channel_strip(index).set_volume_control(
                    SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 33 + index))

            self._shift_value(0)
            self._mixer.master_strip().set_volume_control(self._master_slider)
            self._mixer.selected_strip().set_volume_control(None)
            device = DeviceComponent()
            device.set_parameter_controls(
                tuple([
                    EncoderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 17 + index,
                                   Live.MidiMap.MapMode.absolute)
                    for index in range(8)
                ]))
            self.set_device_component(device)
            ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE,
                                        GLOBAL_CHANNEL, 115)
            rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE,
                                       GLOBAL_CHANNEL, 114)
            loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE,
                                        GLOBAL_CHANNEL, 113)
            transport = TransportComponent()
            transport.set_stop_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 116))
            transport.set_play_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 117))
            transport.set_record_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 118))
            session = SessionComponent(0, 0)
            transport_view_modes = TransportViewModeSelector(
                transport, session, ffwd_button, rwd_button, loop_button)

    def disconnect(self):
        self._shift_button.remove_value_listener(self._shift_value)
        self._shift_button = None
        ControlSurface.disconnect(self)

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self.schedule_message(5, self._send_midi, IDENTITY_REQUEST)

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:5] == IDENTITY_RESPONSE:
            if midi_bytes[10] == 38:
                self._mixer.master_strip().set_volume_control(None)
                self._mixer.selected_strip().set_volume_control(
                    self._master_slider)

    def _shift_value(self, value):
        raise value in range(128) or AssertionError
        for index in range(NUM_TRACKS):
            if value == 0:
                self._mixer.channel_strip(index).set_solo_button(None)
                self._mixer.channel_strip(index).set_mute_button(
                    self._mute_solo_buttons[index])
                self._mixer.set_bank_buttons(None, None)
                self._mixer.set_select_buttons(self._track_up_button,
                                               self._track_down_button)
            else:
                self._mixer.channel_strip(index).set_mute_button(None)
                self._mixer.channel_strip(index).set_solo_button(
                    self._mute_solo_buttons[index])
                self._mixer.set_select_buttons(None, None)
                self._mixer.set_bank_buttons(self._track_up_button,
                                             self._track_down_button)
    def _init_mixer_component(self, volume_controls, trackarm_controls, mixer_options, global_channel, volume_map_mode):
        if volume_controls != None and trackarm_controls != None:
            num_strips = max(len(volume_controls), len(trackarm_controls))
            send_info = []
            momentary_buttons = False
            mixer = SpecialMixerComponent(num_strips)
            mixer.name = 'Mixer'
            mixer.master_strip().name = 'Master_Channel_Strip'
            mixer.selected_strip().name = 'Selected_Channel_Strip'
            if mixer_options != None:
                if 'MASTERVOLUME' in mixer_options.keys() and mixer_options['MASTERVOLUME'] in range(128):
                    encoder = EncoderElement(MIDI_CC_TYPE, global_channel, mixer_options['MASTERVOLUME'], volume_map_mode)
                    encoder.name = 'Master_Volume_Control'
                    mixer.master_strip().set_volume_control(encoder)
                if 'NUMSENDS' in mixer_options.keys() and mixer_options['NUMSENDS'] > 0:
                    for send in range(mixer_options['NUMSENDS']):
                        key = 'SEND' + str(send + 1)
                        raise key in mixer_options.keys() or AssertionError
                        send_info.append(mixer_options[key])

                momentary_buttons = 'NOTOGGLE' in mixer_options.keys()
                next_bank_button = None
                prev_bank_button = None
                if 'NEXTBANK' in mixer_options.keys() and mixer_options['NEXTBANK'] in range(128):
                    next_bank_button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, mixer_options['NEXTBANK'])
                    next_bank_button.name = 'Mixer_Next_Bank_Button'
                if 'PREVBANK' in mixer_options.keys() and mixer_options['PREVBANK'] in range(128):
                    prev_bank_button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, mixer_options['PREVBANK'])
                    prev_bank_button.name = 'Mixer_Previous_Bank_Button'
                mixer.set_bank_buttons(next_bank_button, prev_bank_button)
            for track in range(num_strips):
                strip = mixer.channel_strip(track)
                strip.name = 'Channel_Strip_' + str(track)
                if track in range(len(volume_controls)):
                    channel = global_channel
                    cc = volume_controls[track]
                    if isinstance(volume_controls[track], (tuple, list)):
                        cc = volume_controls[track][0]
                        if volume_controls[track][1] in range(16):
                            channel = volume_controls[track][1]
                    if cc in range(128) and channel in range(16):
                        encoder = EncoderElement(MIDI_CC_TYPE, channel, cc, volume_map_mode)
                        encoder.name = str(track) + '_Volume_Control'
                        strip.set_volume_control(encoder)
                if track in range(len(trackarm_controls)) and trackarm_controls[track] in range(128):
                    button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, trackarm_controls[track])
                    button.name = str(track) + '_Arm_Button'
                    strip.set_arm_button(button)
                send_controls = []
                for send in send_info:
                    encoder = None
                    if track in range(len(send)):
                        channel = global_channel
                        cc = send[track]
                        if isinstance(send[track], (tuple, list)):
                            cc = send[track][0]
                            if send[track][1] in range(16):
                                channel = send[track][1]
                        if cc in range(128) and channel in range(16):
                            encoder = EncoderElement(MIDI_CC_TYPE, channel, cc, volume_map_mode)
                            encoder.name = str(track) + '_Send_' + str(list(send_info).index(send)) + '_Control'
                    send_controls.append(encoder)

                strip.set_send_controls(tuple(send_controls))
Example #37
0
class QuNeo(ControlSurface):
    """ Script for Keith McMillen's QuNeo Multi-Touchpad Controller """
    __module__ = __name__
    _active_instances = []

    def _combine_active_instances():
        support_devices = False
        for instance in QuNeo._active_instances:
            support_devices |= instance._device_component != None

        track_offset = 0
        for instance in QuNeo._active_instances:
            instance._activate_combination_mode(track_offset, support_devices)
            track_offset += instance._session.width()

    _combine_active_instances = staticmethod(_combine_active_instances)

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self.set_suppress_rebuild_requests(True)
        self._suppress_session_highlight = True
        self._suppress_send_midi = True
        self._suggested_input_port = 'QUNEO'
        self._suggested_output_port = 'QUNEO'
        self.num_tracks = 7
        self.num_scenes = 4
        self.session = None
        self.mixer = None
        self.transport = None
        self.led_value = None
        self._note_input = []
        self.shift_button = None
        self.sequencer_button = None
        self.launch_button = None
        self.seq_offset_down = None
        self.seq_offset_up = None
        self.seq_offset_left = None
        self.seq_offset_right = None
        self.stop_all_clips = None
        self.track_bank_right = None
        self.track_bank_left = None
        self.scene_bank_down = None
        self.scene_bank_up = None
        self.beat_table = []
        self.sends = []
        self.arm_buttons = None
        self.mute_buttons = None
        self.solo_buttons = None
        self.shift_buttons = []
        self.sequencer_buttons = None
        self.scene_launch_buttons = None
        self.stop_track_buttons = None
        self.clip_slot_buttons = None
        self.instrument_buttons = None
        self.volume_control = None
        self.pan_control = None
        self.current_mode = 0
        self.set_shift_button(ConfigurableButtonElement(True, MIDI_NOTE_TYPE, PAD_CHANNEL, SHIFT_BUTTON, 127))
        self._setup_transport_control()
        self._setup_mixer_control()
        self._setup_session_control()
        self.session.set_mixer(self.mixer)
        self._shift_mode(0)
        self._set_mode(0)
        app = Live.Application.get_application()
        maj = app.get_major_version()
        min = app.get_minor_version()
        bug = app.get_bugfix_version()
        self.show_message(str(maj) + '.' + str(min) + '.' + str(bug))
        self.set_suppress_rebuild_requests(False)

    def disconnect(self):
        self.mixer
        self.session
        if self.shift_button != None:
            self.shift_button.remove_value_listener(self._shift_value)
            self.shift_button = None
        if self.shift_buttons != None:
            for button in self.shift_buttons:
                button.remove_value_listener(self._shift_buttons_value)

            self.shift_buttons = None
        self._note_input = None
        ControlSurface.disconnect(self)

    def refresh_state(self):
        ControlSurface.refresh_state(self)

    def set_shift_button(self, button):
        if not (button == None or isinstance(button, ButtonElement)):
            raise AssertionError
            if self.shift_button != button:
                if self.shift_button != None:
                    self.shift_button.remove_value_listener(self._shift_value)
                self.shift_button = button
                self.shift_button != None and self.shift_button.add_value_listener(self._shift_value)

    def update_mode(self, mode):
        if mode != None:
            self._set_mode(mode)
            self.current_mode = mode

    def set_shift_buttons(self, buttons):
        if buttons != None:
            if self.shift_buttons != buttons:
                self.shift_buttons.remove_value_listener(self._shift_buttons_value)
            self.shift_buttons = buttons
            if self.shift_buttons != None:
                for button in self.shift_buttons:
                    raise isinstance(button, ButtonElement) or AssertionError
                    button.add_value_listener(self._shift_buttons_value, identify_sender=True)

        else:
            if self.shift_buttons != None:
                for button in self.shift_buttons:
                    button.remove_value_listener(self._shift_buttons_value)

            self.shift_buttons = None

    def _shift_buttons_value(self, value, sender):
        raise self.shift_buttons != None or AssertionError
        raise value in range(128) or AssertionError
        mode = int(sender._note * 0.5)
        self.update_mode(mode)

    def _shift_value(self, value):
        if not value in range(128):
            raise AssertionError
            raise self.shift_button != None or AssertionError
            value != 0 and self._shift_mode(1)
            self.shift_button.turn_on()
        else:
            self._shift_mode(0)
            self.shift_button.turn_off()

    def _shift_mode(self, value):
        if value != 0:
            self.set_suppress_rebuild_requests(True)
            self._reassign_grid(0)
            self._reassign_mixer_control(1)
            self.set_suppress_rebuild_requests(False)
        else:
            None
            self._set_mode(self.current_mode)
            self._reassign_mixer_control(1)

    def _update_grid(self):
        if self.sequencer_buttons != None:
            self.session.set_sequencer_buttons(self.sequencer_buttons)
        else:
            self.session.set_sequencer_buttons(None)
        if self.seq_offset_left != None and self.seq_offset_right != None:
            self.session.set_seq_measure_offset(self.seq_offset_left, self.seq_offset_right)
        else:
            self.session.set_seq_measure_offset(None, None)
        if self.seq_offset_up != None and self.seq_offset_down != None:
            self.session.set_seq_note_offset(self.seq_offset_up, self.seq_offset_down)
        else:
            self.session.set_seq_note_offset(None, None)
        if self.launch_button != None:
            self.session.set_slot_launch_button(self.launch_button)
        else:
            self.session.set_slot_launch_button(None)
        if self.scene_launch_buttons != None:
            for index in range(len(self.scene_launch_buttons)):
                self.session.scene(index).set_launch_button(self.scene_launch_buttons[index])

        else:
            for index in range(4):
                self.session.scene(index).set_launch_button(None)

        if self.stop_track_buttons != None:
            self.session.set_stop_track_clip_buttons(tuple(self.stop_track_buttons))
        else:
            self.session.set_stop_track_clip_buttons(None)
        if self.stop_all_clips != None:
            self.session.set_stop_all_clips_button(self.stop_all_clips)
        else:
            self.session.set_stop_all_clips_button(None)
        if self.track_bank_right != None and self.track_bank_left != None:
            self.session.set_track_bank_buttons(self.track_bank_right, self.track_bank_left)
        else:
            self.session.set_track_bank_buttons(None, None)
        if self.scene_bank_up != None and self.scene_bank_down != None:
            self.session.set_scene_bank_buttons(self.scene_bank_up, self.scene_bank_down)
        else:
            self.session.set_scene_bank_buttons(None, None)
        for row in range(4):
            for col in range(7):
                self.clip = self.session.scene(row).clip_slot(col)
                if self.clip_slot_buttons != None:
                    self.clip.set_triggered_to_play_value(30)
                    self.clip.set_triggered_to_record_value(RED_HI)
                    self.clip.set_started_value(30)
                    self.clip.set_recording_value(RED_HI)
                    self.clip.set_stopped_value(80)
                    self.clip.set_triggered_to_record_value(6)
                    self.clip.set_launch_button(self.clip_slot_buttons[row][col])
                else:
                    self.clip.set_launch_button(None)

    def turn_off_all_buttons(self):
        self.arm_buttons = None
        self.mute_buttons = None
        self.solo_buttons = None
        self.scene_launch_buttons = None
        self.stop_track_buttons = None
        if self.clip_slot_buttons != None:
            for row in range(4):
                for col in range(7):
                    button = self.clip_slot_buttons[row][col]
                    button.turn_off()

        self.clip_slot_buttons = None
        if self.shift_buttons != None:
            for button in self.shift_buttons:
                button.turn_off()
                button.remove_value_listener(self._shift_buttons_value)

        if self.sequencer_buttons != None:
            for button in self.sequencer_buttons:
                button.count = 0
                button.note_on()

        self.instrument_buttons = None
        self.shift_buttons = None
        self.sequencer_buttons = None
        self.clip_slot_buttons = None
        self.launch_button = None
        self.stop_all_clips = None
        self.track_bank_left = None
        self.track_bank_right = None
        self.scene_bank_up = None
        self.scene_bank_down = None
        self.seq_offset_left = None
        self.seq_offset_right = None
        self.seq_offset_up = None
        self.seq_offset_down = None

    def _set_mode(self, mode):
        self.turn_off_all_buttons()
        if mode == 0:
            self.stop_track_buttons = []
            self.scene_launch_buttons = []
            self.track_bank_left = self.button(PAD_CHANNEL, SESSION_LEFT)
            self.track_bank_right = self.button(PAD_CHANNEL, SESSION_RIGHT)
            self.scene_bank_up = self.button(PAD_CHANNEL, SESSION_UP)
            self.scene_bank_down = self.button(PAD_CHANNEL, SESSION_DOWN)
            self.stop_all_clips = self.led_button(GRID_CHANNEL, STOP_ALL_CLIPS, 100)
            self.launch_button = self.led_button(GRID_CHANNEL, SLOT_LAUNCH, RED_HI)
            self.clip_slot_buttons = []
            for row in range(4):
                self.clip_slot_buttons.append([])
                for col in range(7):
                    self.clip_slot_buttons[row].append(self.button(GRID_CHANNEL, CLIP_NOTE_MAP[row][col]))

            self.mute_buttons = []
            self.solo_buttons = []
            self.arm_buttons = []
            for index in range(7):
                self.mute_buttons.append(self.led_button(GRID_CHANNEL, TRACK_MUTE[index], GREEN_HI))
                self.solo_buttons.append(self.led_button(GRID_CHANNEL, TRACK_SOLO[index], ORANGE_HI))
                self.arm_buttons.append(self.led_button(GRID_CHANNEL, TRACK_ARM[index], RED_HI))
                self.stop_track_buttons.append(self.led_button(GRID_CHANNEL, STOP_TRACK[index], 100))

            for scene in range(4):
                self.scene_launch_buttons.append(self.led_button(GRID_CHANNEL, SCENE_LAUNCH[scene], GREEN_LO))

            self._update_session()
            self._update_grid()
        elif mode == 1:
            self.seq_offset_left = self.button(PAD_CHANNEL, SESSION_LEFT)
            self.seq_offset_right = self.button(PAD_CHANNEL, SESSION_RIGHT)
            self.seq_offset_up = self.button(PAD_CHANNEL, SESSION_UP)
            self.seq_offset_down = self.button(PAD_CHANNEL, SESSION_DOWN)
            self.sequencer_buttons = []
            for row in range(8):
                for col in range(8):
                    self.sequencer_buttons.append(self.led_button(GRID_CHANNEL, CLIP_NOTE_MAP[row][col], GREEN_HI))

            self._update_session()
            self._update_grid()
            self.session.clear_led()
            self.session.update_notes()
            self.session.on_device_changed()
        else:
            self.track_bank_left = self.button(PAD_CHANNEL, SESSION_LEFT)
            self.track_bank_right = self.button(PAD_CHANNEL, SESSION_RIGHT)
            self.scene_bank_up = self.button(PAD_CHANNEL, SESSION_UP)
            self.scene_bank_down = self.button(PAD_CHANNEL, SESSION_DOWN)
            self._update_session()
            self._update_grid()

    def _reassign_grid(self, value):
        if value == 0:
            self.turn_off_all_buttons()
            self.shift_buttons = []
            for index in range(2):
                self.shift_buttons.append(self.led_button(GRID_CHANNEL, TRACK_ARM[index], 127))
                if index == self.current_mode:
                    self.shift_buttons[index].send_value(127, True)
                else:
                    self.shift_buttons[index].send_value(40, True)

            self._update_session()
            self._update_grid()
        else:
            None

    def button(self, channel, value):
        is_momentary = True
        if value != -1:
            return ButtonElement(is_momentary, MIDI_NOTE_TYPE, channel, value)
        else:
            return None

    def led_button(self, channel, value, vel):
        is_momentary = True
        if value != -1:
            return ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, channel, value, vel)
        else:
            return None

    def slider(self, channel, value):
        if value != -1:
            return SliderElement(MIDI_CC_TYPE, channel, value)
        else:
            return None

    def assign_encoder(self, channel, value):
        if value != -1:
            return EncoderElement(MIDI_CC_TYPE, channel, value, Live.MidiMap.MapMode.relative_two_compliment)
        else:
            return None

    def _reassign_mixer_control(self, shift_value):
        if shift_value == 1:
            for index in range(2):
                self.sends.append(self.slider(SLIDER_CHANNEL, SELECTED_SENDS[index]))

            self.volume_control = self.slider(SLIDER_CHANNEL, SELECTED_VOL)
            self.pan_control = self.slider(SLIDER_CHANNEL, SELECTED_PAN)
        if self.sends != None:
            self.mixer.selected_strip().set_send_controls(tuple(self.sends))
        else:
            self.mixer.selected_strip().set_send_controls(tuple(None))
        if self.volume_control != None:
            self.mixer.selected_strip().set_volume_control(self.volume_control)
        else:
            self.mixer.selected_strip().set_volume_control(None)
        if self.pan_control != None:
            self.mixer.selected_strip().set_pan_control(self.pan_control)
        else:
            self.mixer.selected_strip().set_pan_control(None)

    def _update_session(self):
        if self.shift_buttons != None:
            self.set_shift_buttons(self.shift_buttons)
        else:
            self.set_shift_buttons(None)
        for index in range(7):
            if self.arm_buttons != None:
                self.mixer.channel_strip(index).set_arm_button(self.arm_buttons[index])
            else:
                self.mixer.channel_strip(index).set_arm_button(None)
            if self.solo_buttons != None:
                self.mixer.channel_strip(index).set_solo_button(self.solo_buttons[index])
            else:
                self.mixer.channel_strip(index).set_solo_button(None)
            if self.mute_buttons != None:
                self.mixer.channel_strip(index).set_invert_mute_feedback(True)
                self.mixer.channel_strip(index).set_mute_button(self.mute_buttons[index])
            else:
                self.mixer.channel_strip(index).set_mute_button(None)

    def _setup_transport_control(self):
        self.transport = SpecialTransportComponent()
        self.transport.set_metronome_button(self.led_button(PAD_CHANNEL, METRONOME, 127))
        self.transport.set_play_button(self.led_button(PAD_CHANNEL, PLAY, 127))
        self.transport.set_stop_button(self.led_button(PAD_CHANNEL, STOP, 127))
        self.transport.set_record_button(self.led_button(PAD_CHANNEL, REC, 127))
        self.transport.set_overdub_button(self.led_button(PAD_CHANNEL, OVERDUB, 127))
        self.transport.set_tempo_buttons(self.led_button(PAD_CHANNEL, TEMPO_UP, 127), self.led_button(PAD_CHANNEL, TEMPO_DOWN, 127))

    def _setup_mixer_control(self):
        self.mixer = SpecialMixerComponent(self.num_tracks, self)
        self.mixer.name = 'Mixer'
        self.mixer.set_track_offset(0)
        self.mixer.set_select_buttons(self.button(PAD_CHANNEL, TRACK_RIGHT), self.button(PAD_CHANNEL, TRACK_LEFT))
        self.mixer.set_crossfader_control(self.slider(SLIDER_CHANNEL, CROSSFADER))
        for index in range(4):
            self.mixer.channel_strip(index).set_volume_control(self.slider(SLIDER_CHANNEL, TRACK_VOL[index]))

        self.num_o_tracks = self.song().visible_tracks
        if self.num_o_tracks != None:
            index_count = -1
            index_table = []
            for index in self.song().visible_tracks:
                index_count += 1
                if index.has_midi_output != True:
                    index_table.append(index_count)
                else:
                    None

            if index_table != None:
                for index in range(len(index_table)):
                    x = index_table[index]
                    if x > 3:
                        None
                    else:
                        None

    def _setup_session_control(self):
        self.session = SpecialSessionComponent(self.num_tracks, self.num_scenes, self)
        self.session.set_offsets(0, 0)
        self.session.set_select_buttons(self.button(PAD_CHANNEL, SCENE_DOWN), self.button(PAD_CHANNEL, SCENE_UP))
        self.session.set_clip_loop_start(self.slider(SLIDER_CHANNEL, 6))
        self.session.set_clip_loop_length(self.slider(SLIDER_CHANNEL, 7))

    def _on_selected_scene_changed(self):
        ControlSurface._on_selected_scene_changed(self)

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)

    def _activate_combination_mode(self, track_offset, support_devices):
        self._session.link_with_track_offset(track_offset)
Example #38
0
class AumPC20(APC):
	__doc__ = " Script for Akai's APC20 Controller "


	def __init__(self, c_instance):
		self._shift_modes = None
		APC.__init__(self, c_instance)
		return None
	

	def disconnect(self):
		self._shift_modes = None
		APC.disconnect(self)
		return None
	

	def _activate_combination_mode(self, track_offset, support_devices):
		APC._activate_combination_mode(self, track_offset, support_devices)
		if support_devices:
			self._shift_modes.invert_assignment()
	

	def _setup_session_control(self):
		is_momentary = True
		self._shift_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81, self)		   
		self._session = APCSessionComponent(8, 5)
		self._session.name = 'Session_Control'
		self._matrix = ButtonMatrixElement()
		self._matrix.name = 'Button_Matrix'
		scene_launch_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82), self) for index in range(5) ]
		self._scene_launch_buttons = scene_launch_buttons
		track_stop_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52, self) for index in range(8) ]
		self._track_stop_buttons = track_stop_buttons
		for index in range(len(scene_launch_buttons)):
			scene_launch_buttons[index].name = 'Scene_'+ str(index) + '_Launch_Button'
		for index in range(len(track_stop_buttons)):
			track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button'
		self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
		self._session.set_stop_track_clip_value(2)
		for scene_index in range(5):
			scene = self._session.scene(scene_index)
			scene.name = 'Scene_' + str(scene_index)
			button_row = []
			scene.set_launch_button(scene_launch_buttons[scene_index])
			scene.set_triggered_value(2)
			for track_index in range(8):
				button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53), self)
				button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button'
				button_row.append(button)
				clip_slot = scene.clip_slot(track_index)
				clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index)
				clip_slot.set_triggered_to_play_value(2)
				clip_slot.set_triggered_to_record_value(4)
				clip_slot.set_stopped_value(5)
				clip_slot.set_started_value(1)
				clip_slot.set_recording_value(3)
				clip_slot.set_launch_button(button)

			self._matrix.add_row(tuple(button_row))
		self._session.selected_scene().name = 'Selected_Scene'
		self._session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
		self._session_zoom = ShiftableZoomingComponent(self._session, tuple(track_stop_buttons))
		self._session_zoom.name = 'Session_Overview'
		self._session_zoom.set_button_matrix(self._matrix)
		self._session_zoom.set_zoom_button(self._shift_button)
		self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
		self._session_zoom.set_stopped_value(3)
		self._session_zoom.set_selected_value(5)
	

	def _setup_mixer_control(self):
		is_momentary = True
		self._mixer = SpecialMixerComponent(8)
		self._mixer.name = 'Mixer'
		self._mixer.master_strip().name = 'Master_Channel_Strip'
		self._mixer.selected_strip().name = 'Selected_Channel_Strip'
		self._solo_buttons = []
		for track in range(8):
			strip = self._mixer.channel_strip(track)
			strip.name = 'Channel_Strip_' + str(track)
			solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, self)
			self._solo_buttons.append(solo_button)
			mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)
			solo_button.name = str(track) + '_Solo_Button'
			mute_button.name = str(track) + '_Mute_Button'
			strip.set_solo_button(solo_button)
			strip.set_mute_button(mute_button)
			strip.set_shift_button(self._shift_button)
			strip.set_invert_mute_feedback(True)
		master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
		prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
		master_volume_control.name = 'Master_Volume_Control'
		prehear_control.name = 'Prehear_Volume_Control'
		self._mixer.set_prehear_volume_control(prehear_control)
		self._mixer.master_strip().set_volume_control(master_volume_control)
	

	def _setup_custom_components(self):
		is_momentary = True
		master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80)
		self._master_select_button = master_select_button
		master_select_button.name = 'Master_Select_Button'
		select_buttons = []
		self._select_buttons = []
		arm_buttons = []
		sliders = []
		for track in range(8):
			select_buttons.append(FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51, self))
			self._select_buttons.append(select_buttons[track])
			arm_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48))
			if track is 7:
				self._user3 = arm_buttons[track]
			sliders.append(MonoEncoderElement2(MIDI_CC_TYPE, track, 7, Live.MidiMap.MapMode.absolute, 'Slider_' + str(track), track, self))
			#sliders.append(MonoEncoderElement2(MIDI_CC_TYPE, track, 7))
			select_buttons[-1].name = str(track) + '_Select_Button'
			arm_buttons[-1].name = str(track) + '_Arm_Button'
			#sliders[-1].name = str(track) + '_Volume_Control'
		transport = TransportComponent()
		transport.name = 'Transport'
		slider_modes = SliderModesComponent(self._mixer, tuple(sliders))
		slider_modes.name = 'Slider_Modes'
		self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message, self)
		self._shift_modes.name = 'Shift_Modes'
		self._shift_modes.set_mode_toggle(self._shift_button)
	

	def _product_model_id_byte(self):
		return 123
	

	def _setup_monobridge(self):
		self._monobridge = MonoBridgeElement(self)
		self._monobridge.name = 'MonoBridge'
	

	def _setup_monomod(self):
		self._host = MonomodComponent(self)
		self._host.name = 'Monomod_Host'
		self._host._set_nav_buttons = self._mod_set_nav_buttons(self._host)
		self._host._update_nav_buttons = self._mod_update_nav_buttons(self._host)
		self._host._set_nav_buttons = self._mod_set_nav_buttons(self._host)
		self.hosts = [self._host]
		self._monomod = ButtonMatrixElement()
		self._monomod.name = 'Monomod'
		for row in range(5):
			button_row = []
			for column in range(8):
				button_row.append(self._matrix.get_button(column, row))
			self._monomod.add_row(tuple(button_row))
		self._monomod.add_row(tuple(self._track_stop_buttons))
		self._monomod.add_row(tuple(self._select_buttons))
		self._monomod.add_row(tuple(self._solo_buttons))
		self._monomod_mode = MonomodModeComponent(self._monomod_mode_update, self)
		self._monomod_mode.name = "Monomod_Mode_Component"
	

	def _monomod_mode_update(self):
		if(self._monomod_mode._mode_index == 0) or (self._host._active_client == None):
			self.flash_status = 0
			self._host.set_enabled(False)
			self._host._set_button_matrix(None)
			#self._host._set_nav_buttons(None)
			self._host._set_lock_button(None)
			self._host._set_alt_button(None)
			self._host._set_shift_button(None)
			self._host._set_nav_buttons(None)
			self._scene_launch_buttons[2].set_on_off_values(127, 0)	
			self._scene_launch_buttons[3].set_on_off_values(127, 0)	
			self._monomod.reset()
			self._shift_modes.set_enabled(True)
			#self._session.set_track_bank_buttons(self._right_button, self._left_button)
			#self._session.set_scene_bank_buttons(self._down_button, self._up_button)
			for track in range(8):
				self._mixer.channel_strip(track).set_select_button(self._select_buttons[track])
				self._mixer.channel_strip(track).set_solo_button(self._solo_buttons[track])
			#self._transport.set_nudge_buttons(self._nudge_up_button, self._nudge_down_button)
			self._session.set_enabled(True)
			self._session_zoom._is_zoomed_out = False
			self._session_zoom.set_enabled(True)
			self.request_rebuild_midi_map()
			self._master_select_button.turn_off()
			
		elif(self._monomod_mode._mode_index == 1):
			if self._shift_modes._note_mode_active is True:
				self._shift_modes._mode_callback(ABLETON_MODE)
				self._shift_modes._note_mode_active = False
				self._session_zoom.set_ignore_buttons(False)
				self._shift_modes._transport.update()
				self._shift_modes._on_note_mode_changed()
			#self._transport.set_nudge_buttons(None, None)
			self._shift_modes.set_enabled(False)
			for track in range(8):
				self._mixer.channel_strip(track).set_select_button(None)
				self._mixer.channel_strip(track).set_solo_button(None)
			for scene in range(5):
				self._scene_launch_buttons[scene].turn_off()
			self._session.set_enabled(False)
			self._session_zoom.set_enabled(False)
			#self._session.set_track_bank_buttons(None, None)
			#self._session.set_scene_bank_buttons(None, None)
			self.flash_status = 1
			self._monomod.reset()
			self._host._set_button_matrix(self._monomod)
			#self._host._set_nav_buttons([self._up_button, self._down_button, self._left_button, self._right_button])
			self._host._set_shift_button(self._shift_button)
			self._host._set_lock_button(self._scene_launch_buttons[0])
			self._host._set_alt_button(self._scene_launch_buttons[1])
			self._host._set_nav_buttons([self._scene_launch_buttons[2], self._scene_launch_buttons[3]])
			self._host.set_enabled(True)
			self.request_rebuild_midi_map()
			self._master_select_button.turn_on()
	

	"""m4l bridge"""
	def generate_strip_string(self, display_string):
		#self.log_message(display_string)
		NUM_CHARS_PER_DISPLAY_STRIP = 12
		if (not display_string):
			return (' ' * NUM_CHARS_PER_DISPLAY_STRIP)
		if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))):
			display_string = display_string[:-2]
		if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)):
			for um in [' ',
			 'i',
			 'o',
			 'u',
			 'e',
			 'a']:
				while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)):
					um_pos = display_string.rfind(um, 1)
					display_string = (display_string[:um_pos] + display_string[(um_pos + 1):])
		else:
			display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1))
		ret = u''
		for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)):
			if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)):
				ret += ' '
			else:
				ret += display_string[i]

		ret += ' '
		assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP)
		return ret
	

	def notification_to_bridge(self, name, value, sender):
		if isinstance(sender, MonoEncoderElement2):
			self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name)))
			self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value)))
	

	def touched(self):
		if self._touched is 0:
			self._monobridge._send('touch', 'on')
			self.schedule_message(2, self.check_touch)
		self._touched +=1
	

	def check_touch(self):
		if self._touched > 5:
			self._touched = 5
		elif self._touched > 0:
			self._touched -= 1
		if self._touched is 0:
			self._monobridge._send('touch', 'off')
		else:
			self.schedule_message(2, self.check_touch)
	

	def get_clip_names(self):
		clip_names = []
		for scene in self._session._scenes:
			for clip_slot in scene._clip_slots:
				if clip_slot.has_clip() is True:
					clip_names.append(clip_slot._clip_slot)##.clip.name)
					return clip_slot._clip_slot
					##self.log_message(str(clip_slot._clip_slot.clip.name))
		return clip_names
	



	def update_display(self):
		""" Live -> Script
		Aka on_timer. Called every 100 ms and should be used to update display relevant
		parts of the controller
		"""
		for message in self._scheduled_messages:
			message['Delay'] -= 1
			if (message['Delay'] == 0):
				if (message['Parameter'] != None):
					message['Message'](message['Parameter'])
				else:
					message['Message']()
					del self._scheduled_messages[self._scheduled_messages.index(message)]

		for callback in self._timer_callbacks:
			callback()
		self._timer = (self._timer + 1) % 256
		self.flash()
	

	def flash(self):
		if(self.flash_status > 0):
			for row in range(8):
				for column in range(8):
					button = self._monomod.get_button(column, row)
					if(button._flash_state > 0):
						button.flash(self._timer)
	


### Mod Overrides ####

	def _mod_set_nav_buttons(self, mod):	
		def _set_nav_buttons(buttons):
			if mod._nav_buttons != None:
				mod._nav_buttons[0].remove_value_listener(mod._nav_up_value)
				mod._nav_buttons[1].remove_value_listener(mod._nav_down_value)
			mod._nav_buttons = buttons
			if buttons != None:
				assert len(buttons) == 2
				for button in buttons:
					assert isinstance(button, FlashingButtonElement)
				mod._nav_buttons[0].set_on_off_values(8, 2)	
				mod._nav_buttons[0].add_value_listener(mod._nav_up_value)
				mod._nav_buttons[1].set_on_off_values(8, 2)	
				mod._nav_buttons[1].add_value_listener(mod._nav_down_value)
		return _set_nav_buttons
	

	def _mod_update_nav_buttons(self, mod):
		def _update_nav_buttons():
			if mod._nav_buttons != None:
				if(mod._y > 0):
					mod._nav_buttons[0].turn_on()
				else:
					mod._nav_buttons[0].turn_off()
				if(mod._y < 8):
					mod._nav_buttons[1].turn_on()
				else:
					mod._nav_buttons[1].turn_off() 
		return _update_nav_buttons
Example #39
0
class Serato(ControlSurface):

    def __init__(self, c_instance):
        publish_in_cs_list = True
        ControlSurface.__init__(self, c_instance, not publish_in_cs_list)
        self._device_selection_follows_track_selection = True
        with self.component_guard():
            self._matrix = None
            self._session = None
            self._mixer = None
            self._device = None
            self._scene_launch_buttons = None
            self._track_arm_buttons = None
            self._track_solo_buttons = None
            self._track_mute_buttons = None
            self._track_stop_buttons = None
            self._track_select_buttons = None
            self._device_on_off_button = None
            self._shift_button = None
            self._serato_interface = PySCAClipControl()
            self._serato_interface.PySCA_InitializeClipControl()
            self._setup_session_control()
            self._setup_mixer_control()
            self._setup_device_control()
            self._session.set_mixer(self._mixer)
            self.set_highlighting_session_component(self._session)
        return

    def disconnect(self):
        ControlSurface.disconnect(self)
        self._serato_interface.PySCA_DeinitializeClipControl()
        self._serato_interface = None
        return

    def connect_script_instances(self, instanciated_scripts):
        """ Called by the Application as soon as all scripts are initialized.
            You can connect yourself to other running scripts here, as we do it
            connect the extension modules (MackieControlXTs).
        """
        for control_surface in self._control_surfaces():
            control_surface_session = control_surface.highlighting_session_component()
            if control_surface_session:
                self._session.sync_to(control_surface_session)
                self._on_track_list_changed()
                break

    def build_midi_map(self, midi_map_handle):
        pass

    def update_display(self):
        ControlSurface.update_display(self)
        while self._serato_interface.PySCA_HasIncomingEvent():
            new_event = self._serato_interface.PySCA_GetIncomingEvent()
            if not self._handle_session_event(new_event):
                if not self._handle_mixer_event(new_event):
                    if not self._handle_device_event(new_event):
                        print 'Unhandled Event: ' + str(new_event)

    def _setup_session_control(self):
        is_momentary = True
        self._session = SpecialSessionComponent(NUM_TRACKS, NUM_SCENES)
        self._session.set_serato_interface(self._serato_interface)
        self._matrix = ButtonMatrixElement()
        self._scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_SCENES) ]
        self._track_stop_buttons = [ ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_TRACKS) ]
        stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
        self._session.set_stop_all_clips_button(stop_all_button)
        self._session.set_stop_track_clip_buttons(tuple(self._track_stop_buttons))
        for scene_index in range(NUM_SCENES):
            scene = self._session.scene(scene_index)
            button_row = []
            scene.set_launch_button(self._scene_launch_buttons[scene_index])
            scene.set_index(scene_index)
            scene.set_serato_interface(self._serato_interface)
            for track_index in range(NUM_TRACKS):
                button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(button)
                clip_slot.set_serato_interface(self._serato_interface)

            self._matrix.add_row(tuple(button_row))

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(NUM_TRACKS)
        self._mixer.set_serato_interface(self._serato_interface)
        self._mixer.master_strip().set_serato_interface(self._serato_interface)
        self._track_arm_buttons = []
        self._track_solo_buttons = []
        self._track_mute_buttons = []
        self._track_select_buttons = []
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0)
        for track in range(NUM_TRACKS):
            strip = self._mixer.channel_strip(track)
            strip.set_serato_interface(self._serato_interface)
            self._track_arm_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_solo_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_mute_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            self._track_select_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0))
            strip.set_arm_button(self._track_arm_buttons[-1])
            strip.set_solo_button(self._track_solo_buttons[-1])
            strip.set_mute_button(self._track_mute_buttons[-1])
            strip.set_select_button(self._track_select_buttons[-1])
            strip.set_shift_button(self._shift_button)

    def _setup_device_control(self):
        is_momentary = True
        self._device_on_off_button = ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)
        self._device = SpecialDeviceComponent()
        self._device.set_serato_interface(self._serato_interface)
        self._device.set_parameter_controls(tuple([ SliderElement(MIDI_CC_TYPE, 0, 0) for index in range(NUM_PARAMS) ]))
        self._device.set_on_off_button(self._device_on_off_button)
        self.set_device_component(self._device)

    def _handle_session_event(self, event):
        result = False
        if event.type in CLIP_EVENTS:
            value = 127 * int(event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventClipPlayedDown)
            track_index = event.key1 - 1
            scene_index = event.key2 - 1
            if track_index in range(NUM_TRACKS) and scene_index in range(NUM_SCENES):
                self._matrix.get_button(track_index, scene_index).receive_value(value)
            result = True
        elif event.type in SCENE_EVENTS:
            value = 127 * int(event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventScenePlayedDown)
            scene_index = event.key1 - 1
            if scene_index in range(NUM_SCENES):
                self._scene_launch_buttons[scene_index].receive_value(value)
            result = True
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixSizeChanged:
            new_width = event.key1
            new_height = event.key2
            self._session.set_size(new_width, new_height)
            result = True
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixOffsetChanged:
            x_increment = event.key1
            y_increment = event.key2
            self._session.move_by(x_increment, y_increment)
            result = True
        return result

    def _handle_mixer_event(self, event):
        result = True
        track_index = event.key1 - 1
        value = event.key2
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackMasterGainChange:
            self._mixer.master_strip().set_track_volume(fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackStopped:
            self.song().stop_all_clips()
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackSelect:
            self.song().view.selected_track = self.song().master_track
        else:
            result = track_index in range(NUM_TRACKS) and self._handle_strip_event(event)
        return result

    def _handle_strip_event(self, event):
        result = True
        track_index = event.key1 - 1
        value = event.key2
        if value == 0:
            self._shift_button.receive_value(127)
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSolo:
            self._track_solo_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackRecord:
            self._track_arm_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackActive:
            self._track_mute_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackStopped:
            self._track_stop_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSelect:
            self._track_select_buttons[track_index].receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackGainChange:
            self._mixer.channel_strip(track_index).set_track_volume(fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendAChange:
            self._mixer.channel_strip(track_index).set_send(0, fixed_value(value))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendBChange:
            self._mixer.channel_strip(track_index).set_send(1, fixed_value(value))
        else:
            result = False
        self._shift_button.receive_value(0)
        return result

    def _handle_device_event(self, event):
        result = True
        if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceValueChanged:
            self._device.set_parameter_value(event.key1 - 1, fixed_value(event.key2))
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceActivate:
            self._device_on_off_button.receive_value(127)
        elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceFocusMove:
            self._move_device_focus(event.key1)
        else:
            result = False
        return result

    def _move_device_focus(self, increment):
        if not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain'):
            self.application().view.show_view('Detail')
            self.application().view.show_view('Detail/DeviceChain')
        else:
            modifier_pressed = True
            direction = Live.Application.Application.View.NavDirection.left
            if increment > 0:
                direction = Live.Application.Application.View.NavDirection.right
            self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)
Example #40
0
class Launchkey(ControlSurface):
    """ Script for Novation's Launchkey 25/49/61 keyboards """

    def __init__(self, c_instance, control_factory = LaunchkeyControlFactory(), identity_response = SIZE_RESPONSE):
        ControlSurface.__init__(self, c_instance)
        self._control_factory = control_factory
        self._identity_response = identity_response
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = 'Launchkey InControl'
            self._suggested_output_port = 'Launchkey InControl'
            self._has_sliders = True
            self._current_midi_map = None
            self._master_slider = make_slider(7, 'Master_Volume_Control')
            self._modes_buttons = []
            for index in range(3):
                button = ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, 0, 13 + index)
                self._modes_buttons.append(button)
                self._modes_buttons[-1].add_value_listener(self._dummy_listener)

            self._setup_mixer()
            self._setup_session()
            self._setup_transport()
            self._setup_device()
            self._setup_navigation()
            for component in self.components:
                component.set_enabled(False)

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self.schedule_message(2, self._send_midi, LIVE_MODE_ON)
        self.schedule_message(3, self._send_midi, SIZE_QUERY)

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:11] == self._identity_response:
            self._has_sliders = midi_bytes[11] != 48
            self._send_midi(LED_FLASHING_ON)
            self._update_mixer_offset()
            for control in self.controls:
                if isinstance(control, InputControlElement):
                    control.clear_send_cache()

            for component in self.components:
                component.set_enabled(True)

            if self._has_sliders:
                self._mixer.master_strip().set_volume_control(self._master_slider)
                self._mixer.update()
            else:
                self._mixer.master_strip().set_volume_control(None)
                for index in range(len(self._sliders)):
                    self._mixer.channel_strip(index).set_volume_control(None)
                    self._mixer.channel_strip(index).set_mute_button(None)
                    slider = self._sliders[index]
                    slider.release_parameter()

                self._mixer.selected_strip().set_volume_control(self._master_slider)
            self.request_rebuild_midi_map()

    def disconnect(self):
        ControlSurface.disconnect(self)
        for button in self._modes_buttons:
            if button.value_has_listener(self._dummy_listener):
                button.remove_value_listener(self._dummy_listener)

        self._modes_buttons = None
        self._encoders = None
        self._sliders = None
        self._strip_buttons = None
        self._master_slider = None
        self._current_midi_map = None
        self._transport_view_modes = None
        self._send_midi(LED_FLASHING_OFF)
        self._send_midi(LIVE_MODE_OFF)

    def build_midi_map(self, midi_map_handle):
        self._current_midi_map = midi_map_handle
        ControlSurface.build_midi_map(self, midi_map_handle)

    def _setup_mixer(self):
        mute_solo_flip_button = make_button(59, 'Master_Button')
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.master_strip().set_volume_control(self._master_slider)
        self._sliders = []
        self._strip_buttons = []
        for index in range(8):
            strip = self._mixer.channel_strip(index)
            strip.name = 'Channel_Strip_' + str(index)
            strip.set_invert_mute_feedback(True)
            self._sliders.append(make_slider(41 + index, 'Volume_Control_%d' % index))
            strip.set_volume_control(self._sliders[-1])
            self._strip_buttons.append(make_button(51 + index, 'Mute_Button_%d' % index))

        self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)

    def _setup_session(self):
        scene_launch_button = self._control_factory.create_scene_launch_button()
        scene_stop_button = self._control_factory.create_scene_stop_button()
        self._session = SessionComponent(8, 0)
        self._session.name = 'Session_Control'
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(scene_launch_button)
        self._session.selected_scene().set_triggered_value(GREEN_BLINK)
        self._session.set_stop_all_clips_button(scene_stop_button)
        scene_stop_button.set_on_off_values(AMBER_FULL, LED_OFF)
        self._session.set_mixer(self._mixer)
        self._session.set_stop_clip_value(AMBER_HALF)
        self._session.set_stop_clip_triggered_value(GREEN_BLINK)
        clip_launch_buttons = []
        clip_stop_buttons = []
        for index in range(8):
            clip_launch_buttons.append(self._control_factory.create_clip_launch_button(index))
            clip_stop_buttons.append(self._control_factory.create_clip_stop_button(index))
            clip_slot = self._session.selected_scene().clip_slot(index)
            clip_slot.set_triggered_to_play_value(GREEN_BLINK)
            clip_slot.set_triggered_to_record_value(RED_BLINK)
            clip_slot.set_stopped_value(AMBER_FULL)
            clip_slot.set_started_value(GREEN_FULL)
            clip_slot.set_recording_value(RED_FULL)
            clip_slot.set_launch_button(clip_launch_buttons[-1])
            clip_slot.name = 'Selected_Clip_Slot_' + str(index)

        self._session.set_stop_track_clip_buttons(tuple(clip_stop_buttons))

    def _setup_transport(self):
        rwd_button = make_button(112, 'Rwd_Button')
        ffwd_button = make_button(113, 'FFwd_Button')
        stop_button = make_button(114, 'Stop_Button')
        play_button = make_button(115, 'Play_Button')
        loop_button = make_button(116, 'Loop_Button')
        rec_button = make_button(117, 'Record_Button')
        transport = TransportComponent()
        transport.name = 'Transport'
        transport.set_stop_button(stop_button)
        transport.set_play_button(play_button)
        transport.set_record_button(rec_button)
        transport.set_loop_button(loop_button)
        self._transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button)
        self._transport_view_modes.name = 'Transport_View_Modes'

    def _setup_device(self):
        encoders = [ make_encoder(21 + index, 'Device_Control_%d' % index) for index in xrange(8) ]
        self._encoders = tuple(encoders)
        device = DeviceComponent()
        device.name = 'Device_Component'
        self.set_device_component(device)
        device.set_parameter_controls(self._encoders)

    def _setup_navigation(self):
        self._next_track_button = self._control_factory.create_next_track_button()
        self._prev_track_button = self._control_factory.create_prev_track_button()
        self._session_navigation = SessionNavigationComponent(name='Session_Navigation')
        self._session_navigation.set_next_track_button(self._next_track_button)
        self._session_navigation.set_prev_track_button(self._prev_track_button)

    def _dummy_listener(self, value):
        pass

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._update_mixer_offset()

    def _update_mixer_offset(self):
        all_tracks = self._session.tracks_to_use()
        selected_track = self.song().view.selected_track
        num_strips = self._session.width()
        if selected_track in all_tracks:
            track_index = list(all_tracks).index(selected_track)
            new_offset = track_index - track_index % num_strips
            self._session.set_offsets(new_offset, self._session.scene_offset())
class Novation_Impulse(ControlSurface):
    """ Script for Novation's Impulse keyboards """
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = 'Impulse'
            self._suggested_output_port = 'Impulse'
            self._has_sliders = True
            self._current_midi_map = None
            self._display_reset_delay = -1
            self._shift_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0,
                                               39)
            self._preview_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0,
                                                 41)
            self._master_slider = SliderElement(MIDI_CC_TYPE, 0, 8)
            self._shift_button.name = 'Shift_Button'
            self._master_slider.name = 'Master_Volume_Control'
            self._master_slider.add_value_listener(self._slider_value,
                                                   identify_sender=True)
            self._preview_button.add_value_listener(self._preview_value)
            self._setup_mixer()
            self._setup_session()
            self._setup_transport()
            self._setup_device()
            self._setup_name_display()
            device_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1,
                                          10)
            mixer_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1, 9)
            device_button.name = 'Encoder_Device_Mode'
            mixer_button.name = 'Encoder_Mixer_Mode'
            self._encoder_modes = EncoderModeSelector(self._device_component,
                                                      self._mixer,
                                                      self._next_bank_button,
                                                      self._prev_bank_button,
                                                      self._encoders)
            self._encoder_modes.set_device_mixer_buttons(
                device_button, mixer_button)
            self._string_to_display = None
            for component in self.components:
                component.set_enabled(False)

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self.schedule_message(3, self._send_midi,
                              SYSEX_START + (6, 1, 1, 1, 247))

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:-2] == SYSEX_START + (7, ) and midi_bytes[-2] != 0:
            self._has_sliders = midi_bytes[-2] != 25
            self.schedule_message(1, self._show_startup_message)
            for control in self.controls:
                if isinstance(control, InputControlElement):
                    control.clear_send_cache()

            for component in self.components:
                component.set_enabled(True)

            if self._has_sliders:
                self._mixer.master_strip().set_volume_control(
                    self._master_slider)
                self._mixer.update()
            else:
                self._mixer.master_strip().set_volume_control(None)
                self._mixer.selected_strip().set_volume_control(
                    self._master_slider)
                for index in range(len(self._sliders)):
                    self._mixer.channel_strip(index).set_volume_control(None)
                    slider = self._sliders[index]
                    slider.release_parameter()
                    if slider.value_has_listener(self._slider_value):
                        slider.remove_value_listener(self._slider_value)

            self._encoder_modes.set_provide_volume_mode(not self._has_sliders)
            self.request_rebuild_midi_map()

    def disconnect(self):
        self._name_display_data_source.set_display_string('  ')
        for encoder in self._encoders:
            encoder.remove_value_listener(self._encoder_value)

        self._master_slider.remove_value_listener(self._slider_value)
        if self._has_sliders:
            for slider in tuple(self._sliders):
                slider.remove_value_listener(self._slider_value)

        for button in self._strip_buttons:
            button.remove_value_listener(self._mixer_button_value)

        self._preview_button.remove_value_listener(self._preview_value)
        ControlSurface.disconnect(self)
        self._encoders = None
        self._sliders = None
        self._strip_buttons = None
        self._master_slider = None
        self._current_midi_map = None
        self._shift_button = None
        self._name_display = None
        self._prev_bank_button = None
        self._next_bank_button = None
        self._encoder_modes = None
        self._transport_view_modes = None
        self._send_midi(SYSEX_START + (6, 0, 0, 0, 247))

    def build_midi_map(self, midi_map_handle):
        self._current_midi_map = midi_map_handle
        ControlSurface.build_midi_map(self, midi_map_handle)

    def update_display(self):
        ControlSurface.update_display(self)
        if self._string_to_display != None:
            self._name_display_data_source.set_display_string(
                self._string_to_display)
            self._string_to_display = None
        if self._display_reset_delay >= 0:
            self._display_reset_delay -= 1
            if self._display_reset_delay == -1:
                self._show_current_track_name()

    def _setup_mixer(self):
        mute_solo_flip_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE,
                                              0, 34)
        self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0,
                                              37)
        self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0,
                                              38)
        self._strip_buttons = []
        mute_solo_flip_button.name = 'Mute_Solo_Flip_Button'
        self._next_nav_button.name = 'Next_Track_Button'
        self._prev_nav_button.name = 'Prev_Track_Button'
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.set_select_buttons(self._next_nav_button,
                                       self._prev_nav_button)
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.master_strip().set_volume_control(self._master_slider)
        self._sliders = []
        for index in range(8):
            strip = self._mixer.channel_strip(index)
            strip.name = 'Channel_Strip_' + str(index)
            strip.set_invert_mute_feedback(True)
            self._sliders.append(SliderElement(MIDI_CC_TYPE, 0, index))
            self._sliders[-1].name = str(index) + '_Volume_Control'
            self._sliders[-1].set_feedback_delay(-1)
            self._sliders[-1].add_value_listener(self._slider_value,
                                                 identify_sender=True)
            strip.set_volume_control(self._sliders[-1])
            self._strip_buttons.append(
                ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + index))
            self._strip_buttons[-1].name = str(index) + '_Mute_Button'
            self._strip_buttons[-1].add_value_listener(
                self._mixer_button_value, identify_sender=True)

        self._mixer.master_strip().set_mute_button(
            ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 17))
        self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons),
                                                mute_solo_flip_button)

    def _setup_session(self):
        num_pads = len(PAD_TRANSLATIONS)
        self._session = SessionComponent(8, 0)
        self._session.name = 'Session_Control'
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.set_mixer(self._mixer)
        self._session.set_track_banking_increment(num_pads)
        self._session.set_track_bank_buttons(
            ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 35),
            ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 36))
        pads = []
        for index in range(num_pads):
            pads.append(
                ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 60 + index))
            pads[-1].name = 'Pad_' + str(index)
            clip_slot = self._session.selected_scene().clip_slot(index)
            clip_slot.set_triggered_to_play_value(GREEN_BLINK)
            clip_slot.set_triggered_to_record_value(RED_BLINK)
            clip_slot.set_stopped_value(AMBER_FULL)
            clip_slot.set_started_value(GREEN_FULL)
            clip_slot.set_recording_value(RED_FULL)
            clip_slot.set_launch_button(pads[-1])
            clip_slot.name = str(index) + '_Selected_Clip_Slot'

    def _setup_transport(self):
        rwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 27)
        ffwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 28)
        stop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 29)
        play_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 30)
        loop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 31)
        rec_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 32)
        ffwd_button.name = 'FFwd_Button'
        rwd_button.name = 'Rwd_Button'
        loop_button.name = 'Loop_Button'
        play_button.name = 'Play_Button'
        stop_button.name = 'Stop_Button'
        rec_button.name = 'Record_Button'
        transport = ShiftableTransportComponent()
        transport.name = 'Transport'
        transport.set_stop_button(stop_button)
        transport.set_play_button(play_button)
        transport.set_record_button(rec_button)
        transport.set_shift_button(self._shift_button)
        self._transport_view_modes = TransportViewModeSelector(
            transport, self._session, ffwd_button, rwd_button, loop_button)
        self._transport_view_modes.name = 'Transport_View_Modes'

    def _setup_device(self):
        encoders = []
        for index in range(8):
            encoders.append(
                PeekableEncoderElement(
                    MIDI_CC_TYPE, 1, index,
                    Live.MidiMap.MapMode.relative_binary_offset))
            encoders[-1].set_feedback_delay(-1)
            encoders[-1].add_value_listener(self._encoder_value,
                                            identify_sender=True)
            encoders[-1].name = 'Device_Control_' + str(index)

        self._encoders = tuple(encoders)
        self._prev_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1,
                                               12)
        self._next_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1,
                                               11)
        self._prev_bank_button.name = 'Device_Bank_Down_Button'
        self._next_bank_button.name = 'Device_Bank_Up_Button'
        device = DeviceComponent()
        device.name = 'Device_Component'
        self.set_device_component(device)
        device.set_parameter_controls(self._encoders)
        device.set_bank_nav_buttons(self._prev_bank_button,
                                    self._next_bank_button)

    def _setup_name_display(self):
        self._name_display = PhysicalDisplayElement(16, 1)
        self._name_display.name = 'Display'
        self._name_display.set_message_parts(SYSEX_START + (8, ), (247, ))
        self._name_display_data_source = DisplayDataSource()
        self._name_display.segment(0).set_data_source(
            self._name_display_data_source)

    def _encoder_value(self, value, sender):
        if not sender in self._encoders:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                display_string = self._device_component.is_enabled() and ' - '
                display_string = sender.mapped_parameter(
                ) != None and sender.mapped_parameter().name
            self._set_string_to_display(display_string)

    def _slider_value(self, value, sender):
        if not sender in tuple(self._sliders) + (self._master_slider, ):
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                if self._mixer.is_enabled():
                    display_string = ' - '
                    if sender.mapped_parameter() != None:
                        master = self.song().master_track
                        tracks = self.song().tracks
                        returns = self.song().return_tracks
                        track = None
                        if sender == self._master_slider:
                            track = self._has_sliders and master
                        else:
                            track = self.song().view.selected_track
                    else:
                        track = self._mixer.channel_strip(
                            self._sliders.index(sender))._track
                    display_string = track == master and 'Master'
                elif track in tracks:
                    display_string = str(list(tracks).index(track) + 1)
                elif track in returns:
                    display_string = str(
                        chr(ord('A') + list(returns).index(track)))
                else:
                    raise False or AssertionError
                display_string += ' Volume'
            self._set_string_to_display(display_string)

    def _mixer_button_value(self, value, sender):
        if not value in range(128):
            raise AssertionError
            if self._mixer.is_enabled() and value > 0:
                strip = self._mixer.channel_strip(
                    self._strip_buttons.index(sender))
                self._string_to_display = strip != None and None
                self._name_display.segment(0).set_data_source(
                    strip.track_name_data_source())
                self._name_display.update()
                self._display_reset_delay = STANDARD_DISPLAY_DELAY
            else:
                self._set_string_to_display(' - ')

    def _preview_value(self, value):
        raise value in range(128) or AssertionError
        for encoder in self._encoders:
            encoder.set_peek_mode(value > 0)

    def _show_current_track_name(self):
        if self._name_display != None and self._mixer != None:
            self._string_to_display = None
            self._name_display.segment(0).set_data_source(
                self._mixer.selected_strip().track_name_data_source())
            self._name_display.update()

    def _show_startup_message(self):
        self._name_display.display_message('LIVE')
        self._display_reset_delay = INITIAL_DISPLAY_DELAY

    def _set_string_to_display(self, string_to_display):
        raise isinstance(string_to_display, (str, unicode)) or AssertionError
        self._name_display.segment(0).set_data_source(
            self._name_display_data_source)
        self._string_to_display = string_to_display
        self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._show_current_track_name()
        all_tracks = self._has_sliders or self._session.tracks_to_use()
        selected_track = self.song().view.selected_track
        num_strips = self._session.width()
        if selected_track in all_tracks:
            track_index = list(all_tracks).index(selected_track)
            new_offset = track_index - track_index % num_strips
            if not new_offset / num_strips == int(new_offset / num_strips):
                raise AssertionError
                self._session.set_offsets(new_offset,
                                          self._session.scene_offset())
Example #42
0
class APC40plus22(APC):
    __doc__ = " Script for Akai's APC40 Controller with extra features added "

    def __init__(self, c_instance):
        self._c_instance = c_instance
        self._shift_modes = None  #added from APC20 script
        self._encoder_modes = None  #added
        self._slider_modes = None  #added
        APC.__init__(self, c_instance)
        self.show_message("APC40_22 script loaded")

        # Disabling the scene launch buttons and assigning them to the first 5 repeats on Master
        self._device_buttons = []
        self.setup_device_buttons()

    def disconnect(self):  #this is from the APC20 script
        for button in self._device_buttons:
            button.remove_value_listener(self._device_toggle)
        self._device_buttons = None
        self._shift_modes = None
        self._encoder_modes = None
        self._slider_modes = None
        APC.disconnect(self)

    def setup_device_buttons(self):
        repeat = RepeatComponent(self)
        repeat.set_shift_button(self._shift_button)

    def _setup_session_control(self):
        is_momentary = True
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98)
        right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96)
        left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97)
        up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94)
        down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95)
        right_button.name = 'Bank_Select_Right_Button'
        left_button.name = 'Bank_Select_Left_Button'
        up_button.name = 'Bank_Select_Up_Button'
        down_button.name = 'Bank_Select_Down_Button'
        self._session = PedaledSessionComponent(8, 5)
        self._session.name = 'Session_Control'
        self._session.set_track_bank_buttons(right_button, left_button)
        self._session.set_scene_bank_buttons(down_button, up_button)
        self._matrix = ButtonMatrixElement(
        )  #was: matrix = ButtonMatrixElement()
        self._matrix.name = 'Button_Matrix'  #was: matrix.name = 'Button_Matrix'
        scene_launch_buttons = [
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82))
            for index in range(5)
        ]
        #self._track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ]
        self._track_stop_buttons = [
            ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52)
            for index in range(8)
        ]
        for index in range(len(scene_launch_buttons)):
            scene_launch_buttons[index].name = 'Scene_' + str(
                index) + '_Launch_Button'
        for index in range(len(self._track_stop_buttons)):
            self._track_stop_buttons[index].name = 'Track_' + str(
                index) + '_Stop_Button'
        stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81)
        stop_all_button.name = 'Stop_All_Clips_Button'
        self._session.set_stop_all_clips_button(stop_all_button)
        self._session.set_stop_track_clip_buttons(
            tuple(self._track_stop_buttons))
        self._session.set_stop_track_clip_value(2)

        self._button_rows = []
        for scene_index in range(5):
            scene = self._session.scene(scene_index)
            scene.name = 'Scene_' + str(scene_index)
            button_row = []
            scene.set_launch_button(scene_launch_buttons[scene_index])
            scene.set_triggered_value(2)
            for track_index in range(8):
                #button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53))
                button = ConfigurableButtonElement(
                    is_momentary, MIDI_NOTE_TYPE, track_index,
                    (scene_index +
                     53))  #use Launchpad configurable button instead
                button.name = str(track_index) + '_Clip_' + str(
                    scene_index) + '_Button'
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                    scene_index)
                clip_slot.set_triggered_to_play_value(2)
                clip_slot.set_triggered_to_record_value(4)
                clip_slot.set_stopped_value(3)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(5)
                clip_slot.set_launch_button(button)
            self._matrix.add_row(
                tuple(button_row))  #matrix.add_row(tuple(button_row))
            self._button_rows.append(button_row)

        # Removing the launch selected clip footpedal option
        #self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67))

        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
        self._session_zoom = SessionZoomingComponent(
            self._session)  #use APC20 Zooming instead
        self._session_zoom.name = 'Session_Overview'
        self._session_zoom.set_button_matrix(
            self._matrix)  #was: self._session_zoom.set_button_matrix(matrix)
        self._session_zoom.set_zoom_button(
            self._shift_button)  #set in MatrixModesComponent instead
        self._session_zoom.set_nav_buttons(up_button, down_button, left_button,
                                           right_button)
        self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons))
        self._session_zoom.set_stopped_value(3)
        self._session_zoom.set_selected_value(5)
        return None

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(self, 8)  #added self for parent
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                             80)
        master_select_button.name = 'Master_Select_Button'
        self._mixer.master_strip().set_select_button(
            master_select_button
        )  #set in ShiftableSelectorComponent instead if used for Note Mode
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        select_buttons = []  #added
        arm_buttons = []  #added
        sliders = []  #added
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            #volume_control = SliderElement(MIDI_CC_TYPE, track, 7) #set in ShiftableSelectorComponent instead
            #arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) #see below
            solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        49)
            solo_button.name = str(track) + '_Solo_Button'
            strip.set_solo_button(solo_button)

            if track < 4:
                mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE,
                                            track, 50)
                mute_button.name = str(track) + '_Mute_Button'
                strip.set_mute_button(mute_button)
                strip.set_invert_mute_feedback(True)

            strip.set_shift_button(self._shift_button)
            select_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51))  #added
            select_buttons[-1].name = str(track) + '_Select_Button'  #added
            #strip.set_select_button(select_buttons[-1]) #added
            arm_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48))  #added
            arm_buttons[-1].name = str(track) + '_Arm_Button'  #added
            sliders.append(SliderElement(MIDI_CC_TYPE, track, 7))  #added
            sliders[-1].name = str(track) + '_Volume_Control'  #added

        self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        self._prehear_control = EncoderElement(
            MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
        self._crossfader.name = 'Crossfader'  #not used in APC20
        master_volume_control.name = 'Master_Volume_Control'
        self._prehear_control.name = 'Prehear_Volume_Control'
        self._mixer.set_shift_button(
            self._shift_button)  #added for shifting prehear
        self._mixer.set_crossfader_control(
            self._crossfader)  #not used in APC20
        self._mixer.set_prehear_volume_control(
            self._prehear_control
        )  #functionality overridden in SpecialMixerComponent
        self._mixer.master_strip().set_volume_control(master_volume_control)
        self._slider_modes = SliderModesComponent(
            self._mixer, tuple(sliders))  #added from APC20 script
        self._slider_modes.name = 'Slider_Modes'  #added from APC20 script
        matrix_modes = MatrixModesComponent(self._matrix, self._session,
                                            self._session_zoom,
                                            tuple(self._track_stop_buttons),
                                            self)  #added new
        matrix_modes.name = 'Matrix_Modes'  #added new
        # Original method args for ShiftableSelectorComponent: (self, select_buttons, master_button, arm_buttons, matrix, session, zooming, mixer, transport, slider_modes, mode_callback)
        #self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message)
        self._shift_modes = ShiftableSelectorComponent(
            self, tuple(select_buttons), master_select_button,
            tuple(arm_buttons), self._matrix, self._session,
            self._session_zoom, self._mixer, self._slider_modes, matrix_modes
        )  #, self._send_introduction_message) #also added self for _parent
        self._shift_modes.name = 'Shift_Modes'
        self._shift_modes.set_mode_toggle(self._shift_button)

    def _setup_custom_components(self):
        self._setup_looper_control()
        self._setup_device_and_transport_control()
        self._setup_global_control()

    def _setup_looper_control(self):
        is_momentary = True
        #pedal = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)
        loop_on = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 4, 50)
        loop_start = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 5, 50)
        halve = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 6, 50)
        double = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 7, 50)
        looper = LooperComponent(self)
        looper.set_shift_button(self._shift_button)
        looper.set_loop_toggle_button(loop_on)
        looper.set_loop_start_button(loop_start)
        looper.set_loop_double_button(double)
        looper.set_loop_halve_button(halve)

    def _setup_device_and_transport_control(self):
        is_momentary = True
        device_bank_buttons = []
        device_param_controls = []
        bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button',
                              'Previous_Device_Button', 'Next_Device_Button',
                              'Detail_View_Button', 'Rec_Quantization_Button',
                              'Midi_Overdub_Button', 'Device_Lock_Button',
                              'Metronome_Button')
        for index in range(8):
            device_bank_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 58 + index))
            device_bank_buttons[-1].name = bank_button_labels[index]
            ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0,
                                             24 + index)
            ringed_encoder = RingedEncoderElement(
                MIDI_CC_TYPE, 0, 16 + index, Live.MidiMap.MapMode.absolute)
            ringed_encoder.set_ring_mode_button(ring_mode_button)
            ringed_encoder.set_feedback_delay(
                -1)  #added from Axiom DirectLink example
            ringed_encoder.name = 'Device_Control_' + str(index)
            ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button'
            device_param_controls.append(ringed_encoder)
        self._device = ShiftableDeviceComponent()
        self._device.name = 'Device_Component'
        self._device.set_bank_buttons(tuple(device_bank_buttons))
        self._device.set_shift_button(self._shift_button)
        self._device.set_parameter_controls(tuple(device_param_controls))
        self._device.set_on_off_button(device_bank_buttons[1])
        self.set_device_component(self._device)
        detail_view_toggler = DetailViewControllerComponent()
        detail_view_toggler.name = 'Detail_View_Control'
        detail_view_toggler.set_shift_button(self._shift_button)
        detail_view_toggler.set_device_clip_toggle_button(
            device_bank_buttons[0])
        detail_view_toggler.set_detail_toggle_button(device_bank_buttons[4])
        detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2],
                                                   device_bank_buttons[3])

        # VU Meters
        vu = VUMeters(self)

        transport = ShiftableTransportComponent()
        transport.name = 'Transport'
        play_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 91)
        stop_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 92)
        record_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 93)
        nudge_up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 100)
        nudge_down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 101)
        tap_tempo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99)
        play_button.name = 'Play_Button'
        stop_button.name = 'Stop_Button'
        record_button.name = 'Record_Button'
        nudge_up_button.name = 'Nudge_Up_Button'
        nudge_down_button.name = 'Nudge_Down_Button'
        tap_tempo_button.name = 'Tap_Tempo_Button'
        transport.set_shift_button(self._shift_button)
        transport.set_play_button(play_button)
        transport.set_stop_button(stop_button)
        transport.set_record_button(record_button)
        transport.set_nudge_buttons(nudge_up_button, nudge_down_button)
        transport.set_undo_button(nudge_down_button)  #shifted nudge
        transport.set_redo_button(nudge_up_button)  #shifted nudge
        transport.set_tap_tempo_button(tap_tempo_button)
        self._device.set_lock_button(tap_tempo_button)  #shifted tap tempo
        transport.set_quant_toggle_button(device_bank_buttons[5])
        transport.set_overdub_button(device_bank_buttons[6])
        transport.set_metronome_button(device_bank_buttons[7])
        transport.set_tempo_encoder(self._prehear_control)  #shifted prehear
        bank_button_translator = ShiftableTranslatorComponent()
        bank_button_translator.set_controls_to_translate(
            tuple(device_bank_buttons))
        bank_button_translator.set_shift_button(self._shift_button)

    def _setup_global_control(self):
        is_momentary = True
        self._global_bank_buttons = []
        self._global_param_controls = []
        for index in range(8):
            ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0,
                                        56 + index)
            ringed_encoder = RingedEncoderElement(
                MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute)
            ringed_encoder.name = 'Track_Control_' + str(index)
            ringed_encoder.set_feedback_delay(-1)
            ring_button.name = ringed_encoder.name + '_Ring_Mode_Button'
            ringed_encoder.set_ring_mode_button(ring_button)
            self._global_param_controls.append(ringed_encoder)
        self._global_bank_buttons = []
        global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button',
                              'Send_C_Button')
        for index in range(4):
            self._global_bank_buttons.append(
                ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                          87 + index)
            )  #(not is_momentary, MIDI_NOTE_TYPE, 0, 87 + index))
            self._global_bank_buttons[-1].name = global_bank_labels[index]
        self._encoder_modes = EncoderMixerModeSelectorComponent(self._mixer)
        self._encoder_modes.name = 'Track_Control_Modes'
        #self._encoder_modes.set_modes_buttons(self._global_bank_buttons) # set in ShiftableEncoderSelectorComponent
        self._encoder_modes.set_controls(tuple(self._global_param_controls))
        #self._encoder_device_modes = EncoderDeviceModeSelectorComponent(self._mixer, self._device) #new
        self._encoder_device_modes = EncoderDeviceComponent(
            self._mixer, self._device, self)
        self._encoder_device_modes.name = 'Alt_Device_Control_Modes'  #new
        self._encoder_eq_modes = EncoderEQComponent(
            self._mixer,
            self)  #EncoderEQModeSelectorComponent(self._mixer) #new
        self._encoder_eq_modes.name = 'EQ_Control_Modes'  #new
        global_translation_selector = ChannelTranslationSelector(
        )  #translate track encoders to channels 1 through 4, based on button selection (pan = 1, send A = 2, send B = 3, send C = 4)
        global_translation_selector.name = 'Global_Translations'
        global_translation_selector.set_controls_to_translate(
            tuple(self._global_param_controls))
        global_translation_selector.set_mode_buttons(
            tuple(self._global_bank_buttons))
        encoder_user_modes = EncoderUserModesComponent(
            self, self._encoder_modes, tuple(self._global_param_controls),
            tuple(self._global_bank_buttons), self._mixer, self._device,
            self._encoder_device_modes,
            self._encoder_eq_modes)  #self._mixer, tuple(sliders)) #added
        encoder_user_modes.name = 'Encoder_User_Modes'  #added
        self._encoder_shift_modes = ShiftableEncoderSelectorComponent(
            self, tuple(self._global_bank_buttons), encoder_user_modes,
            self._encoder_modes, self._encoder_eq_modes,
            self._encoder_device_modes
        )  #tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, slider_modes, matrix_modes) #, self._send_introduction_message) #also added self for _parent
        self._encoder_shift_modes.name = 'Encoder_Shift_Modes'
        self._encoder_shift_modes.set_mode_toggle(self._shift_button)

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        #self._slider_modes.update() #added to update alternate slider assignments
        track = self.song().view.selected_track
        device_to_select = track.view.selected_device
        if device_to_select == None and len(track.devices) > 0:
            device_to_select = track.devices[0]
        if device_to_select != None:
            self.song().view.select_device(device_to_select)
        self._device_component.set_device(device_to_select)
        return None

    def _product_model_id_byte(self):
        return 115
class Axiom_AIR_25_49_61(ControlSurface):
    """ Script for the M-Audio Axiom A.I.R. 25, 49 and 61 """

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self._alt_device_component = None
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = "HyperControl"
            self._suggested_output_port = "HyperControl"
            self._single_fader_button_modes = None
            self._has_faders = True
            self._display_reset_delay = -1
            self._hc_byte = HC_BYTE
            self._waiting_for_first_response = True
            self._setup_controls()
            self._setup_displays()
            self._setup_mixer()
            self._setup_session()
            self._setup_transport()
            self._setup_device()
            self._setup_modes()
            self._drum_group_midi_button = None
            self._drum_group_hyper_button = None
            for component in self.components:
                component.set_enabled(False)

    def disconnect(self):
        self._scheduled_messages = []
        for encoder in self._encoders:
            encoder.remove_value_listener(self._encoder_value)

        for fader in self._faders:
            fader.remove_value_listener(self._fader_value)

        for fader_button in self._fader_buttons:
            fader_button.remove_value_listener(self._fader_button_value)

        self._master_fader.remove_value_listener(self._fader_value)
        self._master_fader_button.remove_value_listener(self._fader_button_value)
        self._select_button.remove_value_listener(self._select_button_value)
        self._identify_button.remove_value_listener(self._identify_value)
        self._fader_group_midi_button.remove_value_listener(self._midi_button_value)
        self._fader_group_mix_button.remove_value_listener(self._hyper_button_value)
        self._fader_group_fx_button.remove_value_listener(self._hyper_button_value)
        self._encoder_group_midi_button.remove_value_listener(self._midi_button_value)
        self._encoder_group_mix_button.remove_value_listener(self._hyper_button_value)
        self._encoder_group_fx_button.remove_value_listener(self._hyper_button_value)
        if self._drum_group_midi_button != None:
            self._drum_group_midi_button.remove_value_listener(self._midi_button_value)
        if self._drum_group_hyper_button != None:
            self._drum_group_hyper_button.remove_value_listener(self._hyper_button_value)
        self._alt_device_component = None
        self._name_display = None
        self._value_display = None
        self._bank_display = None
        self._pad_display = None
        self._name_display_data_source = None
        self._value_display_data_source = None
        self._bank_display_data_source = None
        self._pad_display_data_source = None
        self._select_button = None
        self._left_button = None
        self._right_button = None
        self._up_button = None
        self._down_button = None
        self._loop_button = None
        self._ffwd_button = None
        self._rwd_button = None
        self._play_button = None
        self._stop_button = None
        self._rec_button = None
        self._master_fader_button = None
        self._fader_buttons = None
        self._faders = None
        self._encoders = None
        self._drum_pads = None
        self._identify_button = None
        self._main_group_hyper_button = None
        self._main_group_track_button = None
        self._main_group_fx_button = None
        self._encoder_group_midi_button = None
        self._encoder_group_mix_button = None
        self._encoder_group_fx_button = None
        self._fader_group_mode_button = None
        self._fader_group_midi_button = None
        self._fader_group_mix_button = None
        self._fader_group_fx_button = None
        self._drum_group_midi_button = None
        self._drum_group_roll_button = None
        self._drum_group_hyper_button = None
        self._mixer_for_encoders = None
        self._mixer_for_faders = None
        self._device_for_encoders = None
        self._device_for_faders = None
        self._transport = None
        self._session = None
        ControlSurface.disconnect(self)
        self._send_midi(SYSEX_START + DISABLE_HYPERCONTROL)

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self.schedule_message(5, self._send_midi, IDENTITY_REQUEST)

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:10] == AXIOM_AIR_RESPONSE:
            if midi_bytes[12:15] < AXIOM_REV4_RESPONSE:
                self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL)
                self.schedule_message(2, self._send_midi, SYSEX_START + CLEAR_ALL)
                self.schedule_message(3, self._name_display.display_message, "Firmware")
                self.schedule_message(13, self._name_display.display_message, "Update")
                self.schedule_message(23, self._name_display.display_message, "Required")
                self.schedule_message(33, self._send_midi, SYSEX_START + DISABLE_HYPERCONTROL)
            elif midi_bytes[12:15] >= AXIOM_REV4_RESPONSE:
                if self._waiting_for_first_response == True:
                    self._waiting_for_first_response = False
                    self._has_faders = midi_bytes[10] != 50
                    self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL)
                    self.schedule_message(2, self._send_midi, SYSEX_START + SPECIAL_HYPERCONTROL)
                    self.schedule_message(3, self._complete_setup)
                else:
                    self._display_reset_delay = 0
        elif midi_bytes[0:8] == REQUEST_HYPERCONTROL:
            self.schedule_message(5, self._send_midi, IDENTITY_REQUEST)

    def update_display(self):
        ControlSurface.update_display(self)
        if self._display_reset_delay >= 0:
            self._display_reset_delay -= 1
            if self._display_reset_delay == -1:
                self._set_displays_to_default()

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._display_reset_delay = 0

    def restore_bank(self, bank_index):
        ControlSurface.restore_bank(self, bank_index)
        if self._alt_device_component != None:
            self._alt_device_component.restore_bank(bank_index)

    def set_appointed_device(self, device):
        ControlSurface.set_appointed_device(self, device)
        with self.component_guard():
            if self._alt_device_component != None:
                self._alt_device_component.set_device(device)

    def set_alt_device_component(self, device_component):
        self._alt_device_component = device_component

    def _update_device_selection(self):
        track = self.song().view.selected_track
        device_to_select = track.view.selected_device
        if device_to_select == None and len(track.devices) > 0:
            device_to_select = track.devices[0]
        if device_to_select != None:
            self.song().view.select_device(device_to_select)
        self._device_component.set_device(device_to_select)
        if self._alt_device_component != None:
            self._alt_device_component.set_device(device_to_select)

    def _setup_controls(self):
        self._left_button = create_button(99, "Left_Button")
        self._right_button = create_button(100, "Right_Button")
        self._up_button = create_button(101, "Up_Button")
        self._down_button = create_button(102, "Down_Button")
        self._loop_button = create_button(113, "Loop_Button")
        self._rwd_button = create_button(114, "Rwd_Button")
        self._ffwd_button = create_button(115, "FFwd_Button")
        self._stop_button = create_button(116, "Stop_Button")
        self._play_button = create_button(117, "Play_Button")
        self._rec_button = create_button(118, "Record_Button")
        self._select_button = ConfigurableButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, GLOBAL_CHANNEL, 98)
        self._select_button.name = "Select_Button"
        self._select_button.add_value_listener(self._select_button_value)
        self._main_group_hyper_button = create_configurable_button(104, "Fader_Group_HyperControl_Button", 2, 14)
        self._main_group_track_button = create_configurable_button(105, "Main_Group_Track_Button", 2, 11)
        self._main_group_fx_button = create_configurable_button(106, "Main_Group_Inst_FX_Button", 2, 11)
        self._identify_button = create_configurable_button(97, "Identify_Button", 2, 16)
        self._identify_button.add_value_listener(self._identify_value)
        self._fader_buttons = []
        for index in range(8):
            self._fader_buttons.append(create_configurable_button(49 + index, "Fader_Button_%d" % index))
            self._fader_buttons[-1].add_value_listener(self._fader_button_value, identify_sender=True)

        self._faders = []
        for index in range(8):
            self._faders.append(create_slider(33 + index, "Fader_%d" % index))
            self._faders[-1].add_value_listener(self._fader_value, identify_sender=True)

        self._master_fader_button = create_configurable_button(57, "Master_Fader_Button")
        self._master_fader_button.add_value_listener(self._fader_button_value, identify_sender=True)
        self._master_fader = create_slider(41, "Master_Fader")
        self._master_fader.add_value_listener(self._fader_value, identify_sender=True)
        self._fader_group_mode_button = create_configurable_button(61, "Fader_Group_Mode_Button")
        self._fader_group_midi_button = create_configurable_button(60, "Fader_Group_MIDI_Button")
        self._fader_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True)
        self._fader_group_mix_button = create_configurable_button(58, "Fader_Group_Mix_Button", 0, 1)
        self._fader_group_mix_button.add_value_listener(self._hyper_button_value, identify_sender=True)
        self._fader_group_fx_button = create_configurable_button(59, "Fader_Group_Inst_FX_Button", 0, -1)
        self._fader_group_fx_button.add_value_listener(self._hyper_button_value, identify_sender=True)
        self._encoders = []
        for index in range(8):
            self._encoders.append(create_encoder(17 + index, "Encoder_%d" % index))
            self._encoders[-1].add_value_listener(self._encoder_value, identify_sender=True)

        self._encoder_group_midi_button = create_configurable_button(27, "Encoder_Group_MIDI_Button", 0, 72)
        self._encoder_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True)
        self._encoder_group_mix_button = create_configurable_button(25, "Encoder_Group_Mix_Button", 0, 72)
        self._encoder_group_mix_button.add_value_listener(self._hyper_button_value, identify_sender=True)
        self._encoder_group_fx_button = create_configurable_button(26, "Encoder_Group_Inst_FX_Button", 0, 72)
        self._encoder_group_fx_button.add_value_listener(self._hyper_button_value, identify_sender=True)

    def _setup_drum_pads(self):
        self._drum_pads = []
        num_pads = 12 if self._has_faders else 16
        for index in range(8):
            self._drum_pads.append(create_configurable_button(81 + index, "Pad_%d" % index, 0, 0, MIDI_CC_TYPE))

        for index in range(num_pads - 8):
            self._drum_pads.append(
                ConfigurableButtonElement(
                    IS_MOMENTARY, MIDI_NOTE_TYPE, GLOBAL_CHANNEL - 1, 81 + index, GLOBAL_SEND_CHANNEL, 8, MIDI_CC_TYPE
                )
            )
            self._drum_pads[-1].name = "Pad_" + str(index + 8)

        self._drum_group_midi_button = create_configurable_button(91, "Drum_Group_MIDI_Button", 2, -2)
        self._drum_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True)
        self._drum_group_roll_button = create_configurable_button(90, "Drum_Group_Roll_Button", -1)
        self._drum_group_hyper_button = create_configurable_button(89, "Drum_Group_HyperControl_Button", 2, 2)
        self._drum_group_hyper_button.add_value_listener(self._hyper_button_value, identify_sender=True)

    def _setup_displays(self):
        self._name_display = PhysicalDisplayElement(12, 1)
        self._name_display.name = "Name_Display"
        self._name_display.set_message_parts(SYSEX_START + (21,), (0, 247))
        self._name_display.set_clear_all_message(CLEAR_NAME)
        self._name_display_data_source = DisplayDataSource()
        self._name_display.segment(0).set_data_source(self._name_display_data_source)
        self._value_display = NumericalDisplayElement(3, 1)
        self._value_display.name = "Value_Display"
        self._value_display.set_message_parts(SYSEX_START + (20, 48), (0, 247))
        self._value_display.set_clear_all_message(CLEAR_VALUE)
        self._value_display_data_source = DisplayDataSource()
        self._value_display.segment(0).set_data_source(self._value_display_data_source)
        self._bank_display = NumericalDisplayElement(3, 1)
        self._bank_display.name = "Bank_Display"
        self._bank_display.set_message_parts(SYSEX_START + (19,), (0, 247))
        self._bank_display.set_clear_all_message(CLEAR_BANK)
        self._bank_display_data_source = DisplayDataSource()
        self._bank_display.segment(0).set_data_source(self._bank_display_data_source)
        self._pad_display = NumericalDisplayElement(2, 1)
        self._pad_display.name = "Pad_Display"
        self._pad_display.set_message_parts(SYSEX_START + (18,), (0, 247))
        self._pad_display.set_clear_all_message(CLEAR_PAD)
        self._pad_display_data_source = DisplayDataSource()
        self._pad_display.segment(0).set_data_source(self._pad_display_data_source)

    def _setup_mixer(self):
        self._mixer_for_encoders = SpecialMixerComponent(self._name_display, self._value_display, 8)
        self._mixer_for_encoders.name = "Mixer_for_encoders"
        self._mixer_for_faders = SpecialMixerComponent(self._name_display, self._value_display, 8)
        self._mixer_for_faders.name = "Mixer_for_faders"

    def _setup_session(self):
        self._session = SpecialSessionComponent(8, 0)
        self._session.name = "Session_Control"
        self._session.selected_scene().name = "Selected_Scene"
        self._session.set_mixer(self._mixer_for_encoders)
        self._session.set_alt_mixer(self._mixer_for_faders)
        self._session.add_offset_listener(self._update_bank_value)

    def _setup_transport(self):
        self._transport = TransportComponent()
        self._transport.name = "Transport"
        self._transport.set_stop_button(self._stop_button)
        self._transport.set_play_button(self._play_button)
        self._transport.set_record_button(self._rec_button)
        transport_view_modes = TransportViewModeSelector(
            self._transport, self._session, self._ffwd_button, self._rwd_button, self._loop_button
        )
        transport_view_modes.name = "Transport_View_Modes"

    def _setup_device(self):
        self._device_for_encoders = BestBankDeviceComponent()
        self._device_for_encoders.name = "Device_Component_for_encoders"
        self._device_for_faders = BestBankDeviceComponent()
        self._device_for_faders.name = "Device_Component_for_faders"
        self.set_device_component(self._device_for_encoders)
        self.set_alt_device_component(self._device_for_faders)
        self._device_nav = DeviceNavComponent()
        self._device_nav.name = "Device_Nav_Component"

    def _setup_modes(self):
        self._fader_button_modes = FaderButtonModeSelector(self._mixer_for_faders, tuple(self._fader_buttons))
        self._fader_button_modes.name = "Fader_Button_Modes"
        self._fader_button_modes.set_mode_toggle(self._fader_group_mode_button)
        self._fader_modes = FaderModeSelector(
            self._mixer_for_faders,
            self._device_for_faders,
            tuple(self._faders),
            self._fader_button_modes,
            self._master_fader_button,
        )
        self._fader_modes.name = "Fader_Modes"
        self._fader_modes.set_mode_buttons((self._fader_group_mix_button, self._fader_group_fx_button))
        self._encoder_modes = EncoderModeSelector(
            self._mixer_for_encoders, self._device_for_encoders, tuple(self._encoders)
        )
        self._encoder_modes.name = "Encoder_Modes"
        self._encoder_modes.set_mode_buttons((self._encoder_group_mix_button, self._encoder_group_fx_button))
        main_modes = MainModeSelector(
            self._device_for_encoders,
            self._device_for_faders,
            self._session,
            self._mixer_for_faders,
            self._device_nav,
            self._up_button,
            self._down_button,
            self._left_button,
            self._right_button,
            self._select_button,
        )
        main_modes.name = "Main_Modes"
        main_modes.set_mode_buttons((self._main_group_track_button, self._main_group_fx_button))

    def _setup_master_fader(self):
        if self._has_faders:
            self._mixer_for_encoders.master_strip().set_volume_control(self._master_fader)
        else:
            self._mixer_for_encoders.selected_strip().set_volume_control(self._master_fader)

    def _setup_single_fader_button_modes(self):
        self._single_fader_button_modes = SingleFaderButtonModeSelector(
            self._mixer_for_encoders, self._fader_group_midi_button
        )
        self._single_fader_button_modes.name = "Single_Fader_Button_Modes"
        self._single_fader_button_modes.set_mode_toggle(self._fader_group_mode_button)

    def _complete_setup(self):
        self._setup_drum_pads()
        self._set_drum_pads_to_hc()
        self._setup_master_fader()
        if not self._has_faders:
            self._setup_single_fader_button_modes()
        for control in self.controls:
            if isinstance(control, InputControlElement):
                control.clear_send_cache()

        for component in self.components:
            component.set_enabled(True)

        self._fader_group_midi_button.send_value(LED_OFF, True)
        self._encoder_group_midi_button.send_value(LED_OFF, True)
        self._main_group_hyper_button.send_value(AMB_FULL, True)
        self.request_rebuild_midi_map()
        self._on_selected_track_changed()
        self.schedule_message(1, self._show_startup_message)

    def _show_startup_message(self):
        self._send_midi(SYSEX_START + CLEAR_ALL)
        self._name_display.display_message("Ableton Live")
        self._display_reset_delay = INITIAL_DISPLAY_DELAY

    def _select_button_value(self, value):
        self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _identify_value(self, value):
        for encoder in self._encoders:
            encoder.set_identify_mode(value > 0)

        for fader in self._faders:
            fader.set_identify_mode(value > 0)

        self._master_fader.set_identify_mode(value > 0)
        self._display_reset_delay = 0
        self._identify_button.turn_on() if value > 0 else self._identify_button.turn_off()

    def _midi_button_value(self, value, sender):
        if value > 0:
            if sender is self._drum_group_midi_button:
                hc_byte = self._hc_byte ^ PADS
                if hc_byte != self._hc_byte:
                    self._hc_byte = hc_byte
                    self._drum_group_hyper_button.send_value(LED_OFF, True)
                    self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247))
            elif sender is self._encoder_group_midi_button:
                hc_byte = self._hc_byte ^ ENCODERS
                if hc_byte != self._hc_byte:
                    self._hc_byte = hc_byte
                    self._encoder_group_mix_button.send_value(LED_OFF, True)
                    self._encoder_group_fx_button.send_value(LED_OFF, True)
                    if self._encoder_modes.mode_index < 3:
                        self._encoder_modes.set_enabled(False)
                    self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247))
            elif sender is self._fader_group_midi_button:
                if self._has_faders:
                    hc_byte = self._hc_byte ^ FADERS
                    if hc_byte != self._hc_byte:
                        self._hc_byte = hc_byte
                        self._fader_group_mix_button.send_value(LED_OFF, True)
                        self._fader_group_fx_button.send_value(LED_OFF, True)
                        self._fader_group_mode_button.send_value(LED_OFF, True)
                        if self._fader_modes.mode_index < 2:
                            self._fader_modes.set_enabled(False)
                            self._fader_button_modes.set_enabled(False)
                        self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247))
                else:
                    self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _hyper_button_value(self, value, sender):
        if value > 0:
            if sender is self._drum_group_hyper_button:
                if self._hc_byte | PADS != self._hc_byte:
                    self._hc_byte = self._hc_byte | PADS
                    self._send_midi(SYSEX_START + (32, self._hc_byte, 247))
                    self.schedule_message(1, self._set_drum_pads_to_hc)
            elif sender is self._encoder_group_fx_button or sender is self._encoder_group_mix_button:
                if self._hc_byte | ENCODERS != self._hc_byte:
                    self._hc_byte = self._hc_byte | ENCODERS
                    self._send_midi(SYSEX_START + (32, self._hc_byte, 247))
                    self._encoder_group_midi_button.turn_off()
                    if sender is self._encoder_group_fx_button:
                        self._encoder_modes.set_enabled(True)
                        self._display_reset_delay = 0
                        return
                    else:
                        self.schedule_message(1, self._encoder_modes.set_enabled, True)
                        self.schedule_message(1, self._encoder_modes.update)
                        self._display_reset_delay = 2
                        return
            elif sender is self._fader_group_fx_button or sender is self._fader_group_mix_button:
                if self._hc_byte | FADERS != self._hc_byte:
                    self._hc_byte = self._hc_byte | FADERS
                    self._send_midi(SYSEX_START + (32, self._hc_byte, 247))
                    self._fader_group_midi_button.turn_off()
                    self._fader_button_modes.set_enabled(True)
                    if sender is self._fader_group_fx_button:
                        self._fader_modes.set_enabled(True)
                        self._fader_button_modes.set_enabled(True)
                        self._display_reset_delay = 0
                        return
                    else:
                        self.schedule_message(1, self._fader_modes.set_enabled, True)
                        self.schedule_message(1, self._fader_modes.update)
                        self.schedule_message(1, self._fader_button_modes.set_enabled, True)
                        self.schedule_message(1, self._fader_button_modes.update)
                        self._display_reset_delay = 2
                        return
            self._display_reset_delay = 0

    def _set_drum_pads_to_hc(self):
        self._drum_group_midi_button.send_value(LED_OFF, True)
        self._drum_group_hyper_button.send_value(RED_FULL, True)
        for index in range(len(self._drum_pads)):
            self._drum_pads[index].send_value(RED_LOW, True)

    def _fader_button_value(self, value, sender):
        self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _fader_value(self, value, sender):
        param = sender.mapped_parameter()
        if param != None:
            param_range = param.max - param.min
            if param.name == "Track Volume":
                if sender == self._master_fader:
                    if self._has_faders:
                        name_string = "Master  Vol"
                    else:
                        name_string = (
                            self._mixer_for_faders.selected_strip().track_name_data_source().display_string() + "   Vol"
                        )
                else:
                    name_string = (
                        self._mixer_for_faders.channel_strip(self._faders.index(sender))
                        .track_name_data_source()
                        .display_string()
                        + "   Vol"
                    )
            else:
                name_string = param.name
                value = int((param.value - param.min) / param_range * 127)
            value_string = str(value)
        else:
            name_string = "<unmapped>"
            value_string = None
            self.schedule_message(1, self._set_value_string)
        self._set_name_string(name_string)
        self._set_value_string(value_string)

    def _encoder_value(self, value, sender):
        param = sender.mapped_parameter()
        if param != None:
            param_range = param.max - param.min
            if param.name == "Track Volume":
                name_string = (
                    self._mixer_for_encoders.channel_strip(self._encoders.index(sender))
                    .track_name_data_source()
                    .display_string()
                    + "   Vol"
                )
                value = int((param.value - param.min) / param_range * 127)
            elif param.name == "Track Panning":
                name_string = (
                    self._mixer_for_encoders.channel_strip(self._encoders.index(sender))
                    .track_name_data_source()
                    .display_string()
                    + "   Pan"
                )
                value = int(param.value / param_range * 127)
                if value < 0:
                    name_string += "  L"
                elif value > 0:
                    name_string += "  R"
                else:
                    name_string += "  C"
            else:
                name_string = param.name
                value = int((param.value - param.min) / param_range * 127)
            value_string = str(value)
        else:
            name_string = "<unmapped>"
            value_string = None
            self.schedule_message(1, self._set_value_string)
        self._set_name_string(name_string)
        self._set_value_string(value_string)

    def _set_displays_to_default(self):
        self._name_display.segment(0).set_data_source(
            self._mixer_for_encoders.selected_strip().track_name_data_source()
        )
        self._name_display.update()
        self._update_bank_value()
        self._set_value_string(None)
        self._send_midi(SYSEX_START + LCD_HC_DEFAULT)

    def _set_name_string(self, name_string):
        self._name_display.segment(0).set_data_source(self._name_display_data_source)
        self._name_display_data_source.set_display_string(name_string)
        self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _set_value_string(self, value_string=None):
        if value_string != None:
            self._value_display_data_source.set_display_string(value_string)
        else:
            self._value_display.reset()

    def _set_bank_string(self, bank_string=None):
        if bank_string != None:
            self._bank_display_data_source.set_display_string(bank_string)
        else:
            self._bank_display.reset()

    def _update_bank_value(self):
        bank = (self._session.track_offset() + 1) / self._session.width() + 1
        self._set_bank_string(str(bank))

    def _install_mapping(self, midi_map_handle, control, parameter, feedback_delay, feedback_map):
        if not self._in_build_midi_map:
            raise AssertionError
            raise midi_map_handle != None or AssertionError
            raise control != None and parameter != None or AssertionError
            raise isinstance(parameter, Live.DeviceParameter.DeviceParameter) or AssertionError
            raise isinstance(control, InputControlElement) or AssertionError
            raise isinstance(feedback_delay, int) or AssertionError
            if not isinstance(feedback_map, tuple):
                raise AssertionError
                success = False
                feedback_rule = None
                feedback_rule = control.message_type() is MIDI_NOTE_TYPE and Live.MidiMap.NoteFeedbackRule()
                feedback_rule.note_no = 0
                feedback_rule.vel_map = (0,)
            elif control.message_type() is MIDI_CC_TYPE:
                feedback_rule = Live.MidiMap.CCFeedbackRule()
                feedback_rule.cc_no = 0
                feedback_rule.cc_value_map = (0,)
            elif control.message_type() is MIDI_PB_TYPE:
                feedback_rule = Live.MidiMap.PitchBendFeedbackRule()
                feedback_rule.value_pair_map = feedback_map
            raise feedback_rule != None or AssertionError
            feedback_rule.channel = control.message_channel()
            feedback_rule.delay_in_ms = feedback_delay
            success = control.message_type() is MIDI_NOTE_TYPE and Live.MidiMap.map_midi_note_with_feedback_map(
                midi_map_handle, parameter, control.message_channel(), control.message_identifier(), feedback_rule
            )
        elif control.message_type() is MIDI_CC_TYPE:
            success = Live.MidiMap.map_midi_cc_with_feedback_map(
                midi_map_handle,
                parameter,
                control.message_channel(),
                control.message_identifier(),
                control.message_map_mode(),
                feedback_rule,
                not control.needs_takeover(),
            )
        elif control.message_type() is MIDI_PB_TYPE:
            success = Live.MidiMap.map_midi_pitchbend_with_feedback_map(
                midi_map_handle, parameter, control.message_channel(), feedback_rule, not control.needs_takeover()
            )
        return success
Example #44
0
class Schwa_Launchpad_Test(ControlSurface):
    __doc__ = " Script for Schwa_Launchpad_Test in APC emulation mode "

    _active_instances = []

    def _combine_active_instances():
        track_offset = 0
        scene_offset = 0
        for instance in Schwa_Launchpad_Test._active_instances:
            instance._activate_combination_mode(track_offset, scene_offset)
            track_offset += instance._session.width()

    _combine_active_instances = staticmethod(_combine_active_instances)

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        #self.set_suppress_rebuild_requests(True)
        with self.component_guard():
            self._note_map = []
            self._ctrl_map = []
            self._load_MIDI_map()
            self._session = None
            self._session_zoom = None
            self._mixer = None
            self._setup_session_control()
            self._setup_mixer_control()
            self._session.set_mixer(self._mixer)
            self._setup_device_and_transport_control()
            self.set_highlighting_session_component(self._session)
            #self.set_suppress_rebuild_requests(False)
        self._pads = []
        self._load_pad_translations()
        self._do_combine()

    def disconnect(self):
        self._note_map = None
        self._ctrl_map = None
        self._pads = None
        self._do_uncombine()
        self._shift_button = None
        self._session = None
        self._session_zoom = None
        self._mixer = None
        ControlSurface.disconnect(self)

    def _do_combine(self):
        if self not in Schwa_Launchpad_Test._active_instances:
            Schwa_Launchpad_Test._active_instances.append(self)
            Schwa_Launchpad_Test._combine_active_instances()

    def _do_uncombine(self):
        if ((self in Schwa_Launchpad_Test._active_instances)
                and Schwa_Launchpad_Test._active_instances.remove(self)):
            self._session.unlink()
            Schwa_Launchpad_Test._combine_active_instances()

    def _activate_combination_mode(self, track_offset, scene_offset):
        if TRACK_OFFSET != -1:
            track_offset = TRACK_OFFSET
        if SCENE_OFFSET != -1:
            scene_offset = SCENE_OFFSET
        self._session.link_with_track_offset(track_offset, scene_offset)

    def _setup_session_control(self):
        is_momentary = True
        self._session = SpecialSessionComponent(8, 8)
        self._session.name = 'Session_Control'
        self._session.set_track_bank_buttons(self._note_map[SESSIONRIGHT],
                                             self._note_map[SESSIONLEFT])
        self._session.set_scene_bank_buttons(self._note_map[SESSIONDOWN],
                                             self._note_map[SESSIONUP])
        self._session.set_select_buttons(self._note_map[SCENEDN],
                                         self._note_map[SCENEUP])
        self._scene_launch_buttons = [
            self._note_map[SCENELAUNCH[index]] for index in range(8)
        ]
        self._track_stop_buttons = [
            self._note_map[TRACKSTOP[index]] for index in range(8)
        ]
        self._session.set_stop_all_clips_button(self._note_map[STOPALLCLIPS])
        self._session.set_stop_track_clip_buttons(
            tuple(self._track_stop_buttons))
        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(
            self._note_map[SELSCENELAUNCH])
        self._session.set_slot_launch_button(self._note_map[SELCLIPLAUNCH])
        for scene_index in range(8):
            scene = self._session.scene(scene_index)
            scene.name = 'Scene_' + str(scene_index)
            button_row = []
            scene.set_launch_button(self._scene_launch_buttons[scene_index])
            scene.set_triggered_value(2)
            for track_index in range(8):
                button = self._note_map[CLIPNOTEMAP[scene_index][track_index]]
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                    scene_index)
                clip_slot.set_launch_button(button)
        self._session_zoom = SpecialZoomingComponent(self._session)
        self._session_zoom.name = 'Session_Overview'
        self._session_zoom.set_nav_buttons(self._note_map[ZOOMUP],
                                           self._note_map[ZOOMDOWN],
                                           self._note_map[ZOOMLEFT],
                                           self._note_map[ZOOMRIGHT])

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(8)
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        self._mixer.master_strip().set_select_button(self._note_map[MASTERSEL])
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        self._mixer.set_select_buttons(self._note_map[TRACKRIGHT],
                                       self._note_map[TRACKLEFT])
        self._mixer.set_crossfader_control(self._ctrl_map[CROSSFADER])
        self._mixer.set_prehear_volume_control(self._ctrl_map[CUELEVEL])
        self._mixer.master_strip().set_volume_control(
            self._ctrl_map[MASTERVOLUME])
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            strip.set_arm_button(self._note_map[TRACKREC[track]])
            strip.set_solo_button(self._note_map[TRACKSOLO[track]])
            strip.set_mute_button(self._note_map[TRACKMUTE[track]])
            strip.set_select_button(self._note_map[TRACKSEL[track]])
            strip.set_volume_control(self._ctrl_map[TRACKVOL[track]])
            strip.set_pan_control(self._ctrl_map[TRACKPAN[track]])
            strip.set_send_controls((self._ctrl_map[TRACKSENDA[track]],
                                     self._ctrl_map[TRACKSENDB[track]],
                                     self._ctrl_map[TRACKSENDC[track]]))
            strip.set_invert_mute_feedback(True)

    def _setup_device_and_transport_control(self):
        is_momentary = True
        self._device = DeviceComponent()
        self._device.name = 'Device_Component'
        device_bank_buttons = []
        device_param_controls = []
        for index in range(8):
            device_param_controls.append(self._ctrl_map[PARAMCONTROL[index]])
            device_bank_buttons.append(self._note_map[DEVICEBANK[index]])
        if None not in device_bank_buttons:
            self._device.set_bank_buttons(tuple(device_bank_buttons))
        if None not in device_param_controls:
            self._device.set_parameter_controls(tuple(device_param_controls))
        self._device.set_on_off_button(self._note_map[DEVICEONOFF])
        self._device.set_bank_nav_buttons(self._note_map[DEVICEBANKNAVLEFT],
                                          self._note_map[DEVICEBANKNAVRIGHT])
        self._device.set_lock_button(self._note_map[DEVICELOCK])
        self.set_device_component(self._device)

        detail_view_toggler = DetailViewControllerComponent()
        detail_view_toggler.name = 'Detail_View_Control'
        detail_view_toggler.set_device_clip_toggle_button(
            self._note_map[CLIPTRACKVIEW])
        detail_view_toggler.set_detail_toggle_button(
            self._note_map[DETAILVIEW])
        detail_view_toggler.set_device_nav_buttons(
            self._note_map[DEVICENAVLEFT], self._note_map[DEVICENAVRIGHT])

        transport = SpecialTransportComponent()
        transport.name = 'Transport'
        transport.set_play_button(self._note_map[PLAY])
        transport.set_stop_button(self._note_map[STOP])
        transport.set_record_button(self._note_map[REC])
        transport.set_nudge_buttons(self._note_map[NUDGEUP],
                                    self._note_map[NUDGEDOWN])
        transport.set_undo_button(self._note_map[UNDO])
        transport.set_redo_button(self._note_map[REDO])
        transport.set_tap_tempo_button(self._note_map[TAPTEMPO])
        transport.set_quant_toggle_button(self._note_map[RECQUANT])
        transport.set_overdub_button(self._note_map[OVERDUB])
        transport.set_metronome_button(self._note_map[METRONOME])
        transport.set_tempo_control(self._ctrl_map[TEMPOCONTROL])
        transport.set_loop_button(self._note_map[LOOP])
        transport.set_seek_buttons(self._note_map[SEEKFWD],
                                   self._note_map[SEEKRWD])
        transport.set_punch_buttons(self._note_map[PUNCHIN],
                                    self._note_map[PUNCHOUT])
        ##transport.set_song_position_control(self._ctrl_map[SONGPOSITION]) #still not implemented as of Live 8.1.6

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        track = self.song().view.selected_track
        device_to_select = track.view.selected_device
        if device_to_select == None and len(track.devices) > 0:
            device_to_select = track.devices[0]
        if device_to_select != None:
            self.song().view.select_device(device_to_select)
        self._device_component.set_device(device_to_select)

    def _load_pad_translations(self):
        if -1 not in DRUM_PADS:
            pad = []
            for row in range(4):
                for col in range(4):
                    pad = (
                        col,
                        row,
                        DRUM_PADS[row * 4 + col],
                        PADCHANNEL,
                    )
                    self._pads.append(pad)
            self.set_pad_translations(tuple(self._pads))

    def _load_MIDI_map(self):
        is_momentary = True
        for note in range(128):
            button = ButtonElement(is_momentary, MESSAGETYPE, BUTTONCHANNEL,
                                   note)
            button.name = 'Note_' + str(note)
            self._note_map.append(button)
        self._note_map.append(
            None)  #add None to the end of the list, selectable with [-1]
        if MESSAGETYPE == MIDI_CC_TYPE and BUTTONCHANNEL == SLIDERCHANNEL:
            for ctrl in range(128):
                self._ctrl_map.append(None)
        else:
            for ctrl in range(128):
                control = SliderElement(MIDI_CC_TYPE, SLIDERCHANNEL, ctrl)
                control.name = 'Ctrl_' + str(ctrl)
                self._ctrl_map.append(control)
            self._ctrl_map.append(None)
class Oxygen_3rd_Gen(ControlSurface):
    """ Script for the 3rd generation of M-Audio's Oxygen controllers """

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            is_momentary = True
            self._suggested_input_port = 'Oxygen'
            self._suggested_output_port = 'Oxygen'
            self._has_slider_section = True
            self._device_selection_follows_track_selection = True
            self._shift_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 57)
            self._shift_button.add_value_listener(self._shift_value)
            self._mixer = SpecialMixerComponent(NUM_TRACKS)
            self._mute_solo_buttons = []
            self._track_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 111)
            self._track_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 110)
            self._master_slider = SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 41)
            for index in range(NUM_TRACKS):
                self._mute_solo_buttons.append(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 49 + index))
                self._mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 33 + index))

            self._shift_value(0)
            self._mixer.master_strip().set_volume_control(self._master_slider)
            self._mixer.selected_strip().set_volume_control(None)
            device = DeviceComponent()
            device.set_parameter_controls(tuple([ EncoderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 17 + index, Live.MidiMap.MapMode.absolute) for index in range(8) ]))
            self.set_device_component(device)
            ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 115)
            rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 114)
            loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 113)
            transport = TransportComponent()
            transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 116))
            transport.set_play_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 117))
            transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 118))
            session = SessionComponent(0, 0)
            transport_view_modes = TransportViewModeSelector(transport, session, ffwd_button, rwd_button, loop_button)
        return

    def disconnect(self):
        self._shift_button.remove_value_listener(self._shift_value)
        self._shift_button = None
        ControlSurface.disconnect(self)
        return

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self.schedule_message(5, self._send_midi, IDENTITY_REQUEST)

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:5] == IDENTITY_RESPONSE:
            if midi_bytes[10] == 38:
                self._mixer.master_strip().set_volume_control(None)
                self._mixer.selected_strip().set_volume_control(self._master_slider)
        return

    def _shift_value(self, value):
        raise value in range(128) or AssertionError
        for index in range(NUM_TRACKS):
            if value == 0:
                self._mixer.channel_strip(index).set_solo_button(None)
                self._mixer.channel_strip(index).set_mute_button(self._mute_solo_buttons[index])
                self._mixer.set_bank_buttons(None, None)
                self._mixer.set_select_buttons(self._track_up_button, self._track_down_button)
            else:
                self._mixer.channel_strip(index).set_mute_button(None)
                self._mixer.channel_strip(index).set_solo_button(self._mute_solo_buttons[index])
                self._mixer.set_select_buttons(None, None)
                self._mixer.set_bank_buttons(self._track_up_button, self._track_down_button)

        return
class APC_64_40_9_vu(APC):
    """ Script for Akai's APC40 Controller """
    def __init__(self, c_instance):
        self._c_instance = c_instance
        self._shift_modes = None
        self._encoder_modes = None
        self._slider_modes = None
        self._sequencer = None
        APC.__init__(self, c_instance)
        self._device_selection_follows_track_selection = True

    def disconnect(self):
        self._shift_modes = None
        self._encoder_modes = None
        self._slider_modes = None
        self._sequencer = None
        APC.disconnect(self)

    def _setup_session_control(self):
        is_momentary = True
        self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98)
        self._right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96)
        self._left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97)
        self._up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94)
        self._down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95)
        self._right_button.name = 'Bank_Select_Right_button'
        self._left_button.name = 'Bank_Select_Left_button'
        self._up_button.name = 'Bank_Select_Up_button'
        self._down_button.name = 'Bank_Select_Down_button'
        self._session = PedaledSessionComponent(8, 5)
        self._session.name = 'Session_Control'
        self._session.set_track_bank_buttons(self._right_button,
                                             self._left_button)
        self._session.set_scene_bank_buttons(self._down_button,
                                             self._up_button)
        self._matrix = ButtonMatrixElement()
        self._matrix.name = 'Button_Matrix'
        self._scene_launch_buttons = [
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, index + 82)
            for index in range(5)
        ]
        self._track_stop_buttons = [
            ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52)
            for index in range(8)
        ]
        for index in range(len(self._scene_launch_buttons)):
            self._scene_launch_buttons[index].name = 'Scene_' + str(
                index) + '_Launch_Button'
        for index in range(len(self._track_stop_buttons)):
            self._track_stop_buttons[index].name = 'Track_' + str(
                index) + '_Stop_Button'
        self._stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                              81)
        self._stop_all_button.name = 'Stop_All_Clips_Button'
        self._session.set_stop_all_clips_button(self._stop_all_button)
        self._session.set_stop_track_clip_buttons(
            tuple(self._track_stop_buttons))
        self._session.set_stop_clip_value(0)
        self._session.set_stop_clip_triggered_value(2)

        self._button_rows = []
        for scene_index in range(5):
            scene = self._session.scene(scene_index)
            scene.name = 'Scene_' + str(scene_index)
            button_row = []
            scene.set_launch_button(self._scene_launch_buttons[scene_index])
            scene.set_triggered_value(2)
            for track_index in range(8):
                button = ConfigurableButtonElement(is_momentary,
                                                   MIDI_NOTE_TYPE, track_index,
                                                   (scene_index + 53))
                button.name = str(track_index) + '_Clip_' + str(
                    scene_index) + '_Button'
                button_row.append(button)
                clip_slot = scene.clip_slot(track_index)
                clip_slot.name = str(track_index) + '_Clip_Slot_' + str(
                    scene_index)
                clip_slot.set_triggered_to_play_value(2)
                clip_slot.set_triggered_to_record_value(4)
                clip_slot.set_stopped_value(5)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(3)
                clip_slot.set_launch_button(button)
            self._matrix.add_row(tuple(button_row))
            self._button_rows.append(button_row)

        self._session.set_slot_launch_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67))

        self._session.selected_scene().name = 'Selected_Scene'
        self._session.selected_scene().set_launch_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64))
        self._session_zoom = ShiftableZoomingComponent(
            self._session, tuple(self._track_stop_buttons))
        self._session_zoom.name = 'Session_Overview'
        self._session_zoom.set_button_matrix(self._matrix)
        self._session_zoom.set_zoom_button(self._shift_button)
        self._session_zoom.set_nav_buttons(self._up_button, self._down_button,
                                           self._left_button,
                                           self._right_button)
        self._session_zoom.set_scene_bank_buttons(
            tuple(self._scene_launch_buttons))
        self._session_zoom.set_stopped_value(3)
        self._session_zoom.set_selected_value(5)

    def _setup_mixer_control(self):
        is_momentary = True
        self._mixer = SpecialMixerComponent(self, 8)
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_Strip'
        master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                             80)
        master_select_button.name = 'Master_Select_Button'
        self._mixer.master_strip().set_select_button(master_select_button)
        self._mixer.selected_strip().name = 'Selected_Channel_Strip'
        select_buttons = []
        arm_buttons = []
        solo_buttons = []
        mute_buttons = []
        sliders = []
        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        49)
            solo_buttons.append(solo_button)
            mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        50)
            mute_buttons.append(mute_button)
            solo_button.name = str(track) + '_Solo_Button'
            mute_button.name = str(track) + '_Mute_Button'
            strip.set_solo_button(solo_button)
            strip.set_mute_button(mute_button)
            strip.set_shift_button(self._shift_button)
            strip.set_invert_mute_feedback(True)
            select_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51))
            select_buttons[-1].name = str(track) + '_Select_Button'
            arm_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48))
            arm_buttons[-1].name = str(track) + '_Arm_Button'
            sliders.append(SliderElement(MIDI_CC_TYPE, track, 7))
            sliders[-1].name = str(track) + '_Volume_Control'

        self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15)
        master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14)
        self._prehear_control = EncoderElement(
            MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment)
        self._crossfader.name = 'Crossfader'
        master_volume_control.name = 'Master_Volume_Control'
        self._prehear_control.name = 'Prehear_Volume_Control'
        self._mixer.set_shift_button(self._shift_button)
        self._mixer.set_crossfader_control(self._crossfader)
        self._mixer.set_prehear_volume_control(self._prehear_control)
        self._mixer.master_strip().set_volume_control(master_volume_control)
        self._slider_modes = SliderModesComponent(self._mixer, tuple(sliders))
        self._slider_modes.name = 'Slider_Modes'
        self._matrix_modes = MatrixModesComponent(
            self._matrix, self._session, self._session_zoom,
            tuple(self._track_stop_buttons), self)
        self._matrix_modes.name = 'Matrix_Modes'
        self._sequencer = StepSequencerComponent(
            self, self._session, self._matrix, tuple(self._track_stop_buttons))
        self._sequencer.set_bank_buttons(tuple(select_buttons))
        self._sequencer.set_nav_buttons(self._up_button, self._down_button,
                                        self._left_button, self._right_button)
        self._sequencer.set_button_matrix(self._matrix)
        self._sequencer.set_follow_button(master_select_button)
        self._sequencer.set_velocity_buttons(tuple(arm_buttons))
        self._sequencer.set_shift_button(self._shift_button)
        self._sequencer.set_lane_mute_buttons(tuple(
            self._scene_launch_buttons))
        self._sequencer.set_loop_start_buttons(tuple(mute_buttons))
        self._sequencer.set_loop_length_buttons(tuple(solo_buttons))
        self._shift_modes = ShiftableSelectorComponent(
            self, tuple(select_buttons), master_select_button,
            tuple(self._track_stop_buttons), self._stop_all_button,
            tuple(mute_buttons), tuple(solo_buttons), tuple(arm_buttons),
            tuple(self._scene_launch_buttons), self._matrix, self._session,
            self._session_zoom, self._mixer, self._slider_modes,
            self._matrix_modes, self._sequencer)
        self._shift_modes.name = 'Shift_Modes'
        self._shift_modes.set_mode_toggle(self._shift_button)

    def _setup_custom_components(self):
        self._setup_device_and_transport_control()
        self._setup_global_control()

    def _setup_device_and_transport_control(self):
        is_momentary = True
        device_bank_buttons = []
        device_param_controls = []
        bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button',
                              'Previous_Device_Button', 'Next_Device_Button',
                              'Detail_View_Button', 'Rec_Quantization_Button',
                              'Midi_Overdub_Button', 'Metronome_Button')
        for index in range(8):
            device_bank_buttons.append(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 58 + index))
            device_bank_buttons[-1].name = bank_button_labels[index]
            ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0,
                                             24 + index)
            ringed_encoder = RingedEncoderElement(
                MIDI_CC_TYPE, 0, 16 + index, Live.MidiMap.MapMode.absolute)
            ringed_encoder.set_ring_mode_button(ring_mode_button)
            ringed_encoder.set_feedback_delay(-1)
            ringed_encoder.name = 'Device_Control_' + str(index)
            ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button'
            device_param_controls.append(ringed_encoder)
        self._device = ShiftableDeviceComponent()
        self._device.name = 'Device_Component'
        self._device.set_bank_buttons(tuple(device_bank_buttons))
        self._device.set_shift_button(self._shift_button)
        self._device.set_parameter_controls(tuple(device_param_controls))
        self._device.set_on_off_button(device_bank_buttons[1])
        self.set_device_component(self._device)
        detail_view_toggler = DetailViewCntrlComponent()
        detail_view_toggler.name = 'Detail_View_Control'
        detail_view_toggler.set_shift_button(self._shift_button)
        detail_view_toggler.set_device_clip_toggle_button(
            device_bank_buttons[0])
        detail_view_toggler.set_detail_toggle_button(device_bank_buttons[4])
        detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2],
                                                   device_bank_buttons[3])

        transport = ShiftableTransportComponent()
        transport.name = 'Transport'
        play_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 91)
        stop_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 92)
        record_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 93)
        nudge_up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 100)
        nudge_down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 101)
        tap_tempo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99)
        play_button.name = 'Play_Button'
        stop_button.name = 'Stop_Button'
        record_button.name = 'Record_Button'
        nudge_up_button.name = 'Nudge_Up_button'
        nudge_down_button.name = 'Nudge_Down_button'
        tap_tempo_button.name = 'Tap_Tempo_Button'
        transport.set_shift_button(self._shift_button)
        transport.set_play_button(play_button)
        transport.set_stop_button(stop_button)
        transport.set_record_button(record_button)
        transport.set_nudge_buttons(nudge_up_button, nudge_down_button)
        transport.set_undo_button(nudge_down_button)
        transport.set_redo_button(nudge_up_button)
        transport.set_tap_tempo_button(tap_tempo_button)
        self._device.set_lock_button(tap_tempo_button)
        transport.set_quant_toggle_button(device_bank_buttons[5])
        transport.set_overdub_button(device_bank_buttons[6])
        transport.set_metronome_button(device_bank_buttons[7])
        transport.set_tempo_encoder(self._prehear_control)
        bank_button_translator = ShiftTranslatorComponent()
        bank_button_translator.set_controls_to_translate(
            tuple(device_bank_buttons))
        bank_button_translator.set_shift_button(self._shift_button)

    def _setup_global_control(self):
        is_momentary = True
        self._global_bank_buttons = []
        self._global_param_controls = []
        for index in range(8):
            ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0,
                                        56 + index)
            ringed_encoder = RingedEncoderElement(
                MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute)
            ringed_encoder.name = 'Track_Control_' + str(index)
            ringed_encoder.set_feedback_delay(-1)
            ring_button.name = ringed_encoder.name + '_Ring_Mode_Button'
            ringed_encoder.set_ring_mode_button(ring_button)
            self._global_param_controls.append(ringed_encoder)
        self._global_bank_buttons = []
        global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button',
                              'Send_C_Button')
        for index in range(4):
            self._global_bank_buttons.append(
                ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0,
                                          87 + index))
            self._global_bank_buttons[-1].name = global_bank_labels[index]
        self._encoder_modes = EncModeSelectorComponent(self._mixer)
        self._encoder_modes.name = 'Track_Control_Modes'
        self._encoder_modes.set_controls(tuple(self._global_param_controls))
        self._encoder_device_modes = EncoderDeviceComponent(
            self._mixer, self._device, self)
        self._encoder_device_modes.name = 'Alt_Device_Control_Modes'
        self._encoder_eq_modes = EncoderEQComponent(self._mixer, self)
        self._encoder_eq_modes.name = 'EQ_Control_Modes'
        global_translation_selector = ChannelTranslationSelector()
        global_translation_selector.name = 'Global_Translations'
        global_translation_selector.set_controls_to_translate(
            tuple(self._global_param_controls))
        global_translation_selector.set_mode_buttons(
            tuple(self._global_bank_buttons))
        encoder_user_modes = EncoderUserModesComponent(
            self, self._encoder_modes, tuple(self._global_param_controls),
            tuple(self._global_bank_buttons), self._mixer, self._device,
            self._encoder_device_modes, self._encoder_eq_modes)
        encoder_user_modes.name = 'Encoder_User_Modes'
        self._encoder_shift_modes = ShiftableEncoderSelectorComponent(
            self, tuple(self._global_bank_buttons), encoder_user_modes,
            self._encoder_modes, self._encoder_eq_modes,
            self._encoder_device_modes)
        self._encoder_shift_modes.name = 'Encoder_Shift_Modes'
        self._encoder_shift_modes.set_mode_toggle(self._shift_button)

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        track = self.song().view.selected_track
        device_to_select = track.view.selected_device
        if device_to_select == None and len(track.devices) > 0:
            device_to_select = track.devices[0]
        if device_to_select != None:
            self.song().view.select_device(device_to_select)
        self._device_component.set_device(device_to_select)
        return None

    def _on_track_offset_changed(self):
        self._matrix_modes._on_track_offset_changed()

    def _product_model_id_byte(self):
        return 115
Example #47
0
class SubSelectorComponent(ModeSelectorComponent):
    """ Class that handles different mixer modes """
    def __init__(self, matrix, side_buttons, session):
        assert (matrix, ButtonMatrixElement)
        assert matrix.width() == 8 and matrix.height() == 8
        assert isinstance(side_buttons, tuple)
        assert len(side_buttons) == 8
        assert isinstance(session, SessionComponent)
        ModeSelectorComponent.__init__(self)
        self._session = session
        self._mixer = SpecialMixerComponent(matrix.width())
        self._matrix = matrix
        self._sliders = []
        self._mixer.name = 'Mixer'
        self._mixer.master_strip().name = 'Master_Channel_strip'
        self._mixer.selected_strip().name = 'Selected_Channel_strip'
        for column in range(matrix.width()):
            self._mixer.channel_strip(
                column).name = 'Channel_Strip_' + str(column)
            self._sliders.append(
                PreciseButtonSliderElement(
                    tuple([
                        matrix.get_button(column, 7 - row) for row in range(8)
                    ])))
            self._sliders[-1].name = 'Button_Slider_' + str(column)

        self._side_buttons = side_buttons[4:]
        self._update_callback = None
        self._session.set_mixer(self._mixer)
        self.set_modes_buttons(side_buttons[:4])

    def disconnect(self):
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)

        self._session = None
        self._mixer = None
        for slider in self._sliders:
            slider.release_parameter()
            slider.set_disabled(True)

        self._sliders = None
        self._matrix = None
        self._side_buttons = None
        self._update_callback = None
        ModeSelectorComponent.disconnect(self)

    def set_update_callback(self, callback):
        assert dir(callback).count('im_func') is 1
        self._update_callback = callback

    def set_modes_buttons(self, buttons):
        assert buttons == None or isinstance(
            buttons, tuple) or len(buttons) == self.number_of_modes()
        identify_sender = True
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)

        self._modes_buttons = []
        if buttons != None:
            for button in buttons:
                assert isinstance(button, ButtonElement)
                self._modes_buttons.append(button)
                button.add_value_listener(self._mode_value, identify_sender)

    def set_mode(self, mode):
        assert isinstance(mode, int)
        assert mode in range(-1, self.number_of_modes())
        if ((self._mode_index != mode) or (mode == -1)):
            self._mode_index = mode
            self.update()

    def mode(self):
        result = 0
        if self.is_enabled():
            result = self._mode_index + 1
        return result

    def number_of_modes(self):
        return 4

    def on_enabled_changed(self):
        enabled = self.is_enabled()
        for index in range(self._matrix.width()):
            self._sliders[index].set_disabled(not enabled)

        self._mixer.set_enabled(enabled)
        self.set_mode(-1)

    def release_controls(self):
        for track in range(self._matrix.width()):
            for row in range(self._matrix.height()):
                self._matrix.get_button(track,
                                        row).set_on_off_values(127, LED_OFF)

            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_send_controls((None, None))
            strip.set_pan_control(None)
            strip.set_volume_control(None)

        self._session.set_stop_track_clip_buttons(None)
        self._mixer.set_global_buttons(None, None, None)
        self._session.set_stop_all_clips_button(None)

    def update(self):
        assert (self._modes_buttons != None)
        if self.is_enabled():
            if self._modes_buttons != None:
                for index in range(len(self._modes_buttons)):
                    self._modes_buttons[index].set_on_off_values(
                        GREEN_FULL, GREEN_THIRD)
                    if index == self._mode_index:
                        self._modes_buttons[index].turn_on()
                    else:
                        self._modes_buttons[index].turn_off()

            for button in self._side_buttons:
                button.set_on_off_values(127, LED_OFF)
                button.turn_off()

            for index in range(self._matrix.width()):
                self._sliders[index].set_disabled(self._mode_index == -1)

            self._mixer.set_allow_update(False)
            self._session.set_allow_update(False)
            if self._mode_index == -1:
                self._setup_mixer_overview()
            elif self._mode_index == 0:
                self._setup_volume_mode()
            elif self._mode_index == 1:
                self._setup_pan_mode()
            elif self._mode_index == 2:
                self._setup_send1_mode()
            elif self._mode_index == 3:
                self._setup_send2_mode()
            else:
                assert False
            if self._update_callback != None:
                self._update_callback()
            self._mixer.set_allow_update(True)
            self._session.set_allow_update(True)
        else:
            self.release_controls()

    def _setup_mixer_overview(self):
        trkon_index = 5
        stop_buttons = []
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_send_controls((None, None))
            strip.set_pan_control(None)
            strip.set_volume_control(None)
            self._sliders[track].release_parameter()
            for row in range(self._matrix.height()):
                full_value = GREEN_THIRD
                third_value = GREEN_FULL
                if row == trkon_index:
                    full_value = AMBER_FULL
                    third_value = AMBER_THIRD
                elif row > 3:
                    full_value = RED_FULL
                    third_value = RED_THIRD
                self._matrix.get_button(track, row).set_on_off_values(
                    full_value, third_value)

            strip.set_default_buttons(self._matrix.get_button(track, 0),
                                      self._matrix.get_button(track, 1),
                                      self._matrix.get_button(track, 2),
                                      self._matrix.get_button(track, 3))
            stop_buttons.append(self._matrix.get_button(track, 4))
            strip.set_mute_button(self._matrix.get_button(track, 5))
            strip.set_solo_button(self._matrix.get_button(track, 6))
            strip.set_arm_button(self._matrix.get_button(track, 7))

        for button in self._side_buttons:
            if list(self._side_buttons).index(button) == trkon_index - 4:
                button.set_on_off_values(AMBER_FULL, AMBER_THIRD)
            else:
                button.set_on_off_values(RED_FULL, RED_THIRD)
            button.set_force_next_value()
            button.turn_off()

        self._session.set_stop_track_clip_buttons(tuple(stop_buttons))
        self._session.set_stop_all_clips_button(self._side_buttons[0])
        self._mixer.set_global_buttons(self._side_buttons[3],
                                       self._side_buttons[2],
                                       self._side_buttons[1])

    def _setup_volume_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_send_controls((None, None))
            strip.set_pan_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(track, row).set_on_off_values(
                    GREEN_FULL, LED_OFF)

            self._sliders[track].set_mode(SLIDER_MODE_VOLUME)
            self._sliders[track].set_value_map(VOL_VALUE_MAP)
            strip.set_volume_control(self._sliders[track])

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)

    def _setup_pan_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_send_controls((None, None))
            strip.set_volume_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(track, row).set_on_off_values(
                    AMBER_FULL, LED_OFF)

            self._sliders[track].set_mode(SLIDER_MODE_PAN)
            self._sliders[track].set_value_map(PAN_VALUE_MAP)
            strip.set_pan_control(self._sliders[track])

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)

    def _setup_send1_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_volume_control(None)
            strip.set_pan_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(track, row).set_on_off_values(
                    RED_FULL, LED_OFF)

            self._sliders[track].set_mode(SLIDER_MODE_VOLUME)
            self._sliders[track].set_value_map(SEND_VALUE_MAP)
            strip.set_send_controls((self._sliders[track], None))

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)

    def _setup_send2_mode(self):
        for track in range(self._matrix.width()):
            strip = self._mixer.channel_strip(track)
            strip.set_default_buttons(None, None, None, None)
            strip.set_mute_button(None)
            strip.set_solo_button(None)
            strip.set_arm_button(None)
            strip.set_volume_control(None)
            strip.set_pan_control(None)
            for row in range(self._matrix.height()):
                self._matrix.get_button(track, row).set_on_off_values(
                    RED_FULL, LED_OFF)

            self._sliders[track].set_mode(SLIDER_MODE_VOLUME)
            self._sliders[track].set_value_map(SEND_VALUE_MAP)
            strip.set_send_controls((None, self._sliders[track]))

        self._session.set_stop_track_clip_buttons(None)
        self._session.set_stop_all_clips_button(None)
        self._mixer.set_global_buttons(None, None, None)
Example #48
0
    def _init_mixer_component(self, volume_controls, trackarm_controls, mixer_options, global_channel, volume_map_mode):
        if volume_controls != None and trackarm_controls != None:
            num_strips = max(len(volume_controls), len(trackarm_controls))
            send_info = []
            momentary_buttons = False
            mixer = SpecialMixerComponent(num_strips)
            mixer.name = 'Mixer'
            mixer.master_strip().name = 'Master_Channel_Strip'
            mixer.selected_strip().name = 'Selected_Channel_Strip'
            if mixer_options != None:
                if 'MASTERVOLUME' in mixer_options.keys() and mixer_options['MASTERVOLUME'] in range(128):
                    encoder = EncoderElement(MIDI_CC_TYPE, global_channel, mixer_options['MASTERVOLUME'], volume_map_mode)
                    encoder.name = 'Master_Volume_Control'
                    mixer.master_strip().set_volume_control(encoder)
                if 'NUMSENDS' in mixer_options.keys() and mixer_options['NUMSENDS'] > 0:
                    for send in range(mixer_options['NUMSENDS']):
                        key = 'SEND' + str(send + 1)
                        raise key in mixer_options.keys() or AssertionError
                        send_info.append(mixer_options[key])

                momentary_buttons = 'NOTOGGLE' in mixer_options.keys()
                next_bank_button = None
                prev_bank_button = None
                if 'NEXTBANK' in mixer_options.keys() and mixer_options['NEXTBANK'] in range(128):
                    next_bank_button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, mixer_options['NEXTBANK'])
                    next_bank_button.name = 'Mixer_Next_Bank_Button'
                if 'PREVBANK' in mixer_options.keys() and mixer_options['PREVBANK'] in range(128):
                    prev_bank_button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, mixer_options['PREVBANK'])
                    prev_bank_button.name = 'Mixer_Previous_Bank_Button'
                mixer.set_bank_buttons(next_bank_button, prev_bank_button)
            for track in range(num_strips):
                strip = mixer.channel_strip(track)
                strip.name = 'Channel_Strip_' + str(track)
                if track in range(len(volume_controls)):
                    channel = global_channel
                    cc = volume_controls[track]
                    if isinstance(volume_controls[track], (tuple, list)):
                        cc = volume_controls[track][0]
                        if volume_controls[track][1] in range(16):
                            channel = volume_controls[track][1]
                    if cc in range(128) and channel in range(16):
                        encoder = EncoderElement(MIDI_CC_TYPE, channel, cc, volume_map_mode)
                        encoder.name = str(track) + '_Volume_Control'
                        strip.set_volume_control(encoder)
                if track in range(len(trackarm_controls)) and trackarm_controls[track] in range(128):
                    button = ButtonElement(momentary_buttons, MIDI_CC_TYPE, global_channel, trackarm_controls[track])
                    button.name = str(track) + '_Arm_Button'
                    strip.set_arm_button(button)
                send_controls = []
                for send in send_info:
                    encoder = None
                    if track in range(len(send)):
                        channel = global_channel
                        cc = send[track]
                        if isinstance(send[track], (tuple, list)):
                            cc = send[track][0]
                            if send[track][1] in range(16):
                                channel = send[track][1]
                        if cc in range(128) and channel in range(16):
                            encoder = EncoderElement(MIDI_CC_TYPE, channel, cc, volume_map_mode)
                            encoder.name = str(track) + '_Send_' + str(list(send_info).index(send)) + '_Control'
                    send_controls.append(encoder)

                strip.set_send_controls(tuple(send_controls))
Example #49
0
 def _setup_mixer_control(self):
     is_momentary = True
     self._num_tracks = (7)  #A mixer is one-dimensional;
     global mixer
     mixer = SpecialMixerComponent(7, 0, True, False)
     mixer.name = 'Mixer'
     self._mixer = mixer
     mixer.set_track_offset(
         0)  #Sets start point for mixer strip (offset from left)
     for index in range(7):
         mixer.channel_strip(index).set_volume_control(self._fader[index])
     for index in range(7):
         mixer.channel_strip(
             index).name = 'Mixer_ChannelStrip_' + str(index)
         mixer.track_eq(index).name = 'Mixer_EQ_' + str(index)
         mixer.channel_strip(index)._invert_mute_feedback = True
     self.song().view.selected_track = mixer.channel_strip(
         0
     )._track  #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error