示例#1
0
    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)

        return
示例#2
0
	def _setup_mixer_control(self):
		is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant
		num_tracks = 7 # Here we define the mixer width in tracks (a mixer has only one dimension)
		global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...)
		mixer = MixerComponent(num_tracks, 0) #(num_tracks, num_returns, with_eqs, with_filters)
		mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
		"""set up the mixer buttons"""		  
		self.song().view.selected_track = mixer.channel_strip(0)._track
		mixer.selected_strip().set_mute_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 64))
		#mixer.selected_strip().set_solo_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 44))
		mixer.selected_strip().set_arm_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 72))
		track_select_notes = [65, 73, 66, 74, 67, 75, 68, 76] #more note numbers need to be added if num_scenes is increased
		slider_select_notes = [3, 2, 1, 0, 5, 4, 6, 7]
		#pan_select_notes = [21, 20, 13, 12, 3, 1, 0, 2]
		master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 7)
		#master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 76)
		#prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 26, Live.MidiMap.MapMode.absolute)
		#crossfader = SliderElement(MIDI_CC_TYPE, 0, 24)
		for index in range(num_tracks):
			#mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, track_select_notes[index]))
			mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL, slider_select_notes[index]))
			#mixer.channel_strip(index).set_pan_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, pan_select_notes[index], Live.MidiMap.MapMode.absolute))
		#crossfader.name = 'Crossfader'
		master_volume_control.name = 'Master_Volume_Control'
		#master_select_button.name = 'Master_Select_Button'
		#prehear_control.name = 'Prehear_Volume_Control'
		#mixer.set_crossfader_control(crossfader)
		#mixer.set_prehear_volume_control(prehear_control)
		mixer.master_strip().set_volume_control(master_volume_control)
    def _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)

        # add side buttons as channel 4
        # button = ButtonElement(is_momentary, MESSAGETYPE, SIDE_BUTTONS_CHANNEL, TOP_LEFT_SIDE_BTN_VAL)
        # self._side_buttons.append(button)
        # button = ButtonElement(is_momentary, MESSAGETYPE, SIDE_BUTTONS_CHANNEL, BTM_LEFT_SIDE_BTN_VAL)
        # self._side_buttons.append(button)
        # button = ButtonElement(is_momentary, MESSAGETYPE, SIDE_BUTTONS_CHANNEL, TOP_RITE_SIDE_BTN_VAL)
        # self._side_buttons.append(button)
        # button = ButtonElement(is_momentary, MESSAGETYPE, SIDE_BUTTONS_CHANNEL, BTM_RITE_SIDE_BTN_VAL)
        # self._side_buttons.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)
 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)
示例#5
0
 def disconnect(self):
     if self._parameter_to_map_to is not None:
         if hasattr(self._parameter_to_map_to, 'name'):
             self._parameter_to_map_to.remove_value_listener(
                 self._on_value_changed)
     SliderElement.disconnect(self)
     return
示例#6
0
    def _setup_mixer_control(self):
        is_momentary = True

        """ Instantiate a Mixer Component """
        global mixer  # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...)
        mixer = MixerComponent(mixer_num_tracks, 2, with_eqs=True, with_filters=True)  # (num_tracks, num_returns, with_eqs, with_filters)
        mixer.set_track_offset(0)  # Sets start point for mixer strip (offset from left)
        self.song().view.selected_track = mixer.channel_strip(0)._track  # set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error

        """ Buttons and Sliders association """
        # Master channel
        mixer.master_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, midi_channel, midi_mixer_volume_master))  # sets the continuous controller for volume

        # Other channels, same size as mixer_num_tracks
        # Set volume control, solo and mute buttons
        for index in range(mixer_num_tracks):  # launch_button assignment must match number of scenes
            mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, midi_channel, midi_mixer_volume_channels[index]))  # sets the continuous controller for volume
            mixer.channel_strip(index).set_solo_button(ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_mixer_solo_channels[index]))  # sets the solo button
            mixer.channel_strip(index).set_mute_button(ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_mixer_mute_channels[index]))  # sets the mute ("activate") button

        """ Buttons to select track """
        button_next_track = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_track_select_next)
        button_previous_track = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_track_select_previous)
        mixer.set_select_buttons(button_next_track, button_previous_track)

        """ Listeners """
        # When selected track if changed
        self.song().view.add_selected_track_listener(self.on_track_selected)
示例#7
0
    def _setup_mixer_control(self):
        is_momentary = True
        mixer = MixerComponent(NUM_TRACKS, 2)
        for track in range(NUM_TRACKS):
            strip = mixer.channel_strip(track)
            strip.set_volume_control(SliderElement(MIDI_CC_TYPE, track, 23))
            strip.set_pan_control(
                EncoderElement(MIDI_CC_TYPE, track, 10,
                               Live.MidiMap.MapMode.absolute))
            strip.set_send_controls(
                (EncoderElement(MIDI_CC_TYPE, track, 19,
                                Live.MidiMap.MapMode.absolute),
                 EncoderElement(MIDI_CC_TYPE, track, 20,
                                Live.MidiMap.MapMode.absolute)))
            strip.set_solo_button(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 64))
            strip.set_mute_button(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 63))
            strip.set_crossfade_toggle(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 65))
            eq = mixer.track_eq(track)
            eq.set_gain_controls(
                tuple([
                    EncoderElement(MIDI_CC_TYPE, track, 18 - index,
                                   Live.MidiMap.MapMode.absolute)
                    for index in range(3)
                ]))
            eq.set_cut_buttons(
                tuple([
                    ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                  62 - index) for index in range(3)
                ]))
            filter = mixer.track_filter(track)
            filter.set_filter_controls(
                EncoderElement(MIDI_CC_TYPE, track, 22,
                               Live.MidiMap.MapMode.absolute),
                EncoderElement(MIDI_CC_TYPE, track, 21,
                               Live.MidiMap.MapMode.absolute))

        for ret_track in range(2):
            strip = mixer.return_strip(ret_track)
            strip.set_volume_control(
                SliderElement(MIDI_CC_TYPE, 12, 22 + ret_track))
            strip.set_pan_control(
                EncoderElement(MIDI_CC_TYPE, 12, 20 + ret_track,
                               Live.MidiMap.MapMode.absolute))
            strip.set_mute_button(
                ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12,
                              78 + ret_track))

        mixer.set_crossfader_control(SliderElement(MIDI_CC_TYPE, 12, 8))
        mixer.set_prehear_volume_control(
            EncoderElement(MIDI_CC_TYPE, 12, 24,
                           Live.MidiMap.MapMode.absolute))
        mixer.master_strip().set_volume_control(
            SliderElement(MIDI_CC_TYPE, 12, 7))
        mixer.master_strip().set_pan_control(
            EncoderElement(MIDI_CC_TYPE, 12, 10,
                           Live.MidiMap.MapMode.absolute))
        return mixer
示例#8
0
    def _setup_mixer_control(self):
        is_momentary = True
        num_tracks = 8
        num_returns = 7
        mixer = MixerComponent(num_tracks, num_returns)
        for track in range(num_tracks):
            strip = mixer.channel_strip(track)
            strip.set_volume_control(
                SliderElement(MIDI_CC_TYPE, 15, 54 - track))
            strip.set_pan_control(SliderElement(MIDI_CC_TYPE, 15, 80 - track))
            strip.set_mute_button(
                ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 117 - track))
            strip.set_invert_mute_feedback(True)

        for track in range(num_returns):
            strip = mixer.return_strip(track)
            strip.set_volume_control(
                SliderElement(MIDI_CC_TYPE, 15, 10 + track))

        mixer.set_bank_buttons(
            ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 108),
            ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 109))
        mixer.set_crossfader_control(SliderElement(MIDI_CC_TYPE, 15, 9))
        mixer.master_strip().set_volume_control(
            SliderElement(MIDI_CC_TYPE, 15, 46))
        session = SessionComponent(0, 0)
        session.set_select_buttons(
            ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 95),
            ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 92))
        session.selected_scene().set_launch_button(
            ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 91))
示例#9
0
class MaschineMk2(Maschine):
    """Control Script for Maschine Studio"""
    __module__ = __name__
    _gated_buttons = []

    def __init__(self, c_instance):
        super(MaschineMk2, self).__init__(c_instance)

    def create_pad_button(self, scene_index, track_index, color_source):
        return PadColorButton(True, 0, scene_index, track_index, color_source)

    def create_gated_button(self, identifier, hue):
        button = GatedColorButton(True, MIDI_CC_TYPE, identifier, hue)
        self._gated_buttons.append(button)
        return button

    def _init_maschine(self):
        self._jogwheel = KnobSection(self._modeselect, self._editsection)
        self._note_repeater.registerKnobHandler(self._jogwheel)
        self._mixer.set_touch_mode(2)
        self._device_component.set_touch_mode(2)
        self.prehear_knob = SliderElement(MIDI_CC_TYPE, 0, 41)
        self.prehear_knob.connect_to(
            self.song().master_track.mixer_device.cue_volume)

    def to_color_edit_mode(self, active):
        if self._editsection.is_color_edit() != active:
            self._jogwheel.invoke_color_mode(active and 1 or 0)

    def use_layered_buttons(self):
        return True

    def _final_init(self):
        debug_out('########## LIVE 9 MASCHINE Mk2 V 2.02 ############# ')

    def _click_measure(self):
        pass

    def apply_preferences(self):
        super(MaschineMk2, self).apply_preferences()
        pref_dict = self._pref_dict
        if 'color_mode' in pref_dict:
            value = pref_dict['color_mode']
            self._session.set_color_mode(value)
            self._session._c_mode_button.send_value(value == True and 127 or 0,
                                                    True)
        else:
            self._session.set_color_mode(False)
            self._session._c_mode_button.send_value(0, True)

    def store_preferences(self):
        super(MaschineMk2, self).store_preferences()
        self._pref_dict['color_mode'] = self._session.is_color_mode()

    def preferences_name(self):
        return 'MaschineMk2'

    def cleanup(self):
        for button in self._gated_buttons:
            button.switch_off()
示例#10
0
    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)
示例#11
0
 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 = 'DirectLink'
         self._suggested_output_port = 'DirectLink'
         self._waiting_for_first_response = True
         self._has_sliders = True
         self._current_midi_map = None
         self._display_reset_delay = -1
         self._shift_pressed = False
         self._shift_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15,
                                            13)
         self._master_slider = SliderElement(MIDI_CC_TYPE, 15, 41)
         self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE,
                                               15, 111)
         self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE,
                                               15, 110)
         self._device_bank_buttons = None
         self._device_navigation = None
         self._shift_button.name = 'Shift_Button'
         self._master_slider.name = 'Master_Volume_Control'
         self._next_nav_button.name = 'Next_Track_Button'
         self._prev_nav_button.name = 'Prev_Track_Button'
         self._master_slider.add_value_listener(self._slider_value,
                                                identify_sender=True)
         self._shift_button.add_value_listener(self._shift_value)
         self._setup_mixer()
         self._setup_transport_and_session()
         self._setup_device()
         self._setup_display()
         for component in self.components:
             component.set_enabled(False)
示例#12
0
    def __init__(self, hyperion, mod_num, *a, **kw):
        super(HyperionChan, self).__init__(*a, **kw)

        self.hyperion = hyperion
        self.mod_num = mod_num

        self._track_selector_encoder = EncoderElement(MIDI_CC_TYPE, MIDI_MASTER_CH + 1 + mod_num, 0x15, Live.MidiMap.MapMode.relative_smooth_binary_offset) # Right encoder on Hyperion
        self._track_selector_encoder.add_value_listener(self._on_track_selector_encoder)

        self._fader = SliderElement(MIDI_CC_TYPE, MIDI_MASTER_CH + 1 + mod_num, 0x25)
        self._pots = [
            EncoderElement(MIDI_CC_TYPE, MIDI_MASTER_CH + 1 + mod_num, 0x1E + num, Live.MidiMap.MapMode.absolute, name='Pot{}'.format(num))
            for num in range(8)
        ]
        self._btns = [
            ButtonElement(True, MIDI_CC_TYPE, MIDI_MASTER_CH + 1 + mod_num, 1 + num, name='Btn{}'.format(num))
            for num in range(8)
        ]
        self._enc_right_btn = ButtonElement(True, MIDI_CC_TYPE, MIDI_MASTER_CH + 1 + mod_num, 10, name='EncRightBtn')
        self._enc_right_btn.add_value_listener(self._on_enc_right_btn)

        #self._cs = ChannelStripComponent()
        #self._cs.set_volume_control(self._fader)
        self._vu_slider = SliderElement(MIDI_CC_TYPE, MIDI_MASTER_CH + 1 + mod_num, 60)

        self._vu = VUMeter(self)

        self._track = None

        tracks = self._get_all_tracks(self.hyperion.song().tracks)
        if len(tracks) > self.mod_num:
            self._bind_to_track(tracks[self.mod_num])
        else:
            self._bind_to_track(None)
示例#13
0
	def _setup_mixer_control(self):
		is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant
		num_tracks = 7 # Here we define the mixer width in tracks (a mixer has only one dimension)
		global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...)
		mixer = MixerComponent(num_tracks, 0) #(num_tracks, num_returns, with_eqs, with_filters)
		mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
		"""set up the mixer buttons"""		  
		self.song().view.selected_track = mixer.channel_strip(0)._track
		mixer.selected_strip().set_mute_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 64))
		#mixer.selected_strip().set_solo_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 44))
		mixer.selected_strip().set_arm_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 72))
		track_select_notes = [65, 73, 66, 74, 67, 75, 68, 76] #more note numbers need to be added if num_scenes is increased
		slider_select_notes = [23, 22, 15, 14, 5, 7, 6, 4]
		pan_select_notes = [21, 20, 13, 12, 3, 1, 0, 2]
		master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 4)
		master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 76)
		prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 26, Live.MidiMap.MapMode.absolute)
		crossfader = SliderElement(MIDI_CC_TYPE, 0, 24)
		for index in range(num_tracks):
			mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, track_select_notes[index]))
			mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL, slider_select_notes[index]))
			mixer.channel_strip(index).set_pan_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, pan_select_notes[index], Live.MidiMap.MapMode.absolute))
		crossfader.name = 'Crossfader'
		master_volume_control.name = 'Master_Volume_Control'
		master_select_button.name = 'Master_Select_Button'
		prehear_control.name = 'Prehear_Volume_Control'
		mixer.set_crossfader_control(crossfader)
		mixer.set_prehear_volume_control(prehear_control)
		mixer.master_strip().set_volume_control(master_volume_control)
		mixer.master_strip().set_select_button(master_select_button)
    def _load_MIDI_map(self):
        # Midi messages can be either "Toggle" or "Momentary".
        #
        # A toggle message consists of a single message with value 127, while a
        # momentary message first sends 127, followed by 0.
        #
        # Set this flag according to which kind of messages you're using.
        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)
示例#15
0
 def __init__(self, button_index, monochrome = False, *a, **k):
     super(PadMode, self).__init__(button_index, *a, **k)
     self._note_display_mode = ND_KEYBOARD1
     self.current_scale_index = 0
     self._scale = None
     self._base_note = 0
     self._octave = 0.55
     self.current_scale_index = 0
     self._in_edit_mode = False
     self._editmode = None
     self._is_monochrome = monochrome
     self._color_edit_assign = monochrome and self.assign_edit_mono or self.assign_edit_color
     self.assign_transpose(SCALES[self.current_scale_index])
     is_momentary = True
     self.octave_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 120)
     self.octave_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 121)
     self.base_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 124)
     self.base_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 125)
     self.scale_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 118)
     self.scale_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 119)
     self._adjust_scale.subject = SliderElement(MIDI_CC_TYPE, 2, 116)
     self._adjust_octav.subject = SliderElement(MIDI_CC_TYPE, 2, 115)
     self._adjust_basem.subject = SliderElement(MIDI_CC_TYPE, 2, 117)
     self._do_oct_down.subject = self.octave_down_button
     self._do_oct_up.subject = self.octave_up_button
     self._do_base_down.subject = self.base_down_button
     self._do_base_up.subject = self.base_up_button
     self._do_scale_down.subject = self.scale_down_button
     self._do_scale_up.subject = self.scale_up_button
     self._seg_display = None
示例#16
0
 def _setup_mixer_control(self):
     is_momentary = True
     mixer = MixerComponent(1)
     mixer.selected_strip().set_mute_button(
         SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                            KMK_PAD[9]))
     mixer.selected_strip().set_solo_button(
         SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                            KMK_PAD[13]))
     mixer.set_select_buttons(
         SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                            KMK_PAD[15]),
         SysexButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                            KMK_PAD[14]))
     send_faders = []
     NUM_CONTROLLABLE_SENDS = 4
     for index in range(NUM_CONTROLLABLE_SENDS):
         send_faders.append(
             SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[index + 2]))
     mixer.selected_strip().set_volume_control(
         SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[0]))
     mixer.selected_strip().set_pan_control(
         SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[1]))
     mixer.selected_strip().set_send_controls(tuple(send_faders))
     mixer.set_prehear_volume_control(
         EncoderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[6],
                        Live.MidiMap.MapMode.absolute))
     mixer.master_strip().set_volume_control(
         SliderElement(MIDI_CC_TYPE, CHANNEL, KMK_FADER[7]))
     return mixer
