class BeatStep(ArturiaControlSurface):

    def __init__(self, *a, **k):
        super(BeatStep, self).__init__(*a, **k)
        self._skin = Skin(Colors)
        with self.component_guard():
            self._create_controls()
            self._create_device()
            self._create_session()
            self._create_mixer()
            self._create_transport()

    def _create_controls(self):
        self._device_encoders = ButtonMatrixElement(rows=[ [ EncoderElement(MIDI_CC_TYPE, 0, identifier, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Encoder_%d_%d' % (column_index, row_index)) for column_index, identifier in enumerate(row) ] for row_index, row in enumerate((
         ENCODER_MSG_IDS[:4], ENCODER_MSG_IDS[8:12]))
                                                         ])
        self._horizontal_scroll_encoder = EncoderElement(MIDI_CC_TYPE, 0, 75, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Horizontal_Scroll_Encoder')
        self._vertical_scroll_encoder = EncoderElement(MIDI_CC_TYPE, 0, 72, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Vertical_Scroll_Encoder')
        self._volume_encoder = EncoderElement(MIDI_CC_TYPE, 0, 91, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Volume_Encoder')
        self._pan_encoder = EncoderElement(MIDI_CC_TYPE, 0, 17, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Pan_Encoder')
        self._send_a_encoder = EncoderElement(MIDI_CC_TYPE, 0, 77, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Send_A_Encoder')
        self._send_b_encoder = EncoderElement(MIDI_CC_TYPE, 0, 93, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Send_B_Encoder')
        self._send_encoders = ButtonMatrixElement(rows=[
         [
          self._send_a_encoder, self._send_b_encoder]])
        self._return_a_encoder = EncoderElement(MIDI_CC_TYPE, 0, 73, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Return_A_Encoder')
        self._return_b_encoder = EncoderElement(MIDI_CC_TYPE, 0, 79, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Return_B_Encoder')
        self._return_encoders = ButtonMatrixElement(rows=[
         [
          self._return_a_encoder, self._return_b_encoder]])
        self._pads = ButtonMatrixElement(rows=[ [ ButtonElement(True, MIDI_NOTE_TYPE, PAD_CHANNEL, identifier, name='Pad_%d_%d' % (col_index, row_index), skin=self._skin) for col_index, identifier in enumerate(row) ] for row_index, row in enumerate(PAD_MSG_IDS)
                                              ])
        self._stop_button = ButtonElement(True, MIDI_CC_TYPE, 0, 1, name='Stop_Button')
        self._play_button = ButtonElement(True, MIDI_CC_TYPE, 0, 2, name='Play_Button')

    def _create_device(self):
        self._device = DeviceComponent(name='Device', is_enabled=False, layer=Layer(parameter_controls=self._device_encoders), device_selection_follows_track_selection=True)
        self._device.set_enabled(True)
        self.set_device_component(self._device)

    def _create_session(self):
        self._session = SessionComponent(name='Session', is_enabled=False, num_tracks=self._pads.width(), num_scenes=self._pads.height(), enable_skinning=True, layer=Layer(clip_launch_buttons=self._pads, scene_select_control=self._vertical_scroll_encoder))
        self._session.set_enabled(True)

    def _create_mixer(self):
        self._mixer = MixerComponent(name='Mixer', is_enabled=False, num_returns=2, layer=Layer(track_select_encoder=self._horizontal_scroll_encoder, selected_track_volume_control=self._volume_encoder, selected_track_pan_control=self._pan_encoder, selected_track_send_controls=self._send_encoders, return_volume_controls=self._return_encoders))
        self._mixer.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(stop_button=self._stop_button, play_button=self._play_button))
        self._transport.set_enabled(True)

    def _collect_setup_messages(self):
        for identifier, hardware_id in izip(ENCODER_MSG_IDS, HARDWARE_ENCODER_IDS):
            self._setup_hardware_encoder(hardware_id, identifier)

        self._setup_hardware_button(HARDWARE_STOP_BUTTON_ID, 1, msg_type='cc')
        self._setup_hardware_button(HARDWARE_PLAY_BUTTON_ID, 2, msg_type='cc')
        for hardware_id, identifier in izip(HARDWARE_PAD_IDS, chain(*PAD_MSG_IDS)):
            self._setup_hardware_button(hardware_id, identifier, PAD_CHANNEL, msg_type='note')
Exemple #2
0
 def __init__(self, *a, **k):
     super(Advance, self).__init__(*a, **k)
     with self.component_guard():
         encoders = ButtonMatrixElement(rows=[[
             make_encoder(index + 22, b'Encoder_%d' % index)
             for index in xrange(8)
         ]])
         pads = ButtonMatrixElement(rows=[[
             make_button(identifier, b'Pad_%d_%d' % (col, row))
             for col, identifier in enumerate(row_ids)
         ] for row, row_ids in enumerate(PAD_IDS)])
         device = DeviceComponent(
             is_enabled=False,
             layer=Layer(parameter_controls=encoders),
             device_selection_follows_track_selection=True)
         device.set_enabled(True)
         self.set_device_component(device)
         drums = DrumRackComponent(is_enabled=False, layer=Layer(pads=pads))
         drums.set_enabled(True)
         play_button = make_button(118, b'Play_Button', MIDI_CC_TYPE, 0)
         stop_button = make_button(117, b'Stop_Button', MIDI_CC_TYPE, 0)
         record_button = make_button(119, b'Record_Button', MIDI_CC_TYPE, 0)
         loop_button = make_button(114, b'Loop_Button', MIDI_CC_TYPE, 0)
         transport = TransportComponent(is_enabled=False,
                                        layer=Layer(
                                            play_button=play_button,
                                            stop_button=stop_button,
                                            record_button=record_button,
                                            loop_button=loop_button))
         transport.set_enabled(True)
Exemple #3
0
 def __init__(self, *a, **k):
     super(MPK225, self).__init__(*a, **k)
     with self.component_guard():
         midimap = MidiMap()
         drum_rack = DrumRackComponent(
             name='Drum_Rack',
             is_enabled=False,
             layer=Layer(pads=midimap['Drum_Pads']))
         drum_rack.set_enabled(True)
         transport = TransportComponent(
             name='Transport',
             is_enabled=False,
             layer=Layer(play_button=midimap['Play'],
                         record_button=midimap['Record'],
                         stop_button=midimap['Stop'],
                         seek_forward_button=midimap['Forward'],
                         seek_backward_button=midimap['Backward'],
                         loop_button=midimap['Loop']))
         transport.set_enabled(True)
         device = DeviceComponent(
             name='Device',
             is_enabled=False,
             layer=Layer(parameter_controls=midimap['Encoders']),
             device_selection_follows_track_selection=True)
         device.set_enabled(True)
         self.set_device_component(device)
Exemple #4
0
 def __init__(self, *a, **k):
     super(MPK225, self).__init__(*a, **k)
     with self.component_guard():
         midimap = MidiMap()
         drum_rack = DrumRackComponent(name="Drum_Rack", is_enabled=False, layer=Layer(pads=midimap["Drum_Pads"]))
         drum_rack.set_enabled(True)
         transport = TransportComponent(
             name="Transport",
             is_enabled=False,
             layer=Layer(
                 play_button=midimap["Play"],
                 record_button=midimap["Record"],
                 stop_button=midimap["Stop"],
                 seek_forward_button=midimap["Forward"],
                 seek_backward_button=midimap["Backward"],
                 loop_button=midimap["Loop"],
             ),
         )
         transport.set_enabled(True)
         device = DeviceComponent(
             name="Device", is_enabled=False, layer=Layer(parameter_controls=midimap["Encoders"])
         )
         device.set_enabled(True)
         self.set_device_component(device)
         self._device_selection_follows_track_selection = True
Exemple #5
0
 def __init__(self, *a, **k):
     super(MPK261, self).__init__(*a, **k)
     with self.component_guard():
         midimap = MidiMap()
         drum_rack = DrumRackComponent(
             name='Drum_Rack',
             is_enabled=False,
             layer=Layer(pads=midimap['Drum_Pads']))
         drum_rack.set_enabled(True)
         transport = TransportComponent(
             name='Transport',
             is_enabled=False,
             layer=Layer(play_button=midimap['Play'],
                         record_button=midimap['Record'],
                         stop_button=midimap['Stop'],
                         seek_forward_button=midimap['Forward'],
                         seek_backward_button=midimap['Backward'],
                         loop_button=midimap['Loop']))
         transport.set_enabled(True)
         mixer_size = len(midimap['Sliders'])
         mixer = MixerComponent(mixer_size,
                                name='Mixer',
                                is_enabled=False,
                                layer=Layer(
                                    volume_controls=midimap['Sliders'],
                                    pan_controls=midimap['Encoders'],
                                    arm_buttons=midimap['Arm_Buttons']))
         mixer.set_enabled(True)
 def __init__(self, *a, **k):
     super(Alesis_VI, self).__init__(*a, **k)
     with self.component_guard():
         midimap = MidiMap()
         transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=midimap['Play'], stop_button=midimap['Stop'], loop_button=midimap['Loop'], record_button=midimap['Record'], seek_forward_button=midimap['Forward'], seek_backward_button=midimap['Backward']))
         mixer_size = len(midimap['Volume_Encoders'])
         mixer = MixerComponent(mixer_size, name='Mixer', is_enabled=False, layer=Layer(volume_controls=midimap['Volume_Encoders']))
         transport.set_enabled(True)
         mixer.set_enabled(True)
Exemple #7
0
 def __init__(self, *a, **k):
     super(Alesis_VI, self).__init__(*a, **k)
     with self.component_guard():
         midimap = MidiMap()
         transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=midimap['Play'], stop_button=midimap['Stop'], loop_button=midimap['Loop'], record_button=midimap['Record'], seek_forward_button=midimap['Forward'], seek_backward_button=midimap['Backward']))
         mixer_size = len(midimap['Volume_Encoders'])
         mixer = MixerComponent(mixer_size, name='Mixer', is_enabled=False, layer=Layer(volume_controls=midimap['Volume_Encoders']))
         transport.set_enabled(True)
         mixer.set_enabled(True)
Exemple #8
0
 def __init__(self, *a, **k):
     super(MPK225, self).__init__(*a, **k)
     with self.component_guard():
         midimap = MidiMap()
         drum_rack = DrumRackComponent(name='Drum_Rack', is_enabled=False, layer=Layer(pads=midimap['Drum_Pads']))
         drum_rack.set_enabled(True)
         transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=midimap['Play'], record_button=midimap['Record'], stop_button=midimap['Stop'], seek_forward_button=midimap['Forward'], seek_backward_button=midimap['Backward'], loop_button=midimap['Loop']))
         transport.set_enabled(True)
         device = DeviceComponent(name='Device', is_enabled=False, layer=Layer(parameter_controls=midimap['Encoders']), device_selection_follows_track_selection=True)
         device.set_enabled(True)
         self.set_device_component(device)
class BeatStep(ArturiaControlSurface):

    def __init__(self, *a, **k):
        super(BeatStep, self).__init__(*a, **k)
        self._skin = Skin(Colors)
        with self.component_guard():
            self._create_controls()
            self._create_device()
            self._create_session()
            self._create_mixer()
            self._create_transport()

    def _create_controls(self):
        self._device_encoders = ButtonMatrixElement(rows=[ [ EncoderElement(MIDI_CC_TYPE, 0, identifier, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Encoder_%d_%d' % (column_index, row_index)) for column_index, identifier in enumerate(row) ] for row_index, row in enumerate((ENCODER_MSG_IDS[:4], ENCODER_MSG_IDS[8:12])) ])
        self._horizontal_scroll_encoder = EncoderElement(MIDI_CC_TYPE, 0, 75, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Horizontal_Scroll_Encoder')
        self._vertical_scroll_encoder = EncoderElement(MIDI_CC_TYPE, 0, 72, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Vertical_Scroll_Encoder')
        self._volume_encoder = EncoderElement(MIDI_CC_TYPE, 0, 91, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Volume_Encoder')
        self._pan_encoder = EncoderElement(MIDI_CC_TYPE, 0, 17, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Pan_Encoder')
        self._send_a_encoder = EncoderElement(MIDI_CC_TYPE, 0, 77, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Send_A_Encoder')
        self._send_b_encoder = EncoderElement(MIDI_CC_TYPE, 0, 93, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Send_B_Encoder')
        self._send_encoders = ButtonMatrixElement(rows=[[self._send_a_encoder, self._send_b_encoder]])
        self._return_a_encoder = EncoderElement(MIDI_CC_TYPE, 0, 73, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Return_A_Encoder')
        self._return_b_encoder = EncoderElement(MIDI_CC_TYPE, 0, 79, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Return_B_Encoder')
        self._return_encoders = ButtonMatrixElement(rows=[[self._return_a_encoder, self._return_b_encoder]])
        self._pads = ButtonMatrixElement(rows=[ [ ButtonElement(True, MIDI_NOTE_TYPE, PAD_CHANNEL, identifier, name='Pad_%d_%d' % (col_index, row_index), skin=self._skin) for col_index, identifier in enumerate(row) ] for row_index, row in enumerate(PAD_MSG_IDS) ])
        self._stop_button = ButtonElement(True, MIDI_CC_TYPE, 0, 1, name='Stop_Button')
        self._play_button = ButtonElement(True, MIDI_CC_TYPE, 0, 2, name='Play_Button')

    def _create_device(self):
        self._device = DeviceComponent(name='Device', is_enabled=False, layer=Layer(parameter_controls=self._device_encoders))
        self._device.set_enabled(True)
        self.set_device_component(self._device)
        self._device_selection_follows_track_selection = True

    def _create_session(self):
        self._session = SessionComponent(name='Session', is_enabled=False, num_tracks=self._pads.width(), num_scenes=self._pads.height(), enable_skinning=True, layer=Layer(clip_launch_buttons=self._pads, scene_select_control=self._vertical_scroll_encoder))
        self._session.set_enabled(True)

    def _create_mixer(self):
        self._mixer = MixerComponent(name='Mixer', is_enabled=False, num_returns=2, layer=Layer(track_select_encoder=self._horizontal_scroll_encoder, selected_track_volume_control=self._volume_encoder, selected_track_pan_control=self._pan_encoder, selected_track_send_controls=self._send_encoders, return_volume_controls=self._return_encoders))
        self._mixer.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(stop_button=self._stop_button, play_button=self._play_button))
        self._transport.set_enabled(True)

    def _collect_setup_messages(self):
        for identifier, hardware_id in izip(ENCODER_MSG_IDS, HARDWARE_ENCODER_IDS):
            self._setup_hardware_encoder(hardware_id, identifier)

        self._setup_hardware_button(HARDWARE_STOP_BUTTON_ID, 1, msg_type='cc')
        self._setup_hardware_button(HARDWARE_PLAY_BUTTON_ID, 2, msg_type='cc')
        for hardware_id, identifier in izip(HARDWARE_PAD_IDS, chain(*PAD_MSG_IDS)):
            self._setup_hardware_button(hardware_id, identifier, PAD_CHANNEL, msg_type='note')
 def __init__(self, *a, **k):
     super(MPK249, self).__init__(*a, **k)
     with self.component_guard():
         midimap = MidiMap()
         drum_rack = DrumRackComponent(name='Drum_Rack', is_enabled=False, layer=Layer(pads=midimap['Drum_Pads']))
         drum_rack.set_enabled(True)
         transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=midimap['Play'], record_button=midimap['Record'], stop_button=midimap['Stop'], seek_forward_button=midimap['Forward'], seek_backward_button=midimap['Backward'], loop_button=midimap['Loop']))
         transport.set_enabled(True)
         mixer_size = len(midimap['Sliders'])
         mixer = MixerComponent(mixer_size, name='Mixer', is_enabled=False, layer=Layer(volume_controls=midimap['Sliders'], pan_controls=midimap['Encoders'], arm_buttons=midimap['Arm_Buttons']))
         mixer.set_enabled(True)
Exemple #11
0
 def __init__(self, *a, **k):
     super(Advance, self).__init__(*a, **k)
     with self.component_guard():
         encoders = ButtonMatrixElement(rows=[[ make_encoder(index + 22, 'Encoder_%d' % index) for index in xrange(8) ]])
         pads = ButtonMatrixElement(rows=[ [ make_button(identifier, 'Pad_%d_%d' % (col, row)) for col, identifier in enumerate(row_ids) ] for row, row_ids in enumerate(PAD_IDS) ])
         device = DeviceComponent(is_enabled=False, layer=Layer(parameter_controls=encoders), device_selection_follows_track_selection=True)
         device.set_enabled(True)
         self.set_device_component(device)
         drums = DrumRackComponent(is_enabled=False, layer=Layer(pads=pads))
         drums.set_enabled(True)
         play_button = make_button(118, 'Play_Button', MIDI_CC_TYPE, 0)
         stop_button = make_button(117, 'Stop_Button', MIDI_CC_TYPE, 0)
         record_button = make_button(119, 'Record_Button', MIDI_CC_TYPE, 0)
         loop_button = make_button(114, 'Loop_Button', MIDI_CC_TYPE, 0)
         transport = TransportComponent(is_enabled=False, layer=Layer(play_button=play_button, stop_button=stop_button, record_button=record_button, loop_button=loop_button))
         transport.set_enabled(True)
Exemple #12
0
class KeyPad(ControlSurface):
    """
    Reloop KeyPad controller script.
    """
    _encoder_range = range(73, 81)
    _product_model_id = 101

    def __init__(self, c_instance):
        super(KeyPad, self).__init__(c_instance)
        with self.component_guard():
            self._create_controls()
            self._setup_mixer()
            self._setup_transport()
            self._setup_session()
            self._setup_cue_control()
            self.set_pad_translations(PAD_TRANSLATIONS)

    def _preset_message(self, send_byte):
        """ Sysex message for setting the preset to #2. """
        return (240, 38, self._product_model_id, send_byte, 17, 2, 247)

    def refresh_state(self):
        super(KeyPad, self).refresh_state()
        self.schedule_message(2, self._send_midi, self._preset_message(1))

    def handle_sysex(self, midi_bytes):
        if midi_bytes != self._preset_message(2):
            super(KeyPad, self).handle_sysex(midi_bytes)
        else:
            map(lambda x: x.set_enabled(True),
                (self._mixer, self._session, self._transport,
                 self._cue_control))

    def _create_controls(self):
        def make_controls_range(maker, label, cc_range):
            ccs = [(index + 1, cc) for index, cc in enumerate(cc_range)]
            return [maker(1, cc, label % index) for index, cc in ccs] + [
                maker(2, cc, label % (index + len(ccs))) for index, cc in ccs
            ]

        def make_controls(maker, label, cc_offset):
            return make_controls_range(maker, label,
                                       xrange(cc_offset, cc_offset + 8))

        make_non_momentary_button = partial(make_button, is_momentary=False)
        self._encoders = make_controls(make_encoder, 'Encoder_%d', 57)
        self._rotaries_a = make_controls(make_slider, 'Rotary_A%d', 89)
        self._rotaries_b = make_controls(make_slider, 'Rotary_B%d', 97)
        self._faders = make_controls(make_slider, 'Fader_%d', 0)
        self._mute_buttons = make_controls(make_non_momentary_button,
                                           'Mute_%d_Button', 8)
        self._solo_buttons = make_controls(make_button, 'Solo_%d_Button', 24)
        self._arm_buttons = make_controls(make_button, 'Arm_%d_Button', 40)
        self._play_button = make_button(1, 105, 'Play_Button')
        self._stop_button = make_button(1, 106, 'Stop_Button')
        self._record_button = make_button(1, 107, 'Record_Button')
        self._encoder_pushes = make_controls_range(
            partial(make_button, is_momentary=False), 'Encoder_%d_Button',
            self._encoder_range)
        self._shifted_mute_buttons = make_controls(make_non_momentary_button,
                                                   'Shifted_Mute_%d_Button',
                                                   16)
        self._shifted_solo_buttons = make_controls(make_button,
                                                   'Shifted_Solo_%d_Button',
                                                   32)
        self._all_shifted_arm_buttons = make_controls(make_button,
                                                      'Shifted_Arm_%d_Button',
                                                      49)
        self._shifted_arm_buttons = [
            CombinedButtonsElement(
                buttons=(self._all_shifted_arm_buttons[index],
                         self._all_shifted_arm_buttons[index + 8]))
            for index in xrange(8)
        ]
        self._shifted_play_button = make_button(1, 108, 'Shifted_Play_Button')
        self._shifted_stop_button = make_button(1, 109, 'Shifted_Stop_Button')
        self._shifted_record_button = make_button(1, 110,
                                                  'Shifted_Record_Button')
        self._shifted_octave_down_button = make_button(
            1, 111, 'Shifted_Octave_Down_Button')
        self._shifted_octave_up_button = make_button(
            1, 112, 'Shifted_Octave_Up_Button')

    def _setup_mixer(self):
        self._mixer = MixerComponent(NUM_CHANNEL_STRIPS)
        self._mixer.name = 'Mixer'
        self._mixer.set_enabled(False)
        for index in xrange(NUM_CHANNEL_STRIPS):
            strip = self._mixer.channel_strip(index)
            strip.set_invert_mute_feedback(True)
            sends = ButtonMatrixElement(name='%d_Send_Controls' % (index + 1),
                                        rows=[(self._rotaries_a[index],
                                               self._rotaries_b[index])])
            strip.layer = Layer(volume_control=self._faders[index],
                                pan_control=self._encoders[index],
                                send_controls=sends,
                                mute_button=self._mute_buttons[index],
                                solo_button=self._solo_buttons[index],
                                arm_button=self._arm_buttons[index],
                                select_button=self._encoder_pushes[index])

    def _setup_transport(self):
        self._transport = TransportComponent(name='Transport')
        self._transport.set_enabled(False)
        self._transport.layer = Layer(
            play_button=self._play_button,
            stop_button=self._stop_button,
            record_button=self._record_button,
            overdub_button=self._shifted_record_button,
            loop_button=self._shifted_arm_buttons[3],
            tap_tempo_button=self._shifted_arm_buttons[4],
            metronome_button=self._shifted_arm_buttons[5],
            nudge_down_button=self._shifted_arm_buttons[6],
            nudge_up_button=self._shifted_arm_buttons[7])

    def _setup_session(self):
        self._session = SessionComponent(NUM_CHANNEL_STRIPS,
                                         name='Session_Control')
        self._session.set_enabled(False)
        stop_buttons = ButtonMatrixElement(name='Track_Stop_Buttons',
                                           rows=[self._shifted_solo_buttons])
        self._session.layer = Layer(
            stop_all_clips_button=self._shifted_stop_button,
            stop_track_clip_buttons=stop_buttons,
            select_prev_button=self._shifted_octave_down_button,
            select_next_button=self._shifted_octave_up_button)
        self._session.selected_scene().name = 'Selected_Scene_Control'
        self._session.selected_scene().layer = Layer(
            launch_button=self._shifted_play_button)
        for index in xrange(NUM_CHANNEL_STRIPS):
            slot = self._session.selected_scene().clip_slot(index)
            slot.layer = Layer(launch_button=self._shifted_mute_buttons[index])

    def _setup_cue_control(self):
        self._cue_control = CuePointControlComponent(name='Cue_Point_Control')
        self._cue_control.set_enabled(False)
        self._cue_control.layer = Layer(
            toggle_cue_button=self._shifted_arm_buttons[0],
            prev_cue_button=self._shifted_arm_buttons[1],
            next_cue_button=self._shifted_arm_buttons[2])
class KeyLab(ArturiaControlSurface):

    def __init__(self, *a, **k):
        super(KeyLab, self).__init__(*a, **k)
        with self.component_guard():
            self._create_controls()
            self._create_display()
            self._create_device()
            self._create_drums()
            self._create_transport()
            self._create_session()
            self._create_session_recording()
            self._create_mixer()

    def _create_controls(self):
        self._device_encoders = ButtonMatrixElement(rows=[ [ EncoderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, identifier, Live.MidiMap.MapMode.relative_smooth_binary_offset, name='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='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='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, '_' + button_name, make_keylab_button(button_name))

        self._pads = ButtonMatrixElement(rows=[ [ ButtonElement(True, MIDI_CC_TYPE, PAD_CHANNEL, col_index + row_offset, name='Pad_%d_%d' % (col_index, row_index)) for col_index in xrange(4) ] for row_index, row_offset in enumerate(xrange(48, 35, -4)) ])

    def _create_display(self):
        self._display_line1, self._display_line2 = DisplayElement(16, 1), DisplayElement(16, 1)
        for index, display_line in enumerate((self._display_line1, self._display_line2)):
            display_line.set_message_parts(SETUP_MSG_PREFIX + (4, 0, 96), SETUP_MSG_SUFFIX)
            display_line.segment(0).set_position_identifier((index + 1,))

        def adjust_null_terminated_string(string, width):
            return string.ljust(width, ' ') + '\x00'

        self._display_line1_data_source, self._display_line2_data_source = DisplayDataSource(adjust_string_fn=adjust_null_terminated_string), DisplayDataSource(adjust_string_fn=adjust_null_terminated_string)
        self._display_line1.segment(0).set_data_source(self._display_line1_data_source)
        self._display_line2.segment(0).set_data_source(self._display_line2_data_source)
        self._display_line1_data_source.set_display_string('KeyLab')
        self._display_line2_data_source.set_display_string('Ableton Live')

    def _create_device(self):
        self._device = DeviceComponent(name='Device', is_enabled=False, layer=Layer(parameter_controls=self._device_encoders))
        self._device.set_enabled(True)
        self.set_device_component(self._device)
        self._device_selection_follows_track_selection = True
        self._device_navigation = DeviceNavigationComponent(name='Device_Navigation', is_enabled=False, layer=Layer(device_nav_left_button=self._device_left_button, device_nav_right_button=self._device_right_button))
        self._device_navigation.set_enabled(True)

    def _create_drums(self):
        self._drums = DrumRackComponent(name='Drums', is_enabled=False, layer=Layer(pads=self._pads))
        self._drums.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=self._play_button, stop_button=self._stop_button, record_button=self._record_button, loop_button=self._loop_button))
        self._transport.set_enabled(True)

    def _create_session(self):
        self._session = SessionComponent(num_tracks=8, num_scenes=1, name='Session', is_enabled=False, layer=Layer(select_next_button=self._scene_down_button, select_prev_button=self._scene_up_button, selected_scene_launch_button=self._scene_launch_button, stop_all_clips_button=self._stop_all_clips_button, scene_select_encoder=self._vertical_scroll_encoder))
        self._session.set_enabled(True)

    def _create_session_recording(self):
        self._session_recording = SessionRecordingComponent(ClipCreator(), ViewControlComponent(), name='Session_Recording', is_enabled=False, layer=Layer(record_button=self._session_record_button))
        self._session_recording.set_enabled(True)

    def _create_mixer(self):
        self._mixer = MixerComponent(num_tracks=self._volume_sliders.width(), name='Mixer', is_enabled=False, layer=Layer(volume_controls=self._volume_sliders, track_select_encoder=self._horizontal_scroll_encoder))
        self._mixer.master_strip().layer = Layer(volume_control=self._master_slider)
        self._mixer.set_enabled(True)

    def _collect_setup_messages(self):
        for hardware_id, identifier in izip(ENCODER_HARDWARE_IDS, ENCODER_MSG_IDS):
            self._setup_hardware_encoder(hardware_id, identifier, ENCODER_CHANNEL)

        for hardware_id, identifier in izip(SLIDER_HARDWARE_IDS, SLIDER_MSG_IDS):
            self._setup_hardware_slider(hardware_id, identifier, ENCODER_CHANNEL)

        for hardware_id, identifier in BUTTON_HARDWARE_AND_MESSAGE_IDS.itervalues():
            self._setup_hardware_button(hardware_id, identifier)

        for hardware_id, identifier in izip(PAD_HARDWARE_IDS, PAD_MSG_IDS):
            self._setup_hardware_pad(hardware_id, identifier)

    def _setup_hardware_encoder(self, hardware_id, identifier, channel = 0):
        self._set_encoder_cc_msg_type(hardware_id, is_relative=True)
        self._set_identifier(hardware_id, identifier)
        self._set_channel(hardware_id, channel)

    def _setup_hardware_button(self, hardware_id, identifier, channel = 0, **k):
        self._set_encoder_cc_msg_type(hardware_id)
        self._set_identifier(hardware_id, identifier)
        self._set_channel(hardware_id, channel)
        self._set_value_minimum(hardware_id)
        self._set_value_maximum(hardware_id)

    def _setup_hardware_pad(self, hardware_id, identifier, channel = PAD_CHANNEL):
        self._set_pad_note_msg_type(hardware_id)
        self._set_identifier(hardware_id, identifier)
        self._set_channel(hardware_id, channel)

    def _set_pad_note_msg_type(self, hardware_id):
        self._collect_setup_message(MODE_PROPERTY, hardware_id, PAD_NOTE_MODE)
Exemple #14
0
class KeyPad(ControlSurface):
    """
    Reloop KeyPad controller script.
    """
    _encoder_range = range(73, 81)
    _product_model_id = 101

    def __init__(self, c_instance):
        super(KeyPad, self).__init__(c_instance)
        with self.component_guard():
            self._create_controls()
            self._setup_mixer()
            self._setup_transport()
            self._setup_session()
            self._setup_cue_control()
            self.set_pad_translations(PAD_TRANSLATIONS)

    def _preset_message(self, send_byte):
        """ Sysex message for setting the preset to #2. """
        return (240,
         38,
         self._product_model_id,
         send_byte,
         17,
         2,
         247)

    def refresh_state(self):
        super(KeyPad, self).refresh_state()
        self.schedule_message(2, self._send_midi, self._preset_message(1))

    def handle_sysex(self, midi_bytes):
        if midi_bytes != self._preset_message(2):
            super(KeyPad, self).handle_sysex(midi_bytes)
        else:
            map(lambda x: x.set_enabled(True), (self._mixer,
             self._session,
             self._transport,
             self._cue_control))

    def _create_controls(self):

        def make_controls_range(maker, label, cc_range):
            ccs = [ (index + 1, cc) for index, cc in enumerate(cc_range) ]
            return [ maker(1, cc, label % index) for index, cc in ccs ] + [ maker(2, cc, label % (index + len(ccs))) for index, cc in ccs ]

        def make_controls(maker, label, cc_offset):
            return make_controls_range(maker, label, xrange(cc_offset, cc_offset + 8))

        make_non_momentary_button = partial(make_button, is_momentary=False)
        self._encoders = make_controls(make_encoder, 'Encoder_%d', 57)
        self._rotaries_a = make_controls(make_slider, 'Rotary_A%d', 89)
        self._rotaries_b = make_controls(make_slider, 'Rotary_B%d', 97)
        self._faders = make_controls(make_slider, 'Fader_%d', 0)
        self._mute_buttons = make_controls(make_non_momentary_button, 'Mute_%d_Button', 8)
        self._solo_buttons = make_controls(make_button, 'Solo_%d_Button', 24)
        self._arm_buttons = make_controls(make_button, 'Arm_%d_Button', 40)
        self._play_button = make_button(1, 105, 'Play_Button')
        self._stop_button = make_button(1, 106, 'Stop_Button')
        self._record_button = make_button(1, 107, 'Record_Button')
        self._encoder_pushes = make_controls_range(partial(make_button, is_momentary=False), 'Encoder_%d_Button', self._encoder_range)
        self._shifted_mute_buttons = make_controls(make_non_momentary_button, 'Shifted_Mute_%d_Button', 16)
        self._shifted_solo_buttons = make_controls(make_button, 'Shifted_Solo_%d_Button', 32)
        self._all_shifted_arm_buttons = make_controls(make_button, 'Shifted_Arm_%d_Button', 49)
        self._shifted_arm_buttons = [ CombinedButtonsElement(buttons=(self._all_shifted_arm_buttons[index], self._all_shifted_arm_buttons[index + 8])) for index in xrange(8) ]
        self._shifted_play_button = make_button(1, 108, 'Shifted_Play_Button')
        self._shifted_stop_button = make_button(1, 109, 'Shifted_Stop_Button')
        self._shifted_record_button = make_button(1, 110, 'Shifted_Record_Button')
        self._shifted_octave_down_button = make_button(1, 111, 'Shifted_Octave_Down_Button')
        self._shifted_octave_up_button = make_button(1, 112, 'Shifted_Octave_Up_Button')

    def _setup_mixer(self):
        self._mixer = MixerComponent(NUM_CHANNEL_STRIPS)
        self._mixer.name = 'Mixer'
        self._mixer.set_enabled(False)
        for index in xrange(NUM_CHANNEL_STRIPS):
            strip = self._mixer.channel_strip(index)
            strip.set_invert_mute_feedback(True)
            sends = ButtonMatrixElement(name='%d_Send_Controls' % (index + 1), rows=[(self._rotaries_a[index], self._rotaries_b[index])])
            strip.layer = Layer(volume_control=self._faders[index], pan_control=self._encoders[index], send_controls=sends, mute_button=self._mute_buttons[index], solo_button=self._solo_buttons[index], arm_button=self._arm_buttons[index], select_button=self._encoder_pushes[index])

    def _setup_transport(self):
        self._transport = TransportComponent(name='Transport')
        self._transport.set_enabled(False)
        self._transport.layer = Layer(play_button=self._play_button, stop_button=self._stop_button, record_button=self._record_button, overdub_button=self._shifted_record_button, loop_button=self._shifted_arm_buttons[3], tap_tempo_button=self._shifted_arm_buttons[4], metronome_button=self._shifted_arm_buttons[5], nudge_down_button=self._shifted_arm_buttons[6], nudge_up_button=self._shifted_arm_buttons[7])

    def _setup_session(self):
        self._session = SessionComponent(NUM_CHANNEL_STRIPS, name='Session_Control')
        self._session.set_enabled(False)
        stop_buttons = ButtonMatrixElement(name='Track_Stop_Buttons', rows=[self._shifted_solo_buttons])
        self._session.layer = Layer(stop_all_clips_button=self._shifted_stop_button, stop_track_clip_buttons=stop_buttons, select_prev_button=self._shifted_octave_down_button, select_next_button=self._shifted_octave_up_button)
        self._session.selected_scene().name = 'Selected_Scene_Control'
        self._session.selected_scene().layer = Layer(launch_button=self._shifted_play_button)
        for index in xrange(NUM_CHANNEL_STRIPS):
            slot = self._session.selected_scene().clip_slot(index)
            slot.layer = Layer(launch_button=self._shifted_mute_buttons[index])

    def _setup_cue_control(self):
        self._cue_control = CuePointControlComponent(name='Cue_Point_Control')
        self._cue_control.set_enabled(False)
        self._cue_control.layer = Layer(toggle_cue_button=self._shifted_arm_buttons[0], prev_cue_button=self._shifted_arm_buttons[1], next_cue_button=self._shifted_arm_buttons[2])
Exemple #15
0
    def __init__(self, *a, **k):
        super(MPK261MX, self).__init__(*a, **k)
        self.show_message(
            "-----------------------= MPK261MX LOADING - maxcloutier13 says hi =----------------------------------------------------------"
        )
        self.log_message(
            "-----------------------= MPK261MX LOADING - maxcloutier13 says hi =----------------------------------------------------------"
        )
        with self.component_guard():
            midimap = MidiMap()
            #Super crude manual init for the custom buttons and faders
            #Bank A - Channel 1 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            self._Encoder0 = EncoderElement(
                MIDI_CC_TYPE,
                1,
                22,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder0')
            self._Encoder1 = EncoderElement(
                MIDI_CC_TYPE,
                1,
                23,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder1')
            self._Encoder2 = EncoderElement(
                MIDI_CC_TYPE,
                1,
                24,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder2')
            self._Encoder3 = EncoderElement(
                MIDI_CC_TYPE,
                1,
                25,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder3')
            self._Encoder4 = EncoderElement(
                MIDI_CC_TYPE,
                1,
                26,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder4')
            self._Encoder5 = EncoderElement(
                MIDI_CC_TYPE,
                1,
                27,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder5')
            self._Encoder6 = EncoderElement(
                MIDI_CC_TYPE,
                1,
                28,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder6')
            self._Encoder7 = EncoderElement(
                MIDI_CC_TYPE,
                1,
                29,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder7')
            self._ArmButton0 = ButtonElement(False,
                                             MIDI_CC_TYPE,
                                             0,
                                             32,
                                             name='ArmButton0')
            self._ArmButton1 = ButtonElement(False,
                                             MIDI_CC_TYPE,
                                             0,
                                             33,
                                             name='ArmButton1')
            self._ArmButton2 = ButtonElement(False,
                                             MIDI_CC_TYPE,
                                             0,
                                             34,
                                             name='ArmButton2')
            self._ArmButton3 = ButtonElement(False,
                                             MIDI_CC_TYPE,
                                             0,
                                             35,
                                             name='ArmButton3')
            self._ArmButton4 = ButtonElement(False,
                                             MIDI_CC_TYPE,
                                             0,
                                             36,
                                             name='ArmButton4')
            self._ArmButton5 = ButtonElement(False,
                                             MIDI_CC_TYPE,
                                             0,
                                             37,
                                             name='ArmButton5')
            self._ArmButton6 = ButtonElement(False,
                                             MIDI_CC_TYPE,
                                             0,
                                             38,
                                             name='ArmButton6')
            self._ArmButton7 = ButtonElement(False,
                                             MIDI_CC_TYPE,
                                             0,
                                             39,
                                             name='ArmButton7')
            self._VolumeSlider0 = SliderElement(MIDI_CC_TYPE,
                                                0,
                                                12,
                                                name='VolumeSlider0')
            self._VolumeSlider1 = SliderElement(MIDI_CC_TYPE,
                                                0,
                                                13,
                                                name='VolumeSlider1')
            self._VolumeSlider2 = SliderElement(MIDI_CC_TYPE,
                                                0,
                                                14,
                                                name='VolumeSlider2')
            self._VolumeSlider3 = SliderElement(MIDI_CC_TYPE,
                                                0,
                                                15,
                                                name='VolumeSlider3')
            self._VolumeSlider4 = SliderElement(MIDI_CC_TYPE,
                                                0,
                                                16,
                                                name='VolumeSlider4')
            self._VolumeSlider5 = SliderElement(MIDI_CC_TYPE,
                                                0,
                                                17,
                                                name='VolumeSlider5')
            self._VolumeSlider6 = SliderElement(MIDI_CC_TYPE,
                                                0,
                                                18,
                                                name='VolumeSlider6')
            self._VolumeSlider7 = SliderElement(MIDI_CC_TYPE,
                                                0,
                                                19,
                                                name='VolumeSlider7')
            #Bank B - Channel 2 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            self._Encoder8 = EncoderElement(
                MIDI_CC_TYPE,
                2,
                22,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder8')
            self._Encoder9 = EncoderElement(
                MIDI_CC_TYPE,
                2,
                23,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder9')
            self._Encoder10 = EncoderElement(
                MIDI_CC_TYPE,
                2,
                24,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder10')
            self._Encoder11 = EncoderElement(
                MIDI_CC_TYPE,
                2,
                25,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder11')
            self._Encoder12 = EncoderElement(
                MIDI_CC_TYPE,
                2,
                26,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder12')
            self._Encoder13 = EncoderElement(
                MIDI_CC_TYPE,
                2,
                27,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder13')
            self._Encoder14 = EncoderElement(
                MIDI_CC_TYPE,
                2,
                28,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder14')
            self._Encoder15 = EncoderElement(
                MIDI_CC_TYPE,
                2,
                29,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder15')
            self._ArmButton8 = ButtonElement(False,
                                             MIDI_CC_TYPE,
                                             1,
                                             32,
                                             name='ArmButton8')
            self._ArmButton9 = ButtonElement(False,
                                             MIDI_CC_TYPE,
                                             1,
                                             33,
                                             name='ArmButton9')
            self._ArmButton10 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              1,
                                              34,
                                              name='ArmButton10')
            self._ArmButton11 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              1,
                                              35,
                                              name='ArmButton11')
            self._ArmButton12 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              1,
                                              36,
                                              name='ArmButton12')
            self._ArmButton13 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              1,
                                              37,
                                              name='ArmButton13')
            self._ArmButton14 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              1,
                                              38,
                                              name='ArmButton14')
            self._ArmButton15 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              1,
                                              39,
                                              name='ArmButton15')
            self._VolumeSlider8 = SliderElement(MIDI_CC_TYPE,
                                                1,
                                                12,
                                                name='VolumeSlider8')
            self._VolumeSlider9 = SliderElement(MIDI_CC_TYPE,
                                                1,
                                                13,
                                                name='VolumeSlider9')
            self._VolumeSlider10 = SliderElement(MIDI_CC_TYPE,
                                                 1,
                                                 14,
                                                 name='VolumeSlider10')
            self._VolumeSlider11 = SliderElement(MIDI_CC_TYPE,
                                                 1,
                                                 15,
                                                 name='VolumeSlider11')
            self._VolumeSlider12 = SliderElement(MIDI_CC_TYPE,
                                                 1,
                                                 16,
                                                 name='VolumeSlider12')
            self._VolumeSlider13 = SliderElement(MIDI_CC_TYPE,
                                                 1,
                                                 17,
                                                 name='VolumeSlider13')
            self._VolumeSlider14 = SliderElement(MIDI_CC_TYPE,
                                                 1,
                                                 18,
                                                 name='VolumeSlider14')
            self._VolumeSlider15 = SliderElement(MIDI_CC_TYPE,
                                                 1,
                                                 19,
                                                 name='VolumeSlider15')
            #Bank C - Channel 3 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            self._Encoder16 = EncoderElement(
                MIDI_CC_TYPE,
                3,
                22,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder16')
            self._Encoder17 = EncoderElement(
                MIDI_CC_TYPE,
                3,
                23,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder17')
            self._Encoder18 = EncoderElement(
                MIDI_CC_TYPE,
                3,
                24,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder18')
            self._Encoder19 = EncoderElement(
                MIDI_CC_TYPE,
                3,
                25,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder19')
            self._Encoder20 = EncoderElement(
                MIDI_CC_TYPE,
                3,
                26,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder20')
            self._Encoder21 = EncoderElement(
                MIDI_CC_TYPE,
                3,
                27,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder21')
            self._Encoder22 = EncoderElement(
                MIDI_CC_TYPE,
                3,
                28,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder22')
            self._Encoder23 = EncoderElement(
                MIDI_CC_TYPE,
                3,
                29,
                Live.MidiMap.MapMode.relative_two_compliment,
                name='Encoder23')
            self._ArmButton16 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              2,
                                              32,
                                              name='ArmButton16')
            self._ArmButton17 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              2,
                                              33,
                                              name='ArmButton17')
            self._ArmButton18 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              2,
                                              34,
                                              name='ArmButton18')
            self._ArmButton19 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              2,
                                              35,
                                              name='ArmButton19')
            self._ArmButton20 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              2,
                                              36,
                                              name='ArmButton20')
            self._ArmButton21 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              2,
                                              37,
                                              name='ArmButton21')
            self._ArmButton22 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              2,
                                              38,
                                              name='ArmButton22')
            self._ArmButton23 = ButtonElement(False,
                                              MIDI_CC_TYPE,
                                              2,
                                              39,
                                              name='ArmButton23')
            self._VolumeSlider16 = SliderElement(MIDI_CC_TYPE,
                                                 2,
                                                 12,
                                                 name='VolumeSlider16')
            self._VolumeSlider17 = SliderElement(MIDI_CC_TYPE,
                                                 2,
                                                 13,
                                                 name='VolumeSlider17')
            self._VolumeSlider18 = SliderElement(MIDI_CC_TYPE,
                                                 2,
                                                 14,
                                                 name='VolumeSlider18')
            self._VolumeSlider19 = SliderElement(MIDI_CC_TYPE,
                                                 2,
                                                 15,
                                                 name='VolumeSlider19')
            self._VolumeSlider20 = SliderElement(MIDI_CC_TYPE,
                                                 2,
                                                 16,
                                                 name='VolumeSlider20')
            self._VolumeSlider21 = SliderElement(MIDI_CC_TYPE,
                                                 2,
                                                 17,
                                                 name='VolumeSlider21')
            self._VolumeSlider22 = SliderElement(MIDI_CC_TYPE,
                                                 2,
                                                 18,
                                                 name='VolumeSlider22')
            self._VolumeSlider23 = SliderElement(MIDI_CC_TYPE,
                                                 2,
                                                 19,
                                                 name='VolumeSlider23')
            #Drum rack -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            drum_rack = DrumRackComponent(
                name='Drum_Rack',
                is_enabled=False,
                layer=Layer(pads=midimap['Drum_Pads']))
            drum_rack.set_enabled(True)
            #Transport -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            transport = TransportComponent(name='Transport',
                                           is_enabled=False,
                                           layer=Layer(
                                               play_button=midimap['Play'],
                                               record_button=midimap['Record'],
                                               stop_button=midimap['Stop'],
                                               loop_button=midimap['Loop']))
            #, seek_forward_button=midimap['Forward'], seek_backward_button=midimap['Backward']
            transport.set_enabled(True)
            #Make the Back/Fwd button just normal mapable CC senders
            self._BackButton = ButtonElement(False,
                                             MIDI_CC_TYPE,
                                             0,
                                             116,
                                             name='BackButton')
            self._FwdButton = ButtonElement(False,
                                            MIDI_CC_TYPE,
                                            0,
                                            115,
                                            name='FwdButton')
            #Device -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            self._device = DeviceComponent(
                name='Device',
                is_enabled=False,
                layer=Layer(parameter_controls=midimap['Encoders']),
                device_selection_follows_track_selection=True)
            self._device.set_enabled(True)
            self.set_device_component(self._device)
            #Mixer -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            mixer_size = 24
            self._mixer = MixerComponent(mixer_size,
                                         name='Mixer',
                                         is_enabled=False)
            #Super crude and repetitive mapping because after all this shit I'm not spending time learning how to loop this crap hehe
            #Bank A
            self._mixer.channel_strip(0).layer = Layer(
                volume_control=self._VolumeSlider0,
                arm_button=self._ArmButton0,
                pan_control=self._Encoder0)
            self._mixer.channel_strip(1).layer = Layer(
                volume_control=self._VolumeSlider1,
                arm_button=self._ArmButton1,
                pan_control=self._Encoder1)
            self._mixer.channel_strip(2).layer = Layer(
                volume_control=self._VolumeSlider2,
                arm_button=self._ArmButton2,
                pan_control=self._Encoder2)
            self._mixer.channel_strip(3).layer = Layer(
                volume_control=self._VolumeSlider3,
                arm_button=self._ArmButton3,
                pan_control=self._Encoder3)
            self._mixer.channel_strip(4).layer = Layer(
                volume_control=self._VolumeSlider4,
                arm_button=self._ArmButton4,
                pan_control=self._Encoder4)
            self._mixer.channel_strip(5).layer = Layer(
                volume_control=self._VolumeSlider5,
                arm_button=self._ArmButton5,
                pan_control=self._Encoder5)
            self._mixer.channel_strip(6).layer = Layer(
                volume_control=self._VolumeSlider6,
                arm_button=self._ArmButton6,
                pan_control=self._Encoder6)
            self._mixer.channel_strip(7).layer = Layer(
                volume_control=self._VolumeSlider7,
                arm_button=self._ArmButton7,
                pan_control=self._Encoder7)
            #Bank B
            self._mixer.channel_strip(8).layer = Layer(
                volume_control=self._VolumeSlider8,
                arm_button=self._ArmButton8,
                pan_control=self._Encoder8)
            self._mixer.channel_strip(9).layer = Layer(
                volume_control=self._VolumeSlider9,
                arm_button=self._ArmButton9,
                pan_control=self._Encoder9)
            self._mixer.channel_strip(10).layer = Layer(
                volume_control=self._VolumeSlider10,
                arm_button=self._ArmButton10,
                pan_control=self._Encoder10)
            self._mixer.channel_strip(11).layer = Layer(
                volume_control=self._VolumeSlider11,
                arm_button=self._ArmButton11,
                pan_control=self._Encoder11)
            self._mixer.channel_strip(12).layer = Layer(
                volume_control=self._VolumeSlider12,
                arm_button=self._ArmButton12,
                pan_control=self._Encoder12)
            self._mixer.channel_strip(13).layer = Layer(
                volume_control=self._VolumeSlider13,
                arm_button=self._ArmButton13,
                pan_control=self._Encoder13)
            self._mixer.channel_strip(14).layer = Layer(
                volume_control=self._VolumeSlider14,
                arm_button=self._ArmButton14,
                pan_control=self._Encoder14)
            self._mixer.channel_strip(15).layer = Layer(
                volume_control=self._VolumeSlider15,
                arm_button=self._ArmButton15,
                pan_control=self._Encoder15)
            #Bank C
            self._mixer.channel_strip(16).layer = Layer(
                volume_control=self._VolumeSlider16,
                arm_button=self._ArmButton16,
                pan_control=self._Encoder16)
            self._mixer.channel_strip(17).layer = Layer(
                volume_control=self._VolumeSlider17,
                arm_button=self._ArmButton17,
                pan_control=self._Encoder17)
            self._mixer.channel_strip(18).layer = Layer(
                volume_control=self._VolumeSlider18,
                arm_button=self._ArmButton18,
                pan_control=self._Encoder18)
            self._mixer.channel_strip(19).layer = Layer(
                volume_control=self._VolumeSlider19,
                arm_button=self._ArmButton19,
                pan_control=self._Encoder19)
            self._mixer.channel_strip(20).layer = Layer(
                volume_control=self._VolumeSlider20,
                arm_button=self._ArmButton20,
                pan_control=self._Encoder20)
            self._mixer.channel_strip(21).layer = Layer(
                volume_control=self._VolumeSlider21,
                arm_button=self._ArmButton21,
                pan_control=self._Encoder21)
            self._mixer.channel_strip(22).layer = Layer(
                volume_control=self._VolumeSlider22,
                arm_button=self._ArmButton22,
                pan_control=self._Encoder22)
            self._mixer.channel_strip(23).layer = Layer(
                volume_control=self._VolumeSlider23,
                arm_button=self._ArmButton23,
                pan_control=self._Encoder23)
            self._mixer.set_enabled(True)


#-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class OhmModes(ControlSurface):
	__module__ = __name__
	__doc__ = ' OhmModes controller script '

	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		with self.component_guard():
			self._version_check = 'b994'
			self._host_name = 'Ohm'
			self._color_type = 'OhmRGB'
			self._hosts = []
			self.hosts = []
			self._client = [ None for index in range(6) ]
			self._active_client = None
			self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< OhmModes ' + str(self._version_check) + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>')
			self._rgb = 0
			self._timer = 0
			self._touched = 0
			self.flash_status = 1
			self._backlight = 127
			self._backlight_type = 'static'
			self._ohm = 127
			self._ohm_type = 'static'
			self._pad_translations = PAD_TRANSLATION
			self._device_selection_follows_track_selection = FOLLOW
			self._keys_octave = 5
			self._keys_scale = 0
			self._tempo_buttons = None
			self._setup_monobridge()
			self._setup_controls()
			self._setup_transport_control()
			self._setup_mixer_control()
			self._setup_session_control()
			self._setup_device_control()
			self._setup_crossfader()
			self._setup_ohmmod()
			self._setup_switchboard()
			self._setup_modes()
			self._assign_page_constants()
			self._last_device = None
			self.song().view.add_selected_track_listener(self._update_selected_device)
			self.show_message('OhmModes Control Surface Loaded')
			self._send_midi(tuple(switchxfader))
			if FORCE_TYPE is True:
				self._rgb = FORCE_COLOR_TYPE
			else:
				self.schedule_message(10, self.query_ohm, None)
			self.log_message(str(self._highlighting_session_component))

	def query_ohm(self):
		self._send_midi(tuple(check_model))

	def update_display(self):
		ControlSurface.update_display(self)
		self._timer = (self._timer + 1) % 256
		self.flash()
		self.strobe()

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

	def get_device_bank(self):
		return self._device._bank_index

	def _setup_controls(self):
		is_momentary = True
		self._fader = [ None for index in range(8) ]
		self._dial = [ None for index in range(16) ]
		self._button = [ None for index in range(8) ]
		self._menu = [ None for index in range(6) ]
		for index in range(8):
			self._fader[index] = MonoEncoderElement2(MIDI_CC_TYPE, CHANNEL, OHM_FADERS[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self)

		for index in range(8):
			self._button[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_' + str(index), self)

		for index in range(16):
			self._dial[index] = CodecEncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_DIALS[index], Live.MidiMap.MapMode.absolute, 'Encoder_' + str(index), index, self)

		self._knobs = []
		for index in range(12):
			self._knobs.append(self._dial[index])

		for index in range(6):
			self._menu[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_MENU[index], 'Menu_' + str(index), self)

		self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute)
		self._crossfader.name = 'Crossfader'
		self._livid = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self)
		self._shift_l = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Page_Button_Left', self)
		self._shift_r = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Page_Button_Right', self)
		self._matrix = ButtonMatrixElement()
		self._matrix.name = 'Matrix'
		self._grid = [ None for index in range(8) ]
		self._monomod = ButtonMatrixElement()
		self._monomod.name = 'Monomod'
		for column in range(8):
			self._grid[column] = [ None for index in range(8) ]
			for row in range(8):
				self._grid[column][row] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, column * 8 + row, 'Grid_' + str(column) + '_' + str(row), self)

		for row in range(5):
			button_row = []
			for column in range(7):
				button_row.append(self._grid[column][row])

			self._matrix.add_row(tuple(button_row))

		for row in range(8):
			button_row = []
			for column in range(8):
				button_row.append(self._grid[column][row])

			self._monomod.add_row(tuple(button_row))

		self._mod_matrix = ButtonMatrixElement()
		self._mod_matrix.name = 'Matrix'
		self._dial_matrix = EncoderMatrixElement(self)
		self._dial_matrix.name = 'Dial_Matrix'
		self._dial_button_matrix = ButtonMatrixElement()
		self._dial_button_matrix.name = 'Dial_Button_Matrix'
		for row in range(4):
			button_row = []
			for column in range(4):
				button_row.append(self._grid[column + 4][row])

			self._mod_matrix.add_row(tuple(button_row))

		for row in range(3):
			dial_row = []
			for column in range(4):
				dial_row.append(self._dial[row * 4 + column])

			self._dial_matrix.add_row(tuple(dial_row))

		for row in range(3):
			dial_button_row = []
			for column in range(4):
				dial_button_row.append(self._grid[column][row])

			self._dial_button_matrix.add_row(tuple(dial_button_row))

		self._key = [ self._grid[KEYS[index][1]][KEYS[index][0]] for index in range(32) ]
		self._encoder = [ self._dial[index] for index in range(12) ]
		self._key_matrix = ButtonMatrixElement()
		button_row = []
		for column in range(16):
			button_row.append(self._key[16 + column])

		self._key_matrix.add_row(tuple(button_row))

	def _setup_ohmmod(self):
		self._host = MonomodComponent(self)
		self._host.name = 'Monomod_Host'
		self.hosts = [self._host]
		self._hosts = [self._host]
		for index in range(6):
			self._client[index] = MonoClient(self, index)
			self._client[index].name = 'Client_' + str(index)
			self._client[index]._device_component.set_parameter_controls(tuple([ self._dial[num] for num in range(12) ]))
			self._client[index]._control_defs = {'dials': self._dial_matrix,
			 'buttons': self._dial_button_matrix,
			 'grid': self._mod_matrix,
			 'keys': self._key,
			 'knobs': [ self._dial[num + 12] for num in range(4) ]}

		self._host._active_client = self._client[0]
		self._host._active_client._is_active = True
		self._host.connect_to_clients(self)

	def _setup_switchboard(self):
		self._switchboard = SwitchboardElement(self, self._client)
		self._switchboard.name = 'Switchboard'

	def _setup_modes(self):
		self._shift_mode = ShiftModeComponent(self)
		self._shift_mode.name = 'Shift_Mode'
		self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r, self._livid)
		self._scale_mode = ScaleModeComponent(self)
		self._scale_mode.name = 'Scale_Mode'
		self._octave_mode = OctaveModeComponent(self)
		self._octave_mode.name = 'Octave_Mode'
		self._modNum = ModNumModeComponent(self, self.modNum_update)
		self._modNum.name = 'Mod_Number'
		self._modNum.set_mode = self._modNum_set_mode(self._modNum)
		self._modNum.set_mode_buttons([ self._menu[index] for index in range(6) ])

	def _modNum_set_mode(self, modNum):
		def set_mode(mode):
			if modNum._is_enabled == True:
				assert isinstance(mode, int)
				assert (mode in range(modNum.number_of_modes()))
				if (modNum._mode_index != mode):
					modNum._mode_index = mode
					modNum.update()
		return set_mode
	

	def _setup_transport_control(self):
		self._transport = TransportComponent()
		self._transport.name = 'Transport'

	def _setup_mixer_control(self):
		global mixer
		is_momentary = True
		self._num_tracks = 7
		mixer = SpecialMixerComponent(7, 0, True, False)
		mixer.name = 'Mixer'
		self._mixer = mixer
		for index in range(7):
			mixer.channel_strip(index).set_volume_control(self._fader[index])

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

		self.song().view.selected_track = mixer.channel_strip(0)._track

	def _setup_session_control(self):
		global session
		is_momentary = True
		num_tracks = 7
		num_scenes = 5
		session = SessionComponent(num_tracks, num_scenes)
		session.name = 'Session'
		self._session = session
		session.set_offsets(0, 0)
		self._scene = [ None for index in range(6) ]
		for row in range(num_scenes):
			self._scene[row] = session.scene(row)
			self._scene[row].name = 'Scene_' + str(row)
			for column in range(num_tracks):
				clip_slot = self._scene[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_' + str(row)

		session.set_mixer(self._mixer)
		session.set_show_highlight(True)
		self._session_zoom = SessionZoomingComponent(session)
		self._session_zoom.name = 'Session_Overview'
		self.set_highlighting_session_component(self._session)

	def _assign_session_colors(self):
		self.log_message('assign session colors')
		num_tracks = 7
		num_scenes = 5
		self._session.set_stop_track_clip_value(STOP_CLIP_COLOR[self._rgb])
		for row in range(num_scenes):
			for column in range(num_tracks):
				self._scene[row].clip_slot(column).set_triggered_to_play_value(CLIP_TRIGD_TO_PLAY_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_triggered_to_record_value(CLIP_TRIGD_TO_RECORD_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_stopped_value(CLIP_STOPPED_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_started_value(CLIP_STARTED_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_recording_value(CLIP_RECORDING_COLOR[self._rgb])

		self._session_zoom.set_stopped_value(ZOOM_STOPPED_COLOR[self._rgb])
		self._session_zoom.set_playing_value(ZOOM_PLAYING_COLOR[self._rgb])
		self._session_zoom.set_selected_value(ZOOM_SELECTED_COLOR[self._rgb])
		for row in range(8):
			for column in range(8):
				self._grid[column][row].set_force_next_value()

		self._session.on_scene_list_changed()
		self._shift_mode.update()

	def _setup_device_control(self):
		self._device = DeviceComponent()
		self._device.name = 'Device_Component'
		self.set_device_component(self._device)
		self._device_navigator = DetailViewControllerComponent()
		self._device_navigator.name = 'Device_Navigator'
		self._device_selection_follows_track_selection = FOLLOW

	def device_follows_track(self, val):
		self._device_selection_follows_track_selection = val == 1
		return self

	def _setup_crossfader(self):
		self._mixer.set_crossfader_control(self._crossfader)

	def disconnect(self):
		"""clean things up on disconnect"""
		self.song().view.remove_selected_track_listener(self._update_selected_device)
		self.log_message(time.strftime('%d.%m.%Y %H:%M:%S', time.localtime()) + '--------------= OhmModes log closed =--------------')
		ControlSurface.disconnect(self)

	def _get_num_tracks(self):
		return self.num_tracks

	def flash(self):
		for row in range(8):
			if self._button[row]._flash_state > 0:
				self._button[row].flash(self._timer)
			for column in range(8):
				button = self._grid[column][row]
				if button._flash_state > 0:
					button.flash(self._timer)

	def strobe(self):
		if self._backlight_type != 'static':
			if self._backlight_type is 'pulse':
				self._backlight = int(math.fabs(self._timer * 16 % 64 - 32) + 32)
			if self._backlight_type is 'up':
				self._backlight = int(self._timer * 8 % 64 + 16)
			if self._backlight_type is 'down':
				self._backlight = int(math.fabs(int(self._timer * 8 % 64 - 64)) + 16)
		self._send_midi(tuple([176, 27, int(self._backlight)]))
		if self._ohm_type != 'static':
			if self._ohm_type is 'pulse':
				self._ohm = int(math.fabs(self._timer * 16 % 64 - 32) + 32)
			if self._ohm_type is 'up':
				self._ohm = int(self._timer * 8 % 64 + 16)
			if self._ohm_type is 'down':
				self._ohm = int(math.fabs(int(self._timer * 8 % 64 - 64)) + 16)
		self._send_midi(tuple([176, 63, int(self._ohm)]))
		self._send_midi(tuple([176, 31, int(self._ohm)]))

	def deassign_matrix(self):
		with self.component_guard():
			self._host._set_knobs(None)
			self._host._set_button_matrix(None)
			self._host.set_enabled(False)
			self._modNum.set_enabled(False)
			self.assign_alternate_mappings(0)
			self._scale_mode.set_mode_buttons(None)
			self._scale_mode.set_enabled(False)
			self._octave_mode.set_mode_buttons(None)
			self._octave_mode.set_enabled(False)
			self._session_zoom.set_enabled(False)
			self._session_zoom.set_nav_buttons(None, None, None, None)
			self._session.set_track_bank_buttons(None, None)
			self._session.set_scene_bank_buttons(None, None)
			self._transport.set_enabled(False)
			for column in range(4):
				self._mixer.track_eq(column)._gain_controls = None
				self._mixer.track_eq(column).set_enabled(False)

			for column in range(7):
				self._mixer.channel_strip(column).set_crossfade_toggle(None)
				self._mixer.channel_strip(column).set_mute_button(None)
				self._mixer.channel_strip(column).set_solo_button(None)
				self._mixer.channel_strip(column).set_arm_button(None)
				self._mixer.channel_strip(column).set_send_controls(None)
				self._mixer.channel_strip(column).set_pan_control(None)
				self._mixer.track_eq(column).set_enabled(False)
				for row in range(5):
					self._scene[row].clip_slot(column).set_launch_button(None)

			"""for column in range(8):
				self._button[column]._on_value = SELECT_COLOR[self._rgb]
				for row in range(8):
					self._grid[column][row].set_enabled(True)
					self._grid[column][row].release_parameter()
					self._grid[column][row].use_default_message()
					self._grid[column][row].set_on_off_values(127, 0)
					self._grid[column][row].send_value(0, True)"""
			for column in range(8):
				self._button[column]._on_value = SELECT_COLOR[self._rgb]
				for row in range(8):
					#self._grid[column][row].set_channel(0)
					self._grid[column][row].release_parameter()
					self._grid[column][row].use_default_message()
					self._grid[column][row].set_enabled(True)
					self._grid[column][row].send_value(0, True)
					self._grid[column][row]._on_value = 127
					self._grid[column][row]._off_value = 0
					self._grid[column][row].force_next_send()


			for index in range(6):
				self._menu[index]._on_value = 127
				self._menu[index]._off_value = 0

			for index in range(16):
				self._dial[index].use_default_message()
				self._dial[index].release_parameter()

			self._device.set_parameter_controls(None)
			self._device.set_enabled(False)
			self._device_navigator.set_enabled(False)
			self._mixer.update()
			self._matrix.reset()
		self.request_rebuild_midi_map()

	def _assign_page_constants(self):
		with self.component_guard():
			self._session_zoom.set_zoom_button(self._grid[7][7])
			self._session_zoom.set_button_matrix(self._matrix)
			for column in range(7):
				self._mixer.channel_strip(column).set_select_button(self._button[column])
				self._mixer.channel_strip(column).set_volume_control(self._fader[column])

			self._mixer.master_strip().set_volume_control(self._fader[7])
			self._mixer.master_strip().set_select_button(self._button[7])
			self._mixer.set_prehear_volume_control(self._dial[15])
			self._transport.set_play_button(self._menu[0])
			self._menu[0].send_value(PLAY_COLOR[self._rgb], True)
			self._menu[0]._on_value = PLAY_COLOR[self._rgb]
			self._transport.set_stop_button(self._menu[1])
			self._menu[1]._off_value = STOP_COLOR[self._rgb]
			self._menu[1]._on_value = STOP_COLOR[self._rgb]
			self._menu[1].send_value(STOP_COLOR[self._rgb], True)
			self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[4])

	def assign_page_0(self):
		with self.component_guard():
			self._backlight_type = 'static'
			self._session_zoom.set_enabled(True)
			for column in range(7):	
				self._grid[column][5]._on_value = MUTE_COLOR[self._rgb]
				self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
				self._grid[column][6]._on_value = SOLO_COLOR[self._rgb]
				self._mixer.channel_strip(column).set_solo_button(self._grid[column][6])
				self._grid[column][7]._on_value = ARM_COLOR[self._rgb]
				self._mixer.channel_strip(column).set_arm_button(self._grid[column][7])
				self._mixer.channel_strip(column).set_pan_control(self._dial[column + 8])
				for row in range(5):
					self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])

			for column in range(4):
				self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column], self._dial[column + 4]]))

			for index in range(5):
				self._grid[7][index]._off_value = SCENE_LAUNCH_COLOR[self._rgb]
				self._scene[index].set_launch_button(self._grid[7][index])
				self._grid[7][index].set_force_next_value()
				self._grid[7][index].turn_off()

			for index in range(4):
				self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb]

			self._session.set_track_bank_buttons(self._menu[4], self._menu[3])
			self._session.set_scene_bank_buttons(self._menu[5], self._menu[2])
			self._menu[0]._on_value = PLAY_COLOR[self._rgb]
			self._menu[1]._off_value = STOP_COLOR[self._rgb]
			self._menu[1]._on_value = STOP_COLOR[self._rgb]
			self._transport.set_enabled(True)
			#self._mixer.update_all()
		self.request_rebuild_midi_map()
		#self.log_message('assign_page_0')

	def assign_page_1(self):
		with self.component_guard():
			self._backlight_type = 'pulse'
			self._session_zoom.set_enabled(False)
			for column in range(4):
				for row in range(4):
					self._grid[column][row].send_value(DRUM_COLOR[self._rgb], True)
					self._grid[column + 4][row].send_value(BASS_COLOR[self._rgb], True)
					self._grid[column][row].set_enabled(False)
					self._grid[column][row]._msg_channel = PAGE1_DRUM_CHANNEL
					self._grid[column][row].set_identifier(PAGE1_DRUM_MAP[column][row])
					self._grid[column + 4][row].set_enabled(False)
					self._grid[column + 4][row]._msg_channel = PAGE1_BASS_CHANNEL
					self._grid[column + 4][row].set_identifier(PAGE1_BASS_MAP[column][row])

			scale_mode_buttons = []
			for column in range(8):
				for row in range(3):
					self._grid[column][row + 4].set_enabled(False)
					self._grid[column][row + 4].send_value(KEYS_COLOR[self._rgb], True)
					self._grid[column][row + 4]._msg_channel = PAGE1_KEYS_CHANNEL
					self._grid[column][row + 4].set_identifier(int(PAGE1_KEYS_MAP[column][row]) + int(PAGE1_MODES_MAP[self._scale_mode._mode_index][column]) + int(self._octave_mode._mode_index * 12))

				for row in range(1):
					scale_mode_buttons.append(self._grid[column][7])

			self._scale_mode.set_mode_buttons(tuple(scale_mode_buttons))
			self._scale_mode.set_enabled(True)
			self._octave_mode.set_mode_buttons(tuple([self._menu[5], self._menu[2]]))
			self._octave_mode.set_enabled(True)
			for column in range(7):
				self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column + 8]]))
				self._mixer.channel_strip(column).set_arm_button(self._button[column])

			self._device.set_enabled(True)
			device_param_controls = []
			for index in range(8):
				device_param_controls.append(self._dial[index])

			self._device.set_parameter_controls(tuple(device_param_controls))
			self._menu[0]._on_value = PLAY_COLOR[self._rgb]
			for index in range(4):
				self._menu[2 + index]._on_value = DEVICE_NAV_COLOR[self._rgb]

			self._device_navigator.set_enabled(True)
			self._menu[0]._on_value = PLAY_COLOR[self._rgb]
			self._menu[1]._off_value = STOP_COLOR[self._rgb]
			self._menu[1]._on_value = STOP_COLOR[self._rgb]
			self._transport.set_enabled(True)
		self.request_rebuild_midi_map()

	def assign_page_2(self):
		with self.component_guard():
			self._backlight_type = 'up'
			self._session_zoom.set_enabled(True)
			for column in range(7):
				self._grid[column][5]._on_value = MUTE_COLOR[self._rgb]
				self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
				self._grid[column][6]._on_value = CROSSFADE_ASSIGN_COLOR[self._rgb]
				self._mixer.channel_strip(column).set_crossfade_toggle(self._grid[column][6])
				self._grid[column][7]._msg_channel = 2
				self._grid[column][7].set_identifier(column)
				self._grid[column][7].reset()
				self._grid[column][7].set_enabled(False)
				self._grid[column][7].send_value(4, True)
				for row in range(5):
					self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])

			for row in range(5):
				self._grid[7][row]._off_value = SCENE_LAUNCH_COLOR[self._rgb]
				self._scene[row].set_launch_button(self._grid[7][row])
				self._grid[7][row].set_force_next_value()
				self._grid[7][row].turn_off()

			for column in range(4):
				self._mixer.track_eq(column).set_gain_controls(tuple([self._dial[column + 8], self._dial[column + 4], self._dial[column]]))
				self._mixer.track_eq(column).set_enabled(True)

			for column in range(3):
				self._mixer.channel_strip(column + 4).set_pan_control(self._dial[column + 12])

			for index in range(4):
				self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb]

			self._session.set_track_bank_buttons(self._menu[4], self._menu[3])
			self._session.set_scene_bank_buttons(self._menu[5], self._menu[2])
			self._set_tempo_buttons([self._grid[7][5], self._grid[7][6]])
			self._menu[0]._on_value = PLAY_COLOR[self._rgb]
			self._menu[1]._off_value = STOP_COLOR[self._rgb]
			self._menu[1]._on_value = STOP_COLOR[self._rgb]
			self._transport.set_enabled(True)
			#self._mixer.update()
		self.request_rebuild_midi_map()

	def assign_mod(self):
		with self.component_guard():
			self.deassign_matrix()
			self._host.set_enabled(True)
			self._modNum.set_enabled(True)
			self._host._set_dial_matrix(self._dial_matrix, self._dial_button_matrix)
			self._host._set_button_matrix(self._mod_matrix)
			self._host._set_key_buttons(tuple(self._key))
			if not self._host._active_client.is_connected():
				self.assign_alternate_mappings(self._modNum._mode_index + 1)

	def modNum_update(self):
		if self._modNum._is_enabled == True:
			self.assign_alternate_mappings(0)
			self._host._select_client(int(self._modNum._mode_index))
			self._host.display_active_client()
			if not self._host._active_client.is_connected():
				self.assign_alternate_mappings(self._modNum._mode_index + 1)
			for button in self._modNum._modes_buttons:
				if self._modNum._mode_index == self._modNum._modes_buttons.index(button):
					button.send_value(1)
				else:
					button.send_value(self._client[self._modNum._modes_buttons.index(button)]._mod_color)

	def assign_alternate_mappings(self, chan):
		for column in range(8):
			for row in range(8):
				self._grid[column][row].set_channel(chan)
		for knob in self._encoder:
			knob.set_channel(chan)
			knob.set_enabled(chan is 0)

		self.request_rebuild_midi_map()

	def display_mod_colors(self):
		pass

	def _update_selected_device(self):
		if self._device_selection_follows_track_selection is True:
			track = self.song().view.selected_track
			device_to_select = track.view.selected_device
			if device_to_select == None and len(track.devices) > 0:
				device_to_select = track.devices[0]
			if device_to_select != None:
				self.song().view.select_device(device_to_select)
			self.set_appointed_device(device_to_select)
			self.request_rebuild_midi_map()

	def handle_sysex(self, midi_bytes):
		if len(midi_bytes) > 10:
			if midi_bytes[:11] == tuple([240,
			 126,
			 0,
			 6,
			 2,
			 0,
			 1,
			 97,
			 1,
			 0,
			 7]):
				self.log_message(str('>>>color detected'))
				self._rgb = 0
			elif midi_bytes[:11] == tuple([240,
			 126,
			 0,
			 6,
			 2,
			 0,
			 1,
			 97,
			 1,
			 0,
			 2]):
				self.log_message(str('>>>mono detected'))
				self._rgb = 1
		self._assign_session_colors()

	def to_encoder(self, num, val):
		rv = int(val * 127)
		self._device._parameter_controls[num].receive_value(rv)
		p = self._device._parameter_controls[num]._parameter_to_map_to
		newval = val * (p.max - p.min) + p.min
		p.value = newval

	def set_local_ring_control(self, val = 1):
		self._local_ring_control = val != 0

	def set_absolute_mode(self, val = 1):
		self._absolute_mode = val != 0

	def send_ring_leds(self):
		"""if self._host._is_enabled == True:
		leds = [240, 0, 1, 97, 8, 31]
		for index in range(12):
				wheel = self._encoder[index]
				bytes = wheel._get_ring()
				leds.append(bytes[0])
				leds.append(int(bytes[1]) + int(bytes[2]))
		leds.append(247)
		self._send_midi(tuple(leds))"""
		pass


	def _set_tempo_buttons(self, buttons):
		if self._tempo_buttons != None:
			self._tempo_buttons[0].remove_value_listener(self._tempo_value)
			self._tempo_buttons[1].remove_value_listener(self._tempo_value)
		self._tempo_buttons = buttons
		if buttons != None:
			for button in buttons:
				 assert isinstance(button, FlashingButtonElement)
			self._tempo_buttons[0].set_on_off_values(4, 0)
			self._tempo_buttons[0].add_value_listener(self._tempo_value, True)
			self._tempo_buttons[1].set_on_off_values(4, 0)
			self._tempo_buttons[1].add_value_listener(self._tempo_value, True)
			self._tempo_buttons[0].turn_on()
			self._tempo_buttons[1].turn_on()

	def _tempo_value(self, value, sender):
		if value > 0 and self._tempo_buttons.index(sender) == 0:
			self.song().tempo = round(min(self.song().tempo + 1, 999))
		elif value > 0 and self._tempo_buttons.index(sender) == 1:
			self.song().tempo = round(max(self.song().tempo - 1, 20))

	def generate_strip_string(self, display_string):
		NUM_CHARS_PER_DISPLAY_STRIP = 12
		if not display_string:
			return ' ' * NUM_CHARS_PER_DISPLAY_STRIP
		if len(display_string.strip()) > NUM_CHARS_PER_DISPLAY_STRIP - 1 and display_string.endswith('dB') and display_string.find('.') != -1:
			display_string = display_string[:-2]
		if len(display_string) > NUM_CHARS_PER_DISPLAY_STRIP - 1:
			for um in [' ',
			 'i',
			 'o',
			 'u',
			 'e',
			 'a']:
				while len(display_string) > NUM_CHARS_PER_DISPLAY_STRIP - 1 and display_string.rfind(um, 1) != -1:
					um_pos = display_string.rfind(um, 1)
					display_string = display_string[:um_pos] + display_string[um_pos + 1:]

		else:
			display_string = display_string.center(NUM_CHARS_PER_DISPLAY_STRIP - 1)
		ret = u''
		for i in range(NUM_CHARS_PER_DISPLAY_STRIP - 1):
			if ord(display_string[i]) > 127 or ord(display_string[i]) < 0:
				ret += ' '
			else:
				ret += display_string[i]

		ret += ' '
		return ret

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

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

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

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

		return clip_names

	def shift_update(self):
		pass
Exemple #17
0
class Launchkey_MK2(OptimizedControlSurface):
    identity_request_delay = 0.5

    def __init__(self, c_instance, *a, **k):
        super(Launchkey_MK2, self).__init__(c_instance=c_instance, *a, **k)
        self._is_25_key_model = False
        self._is_in_control_on = True
        with self.component_guard():
            self._skin = make_skin()
            with inject(skin=const(self._skin)).everywhere():
                self._create_controls()
        self._request_task = self._tasks.add(Task.sequence(Task.wait(self.identity_request_delay), Task.run(self._send_identity_request)))
        self._request_task.kill()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[ make_encoder(identifier, name='Encoder_%d' % (index,)) for index, identifier in enumerate(xrange(21, 29)) ]])
        self._top_pad_row = ButtonMatrixElement(rows=[[ make_button(identifier, name='Pad_0_%d' % (index,)) for index, identifier in enumerate(xrange(96, 104)) ]])
        self._bottom_pad_row_raw = [ make_button(identifier, name='Pad_1_%d' % (index,)) for index, identifier in enumerate(xrange(112, 120)) ]
        self._bottom_pad_row = ButtonMatrixElement(rows=[self._bottom_pad_row_raw])
        self._top_launch_button = make_button(104, name='Scene_Launch_Button')
        self._bottom_launch_button = make_button(120, name='Stop_All_Clips_Button')
        self._scene_up_button = make_button(112, MIDI_CC_TYPE, name='Scene_Up_Button')
        self._scene_down_button = make_button(113, MIDI_CC_TYPE, name='Scene_Down_Button')
        self._stop_button = make_button(114, MIDI_CC_TYPE, name='Stop_Button')
        self._play_button = make_button(115, MIDI_CC_TYPE, name='Play_Button')
        self._loop_button = make_button(116, MIDI_CC_TYPE, name='Loop_Button')
        self._record_button = make_button(117, MIDI_CC_TYPE, name='Record_Button')
        self._sliders = ButtonMatrixElement(rows=[[ make_slider(identifier, name='Slider_%d' % (index,)) for index, identifier in enumerate(xrange(41, 49)) ]])
        self._master_slider = make_slider(7, name='Master_Slider')
        self._25_key_slider = make_slider(7, name='Slider', channel=0)
        self._mute_buttons_raw = [ make_button(identifier, MIDI_CC_TYPE, name='Mute_Button_%d' % (index,)) for index, identifier in enumerate(xrange(51, 59)) ]
        self._mute_buttons = ButtonMatrixElement(rows=[self._mute_buttons_raw])
        self._master_button = make_button(59, MIDI_CC_TYPE, name='Master_Button')
        self._track_left_button = make_button(102, MIDI_CC_TYPE, name='Track_Left_Button')
        self._track_right_button = make_button(103, MIDI_CC_TYPE, name='Track_Right_Button')
        self._device_mode_button = self._bottom_pad_row_raw[0]
        self._pan_mode_button = self._bottom_pad_row_raw[1]
        self._send_mode_buttons = dict()
        for index in xrange(consts.MAX_SENDS):
            setattr(self, '_send_%d_button' % (index,), self._bottom_pad_row_raw[index + 2])
            self._send_mode_buttons['send_%d_mode_button' % (index,)] = getattr(self, '_send_%d_button' % (index,))

        self._extended_mode_button = make_button(12, name='Dummy_Extended_Mode_Button')
        self._extended_mode_button.add_value_listener(nop)
        self._encoder_incontrol_button = make_button(13, is_momentary=False, name='Encoder_InControl_Button')
        self._encoder_incontrol_button.add_value_listener(nop)
        self._slider_incontrol_button = make_button(14, is_momentary=False, name='Fader_InControl_Button')
        self._slider_incontrol_button.add_value_listener(nop)
        self._pad_incontrol_button = make_button(15, is_momentary=False, name='Pad_InControl_Button')
        self._pad_incontrol_button.add_value_listener(self._update_pads)
        self._encoder_incontrol_button2 = make_button(16, name='Encoder_InControl_Button')
        self._pad_in_control_status_button = make_button(11, name='Dummy_InControl_Button')

    def _create_session(self):
        self._session = SessionComponent(name='Session', is_enabled=False, num_tracks=self._top_pad_row.width(), num_scenes=self._top_pad_row.height(), enable_skinning=True, layer=Layer(clip_launch_buttons=self._top_pad_row, scene_launch_buttons=ButtonMatrixElement(rows=[[self._top_launch_button]]), stop_track_clip_buttons=self._bottom_pad_row, stop_all_clips_button=self._bottom_launch_button))
        self._session.set_rgb_mode(CLIP_COLOR_TABLE, RGB_COLOR_TABLE)
        self._session.set_mixer(self._mixer)
        self._session.set_enabled(True)

    def _setup_navigation(self):
        self._session_navigation = SessionNavigationComponent(is_enabled=False, name='Session_Navigation', layer=Layer(next_track_button=self._track_right_button, prev_track_button=self._track_left_button, next_scene_button=self._scene_down_button, prev_scene_button=self._scene_up_button))
        self._session_navigation.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(is_enabled=False, name='Transport', layer=Layer(play_button=self._play_button, stop_button=self._stop_button, loop_button=self._loop_button, record_button=self._record_button))
        self._transport.set_enabled(True)

    def _create_mixer(self):
        mixer_volume_layer = None
        if self._is_25_key_model:
            mixer_volume_layer = Layer(volume_control=self._25_key_slider)
        else:
            mixer_volume_layer = Layer(volume_controls=self._sliders)
        self._mixer = MixerComponent(is_enabled=False, name='Mixer', num_tracks=self._sliders.width(), layer=mixer_volume_layer)
        if not self._is_25_key_model:
            self._mixer.master_strip().layer = Layer(volume_control=self._master_slider)
        self._mixer.set_enabled(True)
        self._mute_button_modes = ModesComponent()
        mute_mode = AddLayerMode(self._mixer, Layer(mute_buttons=self._mute_buttons))
        solo_mode = AddLayerMode(self._mixer, Layer(solo_buttons=self._mute_buttons))
        self._mute_button_modes.add_mode('mute_mode', mute_mode)
        self._mute_button_modes.add_mode('solo_mode', solo_mode, behaviour=CancellableBehaviour())
        self._mute_button_modes.layer = Layer(solo_mode_button=self._master_button)
        self._mute_button_modes.selected_mode = 'mute_mode'
        self._mute_button_modes.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(name='Device', is_enabled=False, device_selection_follows_track_selection=True)
        self.set_device_component(self._device)
        self._device.set_enabled(True)

    def _create_background(self):
        self._background = BackgroundComponent(name='BackgroundComponent')

    def _create_encoder_modes(self):
        self._encoder_modes = DisablingModesComponent()
        self._encoder_modes.default_behaviour = mixin(SkinableBehaviourMixin, ImmediateBehaviour)()
        device_mode = LayerMode(self._device, Layer(parameter_controls=self._encoders, bank_buttons=self._top_pad_row))
        pan_mode = AddLayerMode(self._mixer, Layer(pan_controls=self._encoders))
        sends_mode = AddLayerMode(self._mixer, Layer(send_controls=self._encoders))
        background_mode = LayerMode(self._background, Layer(bank_buttons=self._top_pad_row))
        self._encoder_modes.add_mode('device_mode', device_mode, is_enabled=True)
        self._encoder_modes.add_mode('pan_mode', [pan_mode, background_mode], is_enabled=True)
        for index in xrange(6):
            self._encoder_modes.add_mode('send_%d_mode' % (index,), [sends_mode, partial(self._set_send_index, index), background_mode], is_enabled=False)

        self._encoder_modes.selected_mode = 'device_mode'
        self._encoder_modes.set_enabled(True)

    def _create_mode_selector(self):
        self._mode_selector = ModesComponent()
        mode_selection = LayerMode(self._encoder_modes, Layer(device_mode_button=self._device_mode_button, pan_mode_button=self._pan_mode_button, **self._send_mode_buttons))
        device_navigation = AddLayerMode(self._device, Layer(device_nav_left_button=self._track_left_button, device_nav_right_button=self._track_right_button))
        self._mode_selector.add_mode('mode_selection', [partial(self._toggle_in_control, True), mode_selection, device_navigation], behaviour=MomentaryBehaviour())
        session_control = AddLayerMode(self._session, Layer(clip_launch_buttons=self._top_pad_row))
        self._mode_selector.add_mode('session_mode', [partial(self._toggle_in_control, False), session_control])
        self._mode_selector.layer = Layer(mode_selection_button=self._encoder_incontrol_button2)

    def _create_in_control_status_listener(self):
        self._in_control_status = InControlStatusComponent(set_is_in_control_on=self._set_is_in_control_on, is_enabled=False, layer=Layer(in_control_status_button=self._pad_in_control_status_button))
        self._in_control_status.set_enabled(True)

    @subject_slot('value')
    def _update_pads(self, value):
        if value:
            self.update()

    @subject_slot('return_tracks')
    def _on_return_tracks_changed(self):
        num_sends = self._mixer.num_sends
        for index in xrange(6):
            self._encoder_modes.set_mode_enabled('send_%d_mode' % (index,), True if index < num_sends else False)

    def _set_send_index(self, index):
        self._mixer.send_index = index

    def _set_is_in_control_on(self, value):
        self._is_in_control_on = value

    def _toggle_in_control(self, value):
        if not self._is_in_control_on:
            self._send_midi(consts.DRUM_IN_CONTROL_ON_MESSAGE if value else consts.DRUM_IN_CONTROL_OFF_MESSAGE)

    def port_settings_changed(self):
        self._disconnect_and_unregister_all_components()
        self._request_task.restart()

    def handle_sysex(self, midi_bytes):
        if self._is_identity_response(midi_bytes):
            product_id_bytes = self._extract_product_id_bytes(midi_bytes)
            if self._is_identity_response_valid(product_id_bytes):
                self._set_model_type(product_id_bytes)
                self._request_task.kill()
                self.on_identified()
            else:
                self.log_message('MIDI device responded with wrong product id (%s).' % (str(product_id_bytes),))
        else:
            super(Launchkey_MK2, self).handle_sysex(midi_bytes)

    def _extract_product_id_bytes(self, midi_bytes):
        return midi_bytes[5:]

    def _is_identity_response(self, midi_bytes):
        return midi_bytes[3:5] == (6, 2)

    def _is_identity_response_valid(self, product_id_bytes):
        return product_id_bytes[:3] == consts.PRODUCT_ID_BYTE_PREFIX and product_id_bytes[3] in consts.PRODUCT_ID_BYTES

    def _set_model_type(self, product_id_bytes):
        self._is_25_key_model = product_id_bytes[3] == consts.LAUNCHKEY_25_ID_BYTE

    def _send_identity_request(self):
        self._send_midi(consts.IDENTITY_REQUEST)

    def on_identified(self):
        self._extended_mode_button.turn_on()
        with self.component_guard():
            self._create_mixer()
            self._create_session()
            self._setup_navigation()
            self._create_transport()
            self._create_device()
            self._create_background()
            self._create_encoder_modes()
            self._create_mode_selector()
            self._create_in_control_status_listener()
            self._on_return_tracks_changed.subject = self.song()
            self._on_return_tracks_changed()
        self._mode_selector.selected_mode = 'session_mode'
        self.update()

    def disconnect(self):
        self._extended_mode_button.turn_off()
        super(Launchkey_MK2, self).disconnect()