示例#17
0
    def _setup_mixer_control(self):
        #set up the mixer
        self.mixer = MixerComponent(
            NUM_TRACKS, 2)  #(num_tracks, num_returns, with_eqs, with_filters)
        self.mixer.set_track_offset(
            0)  #sets start point for mixer strip (offset from left)
        self.mixer.selected_strip().set_arm_button(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                          KEYBOARD_HIGH_C))
        self.mixer.set_select_buttons(
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                          KEYBOARD_HIGH_C - 2),
            ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,
                          KEYBOARD_HIGH_C - 4))
        self.mixer.master_strip().set_volume_control(
            SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[3]))
        #self.mixer.master_strip().set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[7]))
        #set the selected strip to the first track, so that we don't assign a button to arm the master track, which would cause an assertion error
        self.song().view.selected_track = self.mixer.channel_strip(0)._track
        self.mixer.selected_strip().set_volume_control(
            SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[0]))
        #self.mixer.selected_strip().set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[4]))

        selected_track = self.song().view.selected_track
        all_tracks = ((self.song().tracks + self.song().return_tracks) +
                      (self.song().master_track, ))
        currentTrackIndex = list(all_tracks).index(selected_track)
        if currentTrackIndex < len(all_tracks) - 1:
            self.mixer.channel_strip(currentTrackIndex + 1).set_volume_control(
                SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[1]))
            #self.mixer.channel_strip(currentTrackIndex + 1).set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[5]))
        if currentTrackIndex < len(all_tracks) - 2:
            self.mixer.channel_strip(currentTrackIndex + 2).set_volume_control(
                SliderElement(MIDI_CC_TYPE, CHANNEL, KNOBS[2]))
示例#18
0
	def doStuff(self,x):

		try:
			data, addr = self.sock.recvfrom(64) # buffer size is 1024 byte
			
			addressPattern = data[:data.find("\0")]

			#data = data.split(',i')
			#v = struct.unpack('>i',data[1][2:(2+4)])[0]
			data = data.split(',ii')
			v = struct.unpack('>ii',data[1][1:])

			track_number = v[0]
			midi_cc = v[1]

			b = SliderElement(1, 0, midi_cc)
			song = self.song()

			if (addressPattern == "/pan"):
				b.connect_to(song.tracks[track_number].mixer_device.panning)
			elif (addressPattern == "/volume"):
				b.connect_to(song.tracks[track_number].mixer_device.volume)
			self.show_message(addressPattern)
		except socket.error:
			pass
示例#19
0
    def _set_up_mixer(self):
        is_momentary = True
        self._mixer = MaschineMixerComponent(8)
        self.send_sliders = []
        for track in range(8):
            self.send_sliders.append(
                SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL,
                              SEND_CC_OFF + track))

        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.set_arm_button(
                StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL,
                            ARM_CC_OFF + track))
            strip.set_solo_button(
                StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL,
                            SOLO_CC_OFF + track))
            strip.set_mute_button(
                StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL,
                            MUTE_CC_OFF + track))
            strip.set_volume_control(
                SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL,
                              LEVEL_CC_OFF + track))
            strip.set_pan_control(
                SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, PAN_CC_OFF + track))
            strip.set_select_button(
                StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL,
                            SELECT_CC_OFF + track))
            st = tuple([self.send_sliders[track]])
            strip.set_send_controls(st)

        self.send_slider_toggle_button = StateButton(False, MIDI_CC_TYPE, 0,
                                                     90)
        self._do_toggle_send.subject = self.send_slider_toggle_button
        self._session.set_mixer(self._mixer)
示例#20
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):
        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)
            solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        49)
            mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track,
                                        50)
            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)
示例#22
0
    def _set_initial_mode(self):
        is_momentary = True
        ### MIXER

        for index in range(num_tracks):
            strip = self.mixer.channel_strip(index)
            strip.name = 'Mixer_ChannelStrip_' + str(index)
            strip.set_volume_control(
                SliderElement(MIDI_CC_TYPE, data_channel,
                              mixer_volume_cc[index]))
            strip._invert_mute_feedback = True

        self.mixer.master_strip().set_volume_control(
            SliderElement(MIDI_CC_TYPE, data_channel, mixer_master_cc))
        self.transport.set_stop_button(
            ButtonElement(False, MIDI_CC_TYPE, data_channel,
                          transport_stop_cc))
        self.transport.set_play_button(
            ButtonElement(False, MIDI_CC_TYPE, data_channel,
                          transport_play_cc))
        self.transport.set_record_button(
            ButtonElement(False, MIDI_CC_TYPE, data_channel,
                          transport_record_cc))

        self.log("color: " + str(self.session.tracks_to_use()[0].color))
        self.log("color: " + str(self.session.tracks_to_use()[1].color))
        self.log("color: " + str(self.session.tracks_to_use()[2].color))
        self.log("color: " + str(self.session.tracks_to_use()[3].color))
        self._send_midi([0x09, 0x09, 0x09, 0x09])
    def __init__(self, note_repeat=None, *a, **k):
        super(NoteRepeatComponent, self).__init__(*a, **a)
        self._note_repeat = note_repeat
        self._adjust_cfg_value.subject = SliderElement(MIDI_CC_TYPE, 2, 105)
        self._note_repeat_button = ButtonElement(True, MIDI_CC_TYPE, 0, 102)
        self._do_note_repeat.subject = self._note_repeat_button
        self._cfg_adjust_button = ButtonElement(True, MIDI_CC_TYPE, 2, 106)
        self._cfg_adjust_button.add_value_listener(self._do_cfg_button)
        self._cfg_down = False
        self._hold_mode = False
        self.nr_down = False
        self._current_nr_button = None
        self._do_change_nr_1.subject = SliderElement(MIDI_CC_TYPE, 1, 76)
        self._do_change_nr_2.subject = SliderElement(MIDI_CC_TYPE, 1, 77)
        self._do_change_nr_3.subject = SliderElement(MIDI_CC_TYPE, 1, 78)
        self._do_change_nr_4.subject = SliderElement(MIDI_CC_TYPE, 1, 79)

        def createButton(ccindenfier, nr_freq):
            button = ButtonElement(True, MIDI_CC_TYPE, 1, ccindenfier)
            button.add_value_listener(self._select_value, True)
            button.active = False
            button.freq = nr_freq
            button.cfg = False
            button.hold = False
            return button

        def createCfgButton(ccindenfier, nr_freq_idx):
            button = ButtonElement(True, MIDI_CC_TYPE, 2, ccindenfier)
            button.add_value_listener(self._select_value, True)
            button.active = False
            button.fr_idx = nr_freq_idx
            button.freq = CFG_REPEAT_FREQUENCIES[nr_freq_idx]
            button.cfg = True
            button.hold = False
            return button

        continue
        self._cfg_buttons = [
            createCfgButton(assign[0], assign[1])
            for assign in CTRL_CFG_TO_FREQ
        ]
        for button in self._cfg_buttons:
            if not button.active or 1:
                pass
            button.send_value(0, True)

        self.nr_frq = CTRL_TO_FREQ[4][1]
        self._note_repeat.repeat_rate = (1 / self.nr_frq) * 4
        continue
        self.buttons = [
            createButton(assign[0], assign[1]) for assign in CTRL_TO_FREQ
        ]
        self.buttons[4].active = True
        self._previous_button = self.buttons[4]
        self._last_active_button = self.buttons[4]
        for button in self.buttons:
            if not button.active or 1:
                pass
            button.send_value(0, True)
示例#24
0
 def _init_maschine(self):
     self._jogwheel = KnobSection(self._modeselect, self._editsection)
     self._note_repeater.registerKnobHandler(self._jogwheel)
     self._mixer.set_touch_mode(2)
     self._device_component.set_touch_mode(2)
     self.prehear_knob = SliderElement(MIDI_CC_TYPE, 0, 41)
     self.prehear_knob.connect_to(
         self.song().master_track.mixer_device.cue_volume)
示例#25
0
 def _setup_transport(self):
     is_momentary = True
     transport = TransportComponent()
     studiotransport = MaschineTransport()
     playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108)
     stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110)
     recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109)
     overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107)
     metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104)
     eventRecButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 98)
     playButton.name = 'Play'
     stopButton.name = 'Stop'
     recordButton.name = 'Record'
     overdubButton.name = 'Overdub'
     metrononmeButton.name = 'Metronome'
     transport.set_play_button(playButton)
     transport.set_stop_button(stopButton)
     transport.set_record_button(recordButton)
     transport.set_overdub_button(overdubButton)
     transport.set_metronome_button(metrononmeButton)
     studiotransport.set_session_auto_button(eventRecButton)
     studiotransport.set_arrangement_overdub_button(
         StateButton(is_momentary, MIDI_CC_TYPE, 0, 106))
     studiotransport.set_back_arrange_button(
         StateButton(is_momentary, MIDI_CC_TYPE, 0, 105))
     transport.set_nudge_buttons(
         StateButton(is_momentary, MIDI_CC_TYPE, 1, 51),
         StateButton(is_momentary, MIDI_CC_TYPE, 1, 50))
     punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52)
     punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53)
     punchinbutton.name = 'Punch In'
     punchoutbutton.name = 'Punch Out'
     transport.set_punch_buttons(punchinbutton, punchoutbutton)
     transport.set_loop_button(
         StateButton(is_momentary, MIDI_CC_TYPE, 1, 54))
     self.song_follow_button = ButtonElement(True, MIDI_CC_TYPE, 2, 98)
     self._do_song_follow.subject = self.song_follow_button
     self._song_follow_changed.subject = self.song().view
     self._song_follow_changed()
     self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59)
     self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58)
     transport.set_seek_buttons(self.transp_ff_button,
                                self.transp_rw_button)
     self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 105)
     self.xfadeKnob.connect_to(
         self.song().master_track.mixer_device.crossfader)
     self.master_knob = SliderElement(MIDI_CC_TYPE, 0, 99)
     self.master_knob.connect_to(
         self.song().master_track.mixer_device.volume)
     self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88)
     self._do_tap_tempo.subject = self.tap_button
     self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1,
                                              55)
     self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56)
     self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57)
     self._do_toggle_cue.subject = self.cue_add_delete_button
     self._do_toggle_prev_cue.subject = self.cue_prev_button
     self._do_toggle_next_cue.subject = self.cue_next_button
示例#26
0
 def _setup_transport_control(self):
     is_momentary = True
     transport = TransportComponent()
     transport.set_play_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 80))
     transport.set_record_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 81))
     transport.set_nudge_buttons(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 86), ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 85))
     transport.set_loop_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 84))
     transport.set_punch_buttons(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 82), ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 83))
     transport.set_tempo_control(SliderElement(MIDI_CC_TYPE, 12, 26), SliderElement(MIDI_CC_TYPE, 12, 25))
 def _set_up_machine_knobs(self):
     master_track = self.song().master_track
     self.prehear_knob = SliderElement(MIDI_CC_TYPE, 0, 43)
     self.prehear_knob.connect_to(
         self.song().master_track.mixer_device.cue_volume)
     self._stop_tap_button = ButtonElement(True, MIDI_CC_TYPE, 1, 111)
     self._do_combined_stop_tap.subject = self._stop_tap_button
     self._undo__redo_button = ButtonElement(True, MIDI_CC_TYPE, 2, 85)
     self._do_undo_redo.subject = self._undo__redo_button
示例#28
0
 def release_parameter(self):
     """ Overrides standard to update mapping type on parameter disconnect and clear
     out observers. """
     self._on_parameter_changed.subject = None
     self._on_property_value_changed.subject = None
     SliderElement.release_parameter(self)
     self._smoother.set_parameter(None)
     self._parameter_to_map_to = None
     self._update_mapping_type()
     return
示例#29
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)
示例#30
0
 def connect_to(self, parameter):
     """ Overrides standard so that mapping type can be properly updated on parameter
     assignment.  Also handles setting up observers. """
     self._on_parameter_changed.subject = None
     self._on_parameter_name_changed.subject = None
     SliderElement.connect_to(self, parameter)
     self._smoother.set_parameter(self._parameter_to_map_to)
     self._on_parameter_changed.subject = self._parameter_to_map_to
     self._on_parameter_name_changed.subject = self._parameter_to_map_to
     self._update_mapping_type()
     return
    def connect_to(self, param):
        if self._parameter_to_map_to is not None:
            try:
                self._parameter_to_map_to.remove_value_listener(self._on_value_changed)
            except:
                pass

        SliderElement.connect_to(self, param)
        if param is not None:
            if not self._parameter_to_map_to.value_has_listener(self._on_value_changed):
                self._parameter_to_map_to.add_value_listener(self._on_value_changed)
        self._send_param_val(True)
 def _setup_transport(self):
     is_momentary = True
     transport = TransportComponent()
     studiotransport = MaschineTransport()
     playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108)
     stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110)
     recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109)
     overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107)
     metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104)
     eventRecButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 98)
     playButton.name = 'Play'
     stopButton.name = 'Stop'
     recordButton.name = 'Record'
     overdubButton.name = 'Overdub'
     metrononmeButton.name = 'Metronome'
     transport.set_play_button(playButton)
     transport.set_stop_button(stopButton)
     transport.set_record_button(recordButton)
     transport.set_overdub_button(overdubButton)
     transport.set_metronome_button(metrononmeButton)
     studiotransport.set_session_auto_button(eventRecButton)
     studiotransport.set_arrangement_overdub_button(StateButton(is_momentary, MIDI_CC_TYPE, 0, 106))
     studiotransport.set_back_arrange_button(StateButton(is_momentary, MIDI_CC_TYPE, 0, 105))
     transport.set_nudge_buttons(StateButton(is_momentary, MIDI_CC_TYPE, 1, 51), StateButton(is_momentary, MIDI_CC_TYPE, 1, 50))
     punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52)
     punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53)
     punchinbutton.name = 'Punch In'
     punchoutbutton.name = 'Punch Out'
     transport.set_punch_buttons(punchinbutton, punchoutbutton)
     transport.set_loop_button(StateButton(is_momentary, MIDI_CC_TYPE, 1, 54))
     self.song_follow_button = ButtonElement(True, MIDI_CC_TYPE, 2, 98)
     self._do_song_follow.subject = self.song_follow_button
     self._song_follow_changed.subject = self.song().view
     self._song_follow_changed()
     self.prehear_knob = SliderElement(MIDI_CC_TYPE, 0, 41)
     self.prehear_knob.connect_to(self.song().master_track.mixer_device.cue_volume)
     self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59)
     self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58)
     transport.set_seek_buttons(self.transp_ff_button, self.transp_rw_button)
     self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 105)
     self.xfadeKnob.connect_to(self.song().master_track.mixer_device.crossfader)
     self.master_knob = SliderElement(MIDI_CC_TYPE, 0, 99)
     self.master_knob.connect_to(self.song().master_track.mixer_device.volume)
     self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88)
     self._do_tap_tempo.subject = self.tap_button
     self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 55)
     self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56)
     self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57)
     self._do_toggle_cue.subject = self.cue_add_delete_button
     self._do_toggle_prev_cue.subject = self.cue_prev_button
     self._do_toggle_next_cue.subject = self.cue_next_button
示例#33
0
    def _MG_setup(self):
        mixer = MixerComponent(8)
        mixer.set_track_offset(
            0)  #Sets start point for mixer strip (offset from left)
        transport = TransportComponent()
        mixer.set_track_offset(0)

        for i in xrange(len(KNOBS)):  #set the functions of the knobs
            volume_knob = SliderElement(MIDI_CC_TYPE, 0, KNOBS[i])
            pan_knob = SliderElement(MIDI_CC_TYPE, 1, KNOBS[i])

            send_a = SliderElement(MIDI_CC_TYPE, 2, KNOBS[i])
            send_b = SliderElement(MIDI_CC_TYPE, 3, KNOBS[i])
            send_c = SliderElement(MIDI_CC_TYPE, 4, KNOBS[i])
            send_d = SliderElement(MIDI_CC_TYPE, 5, KNOBS[i])
            send_e = SliderElement(MIDI_CC_TYPE, 6, KNOBS[i])
            send_f = SliderElement(MIDI_CC_TYPE, 7, KNOBS[i])

            mixer.channel_strip(i).set_volume_control(volume_knob)
            mixer.channel_strip(i).set_pan_control(pan_knob)
            mixer.channel_strip(i).set_send_controls(
                [send_a, send_b, send_c, send_d, send_e, send_f])

        # scenes are locked to channel 14
        transport.set_overdub_button(
            ButtonElement(False, MIDI_CC_TYPE, 0, SCENES[0]))
        transport.set_stop_button(
            ButtonElement(False, MIDI_CC_TYPE, 0, SCENES[1]))
示例#34
0
    def _create_controls(self):
        self._device_encoders = ButtonMatrixElement(rows=[[
            EncoderElement(MIDI_CC_TYPE,
                           ENCODER_CHANNEL,
                           identifier,
                           Live.MidiMap.MapMode.relative_smooth_binary_offset,
                           name=b'Device_Encoder_%d_%d' %
                           (col_index, row_index))
            for col_index, identifier in enumerate(row)
        ] for row_index, row in enumerate((ENCODER_MSG_IDS[:4],
                                           ENCODER_MSG_IDS[4:8]))])
        self._horizontal_scroll_encoder = EncoderElement(
            MIDI_CC_TYPE,
            ENCODER_CHANNEL,
            ENCODER_MSG_IDS[(-2)],
            Live.MidiMap.MapMode.relative_smooth_binary_offset,
            name=b'Horizontal_Scroll_Encoder')
        self._vertical_scroll_encoder = EncoderElement(
            MIDI_CC_TYPE,
            ENCODER_CHANNEL,
            ENCODER_MSG_IDS[(-1)],
            Live.MidiMap.MapMode.relative_smooth_binary_offset,
            name=b'Vertical_Scroll_Encoder')
        self._volume_sliders = ButtonMatrixElement(rows=[[
            SliderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, identifier)
            for identifier in SLIDER_MSG_IDS[:-1]
        ]])
        self._master_slider = SliderElement(MIDI_CC_TYPE, ENCODER_CHANNEL,
                                            SLIDER_MSG_IDS[(-1)])

        def make_keylab_button(name):
            button = ButtonElement(True,
                                   MIDI_CC_TYPE,
                                   0,
                                   get_button_identifier_by_name(name),
                                   name=name.title())
            return button

        for button_name in BUTTON_HARDWARE_AND_MESSAGE_IDS.keys():
            setattr(self, b'_' + button_name, make_keylab_button(button_name))

        self._pads = ButtonMatrixElement(rows=[[
            ButtonElement(True,
                          MIDI_CC_TYPE,
                          PAD_CHANNEL,
                          col_index + row_offset,
                          name=b'Pad_%d_%d' % (col_index, row_index))
            for col_index in xrange(4)
        ] for row_index, row_offset in enumerate(xrange(48, 35, -4))])