class Launchpad_Pro_Custom(IdentifiableControlSurface,
                           OptimizedControlSurface):
    identity_request = consts.SYSEX_IDENTITY_REQUEST

    def __init__(self, c_instance, *a, **k):
        product_id_bytes = consts.MANUFACTURER_ID + consts.DEVICE_CODE
        super(Launchpad_Pro_Custom,
              self).__init__(c_instance=c_instance,
                             product_id_bytes=product_id_bytes,
                             *a,
                             **k)
        self._challenge = Live.Application.get_random_int(
            0, 400000000) & 2139062143
        with self.component_guard():
            self._skin = make_default_skin()
            with inject(skin=const(self._skin)).everywhere():
                self._midimap = MidiMap()
            self._target_track_component = TargetTrackComponent(
                name='Target_Track')
            self._create_background()
            self._create_global_component()
            self._last_sent_mode_byte = None
            with inject(layout_setup=const(self._layout_setup),
                        should_arm=const(self._should_arm_track)).everywhere():
                self._create_session()
                self._create_arrangement()
                self._create_recording()
                self._create_actions()
                self._create_drums()
                self._create_mixer()
                self._create_device()
                self._create_modes()
                # self._create_user()
                self._create_arrangement_transport()
            self._on_session_record_changed.subject = self.song()
        self.set_device_component(self._device)
        self._on_session_record_changed()
        return

    def disconnect(self):
        self._send_midi(consts.TURN_OFF_LEDS)
        self._send_midi(consts.QUIT_MESSAGE)
        super(Launchpad_Pro_Custom, self).disconnect()

    def _create_background(self):
        self._modifier_background_component = ModifierBackgroundComponent(
            name='Background_Component',
            is_enabled=False,
            layer=Layer(shift_button=self._midimap['Shift_Button']))
        self._shifted_background = BackgroundComponent(
            name='No_Op_Shifted_Buttons',
            is_enabled=False,
            layer=Layer(
                click_bitton=self._midimap.with_shift('Click_Button'),
                delete_button=self._midimap.with_shift('Delete_Button'),
                duplicate_button=self._midimap.with_shift('Duplicate_Button'),
                double_button=self._midimap.with_shift('Double_Loop_Button'),
                session_record_button=self._midimap.with_shift(
                    'Session_Record_Button')))

    def _create_global_component(self):
        self._actions_component = ActionsComponent(
            name='Global_Actions',
            is_enabled=False,
            layer=Layer(undo_button=self._midimap['Undo_Button'],
                        redo_button=self._midimap.with_shift('Undo_Button'),
                        metronome_button=self._midimap['Click_Button'],
                        quantization_on_button=self._midimap.with_shift(
                            'Quantize_Button')))

    def _create_session(self):
        self._session = SessionComponent(
            NUM_TRACKS,
            NUM_SCENES,
            auto_name=True,
            is_enabled=False,
            enable_skinning=True,
            layer=Layer(
                track_bank_left_button=self._midimap['Arrow_Left_Button'],
                track_bank_right_button=self._midimap['Arrow_Right_Button'],
                scene_bank_up_button=self._midimap['Arrow_Up_Button'],
                scene_bank_down_button=self._midimap['Arrow_Down_Button']))
        self._session.set_enabled(True)
        self._session.set_rgb_mode(LIVE_COLORS_TO_MIDI_VALUES, RGB_COLOR_TABLE)
        SpecialClipSlotComponent.quantization_component = self._actions_component
        for scene_index in xrange(NUM_SCENES):
            scene = self._session.scene(scene_index)
            scene.layer = Layer(
                select_button=self._midimap['Shift_Button'],
                delete_button=self._midimap['Delete_Button'],
                duplicate_button=self._midimap['Duplicate_Button'])
            for track_index in xrange(NUM_TRACKS):
                slot = scene.clip_slot(track_index)
                slot.layer = Layer(
                    select_button=self._midimap['Shift_Button'],
                    delete_button=self._midimap['Delete_Button'],
                    duplicate_button=self._midimap['Duplicate_Button'],
                    double_loop_button=self._midimap['Double_Loop_Button'],
                    quantize_button=self._midimap['Quantize_Button'])

        self._session_zoom = SessionZoomingComponent(self._session,
                                                     name='Session_Overview',
                                                     is_enabled=True,
                                                     enable_skinning=True)

    def _create_arrangement(self):
        self._arrangement = SpecialArrangementComponent(
            NUM_TRACKS,
            NUM_SCENES,
            auto_name=True,
            is_enabled=False,
            enable_skinning=True,
            layer=Layer(
                track_bank_up_button=self._midimap['Arrow_Up_Button'],
                track_bank_down_button=self._midimap['Arrow_Down_Button'],
                quantize_button=self._midimap['Quantize_Button']))
        self._arrangement.set_enabled(True)
        # self._arrangement.set_rgb_mode(LIVE_COLORS_TO_MIDI_VALUES, RGB_COLOR_TABLE)

    def _create_recording(self):
        self._session_record = SpecialSessionRecordingComponent(
            self._target_track_component,
            name='Session_Recording',
            is_enabled=False,
            layer=Layer(record_button=self._midimap['Session_Record_Button']))

    def _create_arrangement_transport(self):
        self._transport = TransportComponent(name='Transport',
                                             is_enabled=False,
                                             play_toggle_model_transform=False)
        self._transport.layer = Layer( play_button=self._midimap['Scene_Launch_Button_Matrix_Raw'][0][7], \
                                       stop_button=self._midimap['Scene_Launch_Button_Matrix_Raw'][0][6], \
                                       loop_button=self._midimap['Scene_Launch_Button_Matrix_Raw'][0][5], \
                                       record_button=self._midimap['Session_Record_Button'] \
                                     )

    def _create_actions(self):
        self._clip_actions_component = ClipActionsComponent(
            self._target_track_component,
            name='Clip_Actions',
            is_enabled=False,
            layer=Layer(duplicate_button=self._midimap['Duplicate_Button'],
                        double_button=self._midimap['Double_Loop_Button'],
                        quantize_button=self._midimap['Quantize_Button']))
        ClipActionsComponent.quantization_component = self._actions_component

    def _create_drums(self):
        self._drum_group_finder = DrumGroupFinderComponent(
            self._target_track_component,
            name='Drum_Group_Finder',
            is_enabled=False,
            layer=None)
        self._on_drum_group_changed.subject = self._drum_group_finder
        self._drum_group_finder.set_enabled(True)
        self._drum_group = DrumGroupComponent(
            self._clip_actions_component,
            name='Drum_Group_Control',
            translation_channel=consts.DR_MAP_CHANNEL)
        self._drum_group.set_enabled(True)
        return

    def _create_mixer(self):
        self._mixer = SpecialMixerComponent(NUM_TRACKS,
                                            auto_name=True,
                                            is_enabled=True,
                                            invert_mute_feedback=True)
        self._mixer.name = 'Mixer_Control'
        self._session.set_mixer(self._mixer)
        # self._arrangement.set_mixer(self._mixer)

    def _create_device(self):
        self._device = SpecialDeviceComponent(
            name='Device_Control',
            is_enabled=False,
            device_selection_follows_track_selection=True)
        self._device_navigation = DeviceNavigationComponent(
            name='Device_Navigation')
        self._device_background = BackgroundComponent(
            name='Device_Background_Component')

    def _setup_drum_group(self):
        self._drum_group.set_drum_group_device(
            self._drum_group_finder.drum_group)

    def _create_translation(self,
                            comp_name,
                            channel,
                            button_layer,
                            should_enable=True,
                            should_reset=True):
        translation_component = TranslationComponent(
            name=comp_name,
            translated_channel=channel,
            should_enable=should_enable,
            should_reset=should_reset,
            is_enabled=False,
            layer=button_layer)
        setattr(self, '_' + comp_name.lower(), translation_component)
        return translation_component

    def _create_modes(self):
        self._modes = ModesComponent(name='Launchpad_Modes', is_enabled=False)
        self._session_layer_mode = AddLayerMode(
            self._session,
            Layer(scene_launch_buttons=self.
                  _midimap['Scene_Launch_Button_Matrix'],
                  clip_launch_buttons=self._midimap['Main_Button_Matrix'],
                  delete_button=self._midimap['Delete_Button'],
                  duplicate_button=self._midimap['Duplicate_Button'],
                  double_button=self._midimap['Double_Loop_Button'],
                  quantize_button=self._midimap['Quantize_Button']))
        # self._arrangement_layer_mode = AddLayerMode(self._arrangement, Layer(transport_buttons=self._midimap['Scene_Launch_Button_Matrix'], track_buttons=self._midimap['Main_Button_Matrix'], quantize_button=self._midimap['Quantize_Button']))
        action_button_background = BackgroundComponent(name='No_Op_Buttons')
        self._action_button_background_layer_mode = LayerMode(
            action_button_background,
            Layer(delete_button=self._midimap['Delete_Button'],
                  quantize_button=self._midimap['Quantize_Button'],
                  duplicate_button=self._midimap['Duplicate_Button'],
                  double_button=self._midimap['Double_Loop_Button']))
        self._clip_delete_layer_mode = AddLayerMode(
            self._clip_actions_component,
            layer=Layer(delete_button=self._midimap['Delete_Button']))
        self._create_session_zooming_modes()
        self._create_session_mode()
        self._create_note_modes()
        self._create_device_mode()
        # self._create_user_mode()
        self._create_arrangement_mode()
        self._create_record_arm_mode()
        self._create_track_select_mode()
        self._create_mute_mode()
        self._create_solo_mode()
        self._create_volume_mode()
        self._create_pan_mode()
        self._create_sends_mode()
        self._create_stop_clips_mode()
        self._modes.layer = Layer(
            session_mode_button=self._midimap['Session_Mode_Button'],
            note_mode_button=self._midimap['Note_Mode_Button'],
            device_mode_button=self._midimap['Device_Mode_Button'],
            arrangement_mode_button=self._midimap['User_Mode_Button'],
            record_arm_mode_button=self._midimap['Record_Arm_Mode_Button'],
            track_select_mode_button=self._midimap['Track_Select_Mode_Button'],
            mute_mode_button=self._midimap['Mute_Mode_Button'],
            solo_mode_button=self._midimap['Solo_Mode_Button'],
            volume_mode_button=self._midimap['Volume_Mode_Button'],
            pan_mode_button=self._midimap['Pan_Mode_Button'],
            sends_mode_button=self._midimap['Sends_Mode_Button'],
            stop_clip_mode_button=self._midimap['Stop_Clip_Mode_Button'])
        self._modes.selected_mode = 'session_mode'
        self._on_layout_changed.subject = self._modes
        self._create_view_control_component()

    def _create_session_zooming_modes(self):
        session_zoom_layer = Layer(
            button_matrix=self._midimap['Main_Button_Matrix'],
            nav_left_button=self._midimap['Arrow_Left_Button'],
            nav_right_button=self._midimap['Arrow_Right_Button'],
            nav_up_button=self._midimap['Arrow_Up_Button'],
            nav_down_button=self._midimap['Arrow_Down_Button'])
        session_zooming_layer_mode = LayerMode(self._session_zoom,
                                               session_zoom_layer)
        self._session_zooming_manager = SessionZoomingManagerComponent(
            self._modes, is_enabled=False)
        session_zooming_button_layer_mode = LayerMode(
            self._session_zooming_manager,
            Layer(session_zooming_button=self._midimap['Session_Mode_Button']))
        self._prioritized_session_zooming_button_layer_mode = LayerMode(
            self._session_zooming_manager,
            Layer(session_zooming_button=self._midimap['Session_Mode_Button'],
                  priority=1))
        self._session_zooming_background = BackgroundComponent(
            name='Session_Zooming_Background')
        session_zooming_background_layer_mode = LayerMode(
            self._session_zooming_background,
            Layer(scene_launch_buttons=self.
                  _midimap['Scene_Launch_Button_Matrix'],
                  delete_button=self._midimap['Delete_Button'],
                  quantize_button=self._midimap['Quantize_Button'],
                  duplicate_button=self._midimap['Duplicate_Button'],
                  double_loop_button=self._midimap['Double_Loop_Button']))
        self._modes.add_mode('session_zooming_mode', [
            self._session_zooming_manager, session_zooming_button_layer_mode,
            session_zooming_layer_mode, session_zooming_background_layer_mode
        ])
        self._modes.add_mode('prioritized_session_zooming_mode', [
            partial(self._layout_switch, consts.SESSION_LAYOUT_SYSEX_BYTE),
            self._session_zooming_manager,
            self._prioritized_session_zooming_button_layer_mode,
            session_zooming_layer_mode, session_zooming_background_layer_mode,
            self.update
        ])

    def _create_session_mode(self):
        self._modes.add_mode(
            'session_mode', [
                partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
                self._session_layer_mode,
                self._session.update_navigation_buttons
            ],
            behaviour=CancelingReenterBehaviour('session_zooming_mode'))

    def _create_note_modes(self):
        note_mode_matrix_translation = self._create_translation(
            'Note_Mode_Matrix_Translation',
            consts.CHROM_MAP_CHANNEL,
            Layer(button_matrix=self._midimap['Main_Button_Matrix'],
                  note_button_matrix=self._midimap['Note_Button_Matrix'],
                  drum_matrix=self._midimap['Drum_Button_Matrix'],
                  mixer_button_matrix=self._midimap['Mixer_Button_Matrix']),
            should_enable=False)
        note_mode_scene_launch_translation = self._create_translation(
            'Note_Mode_Scene_Launch_Translation', consts.CHROM_MAP_CHANNEL,
            Layer(scene_launch_buttons=self.
                  _midimap['Scene_Launch_Button_Matrix']))
        scale_setup_mode_button_lighting = LedLightingComponent(
            name='LED_Lighting_Component',
            is_enabled=False,
            layer=Layer(button=self._midimap.with_shift('Note_Mode_Button')))
        drum_mode_note_matrix_translation = self._create_translation(
            'Drum_Mode_Note_Button_Translation',
            0,
            Layer(note_button_matrix=self._midimap['Note_Button_Matrix']),
            should_enable=False,
            should_reset=False)
        drum_group_layer_mode = LayerMode(
            self._drum_group,
            layer=Layer(
                scroll_up_button=self._midimap['Arrow_Left_Button'],
                scroll_down_button=self._midimap['Arrow_Right_Button'],
                scroll_page_up_button=self._midimap['Arrow_Up_Button'],
                scroll_page_down_button=self._midimap['Arrow_Down_Button'],
                drum_matrix=self._midimap['Drum_Button_Matrix'],
                select_button=self._midimap['Shift_Button'],
                delete_button=self._midimap['Delete_Button']))
        self._note_modes = SpecialModesComponent(name='Note_Modes')
        self._note_modes.add_mode('chromatic_mode', [
            partial(self._layout_setup, consts.NOTE_LAYOUT_SYSEX_BYTE),
            self._clip_delete_layer_mode, note_mode_matrix_translation,
            scale_setup_mode_button_lighting
        ])
        self._note_modes.add_mode('drum_mode', [
            partial(self._layout_setup,
                    consts.DRUM_LAYOUT_SYSEX_BYTE), self._setup_drum_group,
            drum_group_layer_mode, drum_mode_note_matrix_translation
        ])
        self._note_modes.add_mode('audio_mode', [
            partial(self._layout_setup, consts.AUDIO_LAYOUT_SYSEX_BYTE),
            self._clip_delete_layer_mode
        ])
        self._note_modes.set_enabled(False)
        self._modes.add_mode('note_mode', [
            note_mode_scene_launch_translation, self._note_modes,
            self._select_note_mode, self._select_target_track,
            self._clip_actions_component, self._show_playing_clip,
            self._set_clip_actions_type
        ],
                             behaviour=ReenterBehaviour(
                                 self.toggle_detail_view))
        self._session_record.set_modes_component(self._modes)
        self._session_record.set_note_mode_name('note_mode')

    def _create_device_mode(self):
        device_mode_scene_launch_translation = self._create_translation(
            'Device_Mode_Scene_Launch_Translation', consts.DEVICE_MAP_CHANNEL,
            Layer(scene_launch_buttons=self.
                  _midimap['Scene_Launch_Button_Matrix']))
        device_layer_mode = LayerMode(
            self._device,
            layer=Layer(
                parameter_controls=self._midimap['Slider_Button_Matrix']))
        device_nav_layer_mode = LayerMode(
            self._device_navigation,
            layer=Layer(
                device_nav_left_button=self._midimap['Arrow_Left_Button'],
                device_nav_right_button=self._midimap['Arrow_Right_Button']))
        device_background_layer_mode = LayerMode(
            self._device_background,
            layer=Layer(arrow_up_button=self._midimap['Arrow_Up_Button'],
                        arrow_down_button=self._midimap['Arrow_Down_Button']))
        self._modes.add_mode('device_mode', [
            partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
            self._device, device_layer_mode, device_nav_layer_mode,
            device_background_layer_mode, self._clip_actions_component,
            self._clip_delete_layer_mode, device_mode_scene_launch_translation,
            self._show_playing_clip, self._set_clip_actions_type
        ],
                             behaviour=ReenterBehaviour(
                                 self.toggle_detail_view))

    # def _create_user_mode(self):
    #     self._modes.add_mode('user_mode', [partial(self._layout_setup, consts.USER_LAYOUT_SYSEX_BYTE)])

    def _create_arrangement_mode(self):
        self._arrangement_mixer = SpecialMixerComponent(
            NUM_TRACKS,
            auto_name=True,
            is_enabled=True,
            invert_mute_feedback=True)
        self._arrangement_mixer.name = 'Arrangement_Mixer_Control'
        self._arrangement.set_mixer(self._arrangement_mixer)
        arrangement_mixer_layer_mode = LayerMode(
            self._arrangement_mixer,
            layer=Layer(
                track_select_buttons=self._midimap['Main_Button_Matrix'].
                submatrix[4, :],
                arm_buttons=self._midimap['Main_Button_Matrix'].submatrix[
                    7, :],
                solo_buttons=self._midimap['Main_Button_Matrix'].submatrix[
                    6, :],
                mute_buttons=self._midimap['Main_Button_Matrix'].submatrix[
                    5, :]))
        # LHS_layer_mode = LayerMode( quantize_button=self._midimap['Quantize_Button'] )
        self._modes.add_mode('arrangement_mode', [
            partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
            arrangement_mixer_layer_mode,
            self._arrangement.update_navigation_buttons
        ],
                             behaviour=ReenterBehaviour(
                                 self.toggle_detail_view))
        # self._arrangement_background = BackgroundComponent(name='Arrangement_Background')

    def _create_record_arm_mode(self):
        arm_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(arm_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('record_arm_mode', [
            partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
            self._session_layer_mode, arm_layer_mode,
            self._session_zooming_manager,
            self._prioritized_session_zooming_button_layer_mode,
            self._session.update_navigation_buttons
        ],
                             behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_track_select_mode(self):
        track_select_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(
                track_select_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('track_select_mode', [
            partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
            self._session_layer_mode, track_select_layer_mode,
            self._session_zooming_manager,
            self._prioritized_session_zooming_button_layer_mode,
            self._session.update_navigation_buttons
        ],
                             behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_mute_mode(self):
        mute_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(mute_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('mute_mode', [
            partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
            self._session_layer_mode, mute_layer_mode,
            self._session_zooming_manager,
            self._prioritized_session_zooming_button_layer_mode,
            self._session.update_navigation_buttons
        ],
                             behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_solo_mode(self):
        solo_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(solo_buttons=self._midimap['Mixer_Button_Matrix']))
        self._modes.add_mode('solo_mode', [
            partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
            self._session_layer_mode, solo_layer_mode,
            self._session_zooming_manager,
            self._prioritized_session_zooming_button_layer_mode,
            self._session.update_navigation_buttons
        ],
                             behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_volume_mode(self):
        volume_mode_scene_launch_translation = self._create_translation(
            'Volume_Mode_Scene_Launch_Translation', consts.VOLUME_MAP_CHANNEL,
            Layer(scene_launch_buttons=self.
                  _midimap['Scene_Launch_Button_Matrix']))
        volume_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(volume_controls=self._midimap['Slider_Button_Matrix']))
        self._modes.add_mode('volume_mode', [
            partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
            volume_layer_mode, self._action_button_background_layer_mode,
            self._session_zooming_manager,
            self._prioritized_session_zooming_button_layer_mode,
            volume_mode_scene_launch_translation,
            self._session.update_navigation_buttons
        ],
                             behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_pan_mode(self):
        pan_mode_scene_launch_translation = self._create_translation(
            'Pan_Mode_Scene_Launch_Translation', consts.PAN_MAP_CHANNEL,
            Layer(scene_launch_buttons=self.
                  _midimap['Scene_Launch_Button_Matrix']))
        pan_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(pan_controls=self._midimap['Slider_Button_Matrix']))
        self._modes.add_mode('pan_mode', [
            partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
            pan_layer_mode, self._action_button_background_layer_mode,
            self._session_zooming_manager,
            self._prioritized_session_zooming_button_layer_mode,
            pan_mode_scene_launch_translation,
            self._session.update_navigation_buttons
        ],
                             behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_sends_mode(self):
        send_layer_mode = LayerMode(
            self._mixer,
            layer=Layer(send_controls=self._midimap['Slider_Button_Matrix'],
                        send_select_buttons=self.
                        _midimap['Scene_Launch_Button_Matrix']))
        self._modes.add_mode('sends_mode', [
            partial(self._layout_setup, consts.FADER_LAYOUT_SYSEX_BYTE),
            send_layer_mode, self._action_button_background_layer_mode,
            self._session_zooming_manager,
            self._prioritized_session_zooming_button_layer_mode,
            self._session.update_navigation_buttons
        ],
                             behaviour=SpecialReenterBehaviour('session_mode'))

    def _create_stop_clips_mode(self):
        stop_layer_mode = AddLayerMode(
            self._session,
            Layer(
                stop_track_clip_buttons=self._midimap['Mixer_Button_Matrix'],
                stop_scene_clip_buttons=self.
                _midimap['Scene_Stop_Button_Matrix'],
                stop_all_clips_button=self._midimap['Stop_All_Clips_Button']))
        self._modes.add_mode('stop_clip_mode', [
            partial(self._layout_setup, consts.SESSION_LAYOUT_SYSEX_BYTE),
            self._session_layer_mode, stop_layer_mode,
            self._session_zooming_manager,
            self._prioritized_session_zooming_button_layer_mode,
            self._session.update_navigation_buttons
        ],
                             behaviour=SpecialReenterBehaviour('session_mode'))

    def toggle_detail_view(self):
        view = self.application().view
        if view.is_view_visible('Detail'):
            if view.is_view_visible('Detail/DeviceChain'):
                view.show_view('Detail/Clip')
            else:
                view.show_view('Detail/DeviceChain')

    # def _create_user(self):
    #     self._user_matrix_component = UserMatrixComponent(name='User_Matrix_Component', is_enabled=False, layer=Layer(user_button_matrix_ch_6=self._midimap['User_Button_Matrix_Ch_6'], user_button_matrix_ch_7=self._midimap['User_Button_Matrix_Ch_7'], user_button_matrix_ch_8=self._midimap['User_Button_Matrix_Ch_8'], user_button_matrix_ch_14=self._midimap['User_Button_Matrix_Ch_14'], user_button_matrix_ch_15=self._midimap['User_Button_Matrix_Ch_15'], user_button_matrix_ch_16=self._midimap['User_Button_Matrix_Ch_16'], user_left_side_button_matrix_ch_6=self._midimap['User_Left_Side_Button_Matrix_Ch_6'], user_left_side_button_matrix_ch_7=self._midimap['User_Left_Side_Button_Matrix_Ch_7'], user_left_side_button_matrix_ch_8=self._midimap['User_Left_Side_Button_Matrix_Ch_8'], user_left_side_button_matrix_ch_14=self._midimap['User_Left_Side_Button_Matrix_Ch_14'], user_left_side_button_matrix_ch_15=self._midimap['User_Left_Side_Button_Matrix_Ch_15'], user_left_side_button_matrix_ch_16=self._midimap['User_Left_Side_Button_Matrix_Ch_16'], user_right_side_button_matrix_ch_6=self._midimap['User_Right_Side_Button_Matrix_Ch_6'], user_right_side_button_matrix_ch_7=self._midimap['User_Right_Side_Button_Matrix_Ch_7'], user_right_side_button_matrix_ch_8=self._midimap['User_Right_Side_Button_Matrix_Ch_8'], user_right_side_button_matrix_ch_14=self._midimap['User_Right_Side_Button_Matrix_Ch_14'], user_right_side_button_matrix_ch_15=self._midimap['User_Right_Side_Button_Matrix_Ch_15'], user_right_side_button_matrix_ch_16=self._midimap['User_Right_Side_Button_Matrix_Ch_16'], user_bottom_button_matrix_ch_6=self._midimap['User_Bottom_Button_Matrix_Ch_6'], user_bottom_button_matrix_ch_7=self._midimap['User_Bottom_Button_Matrix_Ch_7'], user_bottom_button_matrix_ch_8=self._midimap['User_Bottom_Button_Matrix_Ch_8'], user_bottom_button_matrix_ch_14=self._midimap['User_Bottom_Button_Matrix_Ch_14'], user_bottom_button_matrix_ch_15=self._midimap['User_Bottom_Button_Matrix_Ch_15'], user_bottom_button_matrix_ch_16=self._midimap['User_Bottom_Button_Matrix_Ch_16'], user_arrow_button_matrix_ch_6=self._midimap['User_Arrow_Button_Matrix_Ch_6'], user_arrow_button_matrix_ch_7=self._midimap['User_Arrow_Button_Matrix_Ch_7'], user_arrow_button_matrix_ch_8=self._midimap['User_Arrow_Button_Matrix_Ch_8'], user_arrow_button_matrix_ch_14=self._midimap['User_Arrow_Button_Matrix_Ch_14'], user_arrow_button_matrix_ch_15=self._midimap['User_Arrow_Button_Matrix_Ch_15'], user_arrow_button_matrix_ch_16=self._midimap['User_Arrow_Button_Matrix_Ch_16']))
    #     self._user_matrix_component.set_enabled(True)

    def _create_view_control_component(self):
        return ViewControlComponent(name='View_Control')

    @subject_slot('drum_group')
    def _on_drum_group_changed(self):
        if self._note_modes.selected_mode == 'drum_mode':
            self._drum_group.set_drum_group_device(
                self._drum_group_finder.drum_group)
        if self._modes.selected_mode == 'note_mode':
            self._select_note_mode()
        else:
            self.release_controlled_track()
        self._update_note_mode_button(
            self._drum_group_finder.drum_group is not None)
        return

    def _select_note_mode(self):
        u"""
        Selects which note mode to use depending on the kind of
        current target track and its device chain.  Will also
        select the target if specified.
        """
        track = self._target_track_component.target_track
        drum_device = self._drum_group_finder.drum_group
        if track is None or track.is_foldable or track in self.song(
        ).return_tracks or track == self.song(
        ).master_track or track.is_frozen or track.has_audio_input:
            self._note_modes.selected_mode = 'audio_mode'
        else:
            if drum_device:
                self._note_modes.selected_mode = 'drum_mode'
            else:
                self._note_modes.selected_mode = 'chromatic_mode'
        self._modes.update()
        if self._note_modes.selected_mode == 'audio_mode':
            self.release_controlled_track()
        else:
            self.set_controlled_track(
                self._target_track_component.target_track)
        return

    def _select_target_track(self):
        track = self._target_track_component.target_track
        if track != self.song().view.selected_track:
            self.song().view.selected_track = track

    def _update_note_mode_button(self, focused_track_is_drum_track):
        button = self._midimap['Note_Mode_Button']
        if focused_track_is_drum_track:
            button.default_states = {
                True: 'Mode.Drum.On',
                False: 'Mode.Drum.Off'
            }
        else:
            button.default_states = {
                True: 'Mode.Chromatic.On',
                False: 'Mode.Chromatic.Off'
            }
        button.reset_state()
        self._modes.update()

    def _show_playing_clip(self):
        track = None
        if self._use_sel_track():
            track = self.song().view.selected_track
        else:
            track = self._target_track_component.target_track
        if track in self.song().tracks:
            slot_index = track.fired_slot_index
            if slot_index < 0:
                slot_index = track.playing_slot_index
            if slot_index >= 0:
                clip_slot = track.clip_slots[slot_index]
                self.song().view.highlighted_clip_slot = clip_slot
        return

    def _set_clip_actions_type(self):
        self._clip_actions_component.use_selected_track(self._use_sel_track())
        self._clip_actions_component.update()

    def _use_sel_track(self):
        return self._modes.selected_mode == 'device_mode'

    def _should_arm_track(self):
        return self._modes.selected_mode == 'record_arm_mode'

    @subject_slot('selected_mode')
    def _on_layout_changed(self, mode):
        if mode == 'note_mode':
            self.set_controlled_track(
                self._target_track_component.target_track)
        else:
            self.release_controlled_track()
        self._session_record.set_enabled(mode != 'arrangement_mode')
        self._transport.set_enabled(mode == 'arrangement_mode')
        # Flip between arranement and session views
        if mode == 'arrangement_mode':
            self.application().view.focus_view('Arranger')
        if mode == 'session_mode':
            self.application().view.focus_view('Session')

    @subject_slot('session_record')
    def _on_session_record_changed(self):
        status = self.song().session_record
        feedback_color = int(self._skin['Instrument.FeedbackRecord']
                             if status else self._skin['Instrument.Feedback'])
        self._c_instance.set_feedback_velocity(feedback_color)

    def _clear_send_cache(self):
        with self.component_guard():
            for control in self.controls:
                control.clear_send_cache()

    def _update_hardware(self):
        self._clear_send_cache()
        self.update()

    def _update_global_components(self):
        self._actions_component.update()
        self._session_record.update()
        self._modifier_background_component.update()

    def _layout_setup(self, mode):
        self._layout_switch(mode)
        self._clear_send_cache()
        self._update_global_components()

    def _layout_switch(self, mode):
        prefix = consts.SYSEX_STANDARD_PREFIX + consts.SYSEX_PARAM_BYTE_LAYOUT
        suffix = consts.SYSEX_STANDARD_SUFFIX
        self._send_midi(prefix + mode + suffix)
        self._last_sent_mode_byte = mode

    def port_settings_changed(self):
        self.set_highlighting_session_component(None)
        super(Launchpad_Pro_Custom, self).port_settings_changed()
        return

    def on_identified(self):
        self._send_challenge()

    def _send_challenge(self):
        challenge_bytes = []
        for index in range(4):
            challenge_bytes.append(self._challenge >> 8 * index & 127)

        challenge = consts.CHALLENGE_PREFIX + tuple(challenge_bytes) + (247, )
        self._send_midi(challenge)

    def _on_handshake_successful(self):
        self._do_send_midi(consts.LIVE_MODE_SWITCH_REQUEST)
        with self.component_guard():
            self._modes.set_enabled(True)
            self._actions_component.set_enabled(True)
            self._session_record.set_enabled(True)
            self._modifier_background_component.set_enabled(True)
            self._shifted_background.set_enabled(True)
            self.release_controlled_track()
            self.set_feedback_channels(consts.FEEDBACK_CHANNELS)
            self._transport.set_enabled(False)
        if self._last_sent_mode_byte is not None:
            self._layout_setup(self._last_sent_mode_byte)
        self.set_highlighting_session_component(self._session)
        self.update()
        return

    def _is_challenge_response(self, midi_bytes):
        return len(
            midi_bytes
        ) == 10 and midi_bytes[:7] == consts.SYSEX_STANDARD_PREFIX + consts.SYSEX_CHALLENGE_RESPONSE_BYTE

    def _is_response_valid(self, midi_bytes):
        response = long(midi_bytes[7])
        response += long(midi_bytes[8] << 8)
        return response == Live.Application.encrypt_challenge2(self._challenge)

    def handle_sysex(self, midi_bytes):
        if len(midi_bytes) < 7:
            pass
        else:
            if self._is_challenge_response(
                    midi_bytes) and self._is_response_valid(midi_bytes):
                self._on_handshake_successful()
            else:
                if midi_bytes[
                        6] == consts.SYSEX_STATUS_BYTE_LAYOUT and midi_bytes[
                            7] == consts.NOTE_LAYOUT_SYSEX_BYTE[0]:
                    self._update_hardware()
                else:
                    if midi_bytes[6] in (consts.SYSEX_STATUS_BYTE_MODE,
                                         consts.SYSEX_STATUS_BYTE_LAYOUT):
                        pass
                    else:
                        super(Launchpad_Pro_Custom,
                              self).handle_sysex(midi_bytes)
Exemple #19
0
class Roland_A_PRO(ControlSurface):

    def __init__(self, *a, **k):
        super(Roland_A_PRO, self).__init__(*a, **k)
        with self.component_guard():
            self._create_controls()
            self._create_transport()
            self._create_mixer()
            self._create_device()
            self._create_drums()
            self._create_modes()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[ EncoderElement(MIDI_CC_TYPE, 0, identifier, Live.MidiMap.MapMode.absolute, name='Encoder_%d' % index) for index, identifier in enumerate(ENCODER_IDS) ]])
        self._master_encoder = EncoderElement(MIDI_CC_TYPE, 0, 10, Live.MidiMap.MapMode.absolute, name='Master_Encoder')
        self._sliders = ButtonMatrixElement(rows=[[ SliderElement(MIDI_CC_TYPE, 0, identifier, name='Slider_%d' % index) for index, identifier in enumerate(SLIDER_IDS) ]])
        self._master_slider = SliderElement(MIDI_CC_TYPE, 0, 7, name='Master_Slider')
        self._play_button = ButtonElement(True, MIDI_CC_TYPE, 0, 26)
        self._stop_button = ButtonElement(True, MIDI_CC_TYPE, 0, 25)
        self._record_button = ButtonElement(True, MIDI_CC_TYPE, 0, 28)
        self._forward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 24)
        self._backward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 21)
        self._ff_button = ButtonElement(True, MIDI_CC_TYPE, 0, 23)
        self._rw_button = ButtonElement(True, MIDI_CC_TYPE, 0, 22)
        self._device_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 80)
        self._pan_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 81)
        self._send_a_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 82)
        self._send_b_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 83)
        self._pads = ButtonMatrixElement(rows=[ [ ButtonElement(True, MIDI_NOTE_TYPE, 0, identifier) for identifier in row ] for row in PAD_ROWS ])

    def _create_transport(self):
        self._transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=self._play_button, stop_button=self._stop_button, record_button=self._record_button))
        self._transport.set_enabled(True)

    def _create_mixer(self):
        mixer_size = self._sliders.width()
        self._mixer = MixerComponent(mixer_size, name='Mixer', is_enabled=False, layer=Layer(volume_controls=self._sliders, prehear_volume_control=self._master_encoder))
        self._mixer.master_strip().layer = Layer(volume_control=self._master_slider)
        self._mixer.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(device_selection_follows_track_selection=True)
        self._device_navigation = DeviceNavigationComponent()
        self._device.set_enabled(True)
        self._device_navigation.set_enabled(True)
        self.set_device_component(self._device)

    def _create_drums(self):
        self._drums = DrumRackComponent(name='Drum_Rack', is_enabled=False, layer=Layer(pads=self._pads))
        self._drums.set_enabled(True)

    def _create_modes(self):
        self._encoder_modes = ModesComponent()
        device_layer_mode = LayerMode(self._device, Layer(parameter_controls=self._encoders))
        device_navigation_layer_mode = LayerMode(self._device_navigation, Layer(device_nav_right_button=self._forward_button, device_nav_left_button=self._backward_button))
        self._encoder_modes.add_mode('device_mode', [device_layer_mode, device_navigation_layer_mode])
        self._encoder_modes.add_mode('pan_mode', AddLayerMode(self._mixer, Layer(pan_controls=self._encoders, bank_up_button=self._forward_button, bank_down_button=self._backward_button, track_up_button=self._ff_button, track_down_button=self._rw_button)))
        send_layer_mode = AddLayerMode(self._mixer, Layer(send_controls=self._encoders, bank_up_button=self._forward_button, bank_down_button=self._backward_button, track_up_button=self._ff_button, track_down_button=self._rw_button))
        self._encoder_modes.add_mode('send_a_mode', [send_layer_mode, partial(self._set_send_index, 0)])
        self._encoder_modes.add_mode('send_b_mode', [send_layer_mode, partial(self._set_send_index, 1)])
        self._encoder_modes.layer = Layer(device_mode_button=self._device_mode_button, pan_mode_button=self._pan_mode_button, send_a_mode_button=self._send_a_mode_button, send_b_mode_button=self._send_b_mode_button)
        self._encoder_modes.selected_mode = 'device_mode'
        self._encoder_modes.set_enabled(True)

    def _set_send_index(self, index):
        self._mixer.send_index = index