示例#35
0
    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 = "DirectLink"
            self._suggested_output_port = "DirectLink"
            self._waiting_for_first_response = True
            self._has_sliders = True
            self._current_midi_map = None
            self._display_reset_delay = -1
            self._shift_pressed = False
            self._shift_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 13)
            self._master_slider = SliderElement(MIDI_CC_TYPE, 15, 41)
            self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 111)
            self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 110)
            self._device_bank_buttons = None
            self._device_navigation = None
            self._shift_button.name = "Shift_Button"
            self._master_slider.name = "Master_Volume_Control"
            self._next_nav_button.name = "Next_Track_Button"
            self._prev_nav_button.name = "Prev_Track_Button"
            self._master_slider.add_value_listener(self._slider_value, identify_sender=True)
            self._shift_button.add_value_listener(self._shift_value)
            self._setup_mixer()
            self._setup_transport_and_session()
            self._setup_device()
            self._setup_display()
            for component in self.components:
                component.set_enabled(False)

        return
示例#36
0
 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)
 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)
示例#38
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 = EncoderElement(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 = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, str(track) + '_Solo_Button', self)
			self._solo_buttons.append(solo_button)	# added a
			mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49)
			select_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51, str(track) + '_Select_Button', 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)
		self._crossfader = crossfader
		self._crossfader.name = 'Crossfader'
		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)
示例#39
0
 def _load_MIDI_map(self):
     is_momentary = True
     rgb_skin = make_rgb_skin()
     for note in range(128):
         button = ButtonElement(is_momentary, MESSAGETYPE, BUTTONCHANNEL, note,)
         button.name = 'Button Note_' + str(note)
         button.is_rgb = True
         self._note_map.append(button)
     self._note_map.append(None) #add None to the end of the list, selectable with [-1]
     
     for note in range(128):
         clip_button = ColorButtonElement(self.log_message,is_momentary, MESSAGETYPE, BUTTONCHANNEL, note, skin = rgb_skin)
         clip_button.name = 'Clip Note_' + str(note)
         button.num_delayed_messages = 3
         self._clip_map.append(clip_button)
     self._clip_map.append(None) #add None
     
     if MESSAGETYPE == MIDI_CC_TYPE and BUTTONCHANNEL == SLIDERCHANNEL:
         for i in range(128):
             self._ctrl_map.append(None)
             self._enc_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)
         
         for enc in range(128):
             encoder = EncoderElement(MIDI_CC_TYPE, SLIDERCHANNEL, enc, Live.MidiMap.MapMode.absolute)
             encoder.name = "Encoder_" + str(enc)
             self._enc_map.append(encoder)
         self._enc_map.append(None)
         
     self.log_message('Note Map: %s' % self._note_map)
     self.log_message('Ctrl Map: %s' % self._ctrl_map)
     self.log_message('Enc Map: %s' % self._enc_map)
 def __init__(self, *a, **k):
     super(AudioClipEditComponent, self).__init__(*a, **k)
     self._loop_start_slider = SliderElement(MIDI_CC_TYPE, 2, 60)
     self._action_loop_start.subject = self._loop_start_slider
     self._loop_end_slider = SliderElement(MIDI_CC_TYPE, 2, 61)
     self._action_loop_end.subject = self._loop_end_slider
     self._mark_start_slider = SliderElement(MIDI_CC_TYPE, 2, 62)
     self._action_mark_start.subject = self._mark_start_slider
     self._mark_end_slider = SliderElement(MIDI_CC_TYPE, 2, 63)
     self._action_mark_end.subject = self._mark_end_slider
     self._pitch_c_slider = SliderElement(MIDI_CC_TYPE, 2, 64)
     self._pitch_f_slider = SliderElement(MIDI_CC_TYPE, 2, 65)
     self._gain_slider = SliderElement(MIDI_CC_TYPE, 2, 66)
     self._action_pitch_c.subject = self._pitch_c_slider
     self._action_pitch_f.subject = self._pitch_f_slider
     self._action_gain.subject = self._gain_slider
     self._loop_inc_slider = SliderElement(MIDI_CC_TYPE, 2, 67)
     self._action_loop_inc.subject = self._loop_inc_slider
     self._loop_move_button = ButtonElement(False, MIDI_CC_TYPE, 2, 74)
     self._action_mv_loop.subject = self._loop_move_button
     self._loop_set_button = ButtonElement(False, MIDI_CC_TYPE, 2, 70)
     self._action_loop_toggle.subject = self._loop_set_button
     self._warp_set_button = ButtonElement(False, MIDI_CC_TYPE, 2, 71)
     self._action_warp_toggle.subject = self._warp_set_button
     self._zoom_scroll_button = ButtonElement(False, MIDI_CC_TYPE, 2, 73)
     self._action_scroll_mode.subject = self._zoom_scroll_button
     self.selected_clip_slot = None
     self.inc_index = 4
     self.loop_inc = INC_STEPS[self.inc_index]
     self.start_inc = INC_STEPS[self.inc_index]
     self.mv_loop = False
     self._on_pitch_c_changed.subject = None
     self._on_pitch_f_changed.subject = None
     self._on_gain_changed.subject = None
     self._scroll_mode = False
     self.update_selected_clip()
示例#41
0
    def _init_mixer_component(self):
        is_momentary = True
        global mixer
        mixer = MixerComponent(8)
        mixer.name = 'Mixer'
        mixer.set_track_offset(0)
        self.song().view.selected_track = mixer.channel_strip(0)._track

        for track in range(8):
            #self.log_message("Adding track " + str(track))
            strip = mixer.channel_strip(track)
            strip.name = 'Channel_Strip_' + str(track)
            volume_control = SliderElement(MIDI_CC_TYPE, track, VOL_CC)
            snd_A_control = SliderElement(MIDI_CC_TYPE, track, SND_A_CC)
            snd_B_control = SliderElement(MIDI_CC_TYPE, track, SND_B_CC)
            pan_control = SliderElement(MIDI_CC_TYPE, track, PAN_CC)

            arm_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, track, ARM_CC)
            select_button = ButtonElement(is_momentary, MIDI_CC_TYPE, track, SEL_CC)
            mute_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, track, MUTE_CC)


            volume_control.name = str(track) + '_Volume_Control'
            snd_A_control.name = str(track) + '_Send_A_Control'
            snd_B_control.name = str(track) + '_Send_B_Control'
            pan_control.name = str(track) + '_Pan_Control'

            arm_button.name = str(track) + '_arm_Button'
            select_button.name = str(track) + '_Select_Button'
            mute_button.name = str(track) + '_Mute_Button'


            strip.set_volume_control(volume_control)
            strip.set_send_controls([snd_A_control, snd_B_control])
            strip.set_pan_control(pan_control)

            strip.set_arm_button(arm_button)
            strip.set_select_button(select_button)
            strip.set_mute_button(mute_button)

        return mixer
 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 _setup_transport(self):
     is_momentary = True
     transport = TransportComponent()
     playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108)
     stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110)
     recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109)
     overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107)
     metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104)
     playButton.name = 'Play'
     stopButton.name = 'Stop'
     recordButton.name = 'Record'
     overdubButton.name = 'Overdub'
     metrononmeButton.name = 'Metronome'
     transport.set_play_button(playButton)
     transport.set_stop_button(stopButton)
     transport.set_record_button(recordButton)
     transport.set_overdub_button(overdubButton)
     transport.set_metronome_button(metrononmeButton)
     transport.set_nudge_buttons(StateButton(is_momentary, MIDI_CC_TYPE, 1, 51), StateButton(is_momentary, MIDI_CC_TYPE, 1, 50))
     punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52)
     punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53)
     punchinbutton.name = 'Punch In'
     punchoutbutton.name = 'Punch Out'
     transport.set_punch_buttons(punchinbutton, punchoutbutton)
     transport.set_loop_button(StateButton(is_momentary, MIDI_CC_TYPE, 1, 54))
     self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59)
     self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58)
     transport.set_seek_buttons(self.transp_ff_button, self.transp_rw_button)
     self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 100)
     self.xfadeKnob.connect_to(self.song().master_track.mixer_device.crossfader)
     self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88)
     self.tap_button.add_value_listener(self._do_tap_tempo)
     self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 55)
     self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56)
     self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57)
     self.cue_add_delete_button.add_value_listener(self._do_toggle_cue)
     self.cue_prev_button.add_value_listener(self._do_toggle_prev_cue)
     self.cue_next_button.add_value_listener(self._do_toggle_next_cue)
示例#44
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)
示例#45
0
 def __init__(self, c_instance):
     ControlSurface.__init__(self, c_instance)
     with self.component_guard():
         self._instance = c_instance
         self._has_slider_section = True
         self.log_message("Midilooper initializing...")
         # register_sender(self)
         self._session = SessionComponent(NUM_TRACKS, NUM_ROWS)
         self._session.name = 'Session_Control'
         self._mixer = MixerComponent(NUM_TRACKS, NUM_RETURNS)
         for track in range(NUM_TRACKS):
             strip = self._mixer.channel_strip(track)
             strip.name = 'Channel_Strip_' + str(track)
             # encoder = EncoderElement(MIDI_CC_TYPE, 0, 20 + track, Live.MidiMap.MapMode.absolute)
             control = SliderElement(MIDI_CC_TYPE, 0, 20+track)
             control.name = str(track) + '_Volume_Control'
             strip.set_volume_control(control)
         for track in range(NUM_RETURNS):
             strip = self._mixer.return_strip(track)
             control = SliderElement(MIDI_CC_TYPE, 0, 40+track)
             control.name = str(track) + '_Return_Control'
             strip.set_volume_control(control)
         strip = self._mixer.master_strip()
         strip.name = 'Master_Channel_Strip'
         control = SliderElement(MIDI_CC_TYPE, 0, 50)
         control.name = 'Master_Volume_Control'
         strip.set_volume_control(control)
         self._session.set_offsets(0, 0);
         self._session.set_mixer(self._mixer)
         for row in range(NUM_ROWS):
             scene = self._session.scene(row)
             for track in range(NUM_TRACKS):
                 slot = scene.clip_slot(track)
                 button = ButtonElement(True, MIDI_NOTE_TYPE, track, 36+row)
                 slot.set_launch_button(button)
         self.set_highlighting_session_component(self._session)
         self.request_rebuild_midi_map()
         self.log_message("Midilooper initialized.")
示例#46
0
文件: KeyPad.py 项目: cce/buttons
def make_slider(channel, cc, name):
    element = SliderElement(MIDI_CC_TYPE, channel, cc)
    element.name = name
    return element
def make_slider(cc_no, name):
    slider = SliderElement(MIDI_CC_TYPE, 0, cc_no)
    slider.set_feedback_delay(-1)
    slider.name = name
    return slider
 def set_led_slider(self, track):
     self.slider = SliderElement(MIDI_CC_TYPE, SLIDER_CHANNEL, track + 1)
class VUMeter(ControlSurfaceComponent):
    _active_instances = []

    def __init__(self, parent):
        ControlSurfaceComponent.__init__(self)
        VUMeter._active_instances.append(self)
        self.slider = None
        self._parent = parent
        self._vu_meter = None
        self.frames = [0.0] * RMS_FRAMES
        self.increments = CHANNEL_SCALE_INCREMENTS
        self.top = CHANNEL_SCALE_MAX
        self.bottom = CHANNEL_SCALE_MIN
        self.multiplier = self.calculate_multiplier(self.top, self.bottom, self.increments)
        self.current_level = 0

    def disconnect(self):
        VUMeter._active_instances.remove(self)
        if self._vu_meter != None:
            self._vu_meter.remove_output_meter_left_listener(self.observe)
            self._vu_meter = None

    def observe(self):
        new_frame = self.mean_peak()
        self.store_frame(new_frame)
        self.level = self.scale(new_frame)
        if self.level != self.current_level:
            self.current_level = self.level
            self.send_vu_value(self.level)
        else:
            None

    def store_frame(self, frame):
        self.frames.pop(0)
        self.frames.append(frame)

    def rms(self, frames):
        return math.sqrt(sum((frame * frame for frame in frames)) / len(frames))

    def mean_peak(self):
        return (self._vu_meter.output_meter_left + self._vu_meter.output_meter_right) / 2

    def scale(self, value):
        if value > self.top:
            value = self.top
        elif value < self.bottom:
            value = self.bottom
        value = value - self.bottom
        value = value * self.multiplier
        return int(round(value))

    def calculate_multiplier(self, top, bottom, increments):
        return increments / (top - bottom)

    def set_vu_meter(self, track):
        self.set_led_slider(track)
        self._vu_meter = self.song().tracks[track]
        if self._vu_meter != None:
            self._vu_meter.add_output_meter_left_listener(self.observe)
        else:
            None

    def set_led_slider(self, track):
        self.slider = SliderElement(MIDI_CC_TYPE, SLIDER_CHANNEL, track + 1)

    def send_vu_value(self, level):
        if level != None:
            if level < 1:
                None
            else:
                self.slider.send_value(level, True)
        else:
            None

    def update(self):
        pass
示例#50
0
	def _setup_mixer_control(self):
		is_momentary = True # We use non-latching buttons (keys) throughout, so we'll set this as a constant
		num_tracks = 4 # Here we define the mixer width in tracks (a mixer has only one dimension)
		global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...)
		mixer = MixerComponent(num_tracks, 2, with_eqs=True, with_filters=False) #(num_tracks, num_returns, with_eqs, with_filters)
		mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left)
		"""set up the mixer buttons"""		  
		self.song().view.selected_track = mixer.channel_strip(0)._track
		#mute_notes = [1,5,9,13]
		#solo_notes = [2,6,10,14]
		#arm_notes = [3,7,11,15]
		track_select_notes = [38,39,40,41]#more note numbers need to be added if num_scenes is increased
		send_ccs = [2,6,10,14,1,5,9,13]
		pan_ccs = [3,7,11,15]
		slider_ccs = [4,8,12,16]
		for index in range(num_tracks):
			mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, track_select_notes[index]))
			mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHAN, slider_ccs[index]))
			mixer.channel_strip(index).set_pan_control(EncoderElement(MIDI_CC_TYPE, CHAN, pan_ccs[index], Live.MidiMap.MapMode.absolute))
			#put send A and send B controllers into an array, which is then "tupled" for set_send_controls:
			send_controlers = [EncoderElement(MIDI_CC_TYPE, CHAN, send_ccs[index], Live.MidiMap.MapMode.absolute), EncoderElement(MIDI_CC_TYPE, CHAN, send_ccs[index+num_tracks], Live.MidiMap.MapMode.absolute)]
			mixer.channel_strip(index).set_send_controls(tuple(send_controlers))
		
		crossfader = SliderElement(MIDI_CC_TYPE, CHAN, 28)
		master_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 32)
		returna_pan_control = SliderElement(MIDI_CC_TYPE, CHAN, 19)
		returna_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 20)
		returnb_pan_control = SliderElement(MIDI_CC_TYPE, CHAN, 23)
		returnb_volume_control = SliderElement(MIDI_CC_TYPE, CHAN, 24)
		master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 31)
		prehear_control = EncoderElement(MIDI_CC_TYPE, CHAN, 30, Live.MidiMap.MapMode.absolute)
		crossfader.name = 'Crossfader'
		master_volume_control.name = 'Master_Volume_Control'
		returna_pan_control.name = 'ReturnA_Pan_Control'
		returna_volume_control.name = 'ReturnA_Volume_Control'
		returnb_pan_control.name = 'ReturnB_Pan_Control'
		returnb_volume_control.name = 'ReturnB_Volume_Control'
		master_select_button.name = 'Master_Select_Button'
		prehear_control.name = 'Prehear_Volume_Control'
		mixer.set_crossfader_control(crossfader)
		mixer.master_strip().set_volume_control(master_volume_control)
		mixer.master_strip().set_select_button(master_select_button)
		mixer.set_prehear_volume_control(prehear_control)
		mixer.return_strip(0).set_pan_control(returna_pan_control)
		mixer.return_strip(0).set_volume_control(returna_volume_control)
		mixer.return_strip(1).set_pan_control(returnb_pan_control)
		mixer.return_strip(1).set_volume_control(returnb_volume_control)
 def __init__(self, parent):
     self._parent = parent
     self.master_track = parent.song().master_track
     self.the_slider = SliderElement(MIDI_CC_TYPE, 1, 86)
     self.the_slider.add_value_listener(self._do_main_slider, True)
     self.volume_button = None
     self._set_volume_button(StateButton(True, MIDI_CC_TYPE, 1, 80))
     self.xfade_button = None
     self._set_xfade_button(StateButton(True, MIDI_CC_TYPE, 1, 99))
     self.swing_button = None
     self._set_swing_button(StateButton(True, MIDI_CC_TYPE, 1, 81))
     self.mode = KN2_MODE_VOLUME
     self.previous_mode = -1
     self.tempo_button = None
     self._set_tempo_button(StateButton(True, MIDI_CC_TYPE, 1, 82))
     self.push_button = None
     self._set_push_button(StateButton(True, MIDI_CC_TYPE, 1, 87))
     self.clipn_v_button = None
     self.clipn_h_button = None
     self._set_clipn_h_button(StateButton(True, MIDI_CC_TYPE, 1, 90))
     self._set_clipn_v_button(StateButton(True, MIDI_CC_TYPE, 1, 91))
     self.toggle_buttons = [self.volume_button,
      self.xfade_button,
      self.swing_button,
      self.tempo_button,
      self.clipn_h_button,
      self.clipn_v_button]
     self.shift_button = None
     self._set_shift_button(StateButton(True, MIDI_CC_TYPE, 1, 85))
     self.shift_on = False
     self.scroll_mod_left_button = None
     self.scroll_mod_right_button = None
     self._set_scroll_mod_left_button(ButtonElement(True, MIDI_CC_TYPE, 0, 105))
     self._set_scroll_mod_right_button(ButtonElement(True, MIDI_CC_TYPE, 0, 106))
     self._prev_mode = KN2_MODE_VOLUME
     self.lrmode = LR_CONTROL_CLIP
     self.loop_div_index = 0
     self.loop_incdex = 4.0
     self.arrow_mode_button = ColorButton(True, MIDI_CC_TYPE, 30)
     self.arrow_mode_button.add_value_listener(self.toggle_arrow_mode)
     self.arrow_mode_button.send_value(1, True)
     self.navflags = 0
     self.octave_mod_button = ButtonElement(True, MIDI_CC_TYPE, 1, 70)
     self.octave_mod_button.add_value_listener(self._action_octave)
     self.scale_mod_button = ButtonElement(True, MIDI_CC_TYPE, 1, 71)
     self.scale_mod_button.add_value_listener(self._action_scale)
     self.basenote_mod_button = ButtonElement(True, MIDI_CC_TYPE, 1, 72)
     self.basenote_mod_button.add_value_listener(self._action_base_note)
     self.pad_to_mainknob_mode = 0
     self.octave_dwn_button = ButtonElement(True, MIDI_CC_TYPE, 3, 120)
     self.octave_upp_button = ButtonElement(True, MIDI_CC_TYPE, 3, 121)
     self.scale_dwn_button = ButtonElement(True, MIDI_CC_TYPE, 3, 118)
     self.scale_upp_button = ButtonElement(True, MIDI_CC_TYPE, 3, 119)
     self.basent_dwn_button = ButtonElement(True, MIDI_CC_TYPE, 3, 124)
     self.basent_upp_button = ButtonElement(True, MIDI_CC_TYPE, 3, 125)
     self.octave_dwn_button.add_value_listener(self._action_oct_down)
     self.octave_upp_button.add_value_listener(self._action_oct_up)
     self.scale_dwn_button.add_value_listener(self._action_scale_down)
     self.scale_upp_button.add_value_listener(self._action_scale_up)
     self.basent_dwn_button.add_value_listener(self._action_base_down)
     self.basent_upp_button.add_value_listener(self._action_base_up)
     self._measure_left_click = 0
     self._measure_right_click = 0
     self.mode_assign_map = {KN2_MODE_VOLUME: (self.chg_volume,
                        0,
                        'Master Knob controls MASTER Volume',
                        KN2_MODE_CUE),
      KN2_MODE_CUE: (self.chg_cue,
                     0,
                     'Master Knob controls Cue Level',
                     KN2_MODE_VOLUME),
      KN2_MODE_TEMPO_COARSE: (self.chg_tempo,
                              3,
                              'Master Knob controls TEMPO Coarse',
                              KN2_MODE_TEMPO_FINE),
      KN2_MODE_TEMPO_FINE: (self.chg_tempo_fine,
                            3,
                            'Master Knob controls TEMPO Fine',
                            KN2_MODE_TEMPO_COARSE),
      KN2_MODE_XFADE: (self.chg_xfade,
                       1,
                       'Master Knob controls Crossfader',
                       -1),
      KN2_MODE_QUANT: (self.chg_quant,
                       2,
                       'Master Knob controls Recording Quantize',
                       KN2_MODE_CLIP_QUANT),
      KN2_MODE_CLIP_QUANT: (self.chg_clip_q,
                            2,
                            'Master Knob controls Clip Start Quantize',
                            KN2_MODE_QUANT),
      KN2_MODE_CLIPN_HOR: (self.nav_c_hor,
                           4,
                           'Master Knob Clip View horizontally',
                           -1),
      KN2_MODE_CLIPN_VER: (self.nav_c_ver,
                           5,
                           'Master Knob Clip View vertically',
                           -1),
      KN2_MODE_GENERAL: (self.chg_general,
                         -1,
                         None,
                         -1),
      KN2_P_SCALES: (self.modify_pad_scaling,
                     -1,
                     None,
                     -1)}
 def _set_up_machine_knobs(self):
     master_track = self.song().master_track
     self.master_volume = SliderElement(MIDI_CC_TYPE, 0, 40)
     self.prehear = SliderElement(MIDI_CC_TYPE, 0, 41)
     self.master_volume.connect_to(master_track.mixer_device.volume)
     self.prehear.connect_to(master_track.mixer_device.cue_volume)
 def __init__(self, parent):
     self._parent = parent
     self.master_track = parent.song().master_track
     self.volume_button = None
     self._set_volume_button(StateButton(True, MIDI_CC_TYPE, 3, 110))
     self.the_slider = SliderElement(MIDI_CC_TYPE, 1, 86)
     self.the_slider.add_value_listener(self._do_main_slider, True)
     self.xfade_button = None
     self._set_xfade_button(StateButton(True, MIDI_CC_TYPE, 3, 116))
     self.swing_button = None
     self._set_swing_button(StateButton(True, MIDI_CC_TYPE, 3, 111))
     self.mode = KN2_MODE_VOLUME
     self.previous_mode = -1
     self.tempo_button = None
     self._set_tempo_button(StateButton(True, MIDI_CC_TYPE, 3, 112))
     self.push_button = None
     self._set_push_button(StateButton(True, MIDI_CC_TYPE, 1, 87))
     self.clipn_v_button = None
     self.clipn_h_button = None
     self._set_clipn_h_button(StateButton(True, MIDI_CC_TYPE, 3, 114))
     self._set_clipn_v_button(StateButton(True, MIDI_CC_TYPE, 3, 115))
     self.toggle_buttons = [
         self.volume_button,
         self.xfade_button,
         self.swing_button,
         self.tempo_button,
         self.clipn_h_button,
         self.clipn_v_button,
     ]
     self.shift_button = None
     self._set_shift_button(StateButton(True, MIDI_CC_TYPE, 3, 113))
     self.shift_on = False
     self.scroll_mod_left_button = None
     self.scroll_mod_right_button = None
     self._set_scroll_mod_left_button(StateButton(True, MIDI_CC_TYPE, 0, 105))
     self._set_scroll_mod_right_button(StateButton(True, MIDI_CC_TYPE, 0, 106))
     self._prev_mode = KN2_MODE_VOLUME
     self.lrmode = LR_CONTROL_CLIP
     self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143
     self.loop_div_index = 0
     self.loop_incdex = 4.0
     self.arrow_mode_button = ColorButton(True, MIDI_CC_TYPE, 30)
     self.arrow_mode_button.add_value_listener(self.toggle_arrow_mode)
     self.arrow_mode_button.send_color(LR_MODE_HUES[self.lrmode])
     self.arrow_mode_button.send_value(127, True)
     self.navflags = 0
     self.octave_mod_button = StateButton(True, MIDI_CC_TYPE, 1, 70)
     self.octave_mod_button.add_value_listener(self._action_octave)
     self.scale_mod_button = StateButton(True, MIDI_CC_TYPE, 1, 71)
     self.scale_mod_button.add_value_listener(self._action_scale)
     self.basenote_mod_button = StateButton(True, MIDI_CC_TYPE, 1, 72)
     self.basenote_mod_button.add_value_listener(self._action_base_note)
     self.keycolor_mod_button = StateButton(True, MIDI_CC_TYPE, 1, 73)
     self.keycolor_mod_button.add_value_listener(self._action_key_color)
     self.pad_to_mainknob_mode = 0
     self._measure_left_click = 0
     self._measure_right_click = 0
     self.mode_assign_map = {
         KN2_MODE_VOLUME: (self.chg_volume, 0, "Master Knob controls MASTER Volume", KN2_MODE_CUE),
         KN2_MODE_CUE: (self.chg_cue, 0, "Master Knob controls Cue Level", KN2_MODE_VOLUME),
         KN2_MODE_TEMPO_COARSE: (self.chg_tempo, 3, "Master Knob controls TEMPO Coarse", KN2_MODE_TEMPO_FINE),
         KN2_MODE_TEMPO_FINE: (self.chg_tempo_fine, 3, "Master Knob controls TEMPO Fine", KN2_MODE_TEMPO_COARSE),
         KN2_MODE_XFADE: (self.chg_xfade, 1, "Master Knob controls Crossfader", -1),
         KN2_MODE_QUANT: (self.chg_quant, 2, "Master Knob controls Recording Quantize", KN2_MODE_CLIP_QUANT),
         KN2_MODE_CLIP_QUANT: (self.chg_clip_q, 2, "Master Knob controls Clip Start Quantize", KN2_MODE_QUANT),
         KN2_MODE_CLIPN_HOR: (self.nav_c_hor, 4, "Master Knob Clip View horizontally", -1),
         KN2_MODE_CLIPN_VER: (self.nav_c_ver, 5, "Master Knob Clip View vertically", -1),
         KN2_MODE_GENERAL: (self.chg_general, -1, None, -1),
         KN2_P_SCALES: (self.modify_pad_scaling, -1, None, -1),
     }
class AudioClipEditComponent(CompoundComponent):
    """
    classdocs
    """

    def __init__(self, *a, **k):
        super(AudioClipEditComponent, self).__init__(*a, **k)
        self._loop_start_slider = SliderElement(MIDI_CC_TYPE, 2, 60)
        self._action_loop_start.subject = self._loop_start_slider
        self._loop_end_slider = SliderElement(MIDI_CC_TYPE, 2, 61)
        self._action_loop_end.subject = self._loop_end_slider
        self._mark_start_slider = SliderElement(MIDI_CC_TYPE, 2, 62)
        self._action_mark_start.subject = self._mark_start_slider
        self._mark_end_slider = SliderElement(MIDI_CC_TYPE, 2, 63)
        self._action_mark_end.subject = self._mark_end_slider
        self._pitch_c_slider = SliderElement(MIDI_CC_TYPE, 2, 64)
        self._pitch_f_slider = SliderElement(MIDI_CC_TYPE, 2, 65)
        self._gain_slider = SliderElement(MIDI_CC_TYPE, 2, 66)
        self._action_pitch_c.subject = self._pitch_c_slider
        self._action_pitch_f.subject = self._pitch_f_slider
        self._action_gain.subject = self._gain_slider
        self._loop_inc_slider = SliderElement(MIDI_CC_TYPE, 2, 67)
        self._action_loop_inc.subject = self._loop_inc_slider
        self._loop_move_button = ButtonElement(False, MIDI_CC_TYPE, 2, 74)
        self._action_mv_loop.subject = self._loop_move_button
        self._loop_set_button = ButtonElement(False, MIDI_CC_TYPE, 2, 70)
        self._action_loop_toggle.subject = self._loop_set_button
        self._warp_set_button = ButtonElement(False, MIDI_CC_TYPE, 2, 71)
        self._action_warp_toggle.subject = self._warp_set_button
        self._zoom_scroll_button = ButtonElement(False, MIDI_CC_TYPE, 2, 73)
        self._action_scroll_mode.subject = self._zoom_scroll_button
        self.selected_clip_slot = None
        self.inc_index = 4
        self.loop_inc = INC_STEPS[self.inc_index]
        self.start_inc = INC_STEPS[self.inc_index]
        self.mv_loop = False
        self._on_pitch_c_changed.subject = None
        self._on_pitch_f_changed.subject = None
        self._on_gain_changed.subject = None
        self._scroll_mode = False
        self.update_selected_clip()

    @subject_slot("value")
    def _action_scroll_mode(self, value):
        if value > 0:
            self._scroll_mode = True
        else:
            self._scroll_mode = False

    @subject_slot("value")
    def _action_warp_toggle(self, value):
        if value > 0:
            if self.selected_clip_slot and self.selected_clip_slot.has_clip:
                clip = self.selected_clip_slot.clip
                if clip.is_audio_clip:
                    clip.warping = not clip.warping
                    self._warp_set_button.send_value(clip.warping and 127 or 0, True)

    @subject_slot("value")
    def _action_loop_toggle(self, value):
        if value > 0:
            if self.selected_clip_slot and self.selected_clip_slot.has_clip:
                clip = self.selected_clip_slot.clip
                clip.looping = not clip.looping
                self._loop_set_button.send_value(clip.looping and 127 or 0, True)

    @subject_slot("value")
    def _action_loop_inc(self, value):
        if not (value == 1 and 1):
            inc = -1
            val = self.inc_index + inc
            self.inc_index = val >= 0 and val < len(INC_STEPS) and val
            self.loop_inc = INC_STEPS[val]
            self.start_inc = INC_STEPS[val]
            self.canonical_parent.timed_message(2, "Loop Adjust: " + INC_DISP[val])
            self.canonical_parent.show_message("Loop Adjust: " + INC_DISP[val])

    @subject_slot("value")
    def _action_mv_loop(self, value):
        if value > 0:
            if self.mv_loop:
                self._loop_move_button.send_value(0, True)
                self.mv_loop = False
            else:
                self._loop_move_button.send_value(127, True)
                self.mv_loop = True

    @subject_slot("value")
    def _action_mark_start(self, value):
        if self._scroll_mode:
            scroll = value == 1 and 3 or 2
            self.application().view.scroll_view(scroll, "Detail/Clip", False)
        elif not (value == 1 and 1):
            inc = -1
            clip = self.selected_clip_slot and self.selected_clip_slot.has_clip and self.selected_clip_slot.clip
            ls = clip.start_marker
            le = clip.end_marker
            ls = max(0, min(le - self.start_inc, ls + inc * self.start_inc))
            clip.start_marker = ls
            bars_to_measure(ls, clip.signature_denominator, clip.signature_numerator)
            self.canonical_parent.timed_message(
                2, "Clip Start: " + bars_to_measure(ls, clip.signature_denominator, clip.signature_numerator)
            )

    @subject_slot("value")
    def _action_mark_end(self, value):
        if self._scroll_mode:
            scroll = value == 1 and 3 or 2
            self.application().view.zoom_view(scroll, "Detail/Clip", False)
        elif not (value == 1 and 1):
            inc = -1
            clip = self.selected_clip_slot and self.selected_clip_slot.has_clip and self.selected_clip_slot.clip
            ls = clip.start_marker
            le = clip.end_marker
            le = max(ls + self.start_inc, le + inc * self.start_inc)
            clip.end_marker = le
            self.canonical_parent.timed_message(
                2, "Clip End: " + bars_to_measure(le, clip.signature_denominator, clip.signature_numerator)
            )

    @subject_slot("value")
    def _action_loop_start(self, value):
        if not (value == 1 and 1):
            inc = -1
            if self.selected_clip_slot and self.selected_clip_slot.has_clip:
                clip = self.selected_clip_slot.clip
                ls = clip.loop_start
                le = clip.loop_end
                if self.mv_loop:
                    diff = le - ls
                    ls = max(0, ls + inc * self.loop_inc)
                    clip.loop_end = inc > 0 and ls + diff
                    clip.end_marker = ls + diff
                    clip.loop_start = ls
                    clip.start_marker = ls
                else:
                    clip.loop_start = ls
                    clip.start_marker = ls
                    clip.loop_end = ls + diff
                    clip.end_marker = ls + diff
                self.canonical_parent.timed_message(2, loop_str(clip))
            else:
                ls = max(0, min(le - self.loop_inc, ls + inc * self.loop_inc))
                clip.loop_start = ls
                self.canonical_parent.timed_message(2, loop_str(clip))

    @subject_slot("value")
    def _action_loop_end(self, value):
        if not (value == 1 and 1):
            inc = -1
            if self.selected_clip_slot and self.selected_clip_slot.has_clip:
                clip = self.selected_clip_slot.clip
                ls = clip.loop_start
                le = clip.loop_end
                le = max(ls + self.loop_inc, le + inc * self.loop_inc)
                clip.loop_end = le
                clip.end_marker = self.mv_loop and le
            self.canonical_parent.timed_message(2, loop_str(clip))

    def update(self):
        pass

    @subject_slot("value")
    def _action_pitch_c(self, value):
        cs = self.selected_clip_slot
        if cs and cs.has_clip and cs.clip.is_audio_clip:
            cs.clip.pitch_coarse = midi_to_pitchc(value)

    @subject_slot("value")
    def _action_pitch_f(self, value):
        cs = self.selected_clip_slot
        if cs and cs.has_clip and cs.clip.is_audio_clip:
            cs.clip.pitch_fine = midi_to_pitchf(value)

    @subject_slot("value")
    def _action_gain(self, value):
        cs = self.selected_clip_slot
        if cs and cs.has_clip and cs.clip.is_audio_clip:
            cs.clip.gain = midi_to_gain(value)

    def _update_clip_name(self):
        cs = self.song().view.highlighted_clip_slot
        if not cs:
            track = self.song().view.selected_track
            self.canonical_parent.send_to_display("Rt Trck: " + track.name, 3)
        elif cs.has_clip:
            self.canonical_parent.send_to_display(cs.clip.is_audio_clip and "A" or "M" + ":" + cs.clip.name, 3)
        else:
            track = cs.canonical_parent
            index = list(track.clip_slots).index(cs)
            scene = self.song().scenes[index]
            self.canonical_parent.send_to_display("E<" + str(scene.name) + "> T:" + track.name, 3)

    @subject_slot("has_clip")
    def _on_has_clip_changed(self):
        self._update_clip_name()

    @subject_slot("name")
    def _on_name_changed(self):
        self._update_clip_name()

    def update_selected_clip(self):
        cs = self.song().view.highlighted_clip_slot
        if cs != self.selected_clip_slot:
            self.selected_clip_slot = cs
            self._update_clip_name()
            if cs and cs.has_clip and cs.clip.is_audio_clip:
                self._on_pitch_c_changed.subject = cs.clip
                self._on_pitch_f_changed.subject = cs.clip
                self._on_gain_changed.subject = cs.clip
                self._on_warp_changed.subject = cs.clip
                self._gain_slider.send_value(gain_to_midi(cs.clip.gain))
                self._pitch_c_slider.send_value(pitchc_to_midi(cs.clip.pitch_coarse))
                self._pitch_f_slider.send_value(pitchf_to_midi(cs.clip.pitch_fine))
                self._warp_set_button.send_value(cs.clip.warping and 127 or 0, True)
            else:
                self._on_pitch_c_changed.subject = None
                self._on_pitch_f_changed.subject = None
                self._on_gain_changed.subject = None
                self._on_warp_changed.subject = None
                self._on_loop_changed.subject = None
            if cs and cs.has_clip:
                self._on_loop_changed.subject = cs.clip
                self._on_name_changed.subject = cs.clip
                self._loop_set_button.send_value(cs.clip.looping and 127 or 0, True)
            else:
                self._on_name_changed.subject = None
                self._on_loop_changed.subject = None
            self._on_has_clip_changed.subject = cs

    def on_selected_track_changed(self):
        self.update_selected_clip()

    def on_selected_scene_changed(self):
        self.update_selected_clip()

    @subject_slot("looping")
    def _on_loop_changed(self):
        cs = self.song().view.highlighted_clip_slot
        if cs and cs.has_clip:
            self._loop_set_button.send_value(cs.clip.looping and 127 or 0, True)

    @subject_slot("warping")
    def _on_warp_changed(self):
        cs = self.song().view.highlighted_clip_slot
        if cs and cs.has_clip and cs.clip.is_audio_clip:
            self._warp_set_button.send_value(cs.clip.warping and 127 or 0, True)

    @subject_slot("pitch_coarse")
    def _on_pitch_c_changed(self):
        cs = self.song().view.highlighted_clip_slot
        if cs and cs.has_clip and cs.clip.is_audio_clip:
            self._pitch_c_slider.send_value(pitchc_to_midi(cs.clip.pitch_coarse))

    @subject_slot("pitch_fine")
    def _on_pitch_f_changed(self):
        cs = self.song().view.highlighted_clip_slot
        if cs and cs.has_clip and cs.clip.is_audio_clip:
            self._pitch_f_slider.send_value(pitchf_to_midi(cs.clip.pitch_fine))

    @subject_slot("gain")
    def _on_gain_changed(self):
        cs = self.song().view.highlighted_clip_slot
        if cs and cs.has_clip and cs.clip.is_audio_clip:
            self._gain_slider.send_value(gain_to_midi(cs.clip.gain))