class Launchkey_MK2(OptimizedControlSurface):
    identity_request_delay = 0.5

    def __init__(self, c_instance, *a, **k):
        super(Launchkey_MK2, self).__init__(c_instance=c_instance, *a, **k)
        self._is_25_key_model = False
        self._is_in_control_on = True
        self._identity_response_pending = False
        with self.component_guard():
            self._skin = make_skin()
            with inject(skin=const(self._skin)).everywhere():
                self._create_controls()
        self._request_task = self._tasks.add(Task.sequence(Task.wait(self.identity_request_delay), Task.run(self._send_identity_request)))
        self._request_task.kill()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[ make_encoder(identifier, name=u'Encoder_%d' % (index,)) for index, identifier in enumerate(xrange(21, 29)) ]])
        self._top_pad_row = ButtonMatrixElement(rows=[[ make_button(identifier, name=u'Pad_0_%d' % (index,)) for index, identifier in enumerate(xrange(96, 104)) ]])
        self._bottom_pad_row_raw = [ make_button(identifier, name=u'Pad_1_%d' % (index,)) for index, identifier in enumerate(xrange(112, 120)) ]
        self._bottom_pad_row = ButtonMatrixElement(rows=[self._bottom_pad_row_raw])
        self._top_launch_button = make_button(104, name=u'Scene_Launch_Button')
        self._bottom_launch_button = make_button(120, name=u'Stop_All_Clips_Button')
        self._scene_up_button = make_button(112, MIDI_CC_TYPE, name=u'Scene_Up_Button')
        self._scene_down_button = make_button(113, MIDI_CC_TYPE, name=u'Scene_Down_Button')
        self._stop_button = make_button(114, MIDI_CC_TYPE, name=u'Stop_Button')
        self._play_button = make_button(115, MIDI_CC_TYPE, name=u'Play_Button')
        self._loop_button = make_button(116, MIDI_CC_TYPE, name=u'Loop_Button')
        self._record_button = make_button(117, MIDI_CC_TYPE, name=u'Record_Button')
        self._sliders = ButtonMatrixElement(rows=[[ make_slider(identifier, name=u'Slider_%d' % (index,)) for index, identifier in enumerate(xrange(41, 49)) ]])
        self._master_slider = make_slider(7, name=u'Master_Slider')
        self._25_key_slider = make_slider(7, name=u'Slider', channel=0)
        self._mute_buttons_raw = [ make_button(identifier, MIDI_CC_TYPE, name=u'Mute_Button_%d' % (index,)) for index, identifier in enumerate(xrange(51, 59)) ]
        self._mute_buttons = ButtonMatrixElement(rows=[self._mute_buttons_raw])
        self._master_button = make_button(59, MIDI_CC_TYPE, name=u'Master_Button')
        self._track_left_button = make_button(102, MIDI_CC_TYPE, name=u'Track_Left_Button')
        self._track_right_button = make_button(103, MIDI_CC_TYPE, name=u'Track_Right_Button')
        self._device_mode_button = self._bottom_pad_row_raw[0]
        self._pan_mode_button = self._bottom_pad_row_raw[1]
        self._send_mode_buttons = dict()
        for index in xrange(consts.MAX_SENDS):
            setattr(self, u'_send_%d_button' % (index,), self._bottom_pad_row_raw[index + 2])
            self._send_mode_buttons[u'send_%d_mode_button' % (index,)] = getattr(self, u'_send_%d_button' % (index,))

        self._extended_mode_button = make_button(12, name=u'Dummy_Extended_Mode_Button')
        self._extended_mode_button.add_value_listener(nop)
        self._encoder_incontrol_button = make_button(13, is_momentary=False, name=u'Encoder_InControl_Button')
        self._encoder_incontrol_button.add_value_listener(nop)
        self._slider_incontrol_button = make_button(14, is_momentary=False, name=u'Fader_InControl_Button')
        self._slider_incontrol_button.add_value_listener(nop)
        self._pad_incontrol_button = make_button(15, is_momentary=False, name=u'Pad_InControl_Button')
        self._pad_incontrol_button.add_value_listener(self._update_pads)
        self._encoder_incontrol_button2 = make_button(16, name=u'Encoder_InControl_Button')
        self._pad_in_control_status_button = make_button(11, name=u'Dummy_InControl_Button')

    def _create_session(self):
        self._session = SessionComponent(name=u'Session', is_enabled=False, num_tracks=self._top_pad_row.width(), num_scenes=self._top_pad_row.height(), enable_skinning=True, layer=Layer(clip_launch_buttons=self._top_pad_row, scene_launch_buttons=ButtonMatrixElement(rows=[[self._top_launch_button]]), stop_track_clip_buttons=self._bottom_pad_row, stop_all_clips_button=self._bottom_launch_button))
        self._session.set_rgb_mode(LIVE_COLORS_TO_MIDI_VALUES, RGB_COLOR_TABLE)
        self._session.set_mixer(self._mixer)
        self._session.set_enabled(True)

    def _setup_navigation(self):
        self._session_navigation = SessionNavigationComponent(is_enabled=False, name=u'Session_Navigation', layer=Layer(next_track_button=self._track_right_button, prev_track_button=self._track_left_button, next_scene_button=self._scene_down_button, prev_scene_button=self._scene_up_button))
        self._session_navigation.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(is_enabled=False, name=u'Transport', layer=Layer(play_button=self._play_button, stop_button=self._stop_button, loop_button=self._loop_button, record_button=self._record_button))
        self._transport.set_enabled(True)

    def _create_mixer(self):
        mixer_volume_layer = None
        if self._is_25_key_model:
            mixer_volume_layer = Layer(volume_control=self._25_key_slider)
        else:
            mixer_volume_layer = Layer(volume_controls=self._sliders)
        self._mixer = MixerComponent(is_enabled=False, name=u'Mixer', num_tracks=self._sliders.width(), layer=mixer_volume_layer)
        if not self._is_25_key_model:
            self._mixer.master_strip().layer = Layer(volume_control=self._master_slider)
        self._mixer.set_enabled(True)
        self._mute_button_modes = ModesComponent()
        mute_mode = AddLayerMode(self._mixer, Layer(mute_buttons=self._mute_buttons))
        solo_mode = AddLayerMode(self._mixer, Layer(solo_buttons=self._mute_buttons))
        self._mute_button_modes.add_mode(u'mute_mode', mute_mode)
        self._mute_button_modes.add_mode(u'solo_mode', solo_mode, behaviour=CancellableBehaviour())
        self._mute_button_modes.layer = Layer(solo_mode_button=self._master_button)
        self._mute_button_modes.selected_mode = u'mute_mode'
        self._mute_button_modes.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(name=u'Device', is_enabled=False, device_selection_follows_track_selection=True)
        self.set_device_component(self._device)
        self._device.set_enabled(True)

    def _create_background(self):
        self._background = BackgroundComponent(name=u'BackgroundComponent')

    def _create_encoder_modes(self):
        self._encoder_modes = DisablingModesComponent()
        self._encoder_modes.default_behaviour = mixin(SkinableBehaviourMixin, ImmediateBehaviour)()
        device_mode = LayerMode(self._device, Layer(parameter_controls=self._encoders, bank_buttons=self._top_pad_row))
        pan_mode = AddLayerMode(self._mixer, Layer(pan_controls=self._encoders))
        sends_mode = AddLayerMode(self._mixer, Layer(send_controls=self._encoders))
        background_mode = LayerMode(self._background, Layer(bank_buttons=self._top_pad_row))
        self._encoder_modes.add_mode(u'device_mode', device_mode, is_enabled=True)
        self._encoder_modes.add_mode(u'pan_mode', [pan_mode, background_mode], is_enabled=True)
        for index in xrange(6):
            self._encoder_modes.add_mode(u'send_%d_mode' % (index,), [sends_mode, partial(self._set_send_index, index), background_mode], is_enabled=False)

        self._encoder_modes.selected_mode = u'device_mode'
        self._encoder_modes.set_enabled(True)

    def _create_mode_selector(self):
        self._mode_selector = ModesComponent()
        mode_selection = LayerMode(self._encoder_modes, Layer(device_mode_button=self._device_mode_button, pan_mode_button=self._pan_mode_button, **self._send_mode_buttons))
        device_navigation = AddLayerMode(self._device, Layer(device_nav_left_button=self._track_left_button, device_nav_right_button=self._track_right_button))
        self._mode_selector.add_mode(u'mode_selection', [partial(self._toggle_in_control, True), mode_selection, device_navigation], behaviour=MomentaryBehaviour())
        session_control = AddLayerMode(self._session, Layer(clip_launch_buttons=self._top_pad_row))
        self._mode_selector.add_mode(u'session_mode', [partial(self._toggle_in_control, False), session_control])
        self._mode_selector.layer = Layer(mode_selection_button=self._encoder_incontrol_button2)

    def _create_in_control_status_listener(self):
        self._in_control_status = InControlStatusComponent(set_is_in_control_on=self._set_is_in_control_on, is_enabled=False, layer=Layer(in_control_status_button=self._pad_in_control_status_button))
        self._in_control_status.set_enabled(True)

    @subject_slot(u'value')
    def _update_pads(self, value):
        if value:
            self.update()

    @subject_slot(u'return_tracks')
    def _on_return_tracks_changed(self):
        num_sends = self._mixer.num_sends
        for index in xrange(6):
            self._encoder_modes.set_mode_enabled(u'send_%d_mode' % (index,), True if index < num_sends else False)

    def _set_send_index(self, index):
        self._mixer.send_index = index

    def _set_is_in_control_on(self, value):
        self._is_in_control_on = value

    def _toggle_in_control(self, value):
        if not self._is_in_control_on:
            self._send_midi(consts.DRUM_IN_CONTROL_ON_MESSAGE if value else consts.DRUM_IN_CONTROL_OFF_MESSAGE)

    def port_settings_changed(self):
        self._disconnect_and_unregister_all_components()
        self._request_task.restart()

    def handle_sysex(self, midi_bytes):
        if self._is_identity_response(midi_bytes):
            product_id_bytes = self._extract_product_id_bytes(midi_bytes)
            if self._is_identity_response_valid(product_id_bytes):
                self._set_model_type(product_id_bytes)
                self._request_task.kill()
                if self._identity_response_pending:
                    self.on_identified()
                    self._identity_response_pending = False
            else:
                self.log_message(u'MIDI device responded with wrong product id (%s).' % (str(product_id_bytes),))
        else:
            super(Launchkey_MK2, self).handle_sysex(midi_bytes)

    def _extract_product_id_bytes(self, midi_bytes):
        return midi_bytes[5:]

    def _is_identity_response(self, midi_bytes):
        return midi_bytes[3:5] == (6, 2)

    def _is_identity_response_valid(self, product_id_bytes):
        return product_id_bytes[:3] == consts.PRODUCT_ID_BYTE_PREFIX and product_id_bytes[3] in consts.PRODUCT_ID_BYTES

    def _set_model_type(self, product_id_bytes):
        self._is_25_key_model = product_id_bytes[3] == consts.LAUNCHKEY_25_ID_BYTE

    def _send_identity_request(self):
        self._identity_response_pending = True
        self._send_midi(consts.IDENTITY_REQUEST)

    def on_identified(self):
        self._extended_mode_button.turn_on()
        with self.component_guard():
            self._create_mixer()
            self._create_session()
            self._setup_navigation()
            self._create_transport()
            self._create_device()
            self._create_background()
            self._create_encoder_modes()
            self._create_mode_selector()
            self._create_in_control_status_listener()
            self._on_return_tracks_changed.subject = self.song()
            self._on_return_tracks_changed()
        self._mode_selector.selected_mode = u'session_mode'
        self.update()

    def disconnect(self):
        self._extended_mode_button.turn_off()
        super(Launchkey_MK2, self).disconnect()
Exemple #21
0
class APC_mini_custom(APC):
    # Connecting APC to ableton
    def _product_model_id_byte(self):
        return 40

    def _update_hardware(self):
        self._send_midi((240, 126, 127, 6, 1, 247))
        return

    def _on_identity_response(self, midi_bytes):
        super(APC_mini_custom, self)._on_identity_response(midi_bytes)

    def _send_dongle_challenge(self):
        pass

    def _on_handshake_successful(self):
        pass

    def print_message(self, message):
        self.log_message(message)
        self.show_message(message)

    def receive_midi(self, midi_bytes):
        self.print_message("Received " + str(midi_bytes))
        super(APC_mini_custom, self).receive_midi(midi_bytes)

    def really_send_midi(self, midi_bytes):
        #self.print_message("Sending " + str(midi_bytes))
        super(APC_mini_custom, self)._do_send_midi(midi_bytes)

    # Setting up
    def __init__(self, *a, **k):
        super(APC_mini_custom, self).__init__(*a, **k)
        disp.clearAll(self)
        #disp.splash(self)
        self.print_message("Initialized APC")
        self._skin = skins.make_skin()
        self._suppress_send_midi = False
        with self.component_guard():
            self.setup()

    def setup(self):
        self.setupStarted = True
        self.mute = self.song().master_track.devices[1].parameters[10]
        self._create_controls()
        self._cue_control = self._setup_cue_control()
        self._omni_control = self._setup_omni_control()
        self._master_controls = self._setup_master_controls()
        self._misc_controls = self._setup_misc_control()
        self._setup_transport_control()

    def _create_controls(self):
        make_color_button = partial(make_button, skin=self._skin)
        self._matrix_buttons = [
            make_color_button(0, i, name=b'Matrix_Button_%d' % i)
            for i in range(MATRIX_SIZE * MATRIX_SIZE)
        ]
        cue_rows = 3
        self._cue_buttons = [
            self._matrix_buttons[i] for r in range(cue_rows)
            for i in range(MATRIX_SIZE *
                           (MATRIX_SIZE -
                            (r + 1)), MATRIX_SIZE * (MATRIX_SIZE - r))
        ]
        for button in self._cue_buttons:
            button._skin = skins.get_cue_button()
        self._instrument_buttons = [
            self._matrix_buttons[i] for i in range(MATRIX_SIZE - 1)
        ]
        for button in self._instrument_buttons:
            button._skin = skins.get_instrument_button()

        self._omni_buttons = [
            self._matrix_buttons[MATRIX_SIZE * 3 + i]
            for i in range(MATRIX_SIZE)
        ]
        for button in self._omni_buttons:
            button._skin = skins.get_omni_button()
        self._vertical_buttons = [
            make_color_button(0, 82 + i, name="Vertical_Button_%d" % i)
            for i in range(MATRIX_SIZE)
        ]
        self._horizontal_buttons = [
            make_color_button(0, 64 + i, name="Horizontal_Button_%d" % i)
            for i in range(MATRIX_SIZE)
        ]

        self._left_button = self._horizontal_buttons[2]
        self._right_button = self._horizontal_buttons[3]

        self._master_add_volume_control = make_slider(
            0, 55, name=b'Master_Add_Volume_Control')
        self._master_sub_volume_control = make_slider(
            0, 56, name=b'Master_Sub_Volume_Control')
        self._master_mute_control = self._horizontal_buttons[7]
        self._master_mute_control._skin = skins.get_mute_button()

        self._splash_button = self._vertical_buttons[0]

    def _setup_cue_control(self):
        cue_control = CueComponent(self,
                                   name=b'Cue_Point_Control',
                                   play_on_cue=True)
        cue_control.set_cue_buttons(self._cue_buttons)
        cue_control.set_instrument_buttons(self._instrument_buttons)
        cue_control.set_enabled(True)
        return cue_control

    def _setup_omni_control(self):
        omni_control = OmniComponent(self, name=b"Omni_Control")
        omni_control.set_buttons(self._omni_buttons)
        omni_control.set_enabled(True)
        return omni_control

    def _setup_master_controls(self):
        self._master_mute_control.add_value_listener(
            self._on_master_mute_changed)
        return self._master_mute_control

    def _on_master_mute_changed(self, value):
        if (value > 0):
            if (self.mute.value < .5):
                self.mute.value = 1
                self._master_mute_control.set_light("On")
            else:
                self.mute.value = 0
                self._master_mute_control.set_light("Off")

    def _setup_misc_control(self):
        self._splash_button.add_value_listener(self._on_splash)
        self.splashing = False
        return self._splash_button

    def _on_splash(self, value):
        if (value > 0):
            if (self.splashing):
                self.splashing = False
                disp.clearAll(self)
                self._cue_control.reset_lights()
            else:
                self.splashing = True
                disp.splash(self)

    def _setup_transport_control(self):
        self._transport_control = TransportComponent(name=b'Transport')
        self._transport_control.set_enabled(True)