class MaschineMk2(ControlSurface):
    __module__ = __name__
    __doc__ = 'Control Script for Maschine Mk2 and Maschine Mikro Mk2'

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance, False)
        with self.component_guard():
            self._suppress_send_midi = True
            self.togglecolor = (10, 30, 50, 70, 90)
            self.toggleindex = 0
            self._c_ref = c_instance
            self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143
            self._c_inst = c_instance
            is_momentary = True
            self._active = True
            self._modifier_down = False
            self._return_mode = 0
            self._returntopad = False
            self._mode = CLIP_MODE
            self.init_slot = 0
            self.init_done = False
            self._midi_pause_count = 0
            self.nav_index = 0
            self._base_note = 0
            self._octave = 0.55
            self._scale_select_mode = MODE_PRESS_NONE
            self.send_slider_index = 0
            self._pad_mode = PM_OFF
            self._note_display_mode = ND_KEYBOARD1
            self._set_suppress_rebuild_requests(True)
            self._scenematrix = SceneMatrix(self)
            self._master_knob = Mk2KnobControl(self)
            self._device = self._set_up_device_control()
            self.show_message(str(''))
            self.request_rebuild_midi_map()
            self._set_global_buttons()
            self._set_mode_buttons()
            self._setup_transport()
            self._set_modecontrol()
            self._set_up_session()
            self._set_up_mixer()
            self._set_up_timer()
            self._set_up_machine_knobs()
            self.current_scale_index = 0
            self.assign_transpose(SCALES[self.current_scale_index])
            self.set_highlighting_session_component(self._session)
            self._navigate_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 127)
            self._navigate_button.add_value_listener(self._do_focus_navigate)
            self.display_update_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 86)
            self.display_update_button.add_value_listener(self._a_display_update)
            self._set_suppress_rebuild_requests(False)
            self.song().view.add_detail_clip_listener(self.clip_handle)
            self.song().add_visible_tracks_listener(self.clip_handle)
            self.song().add_scenes_listener(self.clip_handle)
            self.application().view.add_view_focus_changed_listener(self.focus_changed)
            self.log_message('########## LIVE 9 MASCHINE MK2 V 1.02 #############')
            self._suppress_send_midi = False

    def _set_up_mixer(self):
        is_momentary = True
        self._mixer = MixerComponent(8)
        self.send_sliders = []
        for track in range(8):
            self.send_sliders.append(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, SEND_CC_OFF + track))

        for track in range(8):
            strip = self._mixer.channel_strip(track)
            strip.set_arm_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, ARM_CC_OFF + track))
            strip.set_solo_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SOLO_CC_OFF + track))
            strip.set_mute_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, MUTE_CC_OFF + track))
            strip.set_volume_control(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, LEVEL_CC_OFF + track))
            strip.set_pan_control(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, PAN_CC_OFF + track))
            strip.set_select_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SELECT_CC_OFF + track))
            st = tuple([self.send_sliders[track]])
            strip.set_send_controls(st)

        self.send_slider_toggle_button = StateButton(False, MIDI_CC_TYPE, 0, 90)
        self.send_slider_toggle_button.add_value_listener(self._do_toggle_send)
        self._session.set_mixer(self._mixer)

    def _set_global_buttons(self):
        is_momentary = True
        self._undo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 85)
        self._undo_button.add_value_listener(self._do_undo)
        self._redo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 87)
        self._redo_button.add_value_listener(self._do_redo)
        self._armsolomode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 89)
        self._armsolomode_button.add_value_listener(self._do_armsolo_mode)
        self._fire_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 9)
        self._fire_button.add_value_listener(self._do_fire_button)
        self.track_left_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 120)
        self.track_right_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 121)
        self.track_left_button.add_value_listener(self._a_trk_left)
        self.track_right_button.add_value_listener(self._a_trk_right)
        self.test_button = StateButton(True, MIDI_CC_TYPE, 5, 60)
        self.note_repeat_button = StateButton(True, MIDI_CC_TYPE, 5, 61)
        self.test_button.add_value_listener(self.do_test)
        self.note_repeat_button.add_value_listener(self.do_note_repeat)
        self.reset_test_button = StateButton(True, MIDI_CC_TYPE, 5, 62)
        self.reset_test_button.add_value_listener(self.do_reset)

    def _set_mode_buttons(self):
        self.xfade_assign_button = StateButton(True, MIDI_CC_TYPE, 0, 116)
        self._pad_select_button = StateButton(False, MIDI_CC_TYPE, 0, 117)
        self._pad_solo_button = StateButton(False, MIDI_CC_TYPE, 0, 118)
        self._mute_button = StateButton(False, MIDI_CC_TYPE, 0, 119)
        self._pad_scale_up = GatedColorButton(True, MIDI_CC_TYPE, 83, 0)
        self._pad_scale_down = GatedColorButton(True, MIDI_CC_TYPE, 94, 16)
        self._pad_select_button.add_value_listener(self._do_pad_select_multi)
        self._mute_button.add_value_listener(self._do_mute_button)
        self._pad_solo_button.add_value_listener(self._do_pad_solo_multi)
        self.xfade_assign_button.add_value_listener(self._do_xfade_assign)
        self._pad_scale_up.add_value_listener(self._do_pad_note_up)
        self._pad_scale_down.add_value_listener(self._do_pad_note_down)

    def set_appointed_device(self, device):
        with self.component_guard():
            self._device_component.set_device(device)

    def _set_up_device_control(self):
        is_momentary = True
        device = MaschineDeviceComponent(self)
        device.set_device_changed_listener(self._handle_device_changed)
        device.set_device_parm_listener(self._hande_device_parm_changed)
        param_controls = []
        for index in range(8):
            param_controls.append(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_CC_OFF + index))

        device.set_parameter_controls(tuple(param_controls))
        device.set_on_off_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF))
        device.set_bank_nav_buttons(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 4), ButtonElement(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 5))
        self._device_nav_button_left = StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 6)
        self._device_nav_button_right = StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 7)
        self._device_nav_button_left.add_value_listener(self._nav_value_left)
        self._device_nav_button_right.add_value_listener(self._nav_value_right)
        device.name = 'Device_Component'
        self.set_device_component(device)
        return device

    def _setup_transport(self):
        is_momentary = True
        transport = TransportComponent()
        playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108)
        stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110)
        recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109)
        overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107)
        metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104)
        playButton.name = 'Play'
        stopButton.name = 'Stop'
        recordButton.name = 'Record'
        overdubButton.name = 'Overdub'
        metrononmeButton.name = 'Metronome'
        transport.set_play_button(playButton)
        transport.set_stop_button(stopButton)
        transport.set_record_button(recordButton)
        transport.set_overdub_button(overdubButton)
        transport.set_metronome_button(metrononmeButton)
        transport.set_nudge_buttons(StateButton(is_momentary, MIDI_CC_TYPE, 1, 51), StateButton(is_momentary, MIDI_CC_TYPE, 1, 50))
        punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52)
        punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53)
        punchinbutton.name = 'Punch In'
        punchoutbutton.name = 'Punch Out'
        transport.set_punch_buttons(punchinbutton, punchoutbutton)
        transport.set_loop_button(StateButton(is_momentary, MIDI_CC_TYPE, 1, 54))
        self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59)
        self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58)
        transport.set_seek_buttons(self.transp_ff_button, self.transp_rw_button)
        self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 100)
        self.xfadeKnob.connect_to(self.song().master_track.mixer_device.crossfader)
        self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88)
        self.tap_button.add_value_listener(self._do_tap_tempo)
        self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 55)
        self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56)
        self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57)
        self.cue_add_delete_button.add_value_listener(self._do_toggle_cue)
        self.cue_prev_button.add_value_listener(self._do_toggle_prev_cue)
        self.cue_next_button.add_value_listener(self._do_toggle_next_cue)

    def _set_up_machine_knobs(self):
        master_track = self.song().master_track
        self.master_volume = SliderElement(MIDI_CC_TYPE, 0, 40)
        self.prehear = SliderElement(MIDI_CC_TYPE, 0, 41)
        self.master_volume.connect_to(master_track.mixer_device.volume)
        self.prehear.connect_to(master_track.mixer_device.cue_volume)

    def _set_up_session(self):
        is_momentary = True
        self._session = MaschineSessionComponent()
        self._session.add_offset_listener(self.notify_track_scroll)
        nhue = COLOR_HUE_NAV
        self.nav_buttons = (GatedColorButton(True, MIDI_CC_TYPE, 92, nhue),
         GatedColorButton(True, MIDI_CC_TYPE, 81, nhue),
         GatedColorButton(True, MIDI_CC_TYPE, 93, nhue),
         GatedColorButton(True, MIDI_CC_TYPE, 91, nhue))
        self._session.set_scene_bank_buttons(self.nav_buttons[0], self.nav_buttons[1])
        self._session.set_track_bank_buttons(self.nav_buttons[2], self.nav_buttons[3])
        self._session.set_stop_all_clips_button(StateButton(is_momentary, MIDI_CC_TYPE, 0, 111))
        track_stop_buttons = [ StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, index + STOP_CC_OFF) for index in range(4) ]
        self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons))
        self._init_matrix()
        self._set_up_buttons()
        self._session._link()
        self._session.set_advance(STEP4)

    def _set_up_buttons(self):
        self._bmatrix = ButtonMatrixElement()
        for scene_index in range(4):
            button_row = []
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                button = self._matrix[scene_index][track_index]
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(button)
                clip_slot.set_triggered_to_play_value(1)
                clip_slot.set_triggered_to_record_value(1)
                clip_slot.set_started_value(1)
                clip_slot.set_recording_value(1)
                clip_slot.set_stopped_value(1)

            self._bmatrix.add_row(tuple(button_row))

    def _init_matrix(self):
        is_momentary = True
        self._button_sequence = []
        self._matrix = []
        for scene_index in range(4):
            button_row = []
            for track_index in range(4):
                button = VarButtonElement(is_momentary, 0, scene_index, track_index, self)
                partner = TwinButton(is_momentary, 1, button)
                partner.add_value_listener(self.ox, True)
                button_row.append(button)

            self._matrix.append(tuple(button_row))

        for scene_index in [3,
         2,
         1,
         0]:
            for track_index in range(4):
                self._button_sequence.append(self._matrix[scene_index][track_index])

        self._session.set_matrix(self._matrix)

    def set_pad_translations(self, pad_translations):
        ControlSurface.set_pad_translations(pad_translations)

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

    def ox(self, value, button):
        if not isinstance(button, TwinButton):
            raise AssertionError
            self._mode == PAD_MODE and button.fire(value)

    def _update_hardware(self):
        self._session.update()
        self._set_suppress_rebuild_requests(True)
        self._set_mode()
        self._master_knob.update()
        if self._scenematrix.soloexclusive:
            self._armsolomode_button.send_value(1, True)
        else:
            self._armsolomode_button.send_value(0, True)
        self._master_knob.start_up()
        self._pad_scale_up.activate()
        self._pad_scale_down.activate()
        self.current_scale_to_display()
        self.send_to_display(KEY_COLOR_MODES_STRINGS[self._note_display_mode], 1)
        for scene_index in range(4):
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                button = self._matrix[scene_index][track_index]
                button.refresh()

        self._set_suppress_rebuild_requests(False)

    def get_color(self, value, track_index, scene_index):
        if not self._active:
            return
        if self._mode == SCENE_MODE or self._mode == CONTROL_MODE or self._pad_mode == PM_ON:
            element = self._scenematrix.get_element(scene_index, track_index)
            return element.get_color(value)
        elif self._mode == CLIP_MODE:
            scene = self._session.scene(scene_index)
            clip_slot = scene.clip_slot(track_index)._clip_slot
            cindex = 0
            if value == 0:
                cindex = 1
            if clip_slot != None:
                if clip_slot.has_clip:
                    if clip_slot.clip.is_recording or clip_slot.clip.will_record_on_start:
                        return PColor.CLIP_RECORD[cindex]
                    if clip_slot.clip.is_playing:
                        return PColor.CLIP_PLAY[cindex]
                    elif clip_slot.clip.is_triggered:
                        return PColor.CLIP_PLAY[cindex]
                    else:
                        return PColor.CLIP_STOPPED[cindex]
                elif clip_slot.will_record_on_start:
                    return PColor.CLIP_RECORD[cindex]
                elif clip_slot.is_playing:
                    return PColor.CLIP_GROUP_PLAY[cindex]
                elif clip_slot.controls_other_clips:
                    return PColor.CLIP_GROUP_CONTROL[cindex]
                elif clip_slot.is_triggered:
                    return PColor.CLIP_GROUP_TRIGGER[cindex]
        elif self._mode == PAD_MODE:
            button = self._matrix[scene_index][track_index]
            return self.get_color_by_note_mode(button.get_identifier(), value > 0)

    def step_key_color_mode(self):
        self._note_display_mode = (self._note_display_mode + 1) % len(KEY_COLOR_MODES_STRINGS)
        self.show_message('Pad Mode Key Color = ' + KEY_COLOR_MODES_STRINGS[self._note_display_mode])
        self.send_to_display('Colors: ' + KEY_COLOR_MODES_STRINGS[self._note_display_mode], 1)
        if self._mode == PAD_MODE:
            for note_index in range(16):
                button = self._button_sequence[note_index]
                button.send_color_direct(self.get_color_by_note_mode(button.get_identifier(), False))

    def get_color_by_note_mode(self, midi_note, on):
        if self._note_display_mode == ND_BASE_OTHER:
            interval = (midi_note + 12 - self._base_note) % 12
            if on:
                return INTERVAL_COLOR_MAP[interval][0]
            else:
                return INTERVAL_COLOR_MAP[interval][1]
        elif on:
            return KEY_COLOR_MAP[midi_note % 12][0]
        else:
            return KEY_COLOR_MAP[midi_note % 12][1]

    def _send_midi(self, midi_bytes, **keys):
        self._c_ref.send_midi(midi_bytes)
        if self._midi_pause_count == 2:
            time.sleep(0.002)
            self._midi_pause_count = 0
        else:
            self._midi_pause_count = self._midi_pause_count + 1
        return True

    def clip_handle(self):
        if self._mode == SCENE_MODE or self._mode == CONTROL_MODE or self._modifier_down:
            self._scenematrix.update()

    def _a_display_update(self, value):
        if not self.display_update_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            (value != 0 or not self.display_update_button.is_momentary()) and self._update_hardware()
            self.show_message('Maschine Display Updated')

    def _set_up_timer(self):
        self.blink_state = 1

    def update_display(self):
        with self.component_guard():
            with self._is_sending_scheduled_messages():
                self._task_group.update(0.1)
            if self._mode == CLIP_MODE and not self._modifier_down:
                if self.blink_state == 0:
                    self._session.notify(1, 0)
                elif self.blink_state == 1:
                    self._session.notify(1, 1)
                elif self.blink_state == 3:
                    self._session.notify(2, 0)
                elif self.blink_state == 4:
                    self._session.notify(2, 1)
            elif self._mode == PAD_MODE:
                pass
            elif self.blink_state == 0:
                self._scenematrix.notify_scene_mode(1)
            elif self.blink_state == 2:
                self._scenematrix.notify_scene_mode(0)
            self.blink_state = (self.blink_state + 1) % 4
            self.init_slot += 1

    def _invoke_track_edit(self, mode):
        self._deassign_matrix()
        self._scenematrix.assign()
        self._scenematrix.set_mode(mode)
        self._pad_mode = PM_ON
        self.request_rebuild_midi_map()
        self._scenematrix.update()

    def _set_modecontrol(self):
        is_momentary = True
        self.scene_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 112)
        self.clip_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 113)
        self.pad_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 114)
        self.control_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 115)
        self.xfade_assign_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 116)
        self.scene_mode_button.add_value_listener(self._a_mode_scene)
        self.clip_mode_button.add_value_listener(self._a_mode_clip)
        self.pad_mode_button.add_value_listener(self._a_mode_pad)
        self.control_mode_button.add_value_listener(self._a_mode_control)

    def _set_mode(self, mode = None):
        if mode == None:
            mode = self._mode
        if mode == SCENE_MODE:
            self.clip_mode_button.send_value(OFF_VALUE, True)
            self.pad_mode_button.send_value(OFF_VALUE, True)
            self.control_mode_button.send_value(OFF_VALUE, True)
            self.scene_mode_button.send_value(ON_VALUE, True)
        elif mode == CLIP_MODE:
            self.scene_mode_button.send_value(OFF_VALUE, True)
            self.pad_mode_button.send_value(OFF_VALUE, True)
            self.control_mode_button.send_value(OFF_VALUE, True)
            self.clip_mode_button.send_value(ON_VALUE, True)
        elif mode == PAD_MODE:
            self.scene_mode_button.send_value(OFF_VALUE, True)
            self.clip_mode_button.send_value(OFF_VALUE, True)
            self.control_mode_button.send_value(OFF_VALUE, True)
            self.pad_mode_button.send_value(ON_VALUE, True)
        elif mode == CONTROL_MODE:
            self.scene_mode_button.send_value(OFF_VALUE, True)
            self.clip_mode_button.send_value(OFF_VALUE, True)
            self.pad_mode_button.send_value(OFF_VALUE, True)
            self.control_mode_button.send_value(ON_VALUE, True)

    def _reset_matrix(self):
        for scene_index in range(4):
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                button = self._matrix[scene_index][track_index]
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(button)

    def update_button_matrix(self):
        self._session.update()
        for scene_index in range(4):
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                button = self._matrix[scene_index][track_index]
                clip_slot = scene.clip_slot(track_index)
                if clip_slot._clip_slot != None and clip_slot._clip_slot.clip != None:
                    button.send_value(1, True)
                else:
                    button.send_value(0, True)

    def _deassign_matrix(self):
        for scene_index in range(4):
            scene = self._session.scene(scene_index)
            for track_index in range(4):
                clip_slot = scene.clip_slot(track_index)
                clip_slot.set_launch_button(None)

    def _from_pad_mode(self, matrix_mode):
        self._mode = SCENE_MODE
        self._register_buttons()
        self._scenematrix.assign()
        self._scenematrix.set_mode(matrix_mode)
        self._set_suppress_rebuild_requests(True)
        self.request_rebuild_midi_map()
        self._scenematrix.update()
        self._set_suppress_rebuild_requests(False)

    def _enter_pad_mode(self):
        self._set_mode(PAD_MODE)
        if self._mode == CLIP_MODE:
            self._deassign_matrix()
        elif self._mode == SCENE_MODE:
            self._scenematrix.deassign()
        elif self._mode == CONTROL_MODE:
            self._scenematrix.deassign()
            self._master_knob.exit_matrix_mode()
        self._mode = PAD_MODE
        self._set_suppress_rebuild_requests(True)
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                button.send_value(0, True)
                button.set_to_notemode(True)
                self._forwarding_registry[MIDI_NOTE_ON_STATUS, button.get_identifier()] = button
                self._forwarding_registry[MIDI_NOTE_OFF_STATUS, button.get_identifier()] = button

        self._set_suppress_rebuild_requests(False)

    def _register_buttons(self, update = False):
        self._set_suppress_rebuild_requests(True)
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                button.set_to_notemode(False)
                if update:
                    button.send_value(127, True)
                fwkey = [MIDI_NOTE_ON_STATUS]
                fwkey.append(button.get_identifier())
                self._forwarding_registry[tuple(fwkey)] = button
                self._forwarding_registry[MIDI_NOTE_OFF_STATUS, button.get_identifier()] = button

        self._set_suppress_rebuild_requests(False)

    def _back_to_clip_mode(self):
        self._pad_mode = PM_OFF
        self._scenematrix.set_mode(SCENE_MODE_NORMAL)
        self._scenematrix.deassign()
        self._set_up_clip_matrix()

    def _set_up_clip_matrix(self):
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                button.set_to_notemode(False)

        self._set_suppress_rebuild_requests(True)
        self.request_rebuild_midi_map()
        self._reset_matrix()
        self.update_button_matrix()
        self._set_suppress_rebuild_requests(False)

    def _enter_scene_mode(self):
        self._set_mode(SCENE_MODE)
        if self._mode == CLIP_MODE:
            self._deassign_matrix()
        elif self._mode == CONTROL_MODE:
            self._master_knob.exit_matrix_mode()
        elif self._mode == PAD_MODE:
            self._register_buttons()
        self._mode = SCENE_MODE
        self._scenematrix.assign()
        self._scenematrix.set_mode(SCENE_MODE_NORMAL)
        self._return_mode = SCENE_MODE_NORMAL
        self.request_rebuild_midi_map()

    def _enter_clip_mode(self):
        self._set_suppress_rebuild_requests(True)
        self._set_mode(CLIP_MODE)
        if self._mode == SCENE_MODE:
            self._scenematrix.deassign()
        elif self._mode == CONTROL_MODE:
            self._master_knob.exit_matrix_mode()
        self._mode = CLIP_MODE
        self._set_up_clip_matrix()
        self.request_rebuild_midi_map()
        self._set_suppress_rebuild_requests(False)

    def _enter_control_mode(self):
        self._set_mode(CONTROL_MODE)
        if self._mode == CLIP_MODE:
            self._deassign_matrix()
        elif self._mode == PAD_MODE:
            self._mode = CONTROL_MODE
            self._register_buttons()
        self._mode = CONTROL_MODE
        self._set_suppress_rebuild_requests(True)
        self._scenematrix.set_mode(SCENE_MODE_CONTROL)
        self._return_mode = SCENE_MODE_CONTROL
        self._scenematrix.assign()
        self._master_knob.switch_to_matrix_mode()
        self._set_suppress_rebuild_requests(False)
        self.request_rebuild_midi_map()
        self._scenematrix.update()

    def _a_mode_scene(self, value):
        if not self.scene_mode_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.show_message('SCENE MODE')
            self._enter_scene_mode()

    def _a_mode_clip(self, value):
        if not self.clip_mode_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.show_message('CLIP MODE')
            self._enter_clip_mode()

    def _a_mode_pad(self, value):
        if not self.pad_mode_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.show_message('PAD MODE')
            self._enter_pad_mode()

    def _a_mode_control(self, value):
        if not self.control_mode_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.show_message('CONTROL MODE')
            self._enter_control_mode()

    def _do_pad_select_multi(self, value):
        if not value in range(128):
            raise AssertionError
            self._modifier_down = value != 0
            if self._mode == PAD_MODE or self._returntopad:
                value != 0 and self._from_pad_mode(SCENE_MODE_SELECT)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == CLIP_MODE:
            if value != 0:
                self._invoke_track_edit(SCENE_MODE_SELECT)
            else:
                self._back_to_clip_mode()
        elif self._mode != PAD_MODE:
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_SELECT)

    def _do_mute_button(self, value):
        if not self._mute_button != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                self._modifier_down = value != 0
                (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_MUTE)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE:
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
                self._pad_mode = PM_OFF
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_MUTE)
                self._pad_mode = PM_ON
        elif self._mode == CLIP_MODE:
            if value > 0:
                self._invoke_track_edit(SCENE_MODE_MUTE)
            else:
                self._back_to_clip_mode()
                self._pad_mode = PM_OFF

    def _do_pad_solo_multi(self, value):
        if not value in range(128):
            raise AssertionError
            self._modifier_down = value != 0
            if self._mode == PAD_MODE or self._returntopad:
                value != 0 and self._from_pad_mode(SCENE_MODE_SOLO)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == CLIP_MODE:
            if value != 0:
                self._invoke_track_edit(SCENE_MODE_SOLO)
            else:
                self._back_to_clip_mode()
        elif self._mode != PAD_MODE:
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_SOLO)

    def _do_xfade_assign(self, value):
        if not self.xfade_assign_button != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_XFADE)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == CLIP_MODE:
            if value != 0:
                self._invoke_track_edit(SCENE_MODE_XFADE)
            else:
                self._back_to_clip_mode()
        elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE:
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_XFADE)

    def _do_pad_note_up(self, value):
        if not self._pad_scale_up != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                self._pad_scale_up.send_value(value, True)
                self._modifier_down = value != 0
                (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_ARM)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == CLIP_MODE:
            self.show_message('Arm tracks with pads')
            if value != 0:
                self._invoke_track_edit(SCENE_MODE_ARM)
            else:
                self._back_to_clip_mode()
        elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE:
            self.show_message('Arm tracks with pads')
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_ARM)

    def _do_pad_note_down(self, value):
        if not self._pad_scale_down != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                self._pad_scale_down.send_value(value, True)
                self._modifier_down = value != 0
                (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_STOP)
                self._returntopad = True
            else:
                self._returntopad = False
                self._enter_pad_mode()
        elif self._mode == CLIP_MODE:
            self.show_message('Stop tracks with pads')
            if value != 0:
                self._invoke_track_edit(SCENE_MODE_STOP)
            else:
                self._back_to_clip_mode()
        elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE:
            self.show_message('Stop tracks with pads')
            if value == 0:
                self._scenematrix.set_mode(self._return_mode)
            else:
                if self._scenematrix.in_main_mode():
                    self._return_mode = self._scenematrix.mode
                self._scenematrix.set_mode(SCENE_MODE_STOP)

    def modify_track_offset(self, delta):
        self._scenematrix.mod_track_offset(delta)

    def modify_scene_offset(self, delta):
        self._scenematrix.mod_scene_offset(delta)

    def move_view_horizontal(self, delta):
        if delta == 1:
            self._session.bank_right()
        else:
            self._session.bank_left()
        if self._mode == CONTROL_MODE:
            self._scenematrix.update()

    def inc_octave(self, inc):
        scale = SCALES[self.current_scale_index]
        octave = scale.to_octave(self._octave)
        newoctave = octave + inc
        if newoctave < 0:
            newoctave = 0
        elif newoctave > scale.octave_range:
            newoctave = scale.octave_range
        self._octave = scale.to_relative(newoctave, self._octave)
        scale = SCALES[self.current_scale_index]
        self.show_message(' OCTAVE ' + BASE_NOTE[self._base_note] + str(newoctave - 2) + ' to ' + scale.name)
        self.current_scale_to_display()

    def inc_base_note(self, inc):
        newbase = self._base_note + inc
        if newbase < 0:
            self._base_note = 0
        elif newbase > 11:
            self._base_note = 11
        else:
            self._base_note = newbase
        scale = SCALES[self.current_scale_index]
        self.show_message(' Base Note ' + BASE_NOTE[self._base_note] + ' to ' + scale.name)
        self.current_scale_to_display()

    def current_scale_to_display(self):
        scale = SCALES[self.current_scale_index]
        text = scale.name + ' ' + BASE_NOTE[self._base_note] + str(scale.to_octave(self._octave))
        self.send_to_display(text)

    def inc_scale(self, inc):
        nr_of_scales = len(SCALES)
        newindex = self.current_scale_index + inc
        if newindex < 0:
            newindex = 0
        elif newindex >= nr_of_scales:
            newindex = nr_of_scales - 1
        else:
            self.current_scale_index += inc
        newscale = SCALES[self.current_scale_index]
        self.show_message(' PAD Scale ' + newscale.name + ' ' + BASE_NOTE[self._base_note] + str(newscale.to_octave(self._octave) - 2))
        self.current_scale_to_display()

    def update_transpose(self):
        self.assign_transpose(SCALES[self.current_scale_index])
        self._set_suppress_rebuild_requests(True)
        self.request_rebuild_midi_map()
        self._set_suppress_rebuild_requests(False)

    def set_scale(self, scale):
        raise isinstance(scale, PadScale) or AssertionError
        scale_len = len(scale.notevalues)
        octave = scale.to_octave(self._octave)

    def assign_transpose(self, scale):
        raise isinstance(scale, PadScale) or AssertionError
        scale_len = len(scale.notevalues)
        octave = scale.to_octave(self._octave)
        last_note_val = None
        for note_index in range(16):
            button = self._button_sequence[note_index]
            scale_index = note_index % scale_len
            octave_offset = note_index / scale_len
            note_value = scale.notevalues[scale_index] + self._base_note + octave * 12 + octave_offset * 12
            if note_value < 128:
                last_note_val = note_value
            elif last_note_val != None:
                note_value = last_note_val
            button.set_send_note(note_value)
            if self._mode == PAD_MODE:
                button.send_color_direct(self.get_color_by_note_mode(note_value, False))

    def do_reset(self, value):
        if value == 0:
            return
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                data_byte1 = button._original_identifier
                button.send_midi((MIDI_CC_STATUS + 2, data_byte1, 0))

    def do_test(self, value):
        color = self.togglecolor[self.toggleindex]
        self.toggleindex = (self.toggleindex + 1) % len(self.togglecolor)
        if value == 0:
            return
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                self.schedule_message(1, self.dosend, (color,
                 127,
                 127,
                 row,
                 column))

    def dosend(self, parm = None):
        button = self._matrix[parm[3]][parm[4]]
        data_byte1 = button._original_identifier
        button.send_midi((MIDI_CC_STATUS + 0, data_byte1, parm[0]))
        button.send_midi((MIDI_CC_STATUS + 1, data_byte1, parm[1]))
        button.send_midi((MIDI_CC_STATUS + 2, data_byte1, parm[2]))

    def do_note_repeat(self, value):
        nrvalue = 0
        if value != 0:
            nrvalue = 1
        self._c_ref.set_note_repeat_state(nrvalue)

    def _do_toggle_send(self, value):
        nr_of_tracks = len(self.song().return_tracks)
        if value == 0 or nr_of_tracks < 1:
            return
        prev = self.send_slider_index
        self.send_slider_index += 1
        if self.send_slider_index >= nr_of_tracks:
            self.send_slider_index = 0
        self.show_message(' Set Send ' + str(SENDS[self.send_slider_index]))
        if prev != self.send_slider_index:
            for track in range(8):
                strip = self._mixer.channel_strip(track)
                slider_list = []
                for index in range(self.send_slider_index + 1):
                    if index < self.send_slider_index - 1:
                        slider_list.append(None)
                    else:
                        slider_list.append(self.send_sliders[track])
                    strip.set_send_controls(tuple(slider_list))

    def _do_armsolo_mode(self, value):
        if not self._armsolomode_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self._scenematrix.set_armsolo_exclusive(self._armsolomode_button)

    def _do_fire_button(self, value):
        if not self._fire_button != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                clip_slot = (value != 0 or not self._mute_button.is_momentary()) and self.song().view.highlighted_clip_slot
                clip_slot and clip_slot.fire()

    def _do_undo(self, value):
        if not self._undo_button != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                (value != 0 or not self._undo_button.is_momentary()) and self.song().can_undo == 1 and self.song().undo()
                self.show_message(str('UNDO'))

    def _do_redo(self, value):
        if not self._redo_button != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                (value != 0 or not self._redo_button.is_momentary()) and self.song().can_redo == 1 and self.song().redo()
                self.show_message(str('REDO'))

    def _a_trk_left(self, value):
        if not value in range(128):
            raise AssertionError
            if value != 0:
                direction = self.application().view.is_view_visible('Session') and Live.Application.Application.View.NavDirection.left
                self.application().view.scroll_view(direction, 'Session', True)

    def _a_trk_right(self, value):
        if not value in range(128):
            raise AssertionError
            if value != 0:
                direction = self.application().view.is_view_visible('Session') and Live.Application.Application.View.NavDirection.right
                self.application().view.scroll_view(direction, 'Session', True)

    def _nav_value_left(self, value):
        if not self._device_nav_button_left != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                modifier_pressed = True
                value > 0 and (not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain')) and self.application().view.show_view('Detail')
                self.application().view.show_view('Detail/DeviceChain')
            else:
                direction = Live.Application.Application.View.NavDirection.left
                self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)

    def _nav_value_right(self, value):
        if not self._device_nav_button_right != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                modifier_pressed = value > 0 and True
                (not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain')) and self.application().view.show_view('Detail')
                self.application().view.show_view('Detail/DeviceChain')
            else:
                direction = Live.Application.Application.View.NavDirection.right
                self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)

    def _do_tap_tempo(self, value):
        if not value in range(128):
            raise AssertionError
            value > 0 and self.song().tap_tempo()

    def _do_toggle_cue(self, value):
        if not value in range(128):
            raise AssertionError
            value > 0 and self.song().set_or_delete_cue()

    def _do_toggle_prev_cue(self, value):
        if not value in range(128):
            raise AssertionError
            value > 0 and self.song().jump_to_prev_cue()

    def _do_toggle_next_cue(self, value):
        if not value in range(128):
            raise AssertionError
            value > 0 and self.song().jump_to_next_cue()

    def focus_changed(self):
        pass

    def _handle_device_changed(self, device):
        pass

    def _hande_device_parm_changed(self):
        pass

    def _do_focus_navigate(self, value):
        if not self._navigate_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            self.nav_index = value != 0 and (self.nav_index + 1) % len(VIEWS_ALL)
            self.application().view.focus_view(VIEWS_ALL[self.nav_index])
            self.show_message('Focus on : ' + str(VIEWS_ALL[self.nav_index]))

    def scroll_focus(self, delta):
        if delta == 1:
            self.nav_index = (self.nav_index + 1) % len(VIEWS_ALL)
        elif self.nav_index == 0:
            self.nav_index = len(VIEWS_ALL) - 1
        else:
            self.nav_index -= 1
        self.show_message('Focus on : ' + str(VIEWS_ALL[self.nav_index]))
        self.application().view.focus_view(VIEWS_ALL[self.nav_index])

    def scroll_device(self, delta):
        if not (delta == 1 or delta == -1):
            raise AssertionError
            direction = delta == 1 and Live.Application.Application.View.NavDirection.right
        else:
            direction = Live.Application.Application.View.NavDirection.left
        self.application().view.scroll_view(direction, 'Detail/DeviceChain', True)

    def scroll_scene(self, delta):
        if not self.track_left_button != None:
            raise AssertionError
            raise delta == 1 or delta == -1 or AssertionError
            direction = delta == 1 and Live.Application.Application.View.NavDirection.down
        else:
            direction = Live.Application.Application.View.NavDirection.up
        self.application().view.scroll_view(direction, 'Session', True)

    def index_in_strip(self, track):
        for ind in range(len(self._mixer._channel_strips)):
            strack = self._mixer._channel_strips[ind]._track
            if strack == track:
                return ind

        return -1

    def notify_track_scroll(self):
        self._scenematrix.update_control_selection()
        if self._mode == CONTROL_MODE:
            self._scenematrix.eval_matrix()
            self._scenematrix.fire_values()

    def send_to_display(self, text, grid = 0):
        if USE_DISPLAY == False:
            return
        if len(text) > 28:
            text = text[:27]
        msgsysex = [240,
         0,
         0,
         102,
         23,
         18,
         min(grid, 3) * 28]
        filled = text.ljust(28)
        for c in filled:
            msgsysex.append(ord(c))

        msgsysex.append(247)
        self._send_midi(tuple(msgsysex))

    def send_color(self, button, hue, sat, bright):
        raise isinstance(button, ButtonElement) or AssertionError
        raise hue in range(128) or AssertionError
        raise sat in range(128) or AssertionError
        raise bright in range(128) or AssertionError
        data_byte1 = button._original_identifier
        button.send_midi((MIDI_CC_STATUS + 2, data_byte1, bright))
        button.send_midi((MIDI_CC_STATUS + 1, data_byte1, sat))
        button.send_midi((MIDI_CC_STATUS + 0, data_byte1, hue))

    def turn_off_matrix(self):
        for row in range(4):
            for column in range(4):
                button = self._matrix[row][column]
                self.send_color(button, 2, 0, 0)
                button.set_to_notemode(False)

    def remove_listener(self, control, callback):
        if control != None and control.value_has_listener(callback):
            control.remove_value_listener(callback)
        control.disconnect()

    def disconnect(self):
        self.turn_off_matrix()
        self.scene_mode_button.send_value(0, True)
        self.clip_mode_button.send_value(0, True)
        self.pad_mode_button.send_value(0, True)
        self.control_mode_button.send_value(0, True)
        time.sleep(0.2)
        self._active = False
        self._suppress_send_midi = True
        self.remove_listener(self.scene_mode_button, self._a_mode_scene)
        self.remove_listener(self.clip_mode_button, self._a_mode_clip)
        self.remove_listener(self.pad_mode_button, self._a_mode_pad)
        self.remove_listener(self.control_mode_button, self._a_mode_control)
        self.remove_listener(self._undo_button, self._do_undo)
        self.remove_listener(self._redo_button, self._do_redo)
        self.remove_listener(self._armsolomode_button, self._do_armsolo_mode)
        self.remove_listener(self.xfade_assign_button, self._do_xfade_assign)
        self.remove_listener(self._fire_button, self._do_fire_button)
        self._session.remove_offset_listener(self.notify_track_scroll)
        self._mixer.disconnect()
        ControlSurface.disconnect(self)
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())
示例#57
0
class Axiom_DirectLink(ControlSurface):
    """ Script for the M-Audio Axiom DirectLink """

    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 = "DirectLink"
            self._suggested_output_port = "DirectLink"
            self._waiting_for_first_response = True
            self._has_sliders = True
            self._current_midi_map = None
            self._display_reset_delay = -1
            self._shift_pressed = False
            self._shift_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 13)
            self._master_slider = SliderElement(MIDI_CC_TYPE, 15, 41)
            self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 111)
            self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 110)
            self._device_bank_buttons = None
            self._device_navigation = None
            self._shift_button.name = "Shift_Button"
            self._master_slider.name = "Master_Volume_Control"
            self._next_nav_button.name = "Next_Track_Button"
            self._prev_nav_button.name = "Prev_Track_Button"
            self._master_slider.add_value_listener(self._slider_value, identify_sender=True)
            self._shift_button.add_value_listener(self._shift_value)
            self._setup_mixer()
            self._setup_transport_and_session()
            self._setup_device()
            self._setup_display()
            for component in self.components:
                component.set_enabled(False)

        return

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self._waiting_for_first_response = True
        self.schedule_message(3, self._send_midi, SYSEX_START + (32, 46, 247))

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:-2] == SYSEX_START + (32,) and midi_bytes[-2] != 0:
            self._has_sliders = midi_bytes[-2] & 8 != 0
            if self._waiting_for_first_response:
                self._waiting_for_first_response = False
                self.schedule_message(1, self._show_startup_message)
                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)
            self.request_rebuild_midi_map()
        return

    def disconnect(self):
        self._display_data_source.set_display_string("  ")
        self._shift_button.remove_value_listener(self._shift_value)
        self._inst_button.remove_value_listener(self._inst_value)
        for encoder in self._encoders:
            encoder.remove_value_listener(self._encoder_value)

        for slider in tuple(self._sliders) + (self._master_slider,):
            slider.remove_value_listener(self._slider_value)

        for button in tuple(self._strip_buttons) + (self._selected_mute_solo_button,):
            button.remove_value_listener(self._mixer_button_value)

        for button in self._device_bank_buttons:
            button.remove_value_listener(self._device_bank_value)

        self._encoders = None
        self._sliders = None
        self._strip_buttons = None
        self._master_slider = None
        self._current_midi_map = None
        self._selected_mute_solo_button = None
        self._inst_button = None
        self._shift_button = None
        self._device_navigation = None
        self._display = None
        ControlSurface.disconnect(self)
        self._send_midi(SYSEX_START + (32, 0, 247))
        return

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

    def 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._show_current_track_name()

    def _setup_mixer(self):
        self._selected_mute_solo_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 12)
        mute_solo_flip_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 57)
        self._strip_buttons = []
        self._selected_mute_solo_button.name = "Selected_Mute_Button"
        mute_solo_flip_button.name = "Mute_Solo_Flip_Button"
        self._selected_mute_solo_button.add_value_listener(self._mixer_button_value, identify_sender=True)
        self._mixer = ShiftableMixerComponent(8)
        self._mixer.name = "Mixer"
        self._mixer.set_shift_button(self._shift_button)
        self._mixer.set_selected_mute_solo_button(self._selected_mute_solo_button)
        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, 15, 33 + 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, 15, 49 + 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.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)

    def _setup_transport_and_session(self):
        ffwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 115)
        rwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 114)
        loop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 113)
        play_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 117)
        stop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 116)
        rec_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 118)
        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_shift_button(self._shift_button)
        transport.set_stop_button(stop_button)
        transport.set_play_button(play_button)
        transport.set_record_button(rec_button)
        pads = []
        for index in range(len(PAD_TRANSLATIONS)):
            pads.append(ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, 15, PAD_TRANSLATIONS[index][2]))
            pads[-1].name = "Pad_" + str(index)

        self._session = ShiftableSessionComponent(8, 0)
        self._session.name = "Session_Control"
        self._session.selected_scene().name = "Selected_Scene"
        self._session.set_mixer(self._mixer)
        self._session.set_shift_button(self._shift_button)
        self._session.set_clip_slot_buttons(tuple(pads))
        transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button, loop_button)
        transport_view_modes.name = "Transport_View_Modes"

    def _setup_device(self):
        self._encoders = []
        for offset in range(8):
            self._encoders.append(
                PeekableEncoderElement(
                    MIDI_CC_TYPE, 15, 17 + offset, Live.MidiMap.MapMode.relative_smooth_two_compliment
                )
            )
            self._encoders[-1].set_feedback_delay(-1)
            self._encoders[-1].add_value_listener(self._encoder_value, identify_sender=True)
            self._encoders[-1].name = "Device_Control_" + str(offset)

        prev_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 14)
        next_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 15)
        prev_bank_button.name = "Device_Bank_Down_Button"
        next_bank_button.name = "Device_Bank_Up_Button"
        device = BestBankDeviceComponent()
        device.name = "Device_Component"
        self.set_device_component(device)
        device.set_parameter_controls(tuple(self._encoders))
        device.set_bank_nav_buttons(prev_bank_button, next_bank_button)
        self._device_bank_buttons = (prev_bank_button, next_bank_button)
        prev_bank_button.add_value_listener(self._device_bank_value)
        next_bank_button.add_value_listener(self._device_bank_value)
        self._inst_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 109)
        self._inst_button.name = "Inst_Button"
        self._inst_button.add_value_listener(self._inst_value)
        self._device_navigation = DetailViewCntrlComponent()
        self._device_navigation.name = "Device_Navigation_Component"

    def _setup_display(self):
        self._display = PhysicalDisplayElement(5, 1)
        self._display.name = "Display"
        self._display.set_message_parts(SYSEX_START + (17, 1, 0, 0), (247,))
        self._display_data_source = DisplayDataSource()
        self._display.segment(0).set_data_source(self._display_data_source)

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

    def _shift_value(self, value):
        if not value in range(128):
            raise AssertionError
            self._shift_pressed = value > 0
            for encoder in self._encoders:
                encoder.set_peek_mode(self._shift_pressed)

            self._shift_pressed and self._mixer.set_select_buttons(None, None)
            self._session.set_track_bank_buttons(self._next_nav_button, self._prev_nav_button)
            self._device_component.set_bank_nav_buttons(None, None)
            self._device_navigation.set_device_nav_buttons(self._device_bank_buttons[0], self._device_bank_buttons[1])
        else:
            self._session.set_track_bank_buttons(None, None)
            self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button)
            self._device_navigation.set_device_nav_buttons(None, None)
            self._device_component.set_bank_nav_buttons(self._device_bank_buttons[0], self._device_bank_buttons[1])
        self.request_rebuild_midi_map()
        return

    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._display_data_source.set_display_string(display_string)
            self._set_display_data_source(self._display_data_source)
            self._display_reset_delay = STANDARD_DISPLAY_DELAY
        return

    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 "Ma"
                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 += " Vol"
            self._display_data_source.set_display_string(display_string)
            self._set_display_data_source(self._display_data_source)
            self._display_reset_delay = STANDARD_DISPLAY_DELAY
        return

    def _mixer_button_value(self, value, sender):
        if not sender in tuple(self._strip_buttons) + (self._selected_mute_solo_button,):
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                if self._mixer.is_enabled() and value > 0:
                    strip = None
                    strip = sender == self._selected_mute_solo_button and self._mixer.selected_strip()
                else:
                    strip = self._mixer.channel_strip(self._strip_buttons.index(sender))
                strip != None and self._set_display_data_source(strip.track_name_data_source())
            else:
                self._display_data_source.set_display_string(" - ")
                self._set_display_data_source(self._display_data_source)
            self._display_reset_delay = STANDARD_DISPLAY_DELAY
        return

    def _device_bank_value(self, value):
        if not value in range(128):
            raise AssertionError
            if self._device_component.is_enabled() and value > 0:
                data_source = self._device_component.bank_name_data_source()
                data_source = self._shift_pressed and self._device_component.device_name_data_source()
            self._set_display_data_source(data_source)
            self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _inst_value(self, value):
        if not value in range(128):
            raise AssertionError
            value > 0 and self._device_component.is_enabled() and self.song().view.selected_track.view.select_instrument() and self._set_display_data_source(
                self._device_component.device_name_data_source()
            )
            self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _show_current_track_name(self):
        if self._display != None and self._mixer != None:
            self._set_display_data_source(self._mixer.selected_strip().track_name_data_source())
        return

    def _show_startup_message(self):
        self._display.display_message("LIVE")
        self._display_reset_delay = INITIAL_DISPLAY_DELAY

    def _set_display_data_source(self, data_source):
        raise isinstance(data_source, DisplayDataSource) or AssertionError
        self._display.segment(0).set_data_source(data_source)
        data_source.update()
class MainKnobControl:
    __module__ = __name__
    __doc__ = 'Mk2 Module for Controlling Parameters with Master Knob'

    def __init__(self, parent):
        self._parent = parent
        self.master_track = parent.song().master_track
        self.the_slider = SliderElement(MIDI_CC_TYPE, 1, 86)
        self.the_slider.add_value_listener(self._do_main_slider, True)
        self.volume_button = None
        self._set_volume_button(StateButton(True, MIDI_CC_TYPE, 1, 80))
        self.xfade_button = None
        self._set_xfade_button(StateButton(True, MIDI_CC_TYPE, 1, 99))
        self.swing_button = None
        self._set_swing_button(StateButton(True, MIDI_CC_TYPE, 1, 81))
        self.mode = KN2_MODE_VOLUME
        self.previous_mode = -1
        self.tempo_button = None
        self._set_tempo_button(StateButton(True, MIDI_CC_TYPE, 1, 82))
        self.push_button = None
        self._set_push_button(StateButton(True, MIDI_CC_TYPE, 1, 87))
        self.clipn_v_button = None
        self.clipn_h_button = None
        self._set_clipn_h_button(StateButton(True, MIDI_CC_TYPE, 1, 90))
        self._set_clipn_v_button(StateButton(True, MIDI_CC_TYPE, 1, 91))
        self.toggle_buttons = [self.volume_button,
         self.xfade_button,
         self.swing_button,
         self.tempo_button,
         self.clipn_h_button,
         self.clipn_v_button]
        self.shift_button = None
        self._set_shift_button(StateButton(True, MIDI_CC_TYPE, 1, 85))
        self.shift_on = False
        self.scroll_mod_left_button = None
        self.scroll_mod_right_button = None
        self._set_scroll_mod_left_button(ButtonElement(True, MIDI_CC_TYPE, 0, 105))
        self._set_scroll_mod_right_button(ButtonElement(True, MIDI_CC_TYPE, 0, 106))
        self._prev_mode = KN2_MODE_VOLUME
        self.lrmode = LR_CONTROL_CLIP
        self.loop_div_index = 0
        self.loop_incdex = 4.0
        self.arrow_mode_button = ColorButton(True, MIDI_CC_TYPE, 30)
        self.arrow_mode_button.add_value_listener(self.toggle_arrow_mode)
        self.arrow_mode_button.send_value(1, True)
        self.navflags = 0
        self.octave_mod_button = ButtonElement(True, MIDI_CC_TYPE, 1, 70)
        self.octave_mod_button.add_value_listener(self._action_octave)
        self.scale_mod_button = ButtonElement(True, MIDI_CC_TYPE, 1, 71)
        self.scale_mod_button.add_value_listener(self._action_scale)
        self.basenote_mod_button = ButtonElement(True, MIDI_CC_TYPE, 1, 72)
        self.basenote_mod_button.add_value_listener(self._action_base_note)
        self.pad_to_mainknob_mode = 0
        self.octave_dwn_button = ButtonElement(True, MIDI_CC_TYPE, 3, 120)
        self.octave_upp_button = ButtonElement(True, MIDI_CC_TYPE, 3, 121)
        self.scale_dwn_button = ButtonElement(True, MIDI_CC_TYPE, 3, 118)
        self.scale_upp_button = ButtonElement(True, MIDI_CC_TYPE, 3, 119)
        self.basent_dwn_button = ButtonElement(True, MIDI_CC_TYPE, 3, 124)
        self.basent_upp_button = ButtonElement(True, MIDI_CC_TYPE, 3, 125)
        self.octave_dwn_button.add_value_listener(self._action_oct_down)
        self.octave_upp_button.add_value_listener(self._action_oct_up)
        self.scale_dwn_button.add_value_listener(self._action_scale_down)
        self.scale_upp_button.add_value_listener(self._action_scale_up)
        self.basent_dwn_button.add_value_listener(self._action_base_down)
        self.basent_upp_button.add_value_listener(self._action_base_up)
        self._measure_left_click = 0
        self._measure_right_click = 0
        self.mode_assign_map = {KN2_MODE_VOLUME: (self.chg_volume,
                           0,
                           'Master Knob controls MASTER Volume',
                           KN2_MODE_CUE),
         KN2_MODE_CUE: (self.chg_cue,
                        0,
                        'Master Knob controls Cue Level',
                        KN2_MODE_VOLUME),
         KN2_MODE_TEMPO_COARSE: (self.chg_tempo,
                                 3,
                                 'Master Knob controls TEMPO Coarse',
                                 KN2_MODE_TEMPO_FINE),
         KN2_MODE_TEMPO_FINE: (self.chg_tempo_fine,
                               3,
                               'Master Knob controls TEMPO Fine',
                               KN2_MODE_TEMPO_COARSE),
         KN2_MODE_XFADE: (self.chg_xfade,
                          1,
                          'Master Knob controls Crossfader',
                          -1),
         KN2_MODE_QUANT: (self.chg_quant,
                          2,
                          'Master Knob controls Recording Quantize',
                          KN2_MODE_CLIP_QUANT),
         KN2_MODE_CLIP_QUANT: (self.chg_clip_q,
                               2,
                               'Master Knob controls Clip Start Quantize',
                               KN2_MODE_QUANT),
         KN2_MODE_CLIPN_HOR: (self.nav_c_hor,
                              4,
                              'Master Knob Clip View horizontally',
                              -1),
         KN2_MODE_CLIPN_VER: (self.nav_c_ver,
                              5,
                              'Master Knob Clip View vertically',
                              -1),
         KN2_MODE_GENERAL: (self.chg_general,
                            -1,
                            None,
                            -1),
         KN2_P_SCALES: (self.modify_pad_scaling,
                        -1,
                        None,
                        -1)}

    def start_up(self):
        self._set_mode(KN2_MODE_VOLUME)
        self.arrow_mode_button.send_value(127, True)

    def toggle_arrow_mode(self, value):
        if value > 0:
            self.lrmode = (self.lrmode + 1) % 4
            self.arrow_mode_button.send_hue(LR_MODE_HUES[self.lrmode])
            self._parent.show_message('Left/Right Buttons Control:    ' + L_MODE_FUNCTION[self.lrmode] + ' / ' + R_MODE_FUNCTION[self.lrmode])

    def switch_to_matrix_mode(self):
        if self.mode != KN2_MODE_GENERAL:
            self.previous_mode = self.mode
            self._set_mode(KN2_MODE_GENERAL)

    def exit_matrix_mode(self):
        if self.mode == KN2_MODE_GENERAL:
            self._set_mode(self.previous_mode)
            self.previous_mode = -1

    def update_shift(self):
        if self.shift_on:
            self.shift_button.send_value(127, True)
        else:
            self.shift_button.send_value(0, True)

    def _set_mode(self, mode):
        if not mode in range(11):
            raise AssertionError
            self.update_shift()
            if mode == self.mode:
                return
            self._prev_mode = mode
            self.mode = mode
            self.switch_radio_buttons(self.mode_assign_map[self.mode][1])
            message = self.mode_assign_map[self.mode][2]
            message != None and self._parent.show_message(message)

    def switch_radio_buttons(self, which):
        for index in range(len(self.toggle_buttons)):
            if index == which:
                self.toggle_buttons[index].send_value(127, True)
            else:
                self.toggle_buttons[index].send_value(0, True)

    def update(self):
        self.switch_radio_buttons(self.mode_assign_map[self.mode][1])
        self.arrow_mode_button.send_color(LR_MODE_HUES[self.lrmode])
        self.arrow_mode_button.send_value(127, True)

    def _do_main_slider(self, value, encoder):
        if not value in range(128):
            raise AssertionError
            if not isinstance(encoder, EncoderElement):
                raise AssertionError
                if value == 1:
                    delta = 1
                else:
                    delta = -1
                if self.pad_to_mainknob_mode != 0:
                    self.mode_assign_map[KN2_P_SCALES][0](delta)
                elif self.navflags == 0:
                    self.mode_assign_map[self.mode][0](delta)
                if self.lrmode == LR_CONTROL_CLIP:
                    self.navflags & LEFT_DOWN != 0 and self.nav_c_hor(delta)
                self.navflags & RIGHT_DOWN != 0 and self.nav_c_ver(delta)
        elif self.lrmode == LR_CONTROL_SEL:
            if self.navflags & LEFT_DOWN != 0:
                self.nav_track(delta)
            if self.navflags & RIGHT_DOWN != 0:
                self._parent.scroll_scene(delta)
        elif self.lrmode == LR_CONTROL_DEV:
            if self.navflags & LEFT_DOWN != 0:
                self.nav_track(delta)
            if self.navflags & RIGHT_DOWN != 0:
                self._parent.scroll_device(delta)
        elif self.lrmode == LR_CONTROL_LOOP:
            if self.navflags & LEFT_DOWN != 0:
                self.adjust_loop_start(delta)
            if self.navflags & RIGHT_DOWN != 0:
                self.adjust_loop_length(delta)

    def modify_pad_scaling(self, delta):
        if self.pad_to_mainknob_mode & PAD_KNOB_OCTAVE != 0:
            self._parent.inc_octave(delta)
        if self.pad_to_mainknob_mode & PAD_KNOB_SCALE != 0:
            self._parent.inc_scale(delta)
        if self.pad_to_mainknob_mode & PAD_KNOB_BASEN != 0:
            self._parent.inc_base_note(delta)

    def adjust_loop_start(self, delta):
        loopval = self._parent.song().loop_start
        loopval += self.loop_incdex * delta
        if loopval < 0:
            loopval = 0
        elif loopval > 999:
            loopval = 999
        self._parent.song().loop_start = loopval

    def adjust_loop_length(self, delta):
        loopval = self._parent.song().loop_length
        loopval += self.loop_incdex * delta
        if loopval < self.loop_incdex:
            loopval = self.loop_incdex
        elif loopval > 999:
            loopval = 999
        self._parent.song().loop_length = loopval

    def chg_general(self, delta):
        self._parent._scenematrix.control_handler.mod_value(delta, self.shift_on)

    def nav_track(self, direction):
        if direction == 1:
            self._parent._a_trk_right(1)
        else:
            self._parent._a_trk_left(1)

    def nav_c_hor(self, direction):
        self._parent.move_view_horizontal(direction)

    def nav_c_ver(self, direction):
        if direction == 1:
            self._parent._session.bank_up()
        else:
            self._parent._session.bank_down()

    def chg_volume(self, diff):
        if self.shift_on:
            self.repeat(self.master_track.mixer_device.volume, diff)
        else:
            self.master_track.mixer_device.volume.value = self.calc_new_parm(self.master_track.mixer_device.volume, diff)

    def chg_xfade(self, diff):
        if self.shift_on:
            self.repeat(self.master_track.mixer_device.crossfader, diff)
        else:
            self.master_track.mixer_device.crossfader.value = self.calc_new_parm(self.master_track.mixer_device.crossfader, diff)

    def chg_cue(self, diff):
        if self.shift_on:
            self.repeat(self.master_track.mixer_device.cue_volume, diff)
        else:
            self.master_track.mixer_device.cue_volume.value = self.calc_new_parm(self.master_track.mixer_device.cue_volume, diff)

    def repeat(self, parm, delta):
        count = 0
        while count < SHIFT_INC:
            parm.value = self.calc_new_parm(parm, delta)
            count += 1

    def calc_new_parm(self, parm, delta):
        parm_range = parm.max - parm.min
        int_val = int((parm.value - parm.min) / parm_range * PARM_RANGE + 0.1)
        inc_val = min(PARM_RANGE, max(0, int_val + delta))
        return float(inc_val) / float(PARM_RANGE) * parm_range + parm.min

    def chg_quant(self, diff):
        rec_quant = self._parent.song().midi_recording_quantization
        index = self.get_quant_index(rec_quant)
        new_index = index + diff
        if new_index >= 0 and new_index < len(QUANT_CONST):
            self._parent.song().midi_recording_quantization = QUANT_CONST[new_index]
            self._parent.show_message(QUANT_DESCR[new_index])

    def chg_clip_q(self, diff):
        quant = self._parent.song().clip_trigger_quantization
        self._parent.song().clip_trigger_quantization = max(0, min(13, quant + diff))
        self._parent.show_message('Clip Quantize ' + CLIQ_DESCR[self._parent.song().clip_trigger_quantization])

    def chg_tempo_fine(self, diff):
        if diff < 0:
            amount = -0.01
        else:
            amount = 0.01
        self.chg_tempo(amount)

    def chg_tempo(self, diff):
        self._parent.song().tempo = max(20, min(999, self._parent.song().tempo + diff))

    def get_quant_index(self, const):
        for index in range(len(QUANT_CONST)):
            if const == QUANT_CONST[index]:
                return index

        return -1

    def _action_octave(self, value):
        if value != 0:
            self.pad_to_mainknob_mode |= PAD_KNOB_OCTAVE
        else:
            self.pad_to_mainknob_mode &= ~PAD_KNOB_OCTAVE

    def _action_scale(self, value):
        if value != 0:
            self.pad_to_mainknob_mode |= PAD_KNOB_SCALE
        else:
            self.pad_to_mainknob_mode &= ~PAD_KNOB_SCALE

    def _action_base_note(self, value):
        if value != 0:
            self.pad_to_mainknob_mode |= PAD_KNOB_BASEN
        else:
            self.pad_to_mainknob_mode &= ~PAD_KNOB_BASEN

    def _set_volume_button(self, button):
        if not (button == None or isinstance(button, ButtonElement)):
            raise AssertionError
            if self.volume_button != None:
                self.volume_button.remove_value_listener(self._action_volume)
            self.volume_button = button
            self.volume_button != None and self.volume_button.add_value_listener(self._action_volume)

    def _action_volume(self, value):
        if not self.volume_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.mode != KN2_MODE_VOLUME and self._set_mode(KN2_MODE_VOLUME)

    def _set_xfade_button(self, button):
        if not (button == None or isinstance(button, ButtonElement)):
            raise AssertionError
            if self.xfade_button != None:
                self.xfade_button.remove_value_listener(self._action_xfade)
            self.xfade_button = button
            self.xfade_button != None and self.xfade_button.add_value_listener(self._action_xfade)

    def _action_xfade(self, value):
        if not self.xfade_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.mode != KN2_MODE_XFADE and self._set_mode(KN2_MODE_XFADE)

    def _set_swing_button(self, button):
        if not (button == None or isinstance(button, ButtonElement)):
            raise AssertionError
            if self.swing_button != None:
                self.swing_button.remove_value_listener(self._action_swing)
            self.swing_button = button
            self.swing_button != None and self.swing_button.add_value_listener(self._action_swing)

    def _action_swing(self, value):
        if not self.swing_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.mode != KN2_MODE_QUANT and self._set_mode(KN2_MODE_QUANT)

    def _set_tempo_button(self, button):
        if not (button == None or isinstance(button, ButtonElement)):
            raise AssertionError
            if self.tempo_button != None:
                self.tempo_button.remove_value_listener(self._action_tempo)
            self.tempo_button = button
            self.tempo_button != None and self.tempo_button.add_value_listener(self._action_tempo)

    def _action_tempo(self, value):
        if not self.tempo_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.mode != KN2_MODE_TEMPO_COARSE and self._set_mode(KN2_MODE_TEMPO_COARSE)

    def _set_clipn_h_button(self, button):
        if not (button == None or isinstance(button, ButtonElement)):
            raise AssertionError
            if self.clipn_h_button != None:
                self.clipn_h_button.remove_value_listener(self._action_clipnh)
            self.clipn_h_button = button
            self.clipn_h_button != None and self.clipn_h_button.add_value_listener(self._action_clipnh)

    def _action_clipnh(self, value):
        if not self.clipn_h_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.mode != KN2_MODE_CLIPN_HOR and self._set_mode(KN2_MODE_CLIPN_HOR)

    def _set_clipn_v_button(self, button):
        if not (button == None or isinstance(button, ButtonElement)):
            raise AssertionError
            if self.clipn_v_button != None:
                self.clipn_v_button.remove_value_listener(self._action_clipnv)
            self.clipn_v_button = button
            self.clipn_v_button != None and self.clipn_v_button.add_value_listener(self._action_clipnv)

    def _action_clipnv(self, value):
        if not self.clipn_v_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.mode != KN2_MODE_CLIPN_VER and self._set_mode(KN2_MODE_CLIPN_VER)

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

    def _action_shift(self, value):
        if not self.shift_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            self.shift_on = value != 0 and not self.shift_on
            self.update_shift()

    def _set_scroll_mod_left_button(self, button):
        if not (button == None or isinstance(button, ButtonElement)):
            raise AssertionError
            if self.scroll_mod_left_button != None:
                self.scroll_mod_left_button.remove_value_listener(self._action_scroll_left)
            self.scroll_mod_left_button = button
            self.scroll_mod_left_button != None and self.scroll_mod_left_button.add_value_listener(self._action_scroll_left)

    def _set_scroll_mod_right_button(self, button):
        if not (button == None or isinstance(button, ButtonElement)):
            raise AssertionError
            if self.scroll_mod_right_button != None:
                self.scroll_mod_right_button.remove_value_listener(self._action_scroll_right)
            self.scroll_mod_right_button = button
            self.scroll_mod_right_button != None and self.scroll_mod_right_button.add_value_listener(self._action_scroll_right)

    def _action_scroll_left(self, value):
        if not self.scroll_mod_left_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.scroll_mod_left_button.send_value(127, True)
            self.navflags |= LEFT_DOWN
            self._measure_left_click = int(round(time.time() * 1000))
        else:
            self.scroll_mod_left_button.send_value(0, True)
            self.navflags &= ~LEFT_DOWN
            clicktime = int(round(time.time() * 1000)) - self._measure_left_click
            if clicktime < CLICK_TIME:
                if self._parent._modifier_down:
                    self._parent.modify_track_offset(-1)
                elif self._parent._mode == PAD_MODE:
                    self._do_lr_as_scale_mode(-1)
                elif self._parent._mode == SCENE_MODE:
                    self._parent.modify_scene_offset(-1)
                elif self._parent._mode == CLIP_MODE:
                    self._parent.move_view_horizontal(-1)
                elif self._parent._mode == CONTROL_MODE:
                    self._parent.move_view_horizontal(-1)

    def _action_scroll_right(self, value):
        if not self.scroll_mod_right_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            value != 0 and self.scroll_mod_right_button.send_value(1)
            self.navflags |= RIGHT_DOWN
            self._measure_right_click = int(round(time.time() * 1000))
        else:
            self.scroll_mod_right_button.send_value(0, True)
            self.navflags &= ~RIGHT_DOWN
            clicktime = int(round(time.time() * 1000)) - self._measure_right_click
            if clicktime < CLICK_TIME:
                if self._parent._modifier_down:
                    self._parent.modify_track_offset(1)
                elif self._parent._mode == PAD_MODE:
                    self._do_lr_as_scale_mode(1)
                elif self._parent._mode == SCENE_MODE:
                    self._parent.modify_scene_offset(1)
                elif self._parent._mode == CLIP_MODE:
                    self._parent.move_view_horizontal(1)
                elif self._parent._mode == CONTROL_MODE:
                    self._parent.move_view_horizontal(1)

    def _do_lr_as_scale_mode(self, delta):
        if self.pad_to_mainknob_mode == PAD_KNOB_SCALE:
            self._parent.inc_scale(delta)
        elif self.pad_to_mainknob_mode == PAD_KNOB_BASEN:
            self._parent.inc_base_note(delta)
        else:
            self._parent.inc_octave(delta)

    def _action_oct_down(self, value):
        if value != 0:
            self._parent.inc_octave(-1)

    def _action_oct_up(self, value):
        if value != 0:
            self._parent.inc_octave(1)

    def _action_scale_down(self, value):
        if value != 0:
            self._parent.inc_scale(-1)

    def _action_scale_up(self, value):
        if value != 0:
            self._parent.inc_scale(1)

    def _action_base_down(self, value):
        if value != 0:
            self._parent.inc_base_note(-1)

    def _action_base_up(self, value):
        if value != 0:
            self._parent.inc_base_note(1)

    def _set_push_button(self, button):
        if not (button == None or isinstance(button, ButtonElement)):
            raise AssertionError
            if self.push_button != None:
                self.push_button.remove_value_listener(self._action_push)
            self.push_button = button
            self.push_button != None and self.push_button.add_value_listener(self._action_push)

    def _action_push(self, value):
        if not self.push_button != None:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                next_mode = self.mode_assign_map[self.mode][3]
                next_mode != -1 and self._set_mode(next_mode)
            self.loop_div_index = self.lrmode == LR_CONTROL_LOOP and self.navflags != 0 and (self.loop_div_index + 1) % len(LOOP_KNOB_DIVISION)
            self._parent.show_message('Loop Selection Granularity : ' + str(LOOP_KNOB_DIVISION[self.loop_div_index]) + ' beats ')
            self.loop_incdex = LOOP_KNOB_DIVISION[self.loop_div_index]

    def remove_listener(self, control, callback):
        if control != None and control.value_has_listener(callback):
            control.remove_value_listener(callback)
        control.disconnect()

    def disconnect(self):
        self.remove_listener(self.the_slider, self._do_main_slider)
        self.remove_listener(self.arrow_mode_button, self.toggle_arrow_mode)
        self.remove_listener(self.volume_button, self._action_volume)
        self.remove_listener(self.xfade_button, self._action_xfade)
        self.remove_listener(self.swing_button, self._action_swing)
        self.remove_listener(self.clipn_h_button, self._action_clipnh)
        self.remove_listener(self.clipn_v_button, self._action_clipnv)
        self.remove_listener(self.shift_button, self._action_shift)
        self.remove_listener(self.scroll_mod_left_button, self._action_scroll_left)
        self.remove_listener(self.scroll_mod_right_button, self._action_scroll_right)
        self.remove_listener(self.push_button, self._action_push)
        self.remove_listener(self.octave_mod_button, self._action_octave)
        self.remove_listener(self.scale_mod_button, self._action_scale)
        self.remove_listener(self.basenote_mod_button, self._action_base_note)
        self.remove_listener(self.octave_dwn_button, self._action_oct_down)
        self.remove_listener(self.octave_upp_button, self._action_oct_up)
        self.remove_listener(self.scale_dwn_button, self._action_scale_down)
        self.remove_listener(self.scale_upp_button, self._action_scale_up)
        self.remove_listener(self.basent_dwn_button, self._action_base_down)
        self.remove_listener(self.basent_upp_button, self._action_base_up)
        self._parent = None
        self.master_track = None
        self.the_slider = None
        self.mode_assign_map = None