Exemple #22
0
class Roland_A_PRO(ControlSurface):
    def __init__(self, *a, **k):
        super(Roland_A_PRO, self).__init__(*a, **k)
        with self.component_guard():
            self._create_controls()
            self._create_transport()
            self._create_mixer()
            self._create_device()
            self._create_drums()
            self._create_modes()

    def _create_controls(self):
        self._encoders = ButtonMatrixElement(rows=[[
            EncoderElement(MIDI_CC_TYPE,
                           0,
                           identifier,
                           Live.MidiMap.MapMode.absolute,
                           name='Encoder_%d' % index)
            for index, identifier in enumerate(ENCODER_IDS)
        ]])
        self._master_encoder = EncoderElement(MIDI_CC_TYPE,
                                              0,
                                              10,
                                              Live.MidiMap.MapMode.absolute,
                                              name='Master_Encoder')
        self._sliders = ButtonMatrixElement(rows=[[
            SliderElement(
                MIDI_CC_TYPE, 0, identifier, name='Slider_%d' % index)
            for index, identifier in enumerate(SLIDER_IDS)
        ]])
        self._master_slider = SliderElement(MIDI_CC_TYPE,
                                            0,
                                            7,
                                            name='Master_Slider')
        self._play_button = ButtonElement(True, MIDI_CC_TYPE, 0, 26)
        self._stop_button = ButtonElement(True, MIDI_CC_TYPE, 0, 25)
        self._record_button = ButtonElement(True, MIDI_CC_TYPE, 0, 28)
        self._forward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 24)
        self._backward_button = ButtonElement(True, MIDI_CC_TYPE, 0, 21)
        self._ff_button = ButtonElement(True, MIDI_CC_TYPE, 0, 23)
        self._rw_button = ButtonElement(True, MIDI_CC_TYPE, 0, 22)
        self._device_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 80)
        self._pan_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 81)
        self._send_a_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 82)
        self._send_b_mode_button = ButtonElement(True, MIDI_CC_TYPE, 0, 83)
        self._pads = ButtonMatrixElement(rows=[[
            ButtonElement(True, MIDI_NOTE_TYPE, 0, identifier)
            for identifier in row
        ] for row in PAD_ROWS])

    def _create_transport(self):
        self._transport = TransportComponent(
            name='Transport',
            is_enabled=False,
            layer=Layer(play_button=self._play_button,
                        stop_button=self._stop_button,
                        record_button=self._record_button))
        self._transport.set_enabled(True)

    def _create_mixer(self):
        mixer_size = self._sliders.width()
        self._mixer = MixerComponent(
            mixer_size,
            name='Mixer',
            is_enabled=False,
            layer=Layer(volume_controls=self._sliders,
                        prehear_volume_control=self._master_encoder))
        self._mixer.master_strip().layer = Layer(
            volume_control=self._master_slider)
        self._mixer.set_enabled(True)

    def _create_device(self):
        self._device = DeviceComponent(
            device_selection_follows_track_selection=True)
        self._device_navigation = DeviceNavigationComponent()
        self._device.set_enabled(True)
        self._device_navigation.set_enabled(True)
        self.set_device_component(self._device)

    def _create_drums(self):
        self._drums = DrumRackComponent(name='Drum_Rack',
                                        is_enabled=False,
                                        layer=Layer(pads=self._pads))
        self._drums.set_enabled(True)

    def _create_modes(self):
        self._encoder_modes = ModesComponent()
        device_layer_mode = LayerMode(self._device,
                                      Layer(parameter_controls=self._encoders))
        device_navigation_layer_mode = LayerMode(
            self._device_navigation,
            Layer(device_nav_right_button=self._forward_button,
                  device_nav_left_button=self._backward_button))
        self._encoder_modes.add_mode(
            'device_mode', [device_layer_mode, device_navigation_layer_mode])
        self._encoder_modes.add_mode(
            'pan_mode',
            AddLayerMode(
                self._mixer,
                Layer(pan_controls=self._encoders,
                      bank_up_button=self._forward_button,
                      bank_down_button=self._backward_button,
                      track_up_button=self._ff_button,
                      track_down_button=self._rw_button)))
        send_layer_mode = AddLayerMode(
            self._mixer,
            Layer(send_controls=self._encoders,
                  bank_up_button=self._forward_button,
                  bank_down_button=self._backward_button,
                  track_up_button=self._ff_button,
                  track_down_button=self._rw_button))
        self._encoder_modes.add_mode(
            'send_a_mode', [send_layer_mode,
                            partial(self._set_send_index, 0)])
        self._encoder_modes.add_mode(
            'send_b_mode', [send_layer_mode,
                            partial(self._set_send_index, 1)])
        self._encoder_modes.layer = Layer(
            device_mode_button=self._device_mode_button,
            pan_mode_button=self._pan_mode_button,
            send_a_mode_button=self._send_a_mode_button,
            send_b_mode_button=self._send_b_mode_button)
        self._encoder_modes.selected_mode = 'device_mode'
        self._encoder_modes.set_enabled(True)

    def _set_send_index(self, index):
        self._mixer.send_index = index
Exemple #23
0
 def __init__(self, *a, **k):
     super(MPK261MXLOOP, self).__init__(*a, **k)
     self.show_message("-----------------------= MPK261MXLOOP LOADING - maxcloutier13 says hi =----------------------------------------------------------")
     self.log_message("-----------------------= MPK261MXLOOP LOADING - maxcloutier13 says hi =----------------------------------------------------------")
     with self.component_guard():
         midimap = MidiMap()
         #Sustain pedal 1 = Play/Record/Overdub switch for live looping
         self._LoopRecordButton = ButtonElement(True, MIDI_CC_TYPE, 0, 64)
         self._LoopRecordButton.add_value_listener(self._launch_clip, False)
         #Sustain pedal 2 = Sustain pour l'instant ;o)
         #self._LoopRecordButton = ButtonElement(True, MIDI_CC_TYPE, 0, 65)            
         #Control up/down/left/right using the daw controls            
         self._UpButton = ButtonElement(False, MIDI_CC_TYPE, 0, 88, name='UpButton')
         self._DownButton = ButtonElement(False, MIDI_CC_TYPE, 0, 89, name='DownButton')
         self._LeftButton = ButtonElement(False, MIDI_CC_TYPE, 0, 20, name='LeftButton')
         self._RightButton = ButtonElement(False, MIDI_CC_TYPE, 0, 21, name='RightButton')
         #Listeners for the functions
         self._UpButton.add_value_listener(self._move_up, False)
         self._DownButton.add_value_listener(self._move_down, False)
         self._LeftButton.add_value_listener(self._move_left, False)
         self._RightButton.add_value_listener(self._move_right, False)
         #Super crude manual init for the custom buttons and faders 
         #Control Bank A - Channel 1 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         self._Encoder0 = EncoderElement(MIDI_CC_TYPE,1,22, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder0')
         self._Encoder1 = EncoderElement(MIDI_CC_TYPE,1,23, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder1')
         self._Encoder2 = EncoderElement(MIDI_CC_TYPE,1,24, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder2')
         self._Encoder3 = EncoderElement(MIDI_CC_TYPE,1,25, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder3')
         self._Encoder4 = EncoderElement(MIDI_CC_TYPE,1,26, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder4')
         self._Encoder5 = EncoderElement(MIDI_CC_TYPE,1,27, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder5')
         self._Encoder6 = EncoderElement(MIDI_CC_TYPE,1,28, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder6')
         self._Encoder7 = EncoderElement(MIDI_CC_TYPE,1,29, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder7')
         self._ArmButton0 = ButtonElement(False, MIDI_CC_TYPE, 0, 32, name='ArmButton0')
         self._ArmButton1 = ButtonElement(False, MIDI_CC_TYPE, 0, 33, name='ArmButton1')
         self._ArmButton2 = ButtonElement(False, MIDI_CC_TYPE, 0, 34, name='ArmButton2')
         self._ArmButton3 = ButtonElement(False, MIDI_CC_TYPE, 0, 35, name='ArmButton3')
         self._ArmButton4 = ButtonElement(False, MIDI_CC_TYPE, 0, 36, name='ArmButton4')
         self._ArmButton5 = ButtonElement(False, MIDI_CC_TYPE, 0, 37, name='ArmButton5')
         self._ArmButton6 = ButtonElement(False, MIDI_CC_TYPE, 0, 38, name='ArmButton6')
         self._ArmButton7 = ButtonElement(False, MIDI_CC_TYPE, 0, 39, name='ArmButton7')
         self._VolumeSlider0 = SliderElement(MIDI_CC_TYPE, 0, 12, name='VolumeSlider0')
         self._VolumeSlider1 = SliderElement(MIDI_CC_TYPE, 0, 13, name='VolumeSlider1')
         self._VolumeSlider2 = SliderElement(MIDI_CC_TYPE, 0, 14, name='VolumeSlider2')
         self._VolumeSlider3 = SliderElement(MIDI_CC_TYPE, 0, 15, name='VolumeSlider3')
         self._VolumeSlider4 = SliderElement(MIDI_CC_TYPE, 0, 16, name='VolumeSlider4')
         self._VolumeSlider5 = SliderElement(MIDI_CC_TYPE, 0, 17, name='VolumeSlider5')
         self._VolumeSlider6 = SliderElement(MIDI_CC_TYPE, 0, 18, name='VolumeSlider6')
         self._VolumeSlider7 = SliderElement(MIDI_CC_TYPE, 0, 19, name='VolumeSlider7')
         #Control Bank B - Channel 2 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         self._Encoder8 = EncoderElement(MIDI_CC_TYPE,2,22, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder8')
         self._Encoder9 = EncoderElement(MIDI_CC_TYPE,2,23, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder9')
         self._Encoder10 = EncoderElement(MIDI_CC_TYPE,2,24, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder10')
         self._Encoder11 = EncoderElement(MIDI_CC_TYPE,2,25, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder11')
         self._Encoder12 = EncoderElement(MIDI_CC_TYPE,2,26, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder12')
         self._Encoder13 = EncoderElement(MIDI_CC_TYPE,2,27, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder13')
         self._Encoder14 = EncoderElement(MIDI_CC_TYPE,2,28, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder14')
         self._Encoder15 = EncoderElement(MIDI_CC_TYPE,2,29, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder15')
         self._ArmButton8 = ButtonElement(False, MIDI_CC_TYPE, 1, 32, name='ArmButton8')
         self._ArmButton9 = ButtonElement(False, MIDI_CC_TYPE, 1, 33, name='ArmButton9')
         self._ArmButton10 = ButtonElement(False, MIDI_CC_TYPE, 1, 34, name='ArmButton10')
         self._ArmButton11 = ButtonElement(False, MIDI_CC_TYPE, 1, 35, name='ArmButton11')
         self._ArmButton12 = ButtonElement(False, MIDI_CC_TYPE, 1, 36, name='ArmButton12')
         self._ArmButton13 = ButtonElement(False, MIDI_CC_TYPE, 1, 37, name='ArmButton13')
         self._ArmButton14 = ButtonElement(False, MIDI_CC_TYPE, 1, 38, name='ArmButton14')
         self._ArmButton15 = ButtonElement(False, MIDI_CC_TYPE, 1, 39, name='ArmButton15')
         self._VolumeSlider8 = SliderElement(MIDI_CC_TYPE, 1, 12, name='VolumeSlider8')
         self._VolumeSlider9 = SliderElement(MIDI_CC_TYPE, 1, 13, name='VolumeSlider9')
         self._VolumeSlider10 = SliderElement(MIDI_CC_TYPE, 1, 14, name='VolumeSlider10')
         self._VolumeSlider11 = SliderElement(MIDI_CC_TYPE, 1, 15, name='VolumeSlider11')
         self._VolumeSlider12 = SliderElement(MIDI_CC_TYPE, 1, 16, name='VolumeSlider12')
         self._VolumeSlider13 = SliderElement(MIDI_CC_TYPE, 1, 17, name='VolumeSlider13')
         self._VolumeSlider14 = SliderElement(MIDI_CC_TYPE, 1, 18, name='VolumeSlider14')
         self._VolumeSlider15 = SliderElement(MIDI_CC_TYPE, 1, 19, name='VolumeSlider15')
         #Control Bank C - Channel 3 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         self._Encoder16 = EncoderElement(MIDI_CC_TYPE,3,22, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder16')
         self._Encoder17 = EncoderElement(MIDI_CC_TYPE,3,23, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder17')
         self._Encoder18 = EncoderElement(MIDI_CC_TYPE,3,24, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder18')
         self._Encoder19 = EncoderElement(MIDI_CC_TYPE,3,25, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder19')
         self._Encoder20 = EncoderElement(MIDI_CC_TYPE,3,26, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder20')
         self._Encoder21 = EncoderElement(MIDI_CC_TYPE,3,27, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder21')
         self._Encoder22 = EncoderElement(MIDI_CC_TYPE,3,28, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder22')
         self._Encoder23 = EncoderElement(MIDI_CC_TYPE,3,29, Live.MidiMap.MapMode.relative_two_compliment, name='Encoder23')
         self._ArmButton16 = ButtonElement(False, MIDI_CC_TYPE, 2, 32, name='ArmButton16')
         self._ArmButton17 = ButtonElement(False, MIDI_CC_TYPE, 2, 33, name='ArmButton17')
         self._ArmButton18 = ButtonElement(False, MIDI_CC_TYPE, 2, 34, name='ArmButton18')
         self._ArmButton19 = ButtonElement(False, MIDI_CC_TYPE, 2, 35, name='ArmButton19')
         self._ArmButton20 = ButtonElement(False, MIDI_CC_TYPE, 2, 36, name='ArmButton20')
         self._ArmButton21 = ButtonElement(False, MIDI_CC_TYPE, 2, 37, name='ArmButton21')
         self._ArmButton22 = ButtonElement(False, MIDI_CC_TYPE, 2, 38, name='ArmButton22')
         self._ArmButton23 = ButtonElement(False, MIDI_CC_TYPE, 2, 39, name='ArmButton23')
         self._VolumeSlider16 = SliderElement(MIDI_CC_TYPE, 2, 12, name='VolumeSlider16')
         self._VolumeSlider17 = SliderElement(MIDI_CC_TYPE, 2, 13, name='VolumeSlider17')
         self._VolumeSlider18 = SliderElement(MIDI_CC_TYPE, 2, 14, name='VolumeSlider18')
         self._VolumeSlider19 = SliderElement(MIDI_CC_TYPE, 2, 15, name='VolumeSlider19')
         self._VolumeSlider20 = SliderElement(MIDI_CC_TYPE, 2, 16, name='VolumeSlider20')
         self._VolumeSlider21 = SliderElement(MIDI_CC_TYPE, 2, 17, name='VolumeSlider21')
         self._VolumeSlider22 = SliderElement(MIDI_CC_TYPE, 2, 18, name='VolumeSlider22')
         self._VolumeSlider23 = SliderElement(MIDI_CC_TYPE, 2, 19, name='VolumeSlider23')
         #Drum Bank A - Channel 4--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         self._Pad0 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 81, name='Pad0')
         self._Pad1 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 83, name='Pad1')
         self._Pad2 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 84, name='Pad2')
         self._Pad3 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 86, name='Pad3')
         self._Pad4 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 74, name='Pad4')
         self._Pad5 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 76, name='Pad5')
         self._Pad6 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 77, name='Pad6')
         self._Pad7 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 79, name='Pad7')
         self._Pad8 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 67, name='Pad8')
         self._Pad9 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 69, name='Pad9')
         self._Pad10 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 71, name='Pad10')
         self._Pad11 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 72, name='Pad11')
         self._Pad12 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 60, name='Pad12')
         self._Pad13 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 62, name='Pad13')
         self._Pad14 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 64, name='Pad14')
         self._Pad15 = ButtonElement(True, MIDI_NOTE_TYPE, 3, 65, name='Pad15')
         self._Pads = ButtonMatrixElement(rows=[[self._Pad0, self._Pad1, self._Pad2, self._Pad3],
                                                [self._Pad4, self._Pad5, self._Pad6, self._Pad7], 
                                                [self._Pad8, self._Pad9, self._Pad10, self._Pad11],
                                                [self._Pad12, self._Pad13, self._Pad14, self._Pad15]])
         #Drum Bank B -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         #Drum Bank C -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         #Drum Bank D -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         #
         #Drum rack -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         drum_rack = DrumRackComponent(name='Drum_Rack', is_enabled=False, layer=Layer(pads=self._Pads))
         drum_rack.set_enabled(True)
         #Transport -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=midimap['Play'], record_button=midimap['Record'], stop_button=midimap['Stop'], loop_button=midimap['Loop']))
         #, seek_forward_button=midimap['Forward'], seek_backward_button=midimap['Backward']
         transport.set_enabled(True)
         #Make the Back/Fwd button just normal mapable CC senders
         self._BackButton = ButtonElement(False, MIDI_CC_TYPE, 0, 116, name='BackButton')
         self._FwdButton = ButtonElement(False, MIDI_CC_TYPE, 0, 115, name='FwdButton')
         #Device -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         self._device = DeviceComponent(name='Device', is_enabled=False, layer=Layer(parameter_controls=midimap['Encoders']), device_selection_follows_track_selection=True)
         self._device.set_enabled(True)
         self.set_device_component(self._device)
         #Mixer -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         mixer_size = 24
         self._mixer = MixerComponent(mixer_size, name='Mixer', is_enabled=False)
         #Super crude and repetitive mapping because after all this shit I'm not spending time learning how to loop this crap hehe
         #Bank A
         self._mixer.channel_strip(0).layer = Layer(volume_control = self._VolumeSlider0, arm_button=self._ArmButton0, pan_control=self._Encoder0)
         self._mixer.channel_strip(1).layer = Layer(volume_control = self._VolumeSlider1, arm_button=self._ArmButton1, pan_control=self._Encoder1)
         self._mixer.channel_strip(2).layer = Layer(volume_control = self._VolumeSlider2, arm_button=self._ArmButton2, pan_control=self._Encoder2)
         self._mixer.channel_strip(3).layer = Layer(volume_control = self._VolumeSlider3, arm_button=self._ArmButton3, pan_control=self._Encoder3)
         self._mixer.channel_strip(4).layer = Layer(volume_control = self._VolumeSlider4, arm_button=self._ArmButton4, pan_control=self._Encoder4)
         self._mixer.channel_strip(5).layer = Layer(volume_control = self._VolumeSlider5, arm_button=self._ArmButton5, pan_control=self._Encoder5)
         self._mixer.channel_strip(6).layer = Layer(volume_control = self._VolumeSlider6, arm_button=self._ArmButton6, pan_control=self._Encoder6)
         self._mixer.channel_strip(7).layer = Layer(volume_control = self._VolumeSlider7, arm_button=self._ArmButton7, pan_control=self._Encoder7)
         #Bank B
         self._mixer.channel_strip(8).layer = Layer(volume_control = self._VolumeSlider8, arm_button=self._ArmButton8, pan_control=self._Encoder8)
         self._mixer.channel_strip(9).layer = Layer(volume_control = self._VolumeSlider9, arm_button=self._ArmButton9, pan_control=self._Encoder9)
         self._mixer.channel_strip(10).layer = Layer(volume_control = self._VolumeSlider10, arm_button=self._ArmButton10, pan_control=self._Encoder10)
         self._mixer.channel_strip(11).layer = Layer(volume_control = self._VolumeSlider11, arm_button=self._ArmButton11, pan_control=self._Encoder11)
         self._mixer.channel_strip(12).layer = Layer(volume_control = self._VolumeSlider12, arm_button=self._ArmButton12, pan_control=self._Encoder12)
         self._mixer.channel_strip(13).layer = Layer(volume_control = self._VolumeSlider13, arm_button=self._ArmButton13, pan_control=self._Encoder13)
         self._mixer.channel_strip(14).layer = Layer(volume_control = self._VolumeSlider14, arm_button=self._ArmButton14, pan_control=self._Encoder14)
         self._mixer.channel_strip(15).layer = Layer(volume_control = self._VolumeSlider15, arm_button=self._ArmButton15, pan_control=self._Encoder15)
         #Bank C     
         self._mixer.channel_strip(16).layer = Layer(volume_control = self._VolumeSlider16, arm_button=self._ArmButton16, pan_control=self._Encoder16)
         self._mixer.channel_strip(17).layer = Layer(volume_control = self._VolumeSlider17, arm_button=self._ArmButton17, pan_control=self._Encoder17)
         self._mixer.channel_strip(18).layer = Layer(volume_control = self._VolumeSlider18, arm_button=self._ArmButton18, pan_control=self._Encoder18)
         self._mixer.channel_strip(19).layer = Layer(volume_control = self._VolumeSlider19, arm_button=self._ArmButton19, pan_control=self._Encoder19)
         self._mixer.channel_strip(20).layer = Layer(volume_control = self._VolumeSlider20, arm_button=self._ArmButton20, pan_control=self._Encoder20)
         self._mixer.channel_strip(21).layer = Layer(volume_control = self._VolumeSlider21, arm_button=self._ArmButton21, pan_control=self._Encoder21)
         self._mixer.channel_strip(22).layer = Layer(volume_control = self._VolumeSlider22, arm_button=self._ArmButton22, pan_control=self._Encoder22)
         self._mixer.channel_strip(23).layer = Layer(volume_control = self._VolumeSlider23, arm_button=self._ArmButton23, pan_control=self._Encoder23)
         self._mixer.set_enabled(True)
         #Track change listener
         self.song().view.add_selected_track_listener(self._update_selected_device)
Exemple #24
0
class KeyLab(ArturiaControlSurface):
    def __init__(self, *a, **k):
        super(KeyLab, self).__init__(*a, **k)
        with self.component_guard():
            self._create_controls()
            self._create_display()
            self._create_device()
            self._create_drums()
            self._create_transport()
            self._create_session()
            self._create_session_recording()
            self._create_mixer()

    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))])

    def _create_display(self):
        self._display_line1, self._display_line2 = DisplayElement(
            16, 1), DisplayElement(16, 1)
        for index, display_line in enumerate(
            (self._display_line1, self._display_line2)):
            display_line.set_message_parts(SETUP_MSG_PREFIX + (4, 0, 96),
                                           SETUP_MSG_SUFFIX)
            display_line.segment(0).set_position_identifier((index + 1, ))

        def adjust_null_terminated_string(string, width):
            return string.ljust(width, b' ') + b'\x00'

        self._display_line1_data_source, self._display_line2_data_source = DisplayDataSource(
            adjust_string_fn=adjust_null_terminated_string), DisplayDataSource(
                adjust_string_fn=adjust_null_terminated_string)
        self._display_line1.segment(0).set_data_source(
            self._display_line1_data_source)
        self._display_line2.segment(0).set_data_source(
            self._display_line2_data_source)
        self._display_line1_data_source.set_display_string(b'KeyLab')
        self._display_line2_data_source.set_display_string(b'Ableton Live')

    def _create_device(self):
        self._device = DeviceComponent(
            name=b'Device',
            is_enabled=False,
            layer=Layer(parameter_controls=self._device_encoders),
            device_selection_follows_track_selection=True)
        self._device.set_enabled(True)
        self.set_device_component(self._device)
        self._device_navigation = DeviceNavigationComponent(
            name=b'Device_Navigation',
            is_enabled=False,
            layer=Layer(device_nav_left_button=self._device_left_button,
                        device_nav_right_button=self._device_right_button))
        self._device_navigation.set_enabled(True)

    def _create_drums(self):
        self._drums = DrumRackComponent(name=b'Drums',
                                        is_enabled=False,
                                        layer=Layer(pads=self._pads))
        self._drums.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(
            name=b'Transport',
            is_enabled=False,
            layer=Layer(play_button=self._play_button,
                        stop_button=self._stop_button,
                        record_button=self._record_button,
                        loop_button=self._loop_button))
        self._transport.set_enabled(True)

    def _create_session(self):
        self._session = SessionComponent(
            num_tracks=8,
            num_scenes=1,
            name=b'Session',
            is_enabled=False,
            layer=Layer(select_next_button=self._scene_down_button,
                        select_prev_button=self._scene_up_button,
                        selected_scene_launch_button=self._scene_launch_button,
                        stop_all_clips_button=self._stop_all_clips_button,
                        scene_select_encoder=self._vertical_scroll_encoder))
        self._session.set_enabled(True)

    def _create_session_recording(self):
        self._session_recording = SessionRecordingComponent(
            ClipCreator(),
            ViewControlComponent(),
            name=b'Session_Recording',
            is_enabled=False,
            layer=Layer(record_button=self._session_record_button))
        self._session_recording.set_enabled(True)

    def _create_mixer(self):
        self._mixer = MixerComponent(
            num_tracks=self._volume_sliders.width(),
            name=b'Mixer',
            is_enabled=False,
            layer=Layer(volume_controls=self._volume_sliders,
                        track_select_encoder=self._horizontal_scroll_encoder))
        self._mixer.master_strip().layer = Layer(
            volume_control=self._master_slider)
        self._mixer.set_enabled(True)

    def _collect_setup_messages(self):
        for hardware_id, identifier in izip(ENCODER_HARDWARE_IDS,
                                            ENCODER_MSG_IDS):
            self._setup_hardware_encoder(hardware_id, identifier,
                                         ENCODER_CHANNEL)

        for hardware_id, identifier in izip(SLIDER_HARDWARE_IDS,
                                            SLIDER_MSG_IDS):
            self._setup_hardware_slider(hardware_id, identifier,
                                        ENCODER_CHANNEL)

        for hardware_id, identifier in BUTTON_HARDWARE_AND_MESSAGE_IDS.itervalues(
        ):
            self._setup_hardware_button(hardware_id, identifier)

        for hardware_id, identifier in izip(PAD_HARDWARE_IDS, PAD_MSG_IDS):
            self._setup_hardware_pad(hardware_id, identifier)

    def _setup_hardware_encoder(self, hardware_id, identifier, channel=0):
        self._set_encoder_cc_msg_type(hardware_id, is_relative=True)
        self._set_identifier(hardware_id, identifier)
        self._set_channel(hardware_id, channel)

    def _setup_hardware_button(self, hardware_id, identifier, channel=0, **k):
        self._set_encoder_cc_msg_type(hardware_id)
        self._set_identifier(hardware_id, identifier)
        self._set_channel(hardware_id, channel)
        self._set_value_minimum(hardware_id)
        self._set_value_maximum(hardware_id)

    def _setup_hardware_pad(self,
                            hardware_id,
                            identifier,
                            channel=PAD_CHANNEL):
        self._set_pad_note_msg_type(hardware_id)
        self._set_identifier(hardware_id, identifier)
        self._set_channel(hardware_id, channel)

    def _set_pad_note_msg_type(self, hardware_id):
        self._collect_setup_message(MODE_PROPERTY, hardware_id, PAD_NOTE_MODE)
class OhmModes(ControlSurface):
	__module__ = __name__
	__doc__ = " OhmModes controller script "


	def __init__(self, c_instance):
		"""everything except the '_on_selected_track_changed' override and 'disconnect' runs from here"""
		ControlSurface.__init__(self, c_instance)
		self.set_suppress_rebuild_requests(True) # Turn off rebuild MIDI map until after we're done setting up

		"""MonoComponent specific variables - best not change these unless you know what you're doing"""
		self._version_check = 'b994'
		self._host_name = 'Ohm'
		self._color_type = 'OhmRGB'
		self._hosts = []
		self.hosts = []
		self._client = [None for index in range(6)]
		self._active_client = None

		self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< OhmModes ' + str(self._version_check) + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>') 		

		self._rgb = 0
		self._timer = 0
		self._touched = 0
		self.flash_status = 1
		self._backlight = 127
		self._backlight_type = 'static'
		self._ohm = 127
		self._ohm_type = 'static'
		self._pad_translations = PAD_TRANSLATION
		self._device_selection_follows_track_selection = FOLLOW
		self._keys_octave = 5
		self._keys_scale = 0

		self._tempo_buttons = None
		self._setup_monobridge()
		self._setup_controls()
		self._setup_transport_control() # Run the transport setup part of the script
		self._setup_mixer_control() # Setup the mixer object
		self._setup_session_control()  # Setup the session object 
		self._setup_device_control() # Setup the device object
		self._setup_crossfader()
		self._setup_ohmmod()
		self._setup_switchboard()
		self._setup_modes() 
		self._assign_page_constants()
		self._last_device = None

		self.set_suppress_rebuild_requests(False) #Turn rebuild back on, now that we're done setting up

		self.song().view.add_selected_track_listener(self._update_selected_device)
		self.show_message('OhmModes Control Surface Loaded')
		self._send_midi(tuple(switchxfader))
		if FORCE_TYPE is True:
			self._rgb = FORCE_COLOR_TYPE
		else:
			self.schedule_message(10, self.query_ohm, None)
	

	def query_ohm(self):
		#self.log_message('querying Ohm')
		self._send_midi(tuple(check_model))

	

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

		for callback in self._timer_callbacks:
			callback()

		self._timer = (self._timer + 1) % 256
		self.flash()
		self.strobe()
	

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

	def get_device_bank(self):
		return self._device._bank_index
	

	def _setup_controls(self):
		is_momentary = True
		self._fader = [None for index in range(8)]
		self._dial = [None for index in range(16)]
		self._button = [None for index in range(8)]
		self._menu = [None for index in range(6)]
		for index in range(8):
			self._fader[index] = MonoEncoderElement2(MIDI_CC_TYPE, CHANNEL, OHM_FADERS[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self)
			#self._fader[index].name = 'Fader_' + str(index), self
		for index in range(8):
			self._button[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_' + str(index), self)
		for index in range(16):
			self._dial[index] = CodecEncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_DIALS[index], Live.MidiMap.MapMode.absolute, 'Encoder_' + str(index), index, self)
			#self._dial[index].name = 'Dial_' + str(index)
		self._knobs = []
		for index in range(12):
			self._knobs.append(self._dial[index])
		for index in range(6):
			self._menu[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_MENU[index], 'Menu_' + str(index), self)	
		self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute)
		self._crossfader.name = "Crossfader"
		self._livid = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self)
		self._shift_l = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Page_Button_Left', self)
		self._shift_r = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Page_Button_Right', self)
		self._matrix = ButtonMatrixElement()
		self._matrix.name = 'Matrix'
		self._grid = [None for index in range(8)]
		self._monomod = ButtonMatrixElement()
		self._monomod.name = 'Monomod'
		for column in range(8):
			self._grid[column] = [None for index in range(8)]
			for row in range(8):
				self._grid[column][row] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, (column * 8) + row, 'Grid_' + str(column) + '_' + str(row), self)
		for row in range(5):
			button_row = []
			for column in range(7):
				button_row.append(self._grid[column][row])
			self._matrix.add_row(tuple(button_row)) 
		for row in range(8):
			button_row = []
			for column in range(8):
				button_row.append(self._grid[column][row])
			self._monomod.add_row(tuple(button_row))

		"""We'll also need to assign some of our controls to ButtonMatrixElements so that we can use them with the Session Zoom and the Mod components"""
		"""We use the same formula here:  first we create the holders:"""
		self._mod_matrix = ButtonMatrixElement()				#this is a standard _Framework object used by many of the other scripts
		self._mod_matrix.name = 'Matrix'
		self._dial_matrix = EncoderMatrixElement(self)		#this is a special Mono object, used specifically for the mod components
		self._dial_matrix.name = 'Dial_Matrix'
		self._dial_button_matrix = ButtonMatrixElement()	#this is a special Mono object, used specifically for the mod components
		self._dial_button_matrix.name = 'Dial_Button_Matrix'
		
		"""And then we fill the with the control elements that are assigned to them"""
		for row in range(4):		#we have 4 rows, and 4 columns, forming the 4x4 grid in the center of the controller
			button_row = []			#since the matrix is two dimensional, first we create the outer array,
			for column in range(4):
				button_row.append(self._grid[column+4][row])		#then we create the inner array.  The process is the same for the other controls here.
			self._mod_matrix.add_row(tuple(button_row)) 				#add_row() is a method of the ButtonMatrixElement.  You can look in its parent module to see how it works
		for row in range(3):
			dial_row = []
			for column in range(4):
				dial_row.append(self._dial[(row*4) + column])
			self._dial_matrix.add_row(tuple(dial_row))
		for row in range(3):
			dial_button_row = []
			for column in range(4):
				dial_button_row.append(self._grid[column][row])
			self._dial_button_matrix.add_row(tuple(dial_button_row))
		self._key = [self._grid[KEYS[index][1]][KEYS[index][0]] for index in range(32)]
		self._encoder = [self._dial[index] for index in range(12)]
		self._key_matrix = ButtonMatrixElement()
		button_row = []						#since we only use one row for the chopper, we can define a 1 dimensional button matrix for this one.   
		for column in range(16):			#We use the ButtonMatrixObject because it takes care of setting up callbacks for all the buttons easily when we need them later
			button_row.append(self._key[16 + column])
		self._key_matrix.add_row(tuple(button_row))
	

	def _setup_ohmmod(self):
		self._host = MonomodComponent(self)
		self._host.name = 'Monomod_Host'
		self.hosts = [self._host]
		self._hosts = [self._host]
		for index in range(6):
			self._client[index] = MonoClient(self, index)
			self._client[index].name = 'Client_' + str(index)
			#self._client[index]._mod_dial = self._encoder[index]
			self._client[index]._device_component.set_parameter_controls(tuple([self._dial[num] for num in range(12)]))		#assign the encoders to the clients so that we can control device parameters through our client
			self._client[index]._control_defs = {'dials':self._dial_matrix, 'buttons':self._dial_button_matrix, 'grid':self._mod_matrix, 'keys':self._key, 'knobs':[self._dial[num+12] for num in range(4)]}  #assign controls that raw data will be addressed at
		self._host._active_client = self._client[0]
		self._host._active_client._is_active = True
		self._host.connect_to_clients(self)
	

	def _setup_switchboard(self):
		self._switchboard = SwitchboardElement(self, self._client)
		self._switchboard.name = 'Switchboard'
	

	def _setup_modes(self):
		self._shift_mode = ShiftModeComponent(self) 
		self._shift_mode.name = 'Shift_Mode'
		self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r, self._livid)
		self._scale_mode = ScaleModeComponent(self)
		self._scale_mode.name = "Scale_Mode"
		self._octave_mode = OctaveModeComponent(self)
		self._octave_mode.name = "Octave_Mode"
		self._modNum = ModNumModeComponent(self, self.modNum_update) 
		self._modNum.name = 'Mod_Number'
		self._modNum.set_mode = self._modNum_set_mode(self._modNum)
		self._modNum.set_mode_buttons([self._menu[index] for index in range(6)])
	

	def _modNum_set_mode(self, modNum):
		def set_mode(mode):
			if modNum._is_enabled == True:
				assert isinstance(mode, int)
				assert (mode in range(modNum.number_of_modes()))
				if (modNum._mode_index != mode):
					modNum._mode_index = mode
					modNum.update()
		return set_mode
		
	

	def _setup_transport_control(self):
		self._transport = TransportComponent() 
		self._transport.name = 'Transport'
	

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

	def _setup_session_control(self):
		is_momentary = True
		num_tracks = 7
		num_scenes = 5 
		global session
		session = SessionComponent(num_tracks, num_scenes)
		session.name = "Session"
		self._session = session	
		session.set_offsets(0, 0)	 
		self._scene = [None for index in range(6)]
		for row in range(num_scenes):
			self._scene[row] = session.scene(row)
			self._scene[row].name = 'Scene_' + str(row)
			for column in range(num_tracks):
				clip_slot = self._scene[row].clip_slot(column)
				clip_slot.name = str(column) + '_Clip_Slot_' + str(row)		
		session.set_mixer(self._mixer)
		self._session_zoom = SessionZoomingComponent(session)	 
		self._session_zoom.name = 'Session_Overview'
	

	def _assign_session_colors(self):
		self.log_message('assign session colors')
		num_tracks = 7
		num_scenes = 5 
		self._session.set_stop_track_clip_value(STOP_CLIP_COLOR[self._rgb])
		for row in range(num_scenes): 
			for column in range(num_tracks):
				self._scene[row].clip_slot(column).set_triggered_to_play_value(CLIP_TRIGD_TO_PLAY_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_triggered_to_record_value(CLIP_TRIGD_TO_RECORD_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_stopped_value(CLIP_STOPPED_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_started_value(CLIP_STARTED_COLOR[self._rgb])
				self._scene[row].clip_slot(column).set_recording_value(CLIP_RECORDING_COLOR[self._rgb])		
		self._session_zoom.set_stopped_value(ZOOM_STOPPED_COLOR[self._rgb])
		self._session_zoom.set_playing_value(ZOOM_PLAYING_COLOR[self._rgb])
		self._session_zoom.set_selected_value(ZOOM_SELECTED_COLOR[self._rgb])
		for row in range(8):
			for column in range(8):
				self._grid[column][row].set_force_next_value()
		self._session.on_scene_list_changed()
		self._shift_mode.update()
	

	def _setup_device_control(self):
		self._device = DeviceComponent()
		self._device.name = 'Device_Component'
		self.set_device_component(self._device)
		self._device_navigator = DetailViewControllerComponent()
		self._device_navigator.name = 'Device_Navigator'
		self._device_selection_follows_track_selection = FOLLOW
	

	def device_follows_track(self, val):
		self._device_selection_follows_track_selection = (val == 1)
		return self
	

	def _setup_crossfader(self):
		self._mixer.set_crossfader_control(self._crossfader)
	

	def disconnect(self):
		"""clean things up on disconnect"""
		self.song().view.remove_selected_track_listener(self._update_selected_device)
		self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= OhmModes log closed =--------------") #Create entry in log file
		ControlSurface.disconnect(self)
		return None
	

	def _get_num_tracks(self):
		return self.num_tracks
	

	def flash(self):
		#if(self.flash_status > 0):
		for row in range(8):
			if(self._button[row]._flash_state > 0):
				self._button[row].flash(self._timer)
			for column in range(8):
				button = self._grid[column][row]
				if(button._flash_state > 0):
					button.flash(self._timer)
	

	def strobe(self):
		if(self._backlight_type != 'static'):
			if(self._backlight_type is 'pulse'):
				self._backlight = int(math.fabs(((self._timer * 16) % 64) -32) +32)
			if(self._backlight_type is 'up'):
				self._backlight = int(((self._timer * 8) % 64) + 16)
			if(self._backlight_type is 'down'):
				self._backlight = int(math.fabs(int(((self._timer * 8) % 64) - 64)) + 16)
		self._send_midi(tuple([176, 27, int(self._backlight)]))
		if(self._ohm_type != 'static'):
			if(self._ohm_type is 'pulse'):
				self._ohm = int(math.fabs(((self._timer * 16) % 64) -32) +32)
			if(self._ohm_type is 'up'):
				self._ohm = int(((self._timer * 8) % 64) + 16)
			if(self._ohm_type is 'down'):
				self._ohm = int(math.fabs(int(((self._timer * 8) % 64) - 64)) + 16)
		self._send_midi(tuple([176, 63, int(self._ohm)]))
		self._send_midi(tuple([176, 31, int(self._ohm)]))	
	

	def deassign_matrix(self):
		self._host._set_knobs(None)
		self._host._set_button_matrix(None)
		self._host.set_enabled(False)
		self._modNum.set_enabled(False)
		self.assign_alternate_mappings(0)
		self._scale_mode.set_mode_buttons(None)
		self._scale_mode.set_enabled(False)
		self._octave_mode.set_mode_buttons(None)
		self._octave_mode.set_enabled(False)
		#self._session_zoom.set_button_matrix(None)
		self._session_zoom.set_enabled(False)
		self._session_zoom.set_nav_buttons(None, None, None, None)
		self._session.set_track_bank_buttons(None, None)
		self._session.set_scene_bank_buttons(None, None)
		self._transport.set_enabled(False)
		for column in range(4):
			#self._mixer.track_eq(column).set_gain_controls(tuple([self._dial[column + 8], self._dial[column + 4], self._dial[column]]))
			self._mixer.track_eq(column)._gain_controls = None
			self._mixer.track_eq(column).set_enabled(False)	
		for column in range(7):
			self._mixer.channel_strip(column).set_crossfade_toggle(None)
			self._mixer.channel_strip(column).set_mute_button(None)
			self._mixer.channel_strip(column).set_solo_button(None)
			self._mixer.channel_strip(column).set_arm_button(None)
			self._mixer.channel_strip(column).set_send_controls(None)
			self._mixer.channel_strip(column).set_pan_control(None)
			self._mixer.track_eq(column).set_enabled(False)
			for row in range(5):
				self._scene[row].clip_slot(column).set_launch_button(None)
		for column in range(8):
			self._button[column]._on_value = SELECT_COLOR[self._rgb]
			for row in range(8):
				self._grid[column][row].set_channel(0)
				self._grid[column][row].release_parameter()
				self._grid[column][row].use_default_message()
				self._grid[column][row].set_enabled(True)
				self._grid[column][row].send_value(0, True)
				self._grid[column][row]._on_value = 127
				self._grid[column][row]._off_value = 0
		for index in range(6):
			self._menu[index]._on_value = 127
			self._menu[index]._off_value = 0
		for index in range(16):
			self._dial[index].use_default_message()
			self._dial[index].release_parameter()
			#self._dial[index].set_enabled(True)
		if(self._device._parameter_controls != None):
			for control in self._device._parameter_controls:
				control.release_parameter()
			self._device._parameter_controls = None
		self._device.set_enabled(False)
		self._device_navigator.set_enabled(False)
		self._mixer.update()
		self._matrix.reset()
		#self._transport.set_play_button(None)
		#self._transport.set_stop_button(None)	
		self.request_rebuild_midi_map()
	

	def _assign_page_constants(self):
		#self._session_zoom.set_zoom_button(self._button[7]) #commented out pn 070111
		self._session_zoom.set_zoom_button(self._grid[7][7]) #added pn 070111
		self._session_zoom.set_button_matrix(self._matrix)
		#self._session_zoom.set_enabled(True)
		for column in range(7):
			self._mixer.channel_strip(column).set_select_button(self._button[column])
			self._mixer.channel_strip(column).set_volume_control(self._fader[column])
		self._mixer.master_strip().set_volume_control(self._fader[7])
		self._mixer.master_strip().set_select_button(self._button[7]) #added pn 070111
		self._mixer.set_prehear_volume_control(self._dial[15])
		self._transport.set_play_button(self._menu[0])
		self._menu[0].send_value(PLAY_COLOR[self._rgb], True)	
		self._menu[0]._on_value = PLAY_COLOR[self._rgb]
		self._transport.set_stop_button(self._menu[1])
		self._menu[1]._off_value = STOP_COLOR[self._rgb]
		self._menu[1]._on_value = STOP_COLOR[self._rgb]
		self._menu[1].send_value(STOP_COLOR[self._rgb], True)	
		#self._livid._on_value = TAP_COLOR[self._rgb]
		#self._transport.set_tap_tempo_button(self._livid)
		#self._livid.send_value(TAP_COLOR, True)
		self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[4])
	

	def assign_page_0(self):
		self._backlight_type = 'static'
		#self._session_zoom.set_button_matrix(self._matrix)
		self._session_zoom.set_enabled(True)
		for column in range(7):
			self._grid[column][5]._on_value = MUTE_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
			self._grid[column][6]._on_value = SOLO_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_solo_button(self._grid[column][6])
			self._grid[column][7]._on_value = ARM_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_arm_button(self._grid[column][7])
			self._mixer.channel_strip(column).set_pan_control(self._dial[column + 8])
			for row in range(5):
				self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])
		for column in range(4):
			self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column], self._dial[column + 4]]))
		for index in range(5):
			self._grid[7][index]._off_value = SCENE_LAUNCH_COLOR[self._rgb]
			self._scene[index].set_launch_button(self._grid[7][index])
			self._grid[7][index].set_force_next_value()
			self._grid[7][index].turn_off()
		for index in range(4):
			self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb]
		self._session.set_track_bank_buttons(self._menu[4], self._menu[3])
		self._session.set_scene_bank_buttons(self._menu[5], self._menu[2])	
		self._menu[0]._on_value = PLAY_COLOR[self._rgb]
		self._menu[1]._off_value = STOP_COLOR[self._rgb]
		self._menu[1]._on_value = STOP_COLOR[self._rgb]
		self._transport.set_enabled(True)
	

	def assign_page_1(self):
		self._backlight_type = 'pulse'
		self._session_zoom.set_enabled(False)
		for column in range(4):
			for row in range(4):
				self._grid[column][row].set_channel(PAGE1_DRUM_CHANNEL)
				self._grid[column][row].set_identifier(PAGE1_DRUM_MAP[column][row])
				self._grid[column][row].send_value(DRUM_COLOR[self._rgb], True)
				self._grid[column][row].set_enabled(False)
				self._grid[column + 4][row].set_channel(PAGE1_BASS_CHANNEL)
				self._grid[column + 4][row].set_identifier(PAGE1_BASS_MAP[column][row])
				self._grid[column + 4][row].send_value(BASS_COLOR[self._rgb], True)
				self._grid[column + 4][row].set_enabled(False)
		scale_mode_buttons = []
		for column in range(8):
			for row in range(3):
				self._grid[column][row + 4].set_enabled(False)
				self._grid[column][row + 4].set_channel(PAGE1_KEYS_CHANNEL)
				self._grid[column][row + 4].set_identifier(int(PAGE1_KEYS_MAP[column][row]) + int(PAGE1_MODES_MAP[self._scale_mode._mode_index][column]) + int(self._octave_mode._mode_index * 12))
				self._grid[column][row + 4].send_value(KEYS_COLOR[self._rgb], True)
			for row in range(1):
				scale_mode_buttons.append(self._grid[column][7])
		self._scale_mode.set_mode_buttons(tuple(scale_mode_buttons))
		self._scale_mode.set_enabled(True)
		self._octave_mode.set_mode_buttons(tuple([self._menu[5], self._menu[2]]))
		self._octave_mode.set_enabled(True)
		for column in range(7):
			self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column + 8]]))
			self._mixer.channel_strip(column).set_arm_button(self._button[column])
		self._device.set_enabled(True)
		device_param_controls = []
		for index in range(8):
			device_param_controls.append(self._dial[index])
		self._device.set_parameter_controls(tuple(device_param_controls))
		self._menu[0]._on_value = (PLAY_COLOR[self._rgb])
		for index in range(4):
			self._menu[2 + index]._on_value = (DEVICE_NAV_COLOR[self._rgb])
		self._device_navigator.set_enabled(True)
		self._menu[0]._on_value = PLAY_COLOR[self._rgb]
		self._menu[1]._off_value = STOP_COLOR[self._rgb]
		self._menu[1]._on_value = STOP_COLOR[self._rgb]
		self._transport.set_enabled(True)
	

	def assign_page_2(self):
		self._backlight_type = 'up'
		#self._session_zoom.set_button_matrix(self._matrix)
		self._session_zoom.set_enabled(True)
		for column in range(7):
			self._grid[column][5]._on_value = MUTE_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
			self._grid[column][6]._on_value = CROSSFADE_ASSIGN_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_crossfade_toggle(self._grid[column][6])
			self._grid[column][7].set_channel(2)
			self._grid[column][7].set_identifier(column)
			self._grid[column][7].reset()
			self._grid[column][7].set_enabled(False)
			self._grid[column][7].send_value(4, True)
			for row in range(5):
				self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])
		for row in range(5):
			self._grid[7][row]._off_value = SCENE_LAUNCH_COLOR[self._rgb]
			self._scene[row].set_launch_button(self._grid[7][row])
			self._grid[7][row].set_force_next_value()
			self._grid[7][row].turn_off()
		for column in range(4):
			self._mixer.track_eq(column).set_gain_controls(tuple([self._dial[column + 8], self._dial[column + 4], self._dial[column]]))
			self._mixer.track_eq(column).set_enabled(True)	
		for column in range(3):
			self._mixer.channel_strip(column+4).set_pan_control(self._dial[column + 12])
		for index in range(4):
			self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb]
		self._session.set_track_bank_buttons(self._menu[4], self._menu[3])
		self._session.set_scene_bank_buttons(self._menu[5], self._menu[2])
		self._set_tempo_buttons([self._grid[7][5], self._grid[7][6]])
		self._menu[0]._on_value = PLAY_COLOR[self._rgb]
		self._menu[1]._off_value = STOP_COLOR[self._rgb]
		self._menu[1]._on_value = STOP_COLOR[self._rgb]
		self._transport.set_enabled(True)
	

	"""
	def assign_page_0(self):
		self._backlight_type = 'static'
		#self._session_zoom.set_button_matrix(self._matrix)
		self._transport.set_play_button(self._menu[0])
		self._transport.set_stop_button(self._menu[1])
		self._session_zoom.set_enabled(True)
		for column in range(7):
			self._grid[column][5]._on_value = MUTE_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
			self._grid[column][6]._on_value = SOLO_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_solo_button(self._grid[column][6])
			self._grid[column][7]._on_value = ARM_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_arm_button(self._grid[column][7])
			self._mixer.channel_strip(column).set_pan_control(self._dial[column + 8])
			for row in range(5):
				self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])
		for column in range(4):
			self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column], self._dial[column + 4]]))
		for index in range(5):
			self._grid[7][index]._off_value = SCENE_LAUNCH_COLOR[self._rgb]
			self._scene[index].set_launch_button(self._grid[7][index])
		for index in range(4):
			self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb]
		self._session.set_track_bank_buttons(self._menu[4], self._menu[3])
		self._session.set_scene_bank_buttons(self._menu[5], self._menu[2])
	

	def assign_page_1(self):
		self._backlight_type = 'pulse'
		self._transport.set_play_button(self._menu[0])
		self._transport.set_stop_button(self._menu[1])
		self._session_zoom.set_enabled(False)
		for column in range(8):
			for row in range(8):
				self._grid[row][column].set_channel(JESSE_MAP_CHAN)
				self._grid[row][column].set_identifier(JESSE_MAP[column][row])
				self._grid[row][column].send_value(JESSE_MAP_COLORS[self._rgb], True)
				self._grid[row][column].set_enabled(False)
				""self._grid[column + 4][row].set_channel(PAGE1_BASS_CHANNEL)
				self._grid[column + 4][row].set_identifier(PAGE1_BASS_MAP[column][row])
				self._grid[column + 4][row].send_value(BASS_COLOR[self._rgb], True)
				self._grid[column + 4][row].set_enabled(False)
		scale_mode_buttons = []
		for column in range(8):
			for row in range(3):
				self._grid[column][row + 4].set_enabled(False)
				self._grid[column][row + 4].set_channel(PAGE1_KEYS_CHANNEL)
				self._grid[column][row + 4].set_identifier(int(PAGE1_KEYS_MAP[column][row]) + int(PAGE1_MODES_MAP[self._scale_mode._mode_index][column]) + int(self._octave_mode._mode_index * 12))
				self._grid[column][row + 4].send_value(KEYS_COLOR[self._rgb], True)
			for row in range(1):
				scale_mode_buttons.append(self._grid[column][7])""
		#self._scale_mode.set_mode_buttons(tuple(scale_mode_buttons))
		#self._scale_mode.set_enabled(True)
		#self._octave_mode.set_mode_buttons(tuple([self._menu[5], self._menu[2]]))
		#self._octave_mode.set_enabled(True)
		for column in range(7):
			self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column + 8]]))
			self._mixer.channel_strip(column).set_arm_button(self._button[column])
		self._device.set_enabled(True)
		device_param_controls = []
		for index in range(8):
			device_param_controls.append(self._dial[index])
		self._device.set_parameter_controls(tuple(device_param_controls))
		for index in range(4):
			self._menu[2 + index]._on_value = (DEVICE_NAV_COLOR[self._rgb])
		self._device_navigator.set_enabled(True)
	

	def assign_page_2(self):
		self._backlight_type = 'up'
		self._transport.set_play_button(self._menu[0])
		self._transport.set_stop_button(self._menu[1])
		#self._session_zoom.set_button_matrix(self._matrix)
		self._session_zoom.set_enabled(True)
		for column in range(7):
			self._grid[column][5]._on_value = MUTE_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_mute_button(self._grid[column][5])
			self._grid[column][6]._on_value = CROSSFADE_ASSIGN_COLOR[self._rgb]
			self._mixer.channel_strip(column).set_crossfade_toggle(self._grid[column][6])
			self._grid[column][7].set_channel(2)
			self._grid[column][7].set_identifier(column)
			self._grid[column][7].reset()
			self._grid[column][7].set_enabled(False)
			self._grid[column][7].send_value(4, True)
			for row in range(5):
				self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row])
		for row in range(5):
			self._grid[7][row]._off_value = SCENE_LAUNCH_COLOR[self._rgb]
			self._scene[row].set_launch_button(self._grid[7][row])
		for column in range(4):
			self._mixer.track_eq(column).set_gain_controls(tuple([self._dial[column + 8], self._dial[column + 4], self._dial[column]]))
			self._mixer.track_eq(column).set_enabled(True)	
		for column in range(3):
			self._mixer.channel_strip(column+4).set_pan_control(self._dial[column + 12])
		for index in range(4):
			self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb]
		self._session.set_track_bank_buttons(self._menu[4], self._menu[3])
		self._session.set_scene_bank_buttons(self._menu[5], self._menu[2])
		self._set_tempo_buttons([self._grid[7][5], self._grid[7][6]])
	
	"""


	def assign_mod(self):
		self.deassign_matrix()
		#self.set_local_ring_control(self._host._active_client._local_ring_control)
		self._host.set_enabled(True)
		self._modNum.set_enabled(True)
		self._host._set_dial_matrix(self._dial_matrix, self._dial_button_matrix)
		self._host._set_button_matrix(self._mod_matrix)
		self._host._set_key_buttons(tuple(self._key))
		if not self._host._active_client.is_connected():
			self.assign_alternate_mappings(self._modNum._mode_index + 1)
	

	def modNum_update(self):
		if self._modNum._is_enabled == True:
			self.assign_alternate_mappings(0)
			self._host._select_client(int(self._modNum._mode_index))
			self._host.display_active_client()
			if not self._host._active_client.is_connected():
				self.assign_alternate_mappings(self._modNum._mode_index + 1)
			for button in self._modNum._modes_buttons:
				if self._modNum._mode_index == self._modNum._modes_buttons.index(button):
					button.send_value(1)
				else:
					button.send_value(self._client[self._modNum._modes_buttons.index(button)]._mod_color)
				#button.send_value(int(self._modNum._mode_index == self._modNum._modes_buttons.index(button))*self._host._active_client._mod_color)
	

	def assign_alternate_mappings(self, chan):
		for column in range(8):
			for row in range(8):
				#self._grid[column][row].set_identifier(OHM_MAP_ID[column][row])
				self._grid[column][row].set_channel(chan)
				#self._grid[column][row].send_value(OHM_MAP_VALUE[column][row])
				self._grid[column][row].set_enabled(chan is 0)
		for knob in self._encoder:
			knob.set_channel(chan)
			knob.set_enabled(chan is 0)
		self.request_rebuild_midi_map()
	

	def display_mod_colors(self):
		#for index in range(6):							#set up a recursion of 6
		#	self._modNum._modes_buttons[index].send_value(self._client[index]._mod_color)		#update the modLEDs to display the color assigned to its contained mod
		pass
	

	def _update_selected_device(self):
		if self._device_selection_follows_track_selection is True:
			track = self.song().view.selected_track
			device_to_select = track.view.selected_device
			if device_to_select == None and len(track.devices) > 0:
				device_to_select = track.devices[0]
			if device_to_select != None:
				self.song().view.select_device(device_to_select)
			#self._device.set_device(device_to_select)
			self.set_appointed_device(device_to_select)
			#self._device_selector.set_enabled(True)
			self.request_rebuild_midi_map()
		return None
	

	def handle_sysex(self, midi_bytes):
		#self.log_message(str('>>sysexIN') + str(midi_bytes))
		if len(midi_bytes) > 10:
			#self.log_message(str('>>sysex>10') + str(midi_bytes[:11]))
			if midi_bytes[:11] == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 7]):
				self.log_message(str('>>>color detected'))
				self._rgb = 0
			elif midi_bytes[:11] == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 2]):
				self.log_message(str('>>>mono detected'))
				self._rgb = 1
		self._assign_session_colors()
	

	"""this method can be linked to from m4l, and provides a way to update the parameter value of an assigned DeviceComponent parameter control"""
	def to_encoder(self, num, val):
		rv=int(val*127)
		self._device._parameter_controls[num].receive_value(rv)
		p = self._device._parameter_controls[num]._parameter_to_map_to
		newval = (val * (p.max - p.min)) + p.min
		p.value = newval
	

	"""this method sets the instance variable for local ring control, and sends the appropriate sysex string to change states on the CNTRLR"""
	def set_local_ring_control(self, val = 1):
		self._local_ring_control = (val!=0)
		"""if(self._local_ring_control is True):
			self._send_midi(tuple([240, 0, 1, 97, 8, 32, 0, 247]))
		else:
			self._send_midi(tuple([240, 0, 1, 97, 8, 32, 1, 247]))"""
	

	"""this method sets the instance variable for absolute encoder changes, and sends the appropriate sysex string to change states on the CNTRLR"""			
	def set_absolute_mode(self, val = 1):
		self._absolute_mode = (val!=0)
		"""if self._absolute_mode is True:
			self._send_midi(tuple([240, 0, 1, 97, 8, 17, 0, 0, 0, 0, 0, 0, 0, 0, 247]))
		else:
			self._send_midi(tuple([240, 0, 1, 97, 8, 17, 127, 127, 127, 127, 127, 127, 127, 127, 247]))"""
	

	"""this method is used to update the individual elements of the encoder rings when the CNTRLR is in local ring control mode"""
	def send_ring_leds(self):
		"""if self._host._is_enabled == True:
			leds = [240, 0, 1, 97, 8, 31]
			for index in range(12):
				wheel = self._encoder[index]
				bytes = wheel._get_ring()
				leds.append(bytes[0])
				leds.append(int(bytes[1]) + int(bytes[2]))
			leds.append(247)
			self._send_midi(tuple(leds))"""
		pass
	

	def receive_midi(self, midi_bytes):
		""" Live -> Script
		MIDI messages are only received through this function, when explicitly 
		forwarded in 'build_midi_map'.
		"""
		assert (midi_bytes != None)
		assert isinstance(midi_bytes, tuple)
		##self.log_message('got message' + str(midi_bytes))
		self.set_suppress_rebuild_requests(True)
		if (len(midi_bytes) is 3):
			msg_type = (midi_bytes[0] & 240)
			forwarding_key = [midi_bytes[0]]
			if (msg_type is not MIDI_PB_TYPE):
				forwarding_key.append(midi_bytes[1])
			if (tuple(forwarding_key) in self._forwarding_registry.keys()):
				recipient = self._forwarding_registry[tuple(forwarding_key)]
				if (recipient != None):
					recipient.receive_value(midi_bytes[2])
			else:
				self.log_message(('Got unknown message: ' + str(midi_bytes)))
		else:
			self.handle_sysex(midi_bytes)
		self.set_suppress_rebuild_requests(False)		 
	

	def _set_tempo_buttons(self, buttons):
		if self._tempo_buttons != None:
			self._tempo_buttons[0].remove_value_listener(self._tempo_value)
			self._tempo_buttons[1].remove_value_listener(self._tempo_value)
		self._tempo_buttons = buttons
		if buttons != None:
			for button in buttons:
				assert isinstance(button, FlashingButtonElement)
			self._tempo_buttons[0].set_on_off_values(4, 0)
			self._tempo_buttons[0].add_value_listener(self._tempo_value, True)
			self._tempo_buttons[1].set_on_off_values(4, 0)
			self._tempo_buttons[1].add_value_listener(self._tempo_value, True)
			self._tempo_buttons[0].turn_on()
			self._tempo_buttons[1].turn_on()
	

	def _tempo_value(self, value, sender):
		if (value > 0) and (self._tempo_buttons.index(sender) == 0):
			self.song().tempo = round(min((self.song().tempo + 1), 999))
		elif (value > 0) and (self._tempo_buttons.index(sender) == 1):
			self.song().tempo = round(max((self.song().tempo - 1), 20))
	

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

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

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

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

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

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

	def shift_update(self):
		pass