def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._suggested_input_port = 'HyperControl' self._suggested_output_port = 'HyperControl' self._device_selection_follows_track_selection = True self.set_pad_translations(PAD_TRANSLATIONS) stop_button = make_button(116) play_button = make_button(117) record_button = make_button(118) select_button = make_button(98) nav_left_button = make_button(99) nav_right_button = make_button(100) nav_up_button = make_button(101) nav_down_button = make_button(102) mixer_modes_toggle = make_button(58) mixer_or_device_toggle = make_button(59) hypercontrol_mode_toggle = make_button(60) encoders = tuple([ make_encoder(33 + index) for index in range(8) ]) transport = TransportComponent() transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_record_button(record_button) session = SessionComponent(8, 0) device = BestBankDeviceComponent() self.set_device_component(device) device_nav = DeviceNavComponent() mixer = SpecialMixerComponent(NUM_TRACKS) session.set_mixer(mixer) mixer_encoder_modes = EncoderMixerModeSelector(mixer) mixer_encoder_modes.set_mode_toggle(mixer_modes_toggle) mixer_or_device = MixerOrDeviceModeSelector(encoders, select_button, nav_up_button, nav_down_button, nav_left_button, nav_right_button, mixer, session, device, mixer_encoder_modes, device_nav) mixer_or_device.set_mode_buttons((mixer_modes_toggle, mixer_or_device_toggle, hypercontrol_mode_toggle))
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): is_momentary = True self._suggested_input_port = 'Oxygen' self._suggested_output_port = 'Oxygen' self._has_slider_section = True self._device_selection_follows_track_selection = True self._shift_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 57) self._shift_button.add_value_listener(self._shift_value) self._mixer = SpecialMixerComponent(NUM_TRACKS) self._mute_solo_buttons = [] self._track_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 111) self._track_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 110) self._master_slider = SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 41) for index in range(NUM_TRACKS): self._mute_solo_buttons.append(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 49 + index)) self._mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 33 + index)) self._shift_value(0) self._mixer.master_strip().set_volume_control(self._master_slider) self._mixer.selected_strip().set_volume_control(None) device = DeviceComponent() device.set_parameter_controls(tuple([ EncoderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 17 + index, Live.MidiMap.MapMode.absolute) for index in range(8) ])) self.set_device_component(device) ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 115) rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 114) loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 113) transport = TransportComponent() transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 116)) transport.set_play_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 117)) transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 118)) session = SessionComponent(0, 0) transport_view_modes = TransportViewModeSelector(transport, session, ffwd_button, rwd_button, loop_button) return
def _init_transport_component(self, transport_controls, global_channel): is_momentary = True if transport_controls: transport = TransportComponent() transport.name = "Transport" if "STOP" in transport_controls.keys() and transport_controls["STOP"] in range(128): stop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls["STOP"]) stop_button.name = "Stop_Button" transport.set_stop_button(stop_button) if "PLAY" in transport_controls.keys() and transport_controls["PLAY"] in range(128): play_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls["PLAY"]) play_button.name = "Play_Button" transport.set_play_button(play_button) if "REC" in transport_controls.keys() and transport_controls["REC"] in range(128): rec_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls["REC"]) rec_button.name = "Record_Button" transport.set_record_button(rec_button) if "LOOP" in transport_controls.keys() and transport_controls["LOOP"] in range(128): loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls["LOOP"]) loop_button.name = "Loop_Button" transport.set_loop_button(loop_button) ffwd_button = None rwd_button = None momentary_seek = "NORELEASE" not in transport_controls.keys() if "FFWD" in transport_controls.keys() and transport_controls["FFWD"] in range(128): ffwd_button = ButtonElement(momentary_seek, MIDI_CC_TYPE, global_channel, transport_controls["FFWD"]) ffwd_button.name = "FFwd_Button" if "RWD" in transport_controls.keys() and transport_controls["RWD"] in range(128): rwd_button = ButtonElement(momentary_seek, MIDI_CC_TYPE, global_channel, transport_controls["RWD"]) rwd_button.name = "Rwd_Button" transport.set_seek_buttons(ffwd_button, rwd_button)
def _init_transport_component(self, transport_controls, global_channel): is_momentary = True if transport_controls: transport = TransportComponent() transport.name = 'Transport' if 'STOP' in transport_controls.keys() and transport_controls['STOP'] in range(128): stop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['STOP']) stop_button.name = 'Stop_Button' transport.set_stop_button(stop_button) if 'PLAY' in transport_controls.keys() and transport_controls['PLAY'] in range(128): play_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['PLAY']) play_button.name = 'Play_Button' transport.set_play_button(play_button) if 'REC' in transport_controls.keys() and transport_controls['REC'] in range(128): rec_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['REC']) rec_button.name = 'Record_Button' transport.set_record_button(rec_button) if 'LOOP' in transport_controls.keys() and transport_controls['LOOP'] in range(128): loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['LOOP']) loop_button.name = 'Loop_Button' transport.set_loop_button(loop_button) ffwd_button = None rwd_button = None momentary_seek = 'NORELEASE' not in transport_controls.keys() if 'FFWD' in transport_controls.keys() and transport_controls['FFWD'] in range(128): ffwd_button = ButtonElement(momentary_seek, MIDI_CC_TYPE, global_channel, transport_controls['FFWD']) ffwd_button.name = 'FFwd_Button' if 'RWD' in transport_controls.keys() and transport_controls['RWD'] in range(128): rwd_button = ButtonElement(momentary_seek, MIDI_CC_TYPE, global_channel, transport_controls['RWD']) rwd_button.name = 'Rwd_Button' transport.set_seek_buttons(ffwd_button, rwd_button)
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): is_momentary = True self._suggested_input_port = 'Oxygen' self._suggested_output_port = 'Oxygen' self._has_slider_section = True self._device_selection_follows_track_selection = True self._shift_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 57) self._shift_button.add_value_listener(self._shift_value) self._mixer = SpecialMixerComponent(NUM_TRACKS) self._mute_solo_buttons = [] self._track_up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 111) self._track_down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 110) self._master_slider = SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 41) for index in range(NUM_TRACKS): self._mute_solo_buttons.append(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 49 + index)) self._mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 33 + index)) self._shift_value(0) self._mixer.master_strip().set_volume_control(self._master_slider) self._mixer.selected_strip().set_volume_control(None) device = DeviceComponent() device.set_parameter_controls(tuple([ EncoderElement(MIDI_CC_TYPE, GLOBAL_CHANNEL, 17 + index, Live.MidiMap.MapMode.absolute) for index in range(8) ])) self.set_device_component(device) ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 115) rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 114) loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 113) transport = TransportComponent() transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 116)) transport.set_play_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 117)) transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, GLOBAL_CHANNEL, 118)) session = SessionComponent(0, 0) transport_view_modes = TransportViewModeSelector(transport, session, ffwd_button, rwd_button, loop_button)
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._suggested_input_port = u'HyperControl' self._suggested_output_port = u'HyperControl' self.set_pad_translations(PAD_TRANSLATIONS) stop_button = make_button(116) play_button = make_button(117) record_button = make_button(118) select_button = make_button(98) nav_left_button = make_button(99) nav_right_button = make_button(100) nav_up_button = make_button(101) nav_down_button = make_button(102) mixer_modes_toggle = make_button(58) mixer_or_device_toggle = make_button(59) hypercontrol_mode_toggle = make_button(60) encoders = tuple([ make_encoder(33 + index) for index in range(8) ]) transport = TransportComponent() transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_record_button(record_button) session = SessionComponent(8, 0) device = BestBankDeviceComponent(device_selection_follows_track_selection=True) self.set_device_component(device) device_nav = DeviceNavComponent() mixer = SpecialMixerComponent(NUM_TRACKS) session.set_mixer(mixer) mixer_encoder_modes = EncoderMixerModeSelector(mixer) mixer_encoder_modes.set_mode_toggle(mixer_modes_toggle) mixer_or_device = MixerOrDeviceModeSelector(encoders, select_button, nav_up_button, nav_down_button, nav_left_button, nav_right_button, mixer, session, device, mixer_encoder_modes, device_nav) mixer_or_device.set_mode_buttons((mixer_modes_toggle, mixer_or_device_toggle, hypercontrol_mode_toggle))
def _setup_transport(self): is_momentary = True transport = TransportComponent() studiotransport = MaschineTransport() playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108) stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110) recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109) overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107) metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104) eventRecButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 98) playButton.name = 'Play' stopButton.name = 'Stop' recordButton.name = 'Record' overdubButton.name = 'Overdub' metrononmeButton.name = 'Metronome' transport.set_play_button(playButton) transport.set_stop_button(stopButton) transport.set_record_button(recordButton) transport.set_overdub_button(overdubButton) transport.set_metronome_button(metrononmeButton) studiotransport.set_session_auto_button(eventRecButton) studiotransport.set_arrangement_overdub_button( StateButton(is_momentary, MIDI_CC_TYPE, 0, 106)) studiotransport.set_back_arrange_button( StateButton(is_momentary, MIDI_CC_TYPE, 0, 105)) transport.set_nudge_buttons( StateButton(is_momentary, MIDI_CC_TYPE, 1, 51), StateButton(is_momentary, MIDI_CC_TYPE, 1, 50)) punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52) punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53) punchinbutton.name = 'Punch In' punchoutbutton.name = 'Punch Out' transport.set_punch_buttons(punchinbutton, punchoutbutton) transport.set_loop_button( StateButton(is_momentary, MIDI_CC_TYPE, 1, 54)) self.song_follow_button = ButtonElement(True, MIDI_CC_TYPE, 2, 98) self._do_song_follow.subject = self.song_follow_button self._song_follow_changed.subject = self.song().view self._song_follow_changed() self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59) self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58) transport.set_seek_buttons(self.transp_ff_button, self.transp_rw_button) self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 105) self.xfadeKnob.connect_to( self.song().master_track.mixer_device.crossfader) self.master_knob = SliderElement(MIDI_CC_TYPE, 0, 99) self.master_knob.connect_to( self.song().master_track.mixer_device.volume) self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88) self._do_tap_tempo.subject = self.tap_button self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 55) self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56) self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57) self._do_toggle_cue.subject = self.cue_add_delete_button self._do_toggle_prev_cue.subject = self.cue_prev_button self._do_toggle_next_cue.subject = self.cue_next_button
def _setup_transport_control(self): is_momentary = True transport = TransportComponent() transport.set_play_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 80)) transport.set_record_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 81)) transport.set_nudge_buttons(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 86), ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 85)) transport.set_loop_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 84)) transport.set_punch_buttons(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 82), ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 83)) transport.set_tempo_control(SliderElement(MIDI_CC_TYPE, 12, 26), SliderElement(MIDI_CC_TYPE, 12, 25))
def _setup_components(self): # Session self._session = SessionComponent(8, len(self._scene_launch_buttons)) self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button(self._scene_launch_button) self._session.set_stop_all_clips_button(self._scene_stop_button) for index in range(8): clip_slot = self._session.selected_scene().clip_slot(index) clip_slot.set_launch_button(self._clip_launch_buttons[index]) clip_slot.name = 'Selected_Clip_Slot_' + str(index) self._session.set_stop_track_clip_buttons(tuple(self._clip_stop_buttons)) # Undo self._do_undo.subject = self._clip_undo_button; # Transport transport = TransportComponent() transport.name = 'Transport' transport.set_stop_button(self._stop_button) transport.set_play_button(self._play_button) transport.set_record_button(self._rec_button) transport.set_loop_button(self._loop_button) self._transport_view_modes = TransportViewModeSelector(transport, self._session, self._ffwd_button, self._rwd_button) self._transport_view_modes.name = 'Transport_View_Modes' session_recording = SessionRecordingComponent(ClipCreator(), ViewControlComponent(), name='Session_Recording', is_enabled=False, layer=Layer(record_button=self._overdub_button)) # Device # device = DeviceComponent() # device.name = 'Device_Component' # self.set_device_component(device) # device.set_parameter_controls(self._encoders) # Navigation self._session_navigation = SessionNavigationComponent(name='Session_Navigation') self._session_navigation.set_next_track_button(self._next_track_button) self._session_navigation.set_prev_track_button(self._prev_track_button) # Playing # self._session.set_scene_launch_buttons(tuple(self._scene_launch_buttons)) for index in range(len(self._scene_launch_buttons)): scene = self._session.scene(index) scene.set_launch_button(self._scene_launch_buttons[index])
def _setup_transport(self): is_momentary = True transport = TransportComponent() studiotransport = MaschineTransport() playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108) stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110) recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109) overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107) metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104) eventRecButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 98) playButton.name = 'Play' stopButton.name = 'Stop' recordButton.name = 'Record' overdubButton.name = 'Overdub' metrononmeButton.name = 'Metronome' transport.set_play_button(playButton) transport.set_stop_button(stopButton) transport.set_record_button(recordButton) transport.set_overdub_button(overdubButton) transport.set_metronome_button(metrononmeButton) studiotransport.set_session_auto_button(eventRecButton) studiotransport.set_arrangement_overdub_button(StateButton(is_momentary, MIDI_CC_TYPE, 0, 106)) studiotransport.set_back_arrange_button(StateButton(is_momentary, MIDI_CC_TYPE, 0, 105)) transport.set_nudge_buttons(StateButton(is_momentary, MIDI_CC_TYPE, 1, 51), StateButton(is_momentary, MIDI_CC_TYPE, 1, 50)) punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52) punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53) punchinbutton.name = 'Punch In' punchoutbutton.name = 'Punch Out' transport.set_punch_buttons(punchinbutton, punchoutbutton) transport.set_loop_button(StateButton(is_momentary, MIDI_CC_TYPE, 1, 54)) self.song_follow_button = ButtonElement(True, MIDI_CC_TYPE, 2, 98) self._do_song_follow.subject = self.song_follow_button self._song_follow_changed.subject = self.song().view self._song_follow_changed() self.prehear_knob = SliderElement(MIDI_CC_TYPE, 0, 41) self.prehear_knob.connect_to(self.song().master_track.mixer_device.cue_volume) self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59) self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58) transport.set_seek_buttons(self.transp_ff_button, self.transp_rw_button) self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 105) self.xfadeKnob.connect_to(self.song().master_track.mixer_device.crossfader) self.master_knob = SliderElement(MIDI_CC_TYPE, 0, 99) self.master_knob.connect_to(self.song().master_track.mixer_device.volume) self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88) self._do_tap_tempo.subject = self.tap_button self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 55) self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56) self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57) self._do_toggle_cue.subject = self.cue_add_delete_button self._do_toggle_prev_cue.subject = self.cue_prev_button self._do_toggle_next_cue.subject = self.cue_next_button
def _setup_transport_control(self): is_momentary = True # We'll only be using momentary buttons here transport = TransportComponent() #Instantiate a Transport Component """set up the buttons""" transport.set_play_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 60)) #ButtonElement(is_momentary, msg_type, channel, identifier) Note that the MIDI_NOTE_TYPE constant is defined in the InputControlElement module transport.set_stop_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 61)) transport.set_record_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 62)) #transport.set_overdub_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 68)) #transport.set_nudge_buttons(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 75), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 73)) #(up_button, down_button) # transport.set_tap_tempo_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 63)) #transport.set_metronome_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 80)) #For some reason, in Ver 7.x.x this method's name has no trailing "e" , and must be called as "set_metronom_button()"... #transport.set_loop_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 82)) #transport.set_punch_buttons(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 85), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 87)) #(in_button, out_button) #transport.set_seek_buttons(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 90), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 92)) # (ffwd_button, rwd_button) """set up the sliders"""
def _setup_transport(self): rwd_button = make_button(112, 'Rwd_Button') ffwd_button = make_button(113, 'FFwd_Button') stop_button = make_button(114, 'Stop_Button') play_button = make_button(115, 'Play_Button') loop_button = make_button(116, 'Loop_Button') rec_button = make_button(117, 'Record_Button') transport = TransportComponent() transport.name = 'Transport' transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_record_button(rec_button) transport.set_loop_button(loop_button) self._transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button) self._transport_view_modes.name = 'Transport_View_Modes'
def _setup_transport(self): rwd_button = make_button(112, 'Rwd_Button') ffwd_button = make_button(113, 'FFwd_Button') stop_button = make_button(114, 'Stop_Button') play_button = make_button(115, 'Play_Button') loop_button = make_button(116, 'Loop_Button') rec_button = make_button(117, 'Record_Button') transport = TransportComponent() transport.name = 'Transport' transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_record_button(rec_button) transport.set_loop_button(loop_button) self._transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button) self._transport_view_modes.name = 'Transport_View_Modes'
def _setup_transport(self): rwd_button = make_button(112, "Rwd_Button") ffwd_button = make_button(113, "FFwd_Button") stop_button = make_button(114, "Stop_Button") play_button = make_button(115, "Play_Button") loop_button = make_button(116, "Loop_Button") rec_button = make_button(117, "Record_Button") transport = TransportComponent() transport.name = "Transport" transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_record_button(rec_button) transport.set_loop_button(loop_button) self._transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button) self._transport_view_modes.name = "Transport_View_Modes"
def _setup_transport_control(self): is_momentary = True transport = TransportComponent() transport.set_play_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 80)) transport.set_record_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 81)) transport.set_nudge_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 86), ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 85)) transport.set_loop_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 84)) transport.set_punch_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 82), ButtonElement(is_momentary, MIDI_NOTE_TYPE, 12, 83)) transport.set_tempo_control(SliderElement(MIDI_CC_TYPE, 12, 26), SliderElement(MIDI_CC_TYPE, 12, 25))
def _init_transport_component(self, transport_controls, global_channel, macro_map_mode): is_momentary = True if transport_controls: transport = TransportComponent() transport.name = 'Transport' #THIS IS NEW STUFF #if 'TEMPO' in transport_control.keys() and transport_controls['TEMPO'] in range(128): tempo_slider = EncoderElement(MIDI_CC_TYPE, global_channel, 1, macro_map_mode) tempo_slider.name = 'Tempo_Slider' transport.set_tempo_control(tempo_slider) #END NEW STUFF if 'STOP' in transport_controls.keys() and transport_controls['STOP'] in range(128): stop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['STOP']) stop_button.name = 'Stop_Button' transport.set_stop_button(stop_button) if 'PLAY' in transport_controls.keys() and transport_controls['PLAY'] in range(128): play_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['PLAY']) play_button.name = 'Play_Button' transport.set_play_button(play_button) if 'REC' in transport_controls.keys() and transport_controls['REC'] in range(128): rec_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['REC']) rec_button.name = 'Record_Button' transport.set_record_button(rec_button) if 'LOOP' in transport_controls.keys() and transport_controls['LOOP'] in range(128): loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['LOOP']) loop_button.name = 'Loop_Button' transport.set_loop_button(loop_button) ffwd_button = None rwd_button = None momentary_seek = 'NORELEASE' not in transport_controls.keys() if 'FFWD' in transport_controls.keys() and transport_controls['FFWD'] in range(128): ffwd_button = ButtonElement(momentary_seek, MIDI_CC_TYPE, global_channel, transport_controls['FFWD']) ffwd_button.name = 'FFwd_Button' if 'RWD' in transport_controls.keys() and transport_controls['RWD'] in range(128): rwd_button = ButtonElement(momentary_seek, MIDI_CC_TYPE, global_channel, transport_controls['RWD']) rwd_button.name = 'Rwd_Button' transport.set_seek_buttons(ffwd_button, rwd_button)
def _init_transport_component(self, transport_controls, global_channel, macro_map_mode): is_momentary = True if transport_controls: transport = TransportComponent() transport.name = 'Transport' #THIS IS NEW STUFF #if 'TEMPO' in transport_control.keys() and transport_controls['TEMPO'] in range(128): tempo_slider = EncoderElement(MIDI_CC_TYPE, global_channel, 1, macro_map_mode) tempo_slider.name = 'Tempo_Slider' transport.set_tempo_control(tempo_slider) #END NEW STUFF if 'STOP' in transport_controls.keys() and transport_controls['STOP'] in range(128): stop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['STOP']) stop_button.name = 'Stop_Button' transport.set_stop_button(stop_button) if 'PLAY' in transport_controls.keys() and transport_controls['PLAY'] in range(128): play_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['PLAY']) play_button.name = 'Play_Button' transport.set_play_button(play_button) if 'REC' in transport_controls.keys() and transport_controls['REC'] in range(128): rec_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['REC']) rec_button.name = 'Record_Button' transport.set_record_button(rec_button) if 'LOOP' in transport_controls.keys() and transport_controls['LOOP'] in range(128): loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, transport_controls['LOOP']) loop_button.name = 'Loop_Button' transport.set_loop_button(loop_button) ffwd_button = None rwd_button = None momentary_seek = 'NORELEASE' not in transport_controls.keys() if 'FFWD' in transport_controls.keys() and transport_controls['FFWD'] in range(128): ffwd_button = ButtonElement(momentary_seek, MIDI_CC_TYPE, global_channel, transport_controls['FFWD']) ffwd_button.name = 'FFwd_Button' if 'RWD' in transport_controls.keys() and transport_controls['RWD'] in range(128): rwd_button = ButtonElement(momentary_seek, MIDI_CC_TYPE, global_channel, transport_controls['RWD']) rwd_button.name = 'Rwd_Button' transport.set_seek_buttons(ffwd_button, rwd_button)
def _setup_mixer_control(self): num_tracks = GRIDSIZE[0] # Here we define the mixer width in tracks (a mixer has only one dimension) global mixer # We want to instantiate the global mixer as a MixerComponent object (it was a global "None" type up until now...) mixer = MixerComponent(num_tracks) #(num_tracks, num_returns, with_eqs, with_filters) mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) """set up the mixer buttons""" self.song().view.selected_track = mixer.channel_strip(0)._track master = mixer.master_strip() master.set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_USER, MASTER_VOLUME)) mixer.set_prehear_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_USER, PREHEAR)) for index in xrange(GRIDSIZE[0]): mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, MIX_FADERS[index])) # mixer.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, CHANNEL_INST, MIX_FADERS[index])) mixer.channel_strip(index).set_pan_control(SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, PAN_CONTROLS[index])) mixer.channel_strip(index).set_arm_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, ARM_BUTTONS[index])) #sets the record arm button mixer.channel_strip(index).set_solo_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, SOLO_BUTTONS[index])) mixer.channel_strip(index).set_mute_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, MUTE_BUTTONS[index])) mixer.channel_strip(index).set_select_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL_INST, TRACK_SELECTS[index])) mixer.channel_strip(index).set_send_controls([SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][0]), SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][1]), SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][2]), SliderElement(MIDI_CC_TYPE, CHANNEL_MIXER, SEND_CONTROLS[index][3])]) """TRANSPORT CONTROLS""" stop_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL_MIXER, STOP_BUTTON) play_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL_MIXER, PLAY_BUTTON) record_button = ButtonElement(False,MIDI_CC_TYPE,CHANNEL_MIXER,RECORD_BUTTON) overdub_button = ButtonElement(False,MIDI_CC_TYPE,CHANNEL_MIXER,OVERDUB_BUTTON) transport = TransportComponent() transport.TEMPO_TOP = 188 transport.set_stop_button(stop_button) transport.set_play_button(play_button) transport.set_overdub_button(overdub_button) transport.set_record_button(record_button) transport.set_seek_buttons(ButtonElement(False,MIDI_CC_TYPE,0,SEEK_LEFT),ButtonElement(False,MIDI_CC_TYPE,0,SEEK_RIGHT)) transport.set_tempo_control(SliderElement(MIDI_CC_TYPE, CHANNEL_USER, TEMPO)) transport.set_metronome_button(ButtonElement(False,MIDI_CC_TYPE,CHANNEL_USER, METRONOME)) transport.set_tap_tempo_button(ButtonElement(False,MIDI_CC_TYPE,CHANNEL_USER,TAP_TEMPO))
def _setup_transport_control(self): is_momentary = True """ Instantiate a Transport Component """ transport = TransportComponent() """ Buttons declaration """ button_play = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_play_button) button_stop = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_stop_button) button_record = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_record_button) button_loop = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_loop_button) button_seek_ffwd = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_seek_ffwd) button_seek_rwd = ButtonElement(is_momentary, MIDI_CC_TYPE, midi_channel, midi_transport_seek_rwd) """ Buttons association """ transport.set_play_button(button_play) transport.set_stop_button(button_stop) transport.set_record_button(button_record) transport.set_loop_button(button_loop) transport.set_seek_buttons(button_seek_ffwd, button_seek_rwd)
def _init_transport_component(self): is_momentary = True momentary_seek = False global_channel = 0 transport = TransportComponent() transport.name = 'Transport' # rec rec_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, REC_CC) rec_button.name = 'Record_Button' transport.set_record_button(rec_button) # play play_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, PLAY_CC) play_button.name = 'Play_Button' transport.set_play_button(play_button) # stop stop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, global_channel, STOP_CC) stop_button.name = 'Stop_Button' transport.set_stop_button(stop_button)
def _setup_transport_control(self): is_momentary = True # We'll only be using momentary buttons here transport = TransportComponent() #Instantiate a Transport Component return """set up the buttons""" transport.set_play_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 61) ) #ButtonElement(is_momentary, msg_type, channel, identifier) Note that the MIDI_NOTE_TYPE constant is defined in the InputControlElement module transport.set_stop_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 63)) transport.set_record_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 66)) transport.set_overdub_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 68)) transport.set_nudge_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 75), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 73)) #(up_button, down_button) transport.set_tap_tempo_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 78)) transport.set_metronome_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 80) ) #For some reason, in Ver 7.x.x this method's name has no trailing "e" , and must be called as "set_metronom_button()"... transport.set_loop_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 82)) transport.set_punch_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 85), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 87)) #(in_button, out_button) transport.set_seek_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 90), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 92)) # (ffwd_button, rwd_button) """set up the sliders""" transport.set_tempo_control( SliderElement(MIDI_CC_TYPE, CHANNEL, 26), SliderElement(MIDI_CC_TYPE, CHANNEL, 25)) #(control, fine_control) transport.set_song_position_control( SliderElement(MIDI_CC_TYPE, CHANNEL, 24))
def _setup_transport(self): is_momentary = True transport = TransportComponent() playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108) stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110) recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109) overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107) metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104) playButton.name = 'Play' stopButton.name = 'Stop' recordButton.name = 'Record' overdubButton.name = 'Overdub' metrononmeButton.name = 'Metronome' transport.set_play_button(playButton) transport.set_stop_button(stopButton) transport.set_record_button(recordButton) transport.set_overdub_button(overdubButton) transport.set_metronome_button(metrononmeButton) transport.set_nudge_buttons(StateButton(is_momentary, MIDI_CC_TYPE, 1, 51), StateButton(is_momentary, MIDI_CC_TYPE, 1, 50)) punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52) punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53) punchinbutton.name = 'Punch In' punchoutbutton.name = 'Punch Out' transport.set_punch_buttons(punchinbutton, punchoutbutton) transport.set_loop_button(StateButton(is_momentary, MIDI_CC_TYPE, 1, 54)) self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59) self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58) transport.set_seek_buttons(self.transp_ff_button, self.transp_rw_button) self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 100) self.xfadeKnob.connect_to(self.song().master_track.mixer_device.crossfader) self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88) self.tap_button.add_value_listener(self._do_tap_tempo) self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 55) self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56) self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57) self.cue_add_delete_button.add_value_listener(self._do_toggle_cue) self.cue_prev_button.add_value_listener(self._do_toggle_prev_cue) self.cue_next_button.add_value_listener(self._do_toggle_next_cue)
class ControlMI(ControlSurface): __module__ = __name__ __doc__ = " ControlMI controller script" def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._suppress_session_highlight = True self._suppress_send_midi = True # Turn off rebuild MIDI map until after we're done setting up self.log("--------------= ControlMI log opened =--------------") with self.component_guard(): # OBJECTS self.session = None self.mixer = None self.view = None self.device = None self.transport = None # INITIALIZE MIXER, SESSIONS self._setup_session_control() # Setup the session object self._setup_mixer_control() # Setup the mixer object self.session.set_mixer(self.mixer) # Bind mixer to session self._setup_device_control() # Setup the device object self._setup_transport_control() # Setup transport object self._set_initial_mode() self.set_device_component( self.device) # Bind device to control surface- self.set_highlighting_session_component(self.session) for component in self.components: component.set_enabled(True) self._suppress_session_highlight = True self._suppress_send_midi = True # Turn rebuild back on, once we're done setting up def _setup_session_control(self): self.show_message( "#################### SESSION: ON ##############################") self.session = SessionComponent(num_tracks, num_scenes) self.session.set_offsets(0, 0) self.session.set_track_bank_buttons( ButtonElement(False, MIDI_CC_TYPE, data_channel, session_right), ButtonElement(False, MIDI_CC_TYPE, data_channel, session_left)) def _setup_mixer_control(self): self.mixer = MixerComponent(num_tracks, 0, False, False) self.mixer.name = 'Mixer' self.mixer.set_track_offset(0) def _setup_device_control(self): self.device = DeviceComponent() self.device.name = 'Device_Component' def _setup_transport_control(self): self.transport = TransportComponent(self) def _clear_controls(self): self.mixer._set_send_nav(None, None) for track_index in range(num_tracks): strip = self.mixer.channel_strip(track_index) strip.set_solo_button(None) strip.set_mute_button(None) strip.set_arm_button(None) strip.set_select_button(None) # TRANSPORT self.transport.set_stop_button(None) self.transport.set_play_button(None) self.transport.set_record_button(None) self.log_message("Controls Cleared") def _set_initial_mode(self): is_momentary = True ### MIXER for index in range(num_tracks): strip = self.mixer.channel_strip(index) strip.name = 'Mixer_ChannelStrip_' + str(index) strip.set_volume_control( SliderElement(MIDI_CC_TYPE, data_channel, mixer_volume_cc[index])) strip._invert_mute_feedback = True self.mixer.master_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, data_channel, mixer_master_cc)) self.transport.set_stop_button( ButtonElement(False, MIDI_CC_TYPE, data_channel, transport_stop_cc)) self.transport.set_play_button( ButtonElement(False, MIDI_CC_TYPE, data_channel, transport_play_cc)) self.transport.set_record_button( ButtonElement(False, MIDI_CC_TYPE, data_channel, transport_record_cc)) self.log("color: " + str(self.session.tracks_to_use()[0].color)) self.log("color: " + str(self.session.tracks_to_use()[1].color)) self.log("color: " + str(self.session.tracks_to_use()[2].color)) self.log("color: " + str(self.session.tracks_to_use()[3].color)) self._send_midi([0x09, 0x09, 0x09, 0x09]) def disconnect(self): """clean things up on disconnect""" self.log("--------------= ControlMI log closed =--------------") self._clear_controls() self.session = None self.mixer = None self.view = None self.device = None self.transport = None self.set_device_component(None) ControlSurface.disconnect(self) return None def log(self, message): self.log_message( time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + message)
class QuNexus_Basic(ControlSurface): __module__ = __name__ __doc__ = "QuNexus Keyboard controller script" def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._setup_mixer_control() self._setup_session_control() self._setup_device_control() self._setup_transport_control() self.set_highlighting_session_component(self.session) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.set_stop_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 68)) self._transport.set_record_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 66)) self._transport.set_play_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 70)) def _setup_session_control(self): num_tracks = 1 #one column (track) num_scenes = 8 #eight rows, which will be mapped to eight "white" notes #(num_tracks, num_scenes) a session highlight ("red box") will appear with any two non-zero values self.session = QuNexusSessionComponent(num_tracks, num_scenes) #(track_offset, scene_offset) Sets the initial offset of the "red box" from top left self.session.set_offsets(0, 0) self.session.set_select_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 63), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 61)) self.session.set_scene_bank_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 51), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 49)) self.session.set_track_bank_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 56), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 54)) self.session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 62)) self.session.set_stop_all_clips_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 58)) for row in range(num_scenes): for col in range(num_tracks): self.session.scene(row).clip_slot(col).set_started_value(127) self.session.scene(row).clip_slot(col).set_stopped_value(0) #here we set up the clip launch assignments for the session clip_launch_notes = [48, 50, 52, 53, 55, 57, 59, 60] #set of eight white notes starting at C3/C4 for index in range(num_scenes): #step though scenes and assign a note to first slot of each self.session.scene(index).clip_slot(0).set_started_value(127) self.session.scene(index).clip_slot(0).set_stopped_value(3) self.session.scene(index).clip_slot(0).set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, clip_launch_notes[index])) #here we set up a mixer and channel strip(s) which move with the session self.session.set_mixer( self.mixer ) #bind the mixer to the session so that they move together def _setup_mixer_control(self): #A mixer is one-dimensional; here we define the width in tracks num_tracks = 1 #set up the mixer self.mixer = MixerComponent( num_tracks, 2, with_eqs=True, with_filters=True ) #(num_tracks, num_returns, with_eqs, with_filters) self.mixer.set_track_offset( 0) #sets start point for mixer strip (offset from left) #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error self.song().view.selected_track = self.mixer.channel_strip(0)._track def _setup_device_control(self): sliders = [] pressures = [92, 94, 98, 102, 106, 108] for index in range(6): sliders.append( SliderElement(MIDI_CC_TYPE, CHANNEL, pressures[index])) self._sliders = tuple(sliders) device = DeviceComponent() self.set_device_component(device) device.set_parameter_controls(self._sliders) def disconnect(self): #clean things up on disconnect #create entry in log file self.log_message( time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "----------QuNexus Basic log closed----------") ControlSurface.disconnect(self) return None
class joyMIDI(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.setup_transport() self.setup_mixer() self.setup_session() def setup_transport(self): # elements self.play_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 93) self.stop_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 94) self.record_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 95) # transport self.transport = TransportComponent() self.transport.set_play_button(self.play_button) self.transport.set_stop_button(self.stop_button) self.transport.set_record_button(self.record_button) def setup_mixer(self): # elements self.mute_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 92) # tracks, return_tracks self.solo_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 84) # tracks, return_tracks self.arm_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 85) # tracks self.senda_up_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 96) # tracks, return_tracks self.senda_down_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 88) # tracks, return_tracks self.sendb_up_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 97) # tracks, return_tracks self.sendb_down_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 89) # tracks, return_tracks self.pan_up_button = ButtonElement( True, MIDI_NOTE_TYPE, 0, 98) # tracks, return_tracks, master_track self.pan_down_button = ButtonElement( True, MIDI_NOTE_TYPE, 0, 90) # tracks, return_tracks, master_track self.volume_up_button = ButtonElement( True, MIDI_NOTE_TYPE, 0, 99) # tracks, return_tracks, master_track self.volume_down_button = ButtonElement( True, MIDI_NOTE_TYPE, 0, 91) # tracks, return_tracks, master_track self.track_nav_encoder = EncoderElement( MIDI_CC_TYPE, 0, 14, Live.MidiMap.MapMode.relative_binary_offset) # mixer self.mixer = MixerComponent(7, 2) self.mixer.selected_strip().set_mute_button(self.mute_button) self.mixer.selected_strip().set_solo_button(self.solo_button) self.mixer.selected_strip().set_arm_button(self.arm_button) # send A/B, pan, volume self.senda_up_button.add_value_listener(self.on_senda_up_changed) self.senda_down_button.add_value_listener(self.on_senda_down_changed) self.sendb_up_button.add_value_listener(self.on_sendb_up_changed) self.sendb_down_button.add_value_listener(self.on_sendb_down_changed) self.pan_up_button.add_value_listener(self.on_pan_up_changed) self.pan_down_button.add_value_listener(self.on_pan_down_changed) self.volume_up_button.add_value_listener(self.on_volume_up_changed) self.volume_down_button.add_value_listener(self.on_volume_down_changed) # nav self.track_nav_encoder.add_value_listener(self.on_mixer_track_nav) def on_senda_up_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.sends[0] param.value = max( param.min, min(param.max, param.value + ((param.max - param.min) / SEND_STEPS))) def on_senda_down_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.sends[0] param.value = max( param.min, min(param.max, param.value - ((param.max - param.min) / SEND_STEPS))) def on_sendb_up_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.sends[1] param.value = max( param.min, min(param.max, param.value + ((param.max - param.min) / SEND_STEPS))) def on_sendb_down_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.sends[1] param.value = max( param.min, min(param.max, param.value - ((param.max - param.min) / SEND_STEPS))) def on_pan_up_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.panning param.value = max( param.min, min(param.max, param.value + ((param.max - param.min) / PAN_STEPS))) def on_pan_down_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.panning param.value = max( param.min, min(param.max, param.value - ((param.max - param.min) / PAN_STEPS))) def on_volume_up_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.volume param.value = max( param.min, min(param.max, param.value + ((param.max - param.min) / VOLUME_STEPS))) def on_volume_down_changed(self, value): if value > 0: param = self.song().view.selected_track.mixer_device.volume param.value = max( param.min, min(param.max, param.value - ((param.max - param.min) / VOLUME_STEPS))) def on_mixer_track_nav(self, value): move = -1 if value > 64 else +1 # get tracks-info tracks = self.song().tracks return_tracks = self.song().return_tracks master_track = self.song().master_track all_tracks = list(chain(tracks, return_tracks)) all_tracks.append(master_track) num_tracks = len(tracks) num_return_tracks = len(return_tracks) num_master_track = 1 num_all_tracks = num_tracks + num_return_tracks + num_master_track # update selected-track index = index_if(lambda t: t == self.song().view.selected_track, all_tracks) index += move index = min(max(index, 0), num_all_tracks - 1) self.song().view.selected_track = all_tracks[index] def setup_session(self): num_tracks = 7 num_scenes = 1 track_offset = 0 scene_offset = 0 # elements self.clip_launch_buttons = ButtonMatrixElement(rows=[[ ButtonElement(True, MIDI_NOTE_TYPE, 0, 76 + i) for i in range(num_tracks) ]]) self.clip_stop_buttons = [ ButtonElement(True, MIDI_NOTE_TYPE, 0, 68 + i) for i in range(num_tracks) ] self.scene_launch_buttons = ButtonMatrixElement(rows=[[ ButtonElement(True, MIDI_NOTE_TYPE, 0, 83 + i) for i in range(num_scenes) ]]) self.scene_stop_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 75) self.session_scene_nav_encoder = EncoderElement( MIDI_CC_TYPE, 0, 15, Live.MidiMap.MapMode.relative_binary_offset) # session self.session = SessionComponent(num_tracks, num_scenes) self.session.set_offsets(track_offset, scene_offset) self.session.add_offset_listener(self.on_session_offset_changed) self.set_highlighting_session_component(self.session) # clips self.session.set_clip_launch_buttons(self.clip_launch_buttons) self.session.set_stop_track_clip_buttons(self.clip_stop_buttons) self.session.set_scene_launch_buttons(self.scene_launch_buttons) self.session.set_stop_all_clips_button(self.scene_stop_button) # nav self.session_scene_nav_encoder.add_value_listener( self.on_session_scene_nav) def on_session_offset_changed(self): pass def on_session_scene_nav(self, value): value -= 64 value = -value track_offset = self.session.track_offset() scene_offset = max(0, self.session.scene_offset() + value) self.session.set_offsets(track_offset, scene_offset) def disconnect(self): u"""Live -> Script Called right before we get disconnected from Live. """ self.log_message('disconnect') self.show_message('disconnect')
class BlockMod(MonOhm): __module__ = __name__ __doc__ = " Monomodular controller script for Livid Block " def __init__(self, *a, **k): self._shift_button = None super(BlockMod, self).__init__(*a, **k) self._host_name = 'BlockMod' self._color_type = 'Monochrome' self._link_mixer = LINK_MIXER self._rgb = 1 self._ohm = 127 self._ohm_type = 'static' self._pad_translations = PAD_TRANSLATION self._mem = [4, 8, 12, 16] self.modhandler._color_type = 'Monochrome' """script initialization methods""" def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_controls(self): is_momentary = True self._fader = [None for index in range(8)] self._dial = [None for index in range(8)] self._button = [None for index in range(8)] self._menu = [None for index in range(6)] for index in range(2): self._fader[index] = MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, SLIDER_CC[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self) #for index in range(8): # self._button[index] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_' + str(index), self) for index in range(8): self._dial[index] = MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, KNOB_CC[index], Live.MidiMap.MapMode.absolute, 'Dial_' + str(index), index + 8, self) for index in range(4): self._menu[index] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, FUNCTION_NOTES[index], 'Menu_' + str(index), self) #self._livid = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self) self._livid = DoublePressElement(MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self)) self._shift_l = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Shift_Button_Left', self) self._shift_r = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Shift_Button_Right', self) self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' self._monomod = ButtonMatrixElement() self._monomod.name = 'Monomod' self._grid = [None for index in range(8)] for column in range(8): self._grid[column] = [None for index in range(8)] for row in range(8): self._grid[column][row] = MonoButtonElement(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._dummy_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, 125) self._dummy_button.name = 'Dummy1' self._dummy_button2 = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, 126) self._dummy_button2.name = 'Dummy2' self._dummy_button3 = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, 127) self._dummy_button2.name = 'Dummy3' self._dial_matrix = ButtonMatrixElement() self._dial_matrix.add_row(self._dial) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_crossfader(self): pass def _setup_mod(self): super(BlockMod, self)._setup_mod() self.modhandler.nav_box.on_value = 8 def _setup_layers(self): self._device_navigator.layer = Layer(priority = 5, prev_button = self._menu[2], next_button = self._menu[3]) self._device.mod_layer = AddLayerMode(self._device, Layer(priority = 5, bank_prev_button = self._menu[0], bank_next_button = self._menu[1])) self._transport.mod_layer = AddLayerMode(self._transport, Layer(priority = 5, play_button = self._menu[2], stop_button = self._menu[3])) self.modhandler.set_mod_button(self._livid) self.modhandler.layer = Layer(priority = 5, grid = self._monomod, nav_up_button = self._menu[0], nav_down_button = self._menu[1], nav_left_button = self._menu[2], nav_right_button = self._menu[3], shift_button = self._shift_r, alt_button = self._shift_l, parameter_controls = self._dial_matrix) self.modhandler.legacy_shift_mode = AddLayerMode(self.modhandler, Layer(priority = 6, channel_buttons = self._monomod.submatrix[:, 1:2], nav_matrix = self._monomod.submatrix[:4, 2:6])) self.modhandler.shift_mode = AddLayerMode(self.modhandler, Layer(priority = 6, lock_button = self._livid, device_selector_matrix = self._monomod.submatrix[:, :1], key_buttons = self._monomod.submatrix[:, 7:8])) self.modhandler.shiftlock_mode = AddLayerMode(self.modhandler, Layer(priority = 6, key_buttons = self._monomod.submatrix[:, 7:8])) def _setup_modes(self): self._monomod_mode = MonomodModeComponent(self, self.monomod_mode_update) self._monomod_mode.name = 'Monomod_Mode' self._monomod_mode.layer = Layer(priority = 5, mode_toggle = self._livid) self._monomod_mode.set_enabled(True) self._on_shift_doublepress_value.subject = self._livid.double_press self._shift_mode = BlockModShiftModeComponent(self, self.shift_update) self._shift_mode.name = 'Shift_Mode' #self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r) self._shift_mode.layer = Layer(priority = 3, toggle1 = self._shift_l, toggle2 = self._shift_r) self._shift_mode.set_enabled(True) self._l_function_mode = FunctionModeComponent(self, self.l_function_update) self._l_function_mode.name = 'Left_Function_Mode' self._r_function_mode = FunctionModeComponent(self, self.r_function_update) self._r_function_mode.name = 'Right_Function_Mode' self._m_function_mode = FunctionModeComponent(self, self.m_function_update) self._m_function_mode.name = 'Main_Function_Mode' self._function_modes = [self._l_function_mode, self._r_function_mode, self._m_function_mode] @subject_slot('value') def _on_shift_doublepress_value(self, value): #self._monomod_mode.set_mode(abs(self._monomod_mode._mode_index -1)) pass """shift/zoom methods""" def deassign_matrix(self): self._session_zoom.set_button_matrix(None) self._session_zoom2.set_button_matrix(None) #self._session.set_stop_track_clip_buttons(None) #self._session2.set_stop_track_clip_buttons(None) self._session_zoom_main.set_button_matrix(None) #self._session_main.set_stop_track_clip_buttons(None) for column in range(4): self._mixer2.channel_strip(column).set_select_button(None) self._mixer2.return_strip(column).set_mute_button(None) self._mixer2.return_strip(column).set_solo_button(None) self._mixer2.return_strip(column).set_arm_button(None) self._mixer2.return_strip(column).set_crossfade_toggle(None) self._mixer2.return_strip(column).set_select_button(None) #shouldn't this be somewhere else? self._mixer2.channel_strip(column).set_crossfade_toggle(None) self._mixer2.channel_strip(column).set_mute_button(None) self._mixer2.channel_strip(column).set_solo_button(None) self._mixer2.channel_strip(column).set_arm_button(None) for row in range(5): self._scene[row].clip_slot(column).set_launch_button(None) self._scene2[row].clip_slot(column).set_launch_button(None) for index in range(5): self._scene[index].set_launch_button(None) self._scene2[index].set_launch_button(None) self._scene_main[index].set_launch_button(None) self._session_zoom.set_nav_buttons(None, None, None, None) self._session_zoom2.set_nav_buttons(None, None, None, None) self._session_zoom_main.set_nav_buttons(None, None, None, None) self._session.set_track_bank_buttons(None, None) self._session.set_scene_bank_buttons(None, None) self._session2.set_track_bank_buttons(None, None) self._session2.set_scene_bank_buttons(None, None) self._session_main.set_track_bank_buttons(None, None) self._session_main.set_scene_bank_buttons(None, None) for column in range(8): self._mixer.channel_strip(column).set_select_button(None) 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) for row in range(5): self._scene_main[row].clip_slot(column).set_launch_button(None) 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].set_on_off_values(127, 0) self._grid[column][row].send_value(0, True) #self._send_reset.set_buttons(tuple(None for index in range(4))) def zoom_off(self): for column in range(4): self._grid[column][5].set_on_value(MUTE[self._rgb]) self._mixer.channel_strip(column).set_mute_button(self._grid[column][5]) self._grid[column][6].set_on_value(ARM[self._rgb]) self._mixer.channel_strip(column).set_arm_button(self._grid[column][6]) for row in range(5): self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row]) if(self._r_function_mode._mode_index in range(0,3)): self._grid[column + 4][5].set_on_value(MUTE[self._rgb]) self._mixer2.channel_strip(column).set_mute_button(self._grid[column + 4][5]) self._grid[column + 4][6].set_on_value(ARM[self._rgb]) self._mixer2.channel_strip(column).set_arm_button(self._grid[column + 4][6]) for row in range(5): self._scene2[row].clip_slot(column).set_launch_button(self._grid[column + 4][row]) elif(self._r_function_mode._mode_index is 3): self._grid[column + 4][5].set_on_value(MUTE[self._rgb]) self._mixer2.return_strip(column).set_mute_button(self._grid[column + 4][5]) for row in range(5): self._grid[column + 4][row].send_value(USER1_COLOR[self._rgb], True) self._grid[column + 4][row].set_channel(RIGHT_USER1_CHANNEL) self._grid[column + 4][row].set_identifier(RIGHT_USER1_MAP[column][row]) self._grid[column + 4][row].set_enabled(False) #this has to happen for translate to work #self._session_zoom2.set_ignore_buttons(True) if(self._r_function_mode._mode_index is 0): for index in range(4): self._grid[index + 4][7].send_value(SEND_RESET[self._rgb], True) #self._send_reset.set_buttons(tuple(self._grid[index + 4][7] for index in range(4))) def zoom_off_m(self): self.deassign_dials() for column in range(8): self._grid[column][5].set_on_value(MUTE[self._rgb]) self._mixer.channel_strip(column).set_mute_button(self._grid[column][5]) self._grid[column][6].set_on_value(ARM[self._rgb]) self._mixer.channel_strip(column).set_arm_button(self._grid[column][6]) for row in range(5): self._scene_main[row].clip_slot(column).set_launch_button(self._grid[column][row]) #self._session_zoom.set_button_matrix(self._matrix) def zoom_left(self): track_stop_buttons = [] track_stop_buttons2 = [] for index in range(4): self._grid[index][6].set_off_value(TRACK_STOP[self._rgb]) track_stop_buttons.append(self._grid[index][6]) self._grid[index + 4][6].set_off_value(TRACK_STOP[self._rgb]) track_stop_buttons2.append(self._grid[index + 4][6]) for index in range(5): self._grid[7][index].set_off_value(SCENE_LAUNCH[self._rgb]) self._scene[index].set_launch_button(self._grid[7][index]) #self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) #self._session.set_stop_track_clip_buttons(self._matrix.submatrix[:4][7:]) #self._session2.set_stop_track_clip_buttons(tuple(track_stop_buttons2)) #self._session2.set_stop_track_clip_buttons(self._matrix.submatrix[4:8][7:]) self._session_zoom.set_button_matrix(self._matrix) self._grid[0][5].set_on_value(RECORD[self._rgb]) self._transport.set_record_button(self._grid[0][5]) self._grid[1][5].set_on_value(OVERDUB[self._rgb]) self._transport.set_overdub_button(self._grid[1][5]) self._grid[2][5].set_on_value(LOOP[self._rgb]) self._transport.set_loop_button(self._grid[2][5]) self._grid[3][5].set_on_value(STOP_ALL[self._rgb]) self._session.set_stop_all_clips_button(self._grid[3][5]) for index in range(4): self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True) #self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4))) for index in range(4): self._grid[index + 4][7].set_off_value(DEVICE_SELECT[self._rgb]) self._device_selector.set_matrix(self._monomod.submatrix[4:8][7:]) self._device_selector.set_offset(4) def zoom_right(self): track_stop_buttons = [] track_stop_buttons2 = [] for index in range(4): self._grid[index][6].set_off_value(TRACK_STOP[self._rgb]) track_stop_buttons.append(self._grid[index][6]) for index in range(5): self._grid[7][index].set_off_value(SCENE_LAUNCH[self._rgb]) self._scene2[index].set_launch_button(self._grid[7][index]) #self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) #self._session.set_stop_track_clip_buttons(self._matrix.submatrix[:4][7:]) if(self._r_function_mode._mode_index < 3): for index in range(4): self._grid[index + 4][6].set_off_value(TRACK_STOP[self._rgb]) track_stop_buttons2.append(self._grid[index + 4][6]) #self._session2.set_stop_track_clip_buttons(self._matrix.submatrix[4:8][7:]) #self._session2.set_stop_track_clip_buttons(tuple(track_stop_buttons2)) self._session_zoom2.set_button_matrix(self._matrix) self._grid[0][5].set_on_value(RECORD[self._rgb]) self._transport.set_record_button(self._grid[0][5]) self._grid[1][5].set_on_value(OVERDUB[self._rgb]) self._transport.set_overdub_button(self._grid[1][5]) self._grid[2][5].set_on_value(LOOP[self._rgb]) self._transport.set_loop_button(self._grid[2][5]) self._grid[3][5].set_on_value(STOP_ALL[self._rgb]) self._session.set_stop_all_clips_button(self._grid[3][5]) for index in range(4): self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True) #self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4))) for index in range(4): self._grid[index][7].set_off_value(DEVICE_SELECT[self._rgb]) self._device_selector.set_matrix(self._monomod.submatrix[:4][7:]) self._device_selector.set_offset(0) def zoom_main(self): track_stop_buttons = [] for index in range(8): self._grid[index][6].set_on_value(TRACK_STOP[self._rgb]) track_stop_buttons.append(self._grid[index][6]) for index in range(5): self._grid[7][index].set_on_value(SCENE_LAUNCH[self._rgb]) self._scene_main[index].set_launch_button(self._grid[7][index]) #self._session_main.set_stop_track_clip_buttons(tuple(track_stop_buttons)) #self._session_main.set_stop_track_clip_buttons(self._matrix[0:8][7:]) self._session_zoom_main.set_button_matrix(self._matrix) self._grid[0][5].set_on_value(RECORD[self._rgb]) self._transport.set_record_button(self._grid[0][5]) self._grid[1][5].set_on_value(OVERDUB[self._rgb]) self._transport.set_overdub_button(self._grid[1][5]) self._grid[2][5].set_on_value(LOOP[self._rgb]) self._transport.set_loop_button(self._grid[2][5]) self._grid[3][5].set_on_value(STOP_ALL[self._rgb]) self._session.set_stop_all_clips_button(self._grid[3][5]) for index in range(4): self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True) #self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4))) for index in range(4): self._grid[index + 4][7].set_off_value(DEVICE_SELECT[self._rgb]) self._device_selector.set_matrix(self._monomod.submatrix[4:8][7:]) self._device_selector.set_offset(4) """function mode callbacks""" def l_function_update(self): mode = self._l_function_mode._mode_index if(self._l_function_mode.is_enabled() is False): self._l_function_mode.set_mode_buttons(None) if not self.modhandler.is_enabled(): if(self._l_function_mode.is_enabled() is True): if(len(self._l_function_mode._modes_buttons) is 0): for index in range(4): self._mixer.channel_strip(index).set_select_button(None) buttons = [] for index in range(4): buttons.append(self._grid[index][7]) self._l_function_mode.set_mode_buttons(tuple(buttons)) if(self._shift_mode._mode_index is 2): for index in range(4): if(mode != index): self._grid[index][7].turn_off() else: self._grid[index][7].turn_on() if(mode is 0): self.assign_device_dials() self.show_message('Mixer Split:Dials Device Mode') elif(mode is 1): self.assign_send_dials() self.show_message('Mixer Split:Dials Send Mode') elif(mode is 2): self.assign_split_volume_dials() self.show_message('Mixer Split:Dials Volume Mode') elif(mode is 3): self.assign_user_dials() self.show_message('Mixer Split:Dials User Map Mode') def r_function_update(self): mode = self._r_function_mode._mode_index if(self._r_function_mode.is_enabled() is False): self._r_function_mode.set_mode_buttons(None) #self._session2.set_show_highlight(False) #self._session._highlighting_callback(self._session._track_offset, self._session._scene_offset, 4, 5, 1) if not self.modhandler.is_enabled(): if(self._r_function_mode.is_enabled() is True): if(len(self._r_function_mode._modes_buttons) is 0): for index in range(4): self._mixer2.channel_strip(index).set_select_button(None) buttons = [] for index in range(4): buttons.append(self._grid[index + 4][7]) self._r_function_mode.set_mode_buttons(tuple(buttons)) if(self._shift_mode._mode_index is 3): for index in range(4): if(mode != index): self._grid[index + 4][7].turn_off() else: self._grid[index + 4][7].turn_on() self._session2.set_offsets(int(self._mem[mode]), self._session2._scene_offset) self.show_message('Mixer Split: Track Offset' + str(RIGHT_MODE_OFFSETS[mode])) def m_function_update(self): mode = self._m_function_mode._mode_index if(self._m_function_mode.is_enabled() is False): self._m_function_mode.set_mode_buttons(None) #self._session.set_show_highlight(False) #self._session2.set_show_highlight(False) #self._session_main._highlighting_callback(self._session_main._track_offset, self._session_main._scene_offset, 8, 5, 1) if not self.modhandler.is_enabled(): if(self._m_function_mode.is_enabled() is True): if(len(self._m_function_mode._modes_buttons) is 0): for index in range(8): self._mixer.channel_strip(index).set_select_button(None) buttons = [] for index in range(4): buttons.append(self._grid[index][7]) self._m_function_mode.set_mode_buttons(tuple(buttons)) if(self._shift_mode._mode_index is 4): for index in range(4): if(mode != index): self._grid[index][7].turn_off() else: self._grid[index][7].turn_on() if(mode is 0): self.assign_device_dials() self.show_message('Mixer Linked:Dials Device Mode') elif(mode is 1): self.assign_send_dials() self.show_message('Mixer Linked:Dials Send Mode') elif(mode is 2): self.assign_volume_dials() self.show_message('Mixer Linked:Dials Volume Mode') elif(mode is 3): self.assign_user_dials() self.show_message('Mixer Linked:Dials User Map Mode') def shift_update(self): self._clutch_device_selection = True #self.allow_updates(False) #if(not self._in_build_midi_map): # self.set_suppress_rebuild_requests(True) self.deassign_channel_select_buttons() self.deassign_matrix() self.deassign_menu() if(self._monomod_mode._mode_index is 0): #if monomod is not on if(self._shift_mode._mode_index is 0): #if no shift is pressed #self._shift_mode._mode_toggle1.turn_off() #self._shift_mode._mode_toggle2.turn_off() if(self.split_mixer() is False): self.set_split_mixer(True) for zoom in self._zooms: zoom._on_zoom_value(0) self.zoom_off() self._device_selector.set_enabled(False) for mode in self._function_modes: mode.set_enabled(False) self.assign_channel_select_buttons() #self._recalculate_selected_channel() #self.assign_transport_to_menu() self.assign_session_nav_to_menu() self.l_function_update() self.r_function_update() self.assign_crossfader() self.set_highlighting_session_component(self._session) self._session._do_show_highlight() #self._session.set_show_highlight(True) elif(self._shift_mode._mode_index is 1): #if no shift is pressed, but mixer is linked #self._shift_mode._mode_toggle1.turn_on() #self._shift_mode._mode_toggle2.turn_on() if(self.split_mixer() is True): self.set_split_mixer(False) for zoom in self._zooms: zoom._on_zoom_value(0) self.zoom_off_m() self._device_selector.set_enabled(False) for mode in self._function_modes: mode.set_enabled(False) self.assign_main_channel_select_buttons() self.assign_session_main_nav_to_menu() self.m_function_update() self.assign_crossfader() self.set_highlighting_session_component(self._session_main) self._session_main._do_show_highlight() elif(self._shift_mode._mode_index > 1): #if a shift is pressed self.assign_device_nav_to_menu() self.deassign_channel_select_buttons() if(self._shift_mode._mode_index is 2): #if shift left #self._shift_mode._mode_toggle1.turn_on() self.zoom_left() self._session_zoom._on_zoom_value(1) self._session.set_enabled(True) #this is a workaround so that the stop buttons still function self._l_function_mode.set_enabled(True) self.set_highlighting_session_component(self._session) self._session._do_show_highlight() elif(self._shift_mode._mode_index is 3): #if shift right #self._shift_mode._mode_toggle2.turn_on() self.zoom_right() self._session_zoom2._on_zoom_value(1) self._session2.set_enabled(True) #this is a workaround so that the stop buttons still function self._r_function_mode.set_enabled(True) self.assign_master_fader() if(self._r_function_mode._mode_index < 4): self.set_highlighting_session_component(self._session2) self._session2._do_show_highlight() elif(self._shift_mode._mode_index is 4): #if either shift pressed while mixer is linked #self._shift_mode._mode_toggle1.turn_on() #self._shift_mode._mode_toggle2.turn_on() self.zoom_main() self._session_zoom_main._on_zoom_value(1) self._session_main.set_enabled(True) #this is a workaround so that the stop buttons still function self._m_function_mode.set_enabled(True) self.assign_master_fader() self.set_highlighting_session_component(self._session_main) self._session_main._do_show_highlight() self._device_selector.set_enabled(True) else: for mode in self._function_modes: mode.set_enabled(False) #self.modhandler._shift_value(int(self._shift_mode._mode_index>1)) self.allow_updates(True) #self.set_suppress_rebuild_requests(False) self._clutch_device_selection = False if(self._shift_mode._mode_index < 2): self._monobridge._send('touch', 'off') else: self._monobridge._send('touch', 'on') """left control management methods""" def deassign_dials(self): for index in range(8): 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._mixer.selected_strip().set_send_controls(None) self._mixer.selected_strip().set_volume_control(None) for track in range(4): self._mixer.channel_strip(track).set_volume_control(None) self._mixer.channel_strip(track+4).set_volume_control(None) self._mixer2.channel_strip(track).set_volume_control(None) self._mixer2.return_strip(track).set_volume_control(None) def assign_device_dials(self): self._ohm_type = OHM_TYPE[0] self._ohm = OHM_VALUE[0] self.deassign_dials() 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._mixer.selected_strip().set_volume_control(self._fader[0]) def assign_send_dials(self): self._ohm_type = OHM_TYPE[1] self._ohm = OHM_VALUE[1] self.deassign_dials() dials = [] for index in range(4): dials.append(self._dial[index]) for index in range(4): if(self._mixer2.return_strip(index)): self._mixer2.return_strip(index).set_volume_control(self._dial[index + 4]) self._mixer.selected_strip().set_send_controls(tuple(dials)) self._mixer.selected_strip().set_volume_control(self._fader[0]) def assign_volume_dials(self): self._ohm_type = OHM_TYPE[2] self._ohm = OHM_VALUE[2] self.deassign_dials() for track in range(8): self._mixer.channel_strip(track).set_volume_control(self._dial[track]) self._mixer.selected_strip().set_volume_control(self._fader[0]) def assign_split_volume_dials(self): self._ohm_type = OHM_TYPE[2] self._ohm = OHM_VALUE[2] self.deassign_dials() for track in range(4): self._mixer.channel_strip(track).set_volume_control(self._dial[track]) self._mixer2.channel_strip(track).set_volume_control(self._dial[track+4]) self._mixer.selected_strip().set_volume_control(self._fader[0]) def assign_user_dials(self): self._ohm_type = OHM_TYPE[3] self._ohm = OHM_VALUE[3] self.deassign_dials() for index in range(8): self._dial[index].set_channel(L_USER_DIAL_CHAN) self._dial[index].set_identifier(L_USER_DIAL_MAP[index]) self._dial[index].set_enabled(False) self._mixer.selected_strip().set_volume_control(self._fader[0]) """menu button management methods""" def deassign_menu(self): self._device.set_lock_button(None) self._device.set_on_off_button(None) #self._device_navigator.set_device_nav_buttons(None, None) self._device_navigator.set_enabled(False) self._device.set_bank_nav_buttons(None, None) self._transport.set_play_button(None) self._transport.set_record_button(None) self._transport.set_stop_button(None) self._transport.set_loop_button(None) self._transport.set_overdub_button(None) self._session.set_stop_all_clips_button(None) self._session_main.set_track_bank_buttons(None, None) self._session_main.set_scene_bank_buttons(None, None) def assign_device_nav_to_menu(self): #self._device_navigator.set_device_nav_buttons(self._menu[2], self._menu[3]) self._device_navigator.set_enabled(True) self._device.set_bank_nav_buttons(self._menu[0], self._menu[1]) def assign_transport_to_menu(self): self._transport.set_play_button(self._menu[0]) self._transport.set_record_button(self._menu[2]) self._transport.set_stop_button(self._menu[1]) session.set_stop_all_clips_button(self._menu[3]) def assign_session_nav_to_menu(self): self._session.set_track_bank_buttons(self._menu[3], self._menu[2]) self._session.set_scene_bank_buttons(self._menu[1], self._menu[0]) def assign_monomod_shift_to_menu(self): #self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[2]) self._device_navigator.set_enabled(True) self._device.set_bank_nav_buttons(self._menu[1], self._menu[0]) def assign_session_bank_to_menu(self): self._session.set_track_bank_buttons(self._menu[3], self._menu[2]) self._session.set_scene_bank_buttons(self._menu[1], self._menu[0]) def assign_session2_bank_to_menu(self): self._session2.set_track_bank_buttons(self._menu[3], self._menu[2]) self._session2.set_scene_bank_buttons(self._menu[1], self._menu[0]) def assign_session_main_nav_to_menu(self): self._session_main.set_track_bank_buttons(self._menu[3], self._menu[2]) self._session_main.set_scene_bank_buttons(self._menu[1], self._menu[0]) """channel selection management methods""" def deassign_channel_select_buttons(self): for index in range(8): if(self._mixer.channel_strip(index)): self._mixer.channel_strip(index).set_select_button(None) self._grid[index][7].release_parameter() for index in range(4): self._mixer2.channel_strip(index).set_select_button(None) self._mixer2.return_strip(index).set_select_button(None) self._mixer2.master_strip().set_select_button(None) self._grid[index + 4][7].release_parameter() def assign_channel_select_buttons(self): for index in range(4): #if(self._mixer.channel_strip(index)): self._grid[index][7].set_on_off_values(127, 0) self._mixer.channel_strip(index).set_select_button(self._grid[index][7]) if(self._r_function_mode._mode_index < 3): for index in range(4): self._grid[index][7].set_on_off_values(127, 0) self._mixer2.channel_strip(index).set_select_button(self._grid[index + 4][7]) else: for index in range(4): self._grid[index][7].set_on_off_values(1, 0) self._mixer2.return_strip(index).set_select_button(self._grid[index + 4][7]) def assign_return_select_buttons(self): for index in range(4): self._grid[index + 4][7].set_off_value(0) if(self._mixer.channel_strip(index)): self._grid[index + 4][7].set_on_value(1) self._mixer.channel_strip(index).set_select_button(self._grid[index + 4][7]) def assign_l_channel_select_buttons(self): self._mixer.set_select_buttons(None, None) self._session.set_select_buttons(None, None) for index in range(4): self._grid[index][7].set_off_value(0) if(self._mixer.channel_strip(index)): self._mixer.channel_strip(index).set_select_button(self._grid[index][7]) def assign_r_channel_select_buttons(self): self._mixer2.set_select_buttons(None, None) self._session2.set_select_buttons(None, None) for index in range(4): self._grid[index + 4][7].set_off_value(0) if(self._mixer2.channel_strip(index)): self._mixer2.channel_strip(index).set_select_button(self._grid[index + 4][7]) def assign_main_channel_select_buttons(self): for index in range(8): self._grid[index][7].set_off_value(0) if(self._mixer.channel_strip(index)): self._grid[index][7].set_on_value(127) self._mixer.channel_strip(index).set_select_button(self._grid[index][7]) def assign_master_fader(self): self._mixer.set_crossfader_control(None) self._mixer.master_strip().set_volume_control(self._fader[1]) def assign_crossfader(self): self._mixer.master_strip().set_volume_control(None) self._mixer.set_crossfader_control(self._fader[1]) """called on timer""" def update_display(self): super(BlockMod, self).update_display() if(self._timer == 0): self._shift_pressed_timer = -12 def strobe(self): if(self._ohm_type != 'static'): if(self._ohm_type is 'pulse'): self._ohm = int(math.fabs(((self._timer * 8) % 64) -32) +32) if(self._ohm_type is 'up'): self._ohm = int(((self._timer * 4) % 64) + 16) if(self._ohm_type is 'down'): self._ohm = int(math.fabs(int(((self._timer * 4) % 64) - 64)) + 16) self._send_midi(tuple([176, 63, int(self._ohm)])) self._send_midi(tuple([176, 31, int(self._ohm)])) def handle_sysex(self, midi_bytes): pass def _on_session_offset_changes(self): if self._r_function_mode._mode_index in range(0,4): self._mem[int(self._r_function_mode._mode_index)] = self._session2.track_offset() # a
class BlockMod(MonOhm): __module__ = __name__ __doc__ = " Monomodular controller script for Livid Block " def __init__(self, *a, **k): self._shift_button = None self._shift_pressed = 0 self._shift_pressed_timer = 0 self._shift_thresh = SHIFT_THRESH super(BlockMod, self).__init__(*a, **k) self._host_name = 'BlockMod' self._color_type = 'Monochrome' self._link_mixer = LINK_MIXER self._rgb = 1 self._ohm = 127 self._ohm_type = 'static' self._pad_translations = PAD_TRANSLATION self._mem = [4, 8, 12, 16] self._host._navbox_selected = 8 """script initialization methods""" def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' 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(2): self._fader[index] = MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, SLIDER_CC[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self) #for index in range(8): # self._button[index] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_' + str(index), self) for index in range(8): self._dial[index] = MonoEncoderElement(MIDI_CC_TYPE, CHANNEL, KNOB_CC[index], Live.MidiMap.MapMode.absolute, 'Dial_' + str(index), index + 8, self) for index in range(4): self._menu[index] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, FUNCTION_NOTES[index], 'Menu_' + str(index), self) self._livid = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self) self._shift_l = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Shift_Button_Left', self) self._shift_r = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Shift_Button_Right', self) self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' self._monomod = ButtonMatrixElement() self._monomod.name = 'Monomod' self._grid = [None for index in range(8)] for column in range(8): self._grid[column] = [None for index in range(8)] for row in range(8): self._grid[column][row] = MonoButtonElement(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._dummy_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, 125) self._dummy_button.name = 'Dummy1' self._dummy_button2 = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, 126) self._dummy_button2.name = 'Dummy2' self._dummy_button3 = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, 127) self._dummy_button2.name = 'Dummy3' def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_crossfader(self): pass def _setup_modes(self): self._monomod_mode = MonomodModeComponent(self, self.monomod_mode_update) self._monomod_mode.name = 'Monomod_Mode' self.set_shift_button(self._livid) self._shift_mode = BlockModShiftModeComponent(self, self.shift_update) self._shift_mode.name = 'Shift_Mode' self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r) self._l_function_mode = FunctionModeComponent(self, self.l_function_update) self._l_function_mode.name = 'Left_Function_Mode' self._r_function_mode = FunctionModeComponent(self, self.r_function_update) self._r_function_mode.name = 'Right_Function_Mode' self._m_function_mode = FunctionModeComponent(self, self.m_function_update) self._m_function_mode.name = 'Main_Function_Mode' self._function_modes = [self._l_function_mode, self._r_function_mode, self._m_function_mode] """livid double press mechanism""" def set_shift_button(self, button): assert ((button == None) or (isinstance(button, MonoButtonElement))) if self._shift_button != None: self._shift_button.remove_value_listener(self._shift_value) self._shift_button = button if self._shift_button != None: self._shift_button.add_value_listener(self._shift_value) def _shift_value(self, value): self._shift_pressed = int(value != 0) if self._shift_pressed > 0: if (self._shift_pressed_timer + self._shift_thresh) > self._timer: if(self._host._active_client != None): if(self._host.is_enabled() != True): self._monomod_mode.set_mode(1) else: self._monomod_mode.set_mode(0) else: self._shift_pressed_timer = self._timer % 256 if(self._cntrlr != None): self._cntrlr._monohm_shift(2) else: if(self._cntrlr != None): self._cntrlr._monohm_shift(0) """shift/zoom methods""" def deassign_matrix(self): self._session_zoom.set_button_matrix(None) self._session_zoom2.set_button_matrix(None) self._session.set_stop_track_clip_buttons(None) self._session2.set_stop_track_clip_buttons(None) self._session_zoom_main.set_button_matrix(None) self._session_main.set_stop_track_clip_buttons(None) for column in range(4): self._mixer2.channel_strip(column).set_select_button(None) self._mixer2.return_strip(column).set_mute_button(None) self._mixer2.return_strip(column).set_solo_button(None) self._mixer2.return_strip(column).set_arm_button(None) self._mixer2.return_strip(column).set_crossfade_toggle(None) self._mixer2.return_strip(column).set_select_button(None) #shouldn't this be somewhere else? self._mixer2.channel_strip(column).set_crossfade_toggle(None) self._mixer2.channel_strip(column).set_mute_button(None) self._mixer2.channel_strip(column).set_solo_button(None) self._mixer2.channel_strip(column).set_arm_button(None) for row in range(5): self._scene[row].clip_slot(column).set_launch_button(None) self._scene2[row].clip_slot(column).set_launch_button(None) for index in range(5): self._scene[index].set_launch_button(None) self._scene2[index].set_launch_button(None) self._scene_main[index].set_launch_button(None) self._session_zoom.set_nav_buttons(None, None, None, None) self._session_zoom2.set_nav_buttons(None, None, None, None) self._session_zoom_main.set_nav_buttons(None, None, None, None) self._session.set_track_bank_buttons(None, None) self._session.set_scene_bank_buttons(None, None) self._session2.set_track_bank_buttons(None, None) self._session2.set_scene_bank_buttons(None, None) self._session_main.set_track_bank_buttons(None, None) self._session_main.set_scene_bank_buttons(None, None) for column in range(8): self._mixer.channel_strip(column).set_select_button(None) 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) for row in range(5): self._scene_main[row].clip_slot(column).set_launch_button(None) 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].set_on_off_values(127, 0) self._grid[column][row].send_value(0, True) self._send_reset.set_buttons(tuple(None for index in range(4))) def zoom_off(self): for column in range(4): self._grid[column][5].set_on_value(MUTE[self._rgb]) self._mixer.channel_strip(column).set_mute_button(self._grid[column][5]) self._grid[column][6].set_on_value(ARM[self._rgb]) self._mixer.channel_strip(column).set_arm_button(self._grid[column][6]) for row in range(5): self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row]) if(self._r_function_mode._mode_index in range(0,3)): self._grid[column + 4][5].set_on_value(MUTE[self._rgb]) self._mixer2.channel_strip(column).set_mute_button(self._grid[column + 4][5]) self._grid[column + 4][6].set_on_value(ARM[self._rgb]) self._mixer2.channel_strip(column).set_arm_button(self._grid[column + 4][6]) for row in range(5): self._scene2[row].clip_slot(column).set_launch_button(self._grid[column + 4][row]) elif(self._r_function_mode._mode_index is 3): self._grid[column + 4][5].set_on_value(MUTE[self._rgb]) self._mixer2.return_strip(column).set_mute_button(self._grid[column + 4][5]) for row in range(5): self._grid[column + 4][row].send_value(USER1_COLOR[self._rgb], True) self._grid[column + 4][row].set_channel(RIGHT_USER1_CHANNEL) self._grid[column + 4][row].set_identifier(RIGHT_USER1_MAP[column][row]) self._grid[column + 4][row].set_enabled(False) #this has to happen for translate to work #self._session_zoom2.set_ignore_buttons(True) if(self._r_function_mode._mode_index is 0): for index in range(4): self._grid[index + 4][7].send_value(SEND_RESET[self._rgb], True) self._send_reset.set_buttons(tuple(self._grid[index + 4][7] for index in range(4))) def zoom_off_m(self): self.deassign_dials() for column in range(8): self._grid[column][5].set_on_value(MUTE[self._rgb]) self._mixer.channel_strip(column).set_mute_button(self._grid[column][5]) self._grid[column][6].set_on_value(ARM[self._rgb]) self._mixer.channel_strip(column).set_arm_button(self._grid[column][6]) for row in range(5): self._scene_main[row].clip_slot(column).set_launch_button(self._grid[column][row]) #self._session_zoom.set_button_matrix(self._matrix) def zoom_left(self): track_stop_buttons = [] track_stop_buttons2 = [] for index in range(4): self._grid[index][6].set_off_value(TRACK_STOP[self._rgb]) track_stop_buttons.append(self._grid[index][6]) self._grid[index + 4][6].set_off_value(TRACK_STOP[self._rgb]) track_stop_buttons2.append(self._grid[index + 4][6]) for index in range(5): self._grid[7][index].set_off_value(SCENE_LAUNCH[self._rgb]) self._scene[index].set_launch_button(self._grid[7][index]) self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session2.set_stop_track_clip_buttons(tuple(track_stop_buttons2)) self._session_zoom.set_button_matrix(self._matrix) self._grid[0][5].set_on_value(RECORD[self._rgb]) self._transport.set_record_button(self._grid[0][5]) self._grid[1][5].set_on_value(OVERDUB[self._rgb]) self._transport.set_overdub_button(self._grid[1][5]) self._grid[2][5].set_on_value(LOOP[self._rgb]) self._transport.set_loop_button(self._grid[2][5]) self._grid[3][5].set_on_value(STOP_ALL[self._rgb]) self._session.set_stop_all_clips_button(self._grid[3][5]) for index in range(4): self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True) self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4))) for index in range(4): self._grid[index + 4][7].set_off_value(DEVICE_SELECT[self._rgb]) self._device_selector.assign_buttons(tuple(self._grid[index + 4][7] for index in range(4)), 4) def zoom_right(self): track_stop_buttons = [] track_stop_buttons2 = [] for index in range(4): self._grid[index][6].set_off_value(TRACK_STOP[self._rgb]) track_stop_buttons.append(self._grid[index][6]) for index in range(5): self._grid[7][index].set_off_value(SCENE_LAUNCH[self._rgb]) self._scene2[index].set_launch_button(self._grid[7][index]) self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) if(self._r_function_mode._mode_index < 3): for index in range(4): self._grid[index + 4][6].set_off_value(TRACK_STOP[self._rgb]) track_stop_buttons2.append(self._grid[index + 4][6]) self._session2.set_stop_track_clip_buttons(tuple(track_stop_buttons2)) self._session_zoom2.set_button_matrix(self._matrix) self._grid[0][5].set_on_value(RECORD[self._rgb]) self._transport.set_record_button(self._grid[0][5]) self._grid[1][5].set_on_value(OVERDUB[self._rgb]) self._transport.set_overdub_button(self._grid[1][5]) self._grid[2][5].set_on_value(LOOP[self._rgb]) self._transport.set_loop_button(self._grid[2][5]) self._grid[3][5].set_on_value(STOP_ALL[self._rgb]) self._session.set_stop_all_clips_button(self._grid[3][5]) for index in range(4): self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True) self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4))) for index in range(4): self._grid[index][7].set_off_value(DEVICE_SELECT[self._rgb]) self._device_selector.assign_buttons(tuple(self._grid[index][7] for index in range(4)), 0) def zoom_main(self): track_stop_buttons = [] for index in range(8): self._grid[index][6].set_on_value(TRACK_STOP[self._rgb]) track_stop_buttons.append(self._grid[index][6]) for index in range(5): self._grid[7][index].set_on_value(SCENE_LAUNCH[self._rgb]) self._scene_main[index].set_launch_button(self._grid[7][index]) self._session_main.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session_zoom_main.set_button_matrix(self._matrix) self._grid[0][5].set_on_value(RECORD[self._rgb]) self._transport.set_record_button(self._grid[0][5]) self._grid[1][5].set_on_value(OVERDUB[self._rgb]) self._transport.set_overdub_button(self._grid[1][5]) self._grid[2][5].set_on_value(LOOP[self._rgb]) self._transport.set_loop_button(self._grid[2][5]) self._grid[3][5].set_on_value(STOP_ALL[self._rgb]) self._session.set_stop_all_clips_button(self._grid[3][5]) for index in range(4): self._grid[index + 4][5].send_value(SEND_RESET[self._rgb], True) self._send_reset.set_buttons(tuple(self._grid[index + 4][5] for index in range(4))) for index in range(4): self._grid[index + 4][7].set_off_value(DEVICE_SELECT[self._rgb]) self._device_selector.assign_buttons(tuple(self._grid[index + 4][7] for index in range(4)), 4) """function mode callbacks""" def l_function_update(self): mode = self._l_function_mode._mode_index #if(self._l_function_mode.is_enabled() is False): # self._l_function_mode.set_mode_buttons(None) if(self._l_function_mode.is_enabled() is True): if(len(self._l_function_mode._modes_buttons) is 0): for index in range(4): self._mixer.channel_strip(index).set_select_button(None) buttons = [] for index in range(4): buttons.append(self._grid[index][7]) self._l_function_mode.set_mode_buttons(tuple(buttons)) if(self._shift_mode._mode_index is 2): for index in range(4): if(mode != index): self._grid[index][7].turn_off() else: self._grid[index][7].turn_on() if(mode is 0): self.assign_device_dials() self.show_message('Mixer Split:Dials Device Mode') elif(mode is 1): self.assign_send_dials() self.show_message('Mixer Split:Dials Send Mode') elif(mode is 2): self.assign_split_volume_dials() self.show_message('Mixer Split:Dials Volume Mode') elif(mode is 3): self.assign_user_dials() self.show_message('Mixer Split:Dials User Map Mode') def r_function_update(self): mode = self._r_function_mode._mode_index #if(self._r_function_mode.is_enabled() is False): # self._r_function_mode.set_mode_buttons(None) #self._session2.set_show_highlight(False) #self._session._highlighting_callback(self._session._track_offset, self._session._scene_offset, 4, 5, 1) if(self._r_function_mode.is_enabled() is True): if(len(self._r_function_mode._modes_buttons) is 0): for index in range(4): self._mixer2.channel_strip(index).set_select_button(None) buttons = [] for index in range(4): buttons.append(self._grid[index + 4][7]) self._r_function_mode.set_mode_buttons(tuple(buttons)) if(self._shift_mode._mode_index is 3): for index in range(4): if(mode != index): self._grid[index + 4][7].turn_off() else: self._grid[index + 4][7].turn_on() self._session2.set_offsets(int(self._mem[mode]), self._session2._scene_offset) self.show_message('Mixer Split: Track Offset' + str(RIGHT_MODE_OFFSETS[mode])) def m_function_update(self): mode = self._m_function_mode._mode_index #if(self._m_function_mode.is_enabled() is False): # self._m_function_mode.set_mode_buttons(None) #self._session.set_show_highlight(False) #self._session2.set_show_highlight(False) #self._session_main._highlighting_callback(self._session_main._track_offset, self._session_main._scene_offset, 8, 5, 1) if(self._m_function_mode.is_enabled() is True): if(len(self._m_function_mode._modes_buttons) is 0): for index in range(8): self._mixer.channel_strip(index).set_select_button(None) buttons = [] for index in range(4): buttons.append(self._grid[index][7]) self._m_function_mode.set_mode_buttons(tuple(buttons)) if(self._shift_mode._mode_index is 4): for index in range(4): if(mode != index): self._grid[index][7].turn_off() else: self._grid[index][7].turn_on() if(mode is 0): self.assign_device_dials() self.show_message('Mixer Linked:Dials Device Mode') elif(mode is 1): self.assign_send_dials() self.show_message('Mixer Linked:Dials Send Mode') elif(mode is 2): self.assign_volume_dials() self.show_message('Mixer Linked:Dials Volume Mode') elif(mode is 3): self.assign_user_dials() self.show_message('Mixer Linked:Dials User Map Mode') def shift_update(self): self._clutch_device_selection = True #self.allow_updates(False) #if(not self._in_build_midi_map): # self.set_suppress_rebuild_requests(True) self.deassign_channel_select_buttons() self.deassign_matrix() self.deassign_menu() if(self._monomod_mode._mode_index is 0): #if monomod is not on if(self._shift_mode._mode_index is 0): #if no shift is pressed self._shift_mode._mode_toggle1.turn_off() self._shift_mode._mode_toggle2.turn_off() if(self.split_mixer() is False): self.set_split_mixer(True) for zoom in self._zooms: zoom._on_zoom_value(0) self.zoom_off() self._device_selector.set_enabled(False) for mode in self._function_modes: mode.set_enabled(False) self.assign_channel_select_buttons() #self._recalculate_selected_channel() #self.assign_transport_to_menu() self.assign_session_nav_to_menu() self.l_function_update() self.r_function_update() self.assign_crossfader() self.set_highlighting_session_component(self._session) self._session._do_show_highlight() #self._session.set_show_highlight(True) elif(self._shift_mode._mode_index is 1): #if no shift is pressed, but mixer is linked self._shift_mode._mode_toggle1.turn_on() self._shift_mode._mode_toggle2.turn_on() if(self.split_mixer() is True): self.set_split_mixer(False) for zoom in self._zooms: zoom._on_zoom_value(0) self.zoom_off_m() self._device_selector.set_enabled(False) for mode in self._function_modes: mode.set_enabled(False) self.assign_main_channel_select_buttons() self.assign_session_main_nav_to_menu() self.m_function_update() self.assign_crossfader() self.set_highlighting_session_component(self._session_main) self._session_main._do_show_highlight() elif(self._shift_mode._mode_index > 1): #if a shift is pressed self.assign_device_nav_to_menu() self.deassign_channel_select_buttons() if(self._shift_mode._mode_index is 2): #if shift left self._shift_mode._mode_toggle1.turn_on() self.zoom_left() self._session_zoom._on_zoom_value(1) self._session.set_enabled(True) #this is a workaround so that the stop buttons still function self._l_function_mode.set_enabled(True) self.set_highlighting_session_component(self._session) self._session._do_show_highlight() elif(self._shift_mode._mode_index is 3): #if shift right self._shift_mode._mode_toggle2.turn_on() self.zoom_right() self._session_zoom2._on_zoom_value(1) self._session2.set_enabled(True) #this is a workaround so that the stop buttons still function self._r_function_mode.set_enabled(True) self.assign_master_fader() if(self._r_function_mode._mode_index < 4): self.set_highlighting_session_component(self._session2) self._session2._do_show_highlight() elif(self._shift_mode._mode_index is 4): #if either shift pressed while mixer is linked self._shift_mode._mode_toggle1.turn_on() self._shift_mode._mode_toggle2.turn_on() self.zoom_main() self._session_zoom_main._on_zoom_value(1) self._session_main.set_enabled(True) #this is a workaround so that the stop buttons still function self._m_function_mode.set_enabled(True) self.assign_master_fader() self.set_highlighting_session_component(self._session_main) self._session_main._do_show_highlight() self._device_selector.set_enabled(True) self.allow_updates(True) #self.set_suppress_rebuild_requests(False) self._clutch_device_selection = False if(self._shift_mode._mode_index < 2): self._monobridge._send('touch', 'off') else: self._monobridge._send('touch', 'on') def monomod_mode_update(self): if (self._monomod_mode._mode_index == 0) or (self._host._active_client == None): self._host.set_enabled(False) self._host._set_button_matrix(None) self._host._set_nav_buttons(None) self._host._set_lock_button(None) self._host._set_alt_button(None) self._host._set_shift_button(None) self._livid.turn_off() self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r) self._shift_mode.update() #self._session._reassign_scenes() elif(self._monomod_mode._mode_index == 1): self._livid.turn_on() self.deassign_matrix() self.deassign_menu() self._monomod.reset() self._host._set_button_matrix(self._monomod) self._host._set_nav_buttons(self._menu[0:4]) self._host._set_lock_button(self._shift_l) self._host._set_alt_button(self._shift_r) self._host._set_shift_button(self._livid) self._shift_mode.set_mode_toggle(None, None) self._host.set_enabled(True) self._shift_mode.update() #self.show_message('Monomod grid enabled') """left control management methods""" def deassign_dials(self): for index in range(8): 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._mixer.selected_strip().set_send_controls(None) self._mixer.selected_strip().set_volume_control(None) for track in range(4): self._mixer.channel_strip(track).set_volume_control(None) self._mixer.channel_strip(track+4).set_volume_control(None) self._mixer2.channel_strip(track).set_volume_control(None) self._mixer2.return_strip(track).set_volume_control(None) def assign_device_dials(self): self._ohm_type = OHM_TYPE[0] self._ohm = OHM_VALUE[0] self.deassign_dials() 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._mixer.selected_strip().set_volume_control(self._fader[0]) def assign_send_dials(self): self._ohm_type = OHM_TYPE[1] self._ohm = OHM_VALUE[1] self.deassign_dials() dials = [] for index in range(4): dials.append(self._dial[index]) for index in range(4): if(self._mixer2.return_strip(index)): self._mixer2.return_strip(index).set_volume_control(self._dial[index + 4]) self._mixer.selected_strip().set_send_controls(tuple(dials)) self._mixer.selected_strip().set_volume_control(self._fader[0]) def assign_volume_dials(self): self._ohm_type = OHM_TYPE[2] self._ohm = OHM_VALUE[2] self.deassign_dials() for track in range(8): self._mixer.channel_strip(track).set_volume_control(self._dial[track]) self._mixer.selected_strip().set_volume_control(self._fader[0]) def assign_split_volume_dials(self): self._ohm_type = OHM_TYPE[2] self._ohm = OHM_VALUE[2] self.deassign_dials() for track in range(4): self._mixer.channel_strip(track).set_volume_control(self._dial[track]) self._mixer2.channel_strip(track).set_volume_control(self._dial[track+4]) self._mixer.selected_strip().set_volume_control(self._fader[0]) def assign_user_dials(self): self._ohm_type = OHM_TYPE[3] self._ohm = OHM_VALUE[3] self.deassign_dials() for index in range(8): self._dial[index].set_channel(L_USER_DIAL_CHAN) self._dial[index].set_identifier(L_USER_DIAL_MAP[index]) self._dial[index].set_enabled(False) self._mixer.selected_strip().set_volume_control(self._fader[0]) """menu button management methods""" def deassign_menu(self): self._device.set_lock_button(None) self._device.set_on_off_button(None) self._device_navigator.set_device_nav_buttons(None, None) self._device.set_bank_nav_buttons(None, None) self._transport.set_play_button(None) self._transport.set_record_button(None) self._transport.set_stop_button(None) self._transport.set_loop_button(None) self._transport.set_overdub_button(None) self._session.set_stop_all_clips_button(None) self._transport.set_play_button(None) self._transport.set_stop_button(None) self._session_main.set_track_bank_buttons(None, None) self._session_main.set_scene_bank_buttons(None, None) def assign_device_nav_to_menu(self): self._device_navigator.set_device_nav_buttons(self._menu[2], self._menu[3]) self._device.set_bank_nav_buttons(self._menu[0], self._menu[1]) def assign_transport_to_menu(self): self._transport.set_play_button(self._menu[0]) self._transport.set_record_button(self._menu[2]) self._transport.set_stop_button(self._menu[1]) session.set_stop_all_clips_button(self._menu[3]) def assign_session_nav_to_menu(self): self._session.set_track_bank_buttons(self._menu[3], self._menu[2]) self._session.set_scene_bank_buttons(self._menu[1], self._menu[0]) def assign_monomod_shift_to_menu(self): self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[2]) self._device.set_bank_nav_buttons(self._menu[1], self._menu[0]) def assign_session_bank_to_menu(self): self._session.set_track_bank_buttons(self._menu[3], self._menu[2]) self._session.set_scene_bank_buttons(self._menu[1], self._menu[0]) def assign_session2_bank_to_menu(self): self._session2.set_track_bank_buttons(self._menu[3], self._menu[2]) self._session2.set_scene_bank_buttons(self._menu[1], self._menu[0]) def assign_session_main_nav_to_menu(self): self._session_main.set_track_bank_buttons(self._menu[3], self._menu[2]) self._session_main.set_scene_bank_buttons(self._menu[1], self._menu[0]) """channel selection management methods""" def deassign_channel_select_buttons(self): for index in range(8): if(self._mixer.channel_strip(index)): self._mixer.channel_strip(index).set_select_button(None) self._grid[index][7].release_parameter() for index in range(4): self._mixer2.channel_strip(index).set_select_button(None) self._mixer2.return_strip(index).set_select_button(None) self._mixer2.master_strip().set_select_button(None) self._grid[index + 4][7].release_parameter() def assign_channel_select_buttons(self): for index in range(4): #if(self._mixer.channel_strip(index)): self._grid[index][7].set_on_off_values(127, 0) self._mixer.channel_strip(index).set_select_button(self._grid[index][7]) if(self._r_function_mode._mode_index < 3): for index in range(4): self._grid[index][7].set_on_off_values(127, 0) self._mixer2.channel_strip(index).set_select_button(self._grid[index + 4][7]) else: for index in range(4): self._grid[index][7].set_on_off_values(1, 0) self._mixer2.return_strip(index).set_select_button(self._grid[index + 4][7]) def assign_return_select_buttons(self): for index in range(4): self._grid[index + 4][7].set_off_value(0) if(self._mixer.channel_strip(index)): self._grid[index + 4][7].set_on_value(1) self._mixer.channel_strip(index).set_select_button(self._grid[index + 4][7]) def assign_l_channel_select_buttons(self): self._mixer.set_select_buttons(None, None) self._session.set_select_buttons(None, None) for index in range(4): self._grid[index][7].set_off_value(0) if(self._mixer.channel_strip(index)): self._mixer.channel_strip(index).set_select_button(self._grid[index][7]) def assign_r_channel_select_buttons(self): self._mixer2.set_select_buttons(None, None) self._session2.set_select_buttons(None, None) for index in range(4): self._grid[index + 4][7].set_off_value(0) if(self._mixer2.channel_strip(index)): self._mixer2.channel_strip(index).set_select_button(self._grid[index + 4][7]) def assign_main_channel_select_buttons(self): for index in range(8): self._grid[index][7].set_off_value(0) if(self._mixer.channel_strip(index)): self._grid[index][7].set_on_value(127) self._mixer.channel_strip(index).set_select_button(self._grid[index][7]) def assign_master_fader(self): self._mixer.set_crossfader_control(None) self._mixer.master_strip().set_volume_control(self._fader[1]) def assign_crossfader(self): self._mixer.master_strip().set_volume_control(None) self._mixer.set_crossfader_control(self._fader[1]) """called on timer""" def update_display(self): super(BlockMod, self).update_display() if(self._timer == 0): self._shift_pressed_timer = -12 def strobe(self): if(self._ohm_type != 'static'): if(self._ohm_type is 'pulse'): self._ohm = int(math.fabs(((self._timer * 8) % 64) -32) +32) if(self._ohm_type is 'up'): self._ohm = int(((self._timer * 4) % 64) + 16) if(self._ohm_type is 'down'): self._ohm = int(math.fabs(int(((self._timer * 4) % 64) - 64)) + 16) self._send_midi(tuple([176, 63, int(self._ohm)])) self._send_midi(tuple([176, 31, int(self._ohm)])) def handle_sysex(self, midi_bytes): pass def _on_session_offset_changes(self): if self._r_function_mode._mode_index in range(0,4): self._mem[int(self._r_function_mode._mode_index)] = self._session2.track_offset() # a
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): is_momentary = True self.set_pad_translations(PAD_TRANSLATIONS) self._suggested_input_port = 'HyperControl' self._suggested_output_port = 'HyperControl' self._display_on_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 15, 79) self._waiting_for_first_response = True mixer1 = DisplayingMixerComponent(0) mixer1.set_select_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 111), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 110)) mixer1.set_mute_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 12)) mixer1.set_solo_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 13)) mixer2 = NotifyingMixerComponent(8) mixer2.set_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 15), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 14)) mixer2.master_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, 15, 41)) for index in range(8): mixer2.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, 15, 33 + index)) device = PageableDeviceComponent(device_selection_follows_track_selection=True) self.set_device_component(device) ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 115) rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 114) loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 113) transport = TransportComponent() transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 116)) transport.set_play_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 117)) transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 118)) session = SessionComponent(0, 0) transport_view_modes = TransportViewModeSelector(transport, session, ffwd_button, rwd_button, loop_button) select_button_modes = SelectButtonModeSelector(mixer2, tuple([ ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 49 + offset) for offset in range(8) ])) select_button_modes.set_mode_toggle(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 57)) self._mixer_encoder_modes = EncoderMixerModeSelector(mixer2) encoders = [] for offset in range(8): encoders.append(PeekableEncoderElement(MIDI_CC_TYPE, 15, 17 + offset, Live.MidiMap.MapMode.relative_smooth_two_compliment)) encoders[-1].set_feedback_delay(-1) mixer_or_device = MixerOrDeviceModeSelector(self._mixer_encoder_modes, device, tuple(encoders), tuple([ ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 74 + offset) for offset in range(4) ])) mixer_or_device.set_mode_toggle(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 109)) mixer_or_device.set_peek_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 78)) self._track_display = PhysicalDisplayElement(8, 1) self._track_display.set_clear_all_message(SYSEX_START + (16, 247)) self._track_display.set_message_parts(SYSEX_START + (17, 1, 0, 0), (247,)) self._track_display.segment(0).set_data_source(mixer1.selected_strip().track_name_data_source()) device_display = PhysicalDisplayElement(8, 1) device_display.set_message_parts(SYSEX_START + (17, 1, 0, 10), (247,)) parameter_display = PhysicalDisplayElement(16, 1) parameter_display.set_message_parts(SYSEX_START + (17, 2, 0, 0), (247,)) select_button_modes.set_mode_display(parameter_display) mixer1.set_display(parameter_display) mixer2.set_bank_display(parameter_display) page_displays = [] for index in range(4): page_displays.append(PhysicalDisplayElement(5, 1)) page_displays[-1].set_message_parts(SYSEX_START + (17, 4, index, 0), (247,)) encoder_display = PhysicalDisplayElement(80, 8) encoder_display.set_message_parts(SYSEX_START + (17, 3), (247,)) for index in range(8): pos_id = tuple() if index != 0: pos_id += (0,) if index > 3: pos_id += (index % 4, 13) else: pos_id += (index % 4, 0) encoder_display.segment(index).set_position_identifier(pos_id) mixer_or_device.set_displays(encoder_display, parameter_display, device_display, tuple(page_displays)) for component in self.components: component.set_enabled(False)
class BCRXL(ControlSurface, IsotonikCommon): def __init__(self, c_instance): self._dynamic = True self._LOG_BCL = False self._preset = 0 self._use_32 = False self._enable_function = False self._track_navigation = False self._swap_arm = False self._direct_bank = False self._relative = False self._bit_14 = False self._fold_enabled = True self._can_fold = False self._show_returns = 0 self._max_returns = -1 self._returns_toggled = False self._has_pans = False self._track_bank_size = 1 self._show_master = 0 self._show_selected = 0 self._button_row_1 = 'select' self._button_row_2 = 'mute' self._button_row_3 = 'solo' self._button_reselect_track = 'fold' self._channel_strip = False self._toggle_1 = False self._toggle_2 = False self._toggle_3 = False self._toggle_4 = False self._has_strip_device_enable = True self._USB = True self._has_transport = False self._showing_selected = False self._x_offset = 0 self._y_offset = 0 self._track_left = 113 self._track_right = 114 self._device_toggle = 109 self._track_fold = 110 self._refresh = 111 self._device_lock = 110 self._bank_up = 111 self._bank_down = 112 self._toggle_returns = False self._user_custom = False IsotonikCommon.__init__(self, parent=self, c_instance=c_instance) self._init(path.dirname(path.realpath(__file__)), 'BCR_XL', 24) super(BCRXL, self).__init__(c_instance) with self.component_guard(): self._startup() def disconnect(self): if self._dynamic: pass self._shutdown() super(BCRXL, self).disconnect() def _sigabort_create(self): if self._show_returns == 3 or self._show_returns == 4: self._fold_enabled = False self._toggle_returns = True if not self._enable_function: self._direct_bank = False self._has_transport = False if self._channel_strip: self._fold_enabled = False self._user_custom = self._enable_function and not self._direct_bank and not self._has_transport self._bcr_controls = BCL(self, self._preset, self._relative, self._bit_14) self._device_selection_follows_track_selection = True self._default_skin = make_default_skin() with inject(skin=const(self._default_skin)).everywhere(): self._create_controls() self._set_offsets_task = self._tasks.add( Task.sequence(Task.wait(0), Task.run(self._set_session_offsets))) self._set_offsets_task.kill() if self._show_selected: self._show_selected_task = self._tasks.add( Task.sequence(Task.wait(1), Task.run(self._show_selected_track))) return False def _enable_components(self): with self.component_guard(): for component in self.components: self.log('Enable: ' + component.name) component.set_enabled(True) def set_session_offsets(self, x, y): self.log('bcrxl: set_session_offsets: ' + str(x) + ',' + str(y)) self._scene = y self._x_offset = x self._y_offset = y self._set_offsets_task.restart() def _set_session_offsets(self): self._set_offsets_task.kill() self.log('_set_session_offsets') self._session.set_offsets(self._x_offset, self._y_offset) def _show_controlled_tracks_message(self, session): track_offset = session.track_offset() self.log('_show_controlled_tracks_message: ' + str(track_offset) + ', ' + str(self._scene)) self._set_session_highlight(track_offset, self._scene, 8, 1, False) def _set_session_highlight(self, track_offset, scene_offset, width, height, include_return_tracks): self.log('_set_session_highlight: ' + str(track_offset) + ', ' + str(scene_offset) + ', ' + str(width) + ', ' + str(height) + ', ' + str(include_return_tracks)) super(BCRXL, self)._set_session_highlight(track_offset, scene_offset, width, height, include_return_tracks) def _on_selected_scene_changed(self): if self._box_follows_scene: self._scene = list(self.song().scenes).index( self.song().view.selected_scene) self._show_controlled_tracks_message( self._on_session_offset_changed.subject) self.log('_on_selected_scene_changed: index: ' + str(self._scene)) super(BCRXL, self)._on_selected_scene_changed() def _show_selected_track(self): self.log('_show_selected_track: ' + str(self._showing_selected) + ', index: ' + str(self._mixer._selected_track_index)) self._showing_selected = not self._showing_selected volume_cc = 0 if self._bit_14 else 1 if self._mixer._selected_track_index != -1: curr_val = self._mixer._channel_strips[ self._mixer. _selected_track_index]._track.mixer_device.volume.value self._do_send_midi( (176 + MIXER_MODE, volume_cc + self._mixer._selected_track_index, int(math.floor(curr_val * 127.0)) if self._showing_selected else 0)) self._show_selected_task = self._tasks.add( Task.sequence(Task.delay(2), Task.run(self._show_selected_track))) def on_identified(self): self.log('on_identified') self._identified = True if hasattr(self, 'default_session'): self.default_session.set_show_highlight(True) self._set_session_highlight(0, 0, 8, 1, False) super(BCRXL, self).on_identified() def _create_controls(self): self.log( '_create_controls: dynamic: ' + str(self._dynamic) + ', function: ' + str(self._enable_function), True) if not self._dynamic: self._track_left = 105 self._track_right = 106 self._device_toggle = 107 elif not self._enable_function: self._device_toggle = 105 self._track_fold = 106 self._device_lock = 106 self._bank_up = 107 self._bank_down = 108 self.log('left: ' + str(self._track_left) + ', right: ' + str(self._track_right) + ', toggle: ' + str(self._device_toggle) + ', user_custom: ' + str(self._user_custom)) if self._dynamic: if self._user_custom: self._bcr_controls.connect(self._toggle_1, self._toggle_2, self._toggle_3, self._toggle_4) else: self._bcr_controls.connect() self._modes = ModesComponent() self._create_our_controls() self._create_mixer() self._create_session() self._create_device() self._create_transport() def log(self, msg, force=False): if self._LOG or force: if isinstance(msg, str): logger.info(msg) else: logger.error('**++** Invalid log msg: ' + str(type(msg)) + ': ' + IsotonikCommon.repr3(msg)) def _create_our_controls(self): self.log('_create_our_controls') def make_button(identifier, name, midi_type=MIDI_CC_TYPE, skin=self._default_skin): control = ButtonElement(False, midi_type, MIXER_MODE, identifier, name=name, skin=skin) return control def make_button_list(identifiers, name, midi_type=MIDI_NOTE_TYPE): return [ make_button(identifier, name % (i + 1), midi_type, self._default_skin) for i, identifier in enumerate(identifiers) ] def make_encoder(identifier, name, bit_14=True): if self._bit_14: self.log('make_encoder: ' + name + ', CC: ' + str(identifier) + ', 14_bit: ' + str(bit_14)) control = EncoderElement( MIDI_CC_TYPE, MIXER_MODE, identifier, Live.MidiMap.MapMode.absolute_14_bit if bit_14 else Live.MidiMap.MapMode.absolute, name=name) else: control = EncoderElement( MIDI_CC_TYPE, MIXER_MODE, identifier, Live.MidiMap.MapMode.absolute if not self._relative else Live.MidiMap.MapMode.relative_two_compliment, name=name) return control self._top_buttons = ButtonMatrixElement(rows=[ make_button_list(chain(xrange(65, 73)), 'BCR_Top_Buttons_%d', MIDI_CC_TYPE) ]) self._bottom_buttons = ButtonMatrixElement(rows=[ make_button_list(chain(xrange(73, 81)), 'BCR_Bottom_Buttons_%d', MIDI_CC_TYPE) ]) self._strip_enable_buttons = ButtonMatrixElement(rows=[ make_button_list(chain(xrange(73, 81)), 'BCR_Bottom_Buttons_%d', MIDI_CC_TYPE) ]) if self._direct_bank or self._has_transport: self._direct_bank_buttons = ButtonMatrixElement(rows=[ make_button_list(chain(xrange(105, 109)), 'BCR_User_Buttons_%d', MIDI_CC_TYPE) ]) self._left_button = make_button(self._track_left, 'Track_Left', MIDI_CC_TYPE) self._right_button = make_button(self._track_right, 'Track_Right', MIDI_CC_TYPE) self._device_engage_button = make_button(self._device_toggle, 'XXL_Pan_Device_Mode') self._track_fold_button = make_button(self._track_fold, 'Track_Fold', MIDI_CC_TYPE) if self._fold_enabled or self._toggle_returns or self._channel_strip: self._on_track_fold.subject = self._track_fold_button self._track_fold_button.enabled = False self._bank_up_button = make_button(self._bank_up, 'Device_Bank_Up', MIDI_CC_TYPE) self._bank_down_button = make_button(self._bank_down, 'Device_Bank_Down', MIDI_CC_TYPE) if self._bit_14: volume_cc = 0 sends_cc = 8 pans_cc = 81 select_cc = 89 else: volume_cc = 1 sends_cc = 81 pans_cc = 9 select_cc = 33 self._volume_encoders = ButtonMatrixElement(rows=[[ make_encoder(volume_cc + i, 'Volume_%d' % (i + 1)) for i in xrange(8) ]]) if self._has_pans: self._pan_encoders = ButtonMatrixElement(rows=[[ make_encoder(pans_cc + i, 'Pan_%d' % (i + 1), bit_14=False) for i in xrange(8) ]]) self._send_encoders = ButtonMatrixElement( rows=[[ make_encoder(sends_cc + i, 'Send_0_%d' % (i + 1)) for i in xrange(8) ], [ make_encoder(sends_cc + 8 + i, 'Send_1_%d' % (i + 1)) for i in xrange(8) ], [ make_encoder(sends_cc + 16 + i, 'Send_2_%d' % (i + 1)) for i in xrange(8) ]]) self._push_buttons = ButtonMatrixElement(rows=[ make_button_list(chain(xrange(select_cc, select_cc + 8)), 'BCR_Track_Select_%d', MIDI_CC_TYPE) ]) def _do_send_midi(self, midi_bytes): is_sysex = midi_bytes[0] == 240 if self._LOG_MIDI and not is_sysex: self.log('_do_send_midi: ' + str(midi_bytes)) if self._LOG_SYSEX and is_sysex: self.log('_do_send_midi: ' + str(midi_bytes)) super(BCRXL, self)._do_send_midi(midi_bytes) def receive_midi(self, midi_bytes): is_sysex = midi_bytes[0] == 240 send_off = False midi_id = 176 + MIXER_MODE adjusted = False if self._LOG_MIDI and not is_sysex: self.log('receive_midi: ' + str(midi_bytes) + ', id: ' + str(midi_id)) if self._LOG_SYSEX and is_sysex: self.log('receive_midi: ' + str(midi_bytes)) if midi_bytes[0] == midi_id: if midi_bytes[2] == 0: if self._has_transport: if midi_bytes[1] in (107, 108): midi_bytes = (midi_id, midi_bytes[1], 127) adjusted = True elif midi_bytes[1] == 106: midi_bytes = (midi_id, midi_bytes[1], 127) self._do_send_midi(midi_bytes) adjusted = True if not self._device_mode: if midi_bytes[1] in pad_identifiers: midi_bytes = (midi_id, midi_bytes[1], 127) adjusted = True if midi_bytes[1] in [self._track_left, self._track_right]: midi_bytes = (midi_id, midi_bytes[1], 127) adjusted = True if self._LOG_MIDI and adjusted: self.log('receive_midi(adjusted): ' + str(midi_bytes) + ', send_off: ' + str(send_off)) if send_off: midi_bytes_new = (midi_id, midi_bytes[1], 0) if self._LOG_MIDI: self.log('send_off:receive_midi: ' + str(midi_bytes_new), True) super(BCRXL, self).receive_midi(midi_bytes_new) super(BCRXL, self).receive_midi(midi_bytes) def _create_user(self): def make_control_button(identifier, name, channel=0, is_pad=False): button = ButtonElement(True, MIDI_NOTE_TYPE if is_pad else MIDI_CC_TYPE, channel, identifier) button.name = name button.set_on_off_values(127, 0) return button def make_control_encoder(identifier, name, channel=0): encoder = EncoderElement( MIDI_CC_TYPE, channel, identifier, Live.MidiMap.MapMode.absolute if not self._relative else Live.MidiMap.MapMode.relative_two_compliment) encoder.reset = nop encoder.set_feedback_delay(-1) encoder.name = name return encoder def make_all_encoders(name_prefix='', make_encoder=make_control_encoder): return ([ make_encoder(13 + index, name_prefix + '_' + str(index) + '_0') for index in xrange(8) ], [ make_encoder(80 + index, name_prefix + '_' + str(index) + '_1') for index in xrange(8) ], [ make_encoder(88 + index, name_prefix + '_' + str(index) + '_2') for index in xrange(8) ], [ make_encoder(96 + index, name_prefix + '_' + str(index) + '_3') for index in xrange(8) ]) make_button = partial(make_control_button, channel=USER_MODE) make_encoder = partial(make_control_encoder, channel=USER_MODE) encoders_row_1, encoders_row_2, encoders_row_3, encoders_row_4 = make_all_encoders( 'User_Encoder', make_encoder) buttons_0 = [ make_button(pad_identifiers[i], 'User_Button_Matrix_' + str(i) + '_0', is_pad=True) for i in xrange(8) ] buttons_1 = [ make_button(pad_identifiers[i + 8], 'User_Button_Matrix_' + str(i) + '_1', is_pad=True) for i in xrange(8) ] self._matrix = ButtonMatrixElement() self._matrix.name = 'User_Button_Matrix' self._matrix.add_row(tuple(buttons_0)) self._matrix.add_row(tuple(buttons_1)) self.request_rebuild_midi_map() def on_selected_track_changed(self): self._selected_track = self.song().view.selected_track if hasattr(self, '_mixer'): if self._show_selected and self._mixer._last_selected_track_index != -1: volume_cc = 0 if self._bit_14 else 1 curr_val = self._mixer._channel_strips[ self._mixer. _last_selected_track_index]._track.mixer_device.volume.value self.log( 'reset value for track: ' + str(self._mixer._last_selected_track_index) + ' to ' + str(curr_val), True) self._do_send_midi( (176 + MIXER_MODE, volume_cc + self._mixer._last_selected_track_index, int(math.floor(curr_val * 127.0)))) if self._fold_enabled: can_fold = False if self._selected_track != None: can_fold = self._selected_track.is_foldable self._can_fold = can_fold self.log('on_selected_track_changed: can_fold: ' + str(can_fold)) self._track_fold_button.enabled = can_fold self._track_fold_button.send_value(127 if can_fold else 0) if hasattr(self, '_device'): self._device.on_selected_track_changed() @subject_slot('value') def _on_track_fold(self, value): self.log('_on_track_fold: ' + str(value) + ', fold_enabled: ' + str(self._fold_enabled) + ', can_fold: ' + str(self._can_fold) + ', toggle_returns: ' + str(self._toggle_returns) + ', channel_strip: ' + str(self._channel_strip)) if self._channel_strip and self._modes.selected_mode != 'device': self.log('process channel_strip') if value: self.device_mode.layer = None self._on_device_engage(127, True) self._device.enable_channel_strip(True, True) self._on_strip_up.subject = self._bank_down_button self._on_strip_down.subject = self._bank_up_button if self._has_strip_device_enable: self._on_strip_enable.replace_subjects( self._strip_enable_buttons) self._update_strip_bank_buttons() self._update_strip_enable_buttons() else: self.device_mode.layer = Layer( device_mode_button=self._device_engage_button) self._device.enable_channel_strip(False, True) self._on_device_engage(0, True) self._on_strip_up.subject = None self._on_strip_down.subject = None if self._has_strip_device_enable: self._on_strip_enable.replace_subjects([]) elif self._fold_enabled: self.log('process fold') self._track_fold_button.send_value(127 if self._can_fold else 0) if self._selected_track: self.log('can_fold: ' + str(self._selected_track.is_foldable)) if self._selected_track.is_foldable: self.log('currently folded: ' + str(self._selected_track.fold_state)) self._selected_track.fold_state = not self._selected_track.fold_state elif self._toggle_returns: self.log('process toggle returns') self._returns_toggled = value == 127 self.log('returns_toggled: ' + str(self._returns_toggled)) self._mixer._reassign_tracks(1 if self._returns_toggled else 0) @subject_slot('value') def _on_strip_up(self, value): self.log('_on_strip_up', True) self._device._do_strip_up() self._update_strip_bank_buttons() @subject_slot('value') def _on_strip_down(self, value): self.log('_on_strip_down', True) self._device._do_strip_down() self._update_strip_bank_buttons() @subject_slot_group('value') def _on_strip_enable(self, value, button): index = list(self._strip_enable_buttons).index(button) self.log('_on_strip_enable: ' + str(index) + ', ' + str(value), True) self._device._do_strip_enable(index) def _update_strip_bank_buttons(self): self._bank_up_button.send_value( 127 if self._device._channel_strip_bank != 0 else 0) self._bank_down_button.send_value( 127 if self._device._channel_strip_bank != 2 else 0) def _update_strip_enable_buttons(self): for i in range(0, len(self._device._iso_rack_enable)): if self._strip_enable_buttons[i] is not None: on = self._device._iso_rack_enable[ i] and self._device._iso_rack_enable[i].value self._strip_enable_buttons[i].send_value(127 if on else 0) @subject_slot('value') def _on_skip_racks(self, value): if value == 127: self._device.toggle_enable_or_select() def _release_parameters(self, controls): if controls != None: for control in controls: if control != None: control.release_parameter() def _create_transport(self): self.log('_create_transport: ' + str(self._has_transport), True) if not self._has_transport: return self._transport = TransportComponent() self._transport.set_stop_button(self._direct_bank_buttons[0]) self._transport.set_play_button(self._direct_bank_buttons[1]) self._transport.set_record_button(self._direct_bank_buttons[2]) self._transport.set_overdub_button(self._direct_bank_buttons[3]) def _create_session(self): self.log('_create_session', True) self._session = SessionComponent(self, name='BCR2K_Session', num_tracks=NUM_TRACKS, track_bank_size=self._track_bank_size, is_enabled=True, auto_name=True) self._session.layer = Layer(track_bank_left_button=self._left_button, track_bank_right_button=self._right_button) self._session.set_mixer(self._mixer) self._session._setup_controls() self._on_session_offset_changed.subject = self._session self._session.set_show_highlight(True) self._set_session_highlight(0, 0, 8, 1, False) @subject_slot('offset') def _on_session_offset_changed(self): self.log('_on_session_offset_changed') session = self._on_session_offset_changed.subject self._show_controlled_tracks_message(session) if hasattr(self._device, '_assign_channel_strip' ) and self._device._assign_channel_strip: self._device._on_session_offset_changed() def _create_mixer(self): self.log('_create_mixer', True) mixer = MixerComponent(self, NUM_TRACKS, 3, show_returns=self._show_returns, max_returns=self._max_returns, show_master=self._show_master, delayed_update=True, is_enabled=True, auto_name=True) layer = Layer(volume_controls=self._volume_encoders, send_controls=self._send_encoders, next_sends_button=self._bank_down_button, prev_sends_button=self._bank_up_button) valid_opts = self._get_button_options() layer += Layer(**valid_opts) mixer.layer = layer self._mixer = mixer self._bcr_controls.setup_mixer_controls() self._modes.add_mode('mixer', [AddLayerMode(self._mixer, layer)]) self._modes.selected_mode = 'mixer' def _get_button_options(self, channel_strip=False): opts = {} use_bottom_row_for_channel_strip = self._has_strip_device_enable if not use_bottom_row_for_channel_strip: channel_strip = False if self._has_pans: opts['pan_controls'] = self._pan_encoders opts[ 'track_select_buttons'] = self._push_buttons if self._button_row_1 == 'select' else ( self._top_buttons if self._button_row_2 == 'select' else (self._bottom_buttons if self._button_row_3 == 'select' and not channel_strip else None)) opts[ 'mute_buttons'] = self._push_buttons if self._button_row_1 == 'mute' else ( self._top_buttons if self._button_row_2 == 'mute' else (self._bottom_buttons if self._button_row_3 == 'mute' and not channel_strip else None)) opts[ 'solo_buttons'] = self._push_buttons if self._button_row_1 == 'solo' else ( self._top_buttons if self._button_row_2 == 'solo' else (self._bottom_buttons if self._button_row_3 == 'solo' and not channel_strip else None)) opts[ 'arm_buttons'] = self._push_buttons if self._button_row_1 == 'arm' else ( self._top_buttons if self._button_row_2 == 'arm' else (self._bottom_buttons if self._button_row_3 == 'arm' and not channel_strip else None)) valid_opts = {} for k, v in opts.iteritems(): if v is not None: valid_opts[k] = v return valid_opts def _on_device_engage(self, value, channel_strip=False): self.log('_on_device_engage: ' + str(value) + ', channel_strip: ' + str(channel_strip)) if value == 127: if not channel_strip: self._session.set_mixer(None) self._session.layer = None self.set_device_component(self._device) self._device_mode = True self._bcr_controls._mode = 1 self._modes.selected_mode = 'device_strip' if channel_strip else 'device' if self._use_32: self._mixer.set_volume_controls(None) else: self._device_mode = False self._bcr_controls._mode = 0 self._bcr_controls.setup_mixer_controls(-1, -1, True, -1) if not channel_strip: self._session.set_mixer(self._mixer) self._session.layer = Layer( track_bank_left_button=self._left_button, track_bank_right_button=self._right_button) if self._fold_enabled or self._toggle_returns: if self._fold_enabled: self._can_fold = self._selected_track != None and self._selected_track.is_foldable self._on_track_fold.subject = self._track_fold_button self._modes.selected_mode = 'mixer' if self._use_32: self._mixer.set_volume_controls(self._volume_encoders) def _create_device(self): self.log('_create_device', True) def make_button(identifier, name, midi_type=MIDI_CC_TYPE, skin=self._default_skin): return ButtonElement(True, midi_type, MIXER_MODE, identifier, name=name, skin=skin) def make_encoder(identifier, name, bit_14=True): if self._bit_14: self.log('make_encoder: ' + name + ', CC: ' + str(identifier) + ', 14_bit: ' + str(bit_14)) control = EncoderElement( MIDI_CC_TYPE, MIXER_MODE, identifier, Live.MidiMap.MapMode.absolute_14_bit if bit_14 else Live.MidiMap.MapMode.absolute, name=name) else: control = EncoderElement( MIDI_CC_TYPE, MIXER_MODE, identifier, Live.MidiMap.MapMode.absolute if not self._relative else Live.MidiMap.MapMode.relative_two_compliment, name=name) return control if self._bit_14: volume_cc = 0 sends_cc = 8 else: volume_cc = 1 sends_cc = 81 if self._use_32: self._device_encoders = ButtonMatrixElement( rows=[[ make_encoder(volume_cc + i, 'Volume_%d' % (i + 1)) for i in xrange(8) ], [ make_encoder(sends_cc + i, 'BCR_Device_0_%d' % (i + 1)) for i in xrange(8) ], [ make_encoder(sends_cc + 8 + i, 'BCR_Device_1_%d' % (i + 1)) for i in xrange(8) ], [ make_encoder(sends_cc + 16 + i, 'BCR_Device_2_%d' % (i + 1)) for i in xrange(8) ]]) self._send_encoders = self._device_encoders.submatrix[:8, 1:4] else: self._device_encoders = self._send_encoders if self._channel_strip: self._device = DeviceComponent_Strip( self, name='XL_Device', is_enabled=True, direct_bank=self._direct_bank, num_params=32 if self._use_32 else 24, path=self._my_path, delayed_update=True) else: self._device = DeviceComponent( self, name='XL_Device', is_enabled=True, direct_bank=self._direct_bank, num_params=32 if self._use_32 else 24, path=self._my_path, delayed_update=True) self.set_preditor_device_component(self._device) if self._direct_bank: device_layer = Layer(parameter_controls=self._device_encoders, device_select=self._top_buttons, device_enable=self._bottom_buttons, device_lock_button=self._track_fold_button, bank_up_button=self._bank_down_button, bank_down_button=self._bank_up_button, direct_bank=self._direct_bank_buttons) else: device_layer = Layer(parameter_controls=self._device_encoders, device_select=self._top_buttons, device_enable=self._bottom_buttons, device_lock_button=self._track_fold_button, bank_up_button=self._bank_down_button, bank_down_button=self._bank_up_button) device_settings_layer = Layer() self.device_mode = DeviceModeComponent(script=self, component=self._device, device_settings_mode=[ AddLayerMode( self._device, device_settings_layer) ], is_enabled=True) self.device_mode.layer = Layer( device_mode_button=self._device_engage_button) if self._has_pans: mixer_layer = Layer(volume_controls=self._volume_encoders, pan_controls=self._pan_encoders) else: mixer_layer = Layer(volume_controls=self._volume_encoders) self._modes.add_mode('device', [ AddLayerMode(self._device, device_layer), AddLayerMode(self._mixer, mixer_layer) ]) if self._channel_strip: if hasattr(self._device, 'enable_channel_strip'): strip_layer = Layer(parameter_controls=self._device_encoders) valid_opts = self._get_button_options(True) mixer_layer += Layer(**valid_opts) self._modes.add_mode('device_strip', [ AddLayerMode(self._device, strip_layer), AddLayerMode(self._mixer, mixer_layer), AddLayerMode( self._session, Layer(track_bank_left_button=self._left_button, track_bank_right_button=self._right_button)) ]) else: self._channel_strip = False def update(self): self.log('update: device_mode: ' + str(self._device_mode)) super(BCRXL, self).update() def refresh_state(self): self.log('refresh_state') super(BCRXL, self).refresh_state() def handle_sysex(self, midi_bytes): if self._LOG_SYSEX: self.log('handle_sysex: ' + str(midi_bytes)) if midi_bytes[:4] == BCR_SYSEX[:4] and midi_bytes[5] == 21: if self._bcr_controls.receive_ack(midi_bytes): if self._device_mode: self._device.map_controls() else: self._mixer.map_controls() if midi_bytes[9:10] != (0, ): self.log('Received sysex error code: ' + str(midi_bytes), True) @subject_slot_group('value') def _on_select_pressed(self, value, button): pass def same_track_selected(self): self.log('BCRXL: same_track_selected') selected_track = self.song().view.selected_track if selected_track != None: if self._device_mode: self.song().view.selected_track = self.song().master_track elif self._button_reselect_track == 'mute': selected_track.mute = not selected_track.mute elif self._button_reselect_track == 'solo': selected_track.solo = not selected_track.solo elif self._button_reselect_track == 'arm': if selected_track.can_be_armed: selected_track.arm = not selected_track.arm elif self._button_reselect_track == 'fold': if self._selected_track.is_foldable: self._selected_track.fold_state = not self._selected_track.fold_state return False
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) transport = TransportComponent() #Instantiate a Transport Component transport.set_play_button(ButtonElement(True, 0, 0, 61)) #ButtonElement(is_momentary, msg_type, channel, identifier) transport.set_stop_button(ButtonElement(True, 0, 0, 63)) transport.set_record_button(ButtonElement(True, 0, 0, 66))
class VoidMaschine(ControlSurface): """ Originally Created on Nov 7, 2010 :: Matt Howell Thanks to Hanz Petrov, Native Instruments, Ableton, Liine """ def __init__(self, c_instance): """ Constructor """ ControlSurface.__init__(self, c_instance) self.name = 'VoidMaschine' self.log_message(self.name + " opened =-- @ "+ time.strftime("%d.%m.%Y %H:%M:%S", time.localtime())) self.set_suppress_rebuild_requests(True) self._suppress_session_highlight = False self._suppress_send_midi = True self._suggested_input_port = MASCHINE_DEVICE_PORT_NAME self._suggested_output_port = MASCHINE_DEVICE_PORT_NAME self._shift_button = None self.transport = TransportComponent() self.transport.name = 'Transport' self.session = None self.session_zoom = None self.mixer = None self.back_to_arranger_button = None self.is_momentary = True self.bpmBeatTime = 0 self.lastBeat = 0 self._setup_transport_control() self._session = VoidSessionComponent(c_instance) self._session.name = 'Session_Control' self._setup_mixer_control() #self._session_zoom = SessionZoomingComponent(self._session) #self._session_zoom.name = 'Session_Overview' #self._session_zoom.set_button_matrix(self._session._matrix) self._set_back_to_arranger_button(ButtonElement(True, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_BACK_TO_ARRANGER)) self.set_suppress_rebuild_requests(False) self._display = PhysicalDisplayElement(56, 8) self._void_message() self._register_timer_callback(self.update_controller) self._register_timer_callback(self.updateTempo) self._register_timer_callback(self.onTempoChange) def _void_message(self): self.sendScreenSysex(self.translateString((SYSEX_SCREEN_BUFFER_15 + 'VoidMaschine' + SYSEX_SCREEN_BUFFER_15)), 1) self.sendScreenSysex(self.translateString(('Voidrunner.com' + SYSEX_SCREEN_BUFFER_15 + ' maschine/ableton')), 2) def _setup_mixer_control(self): self.mixer = MixerComponent(0, 0, with_eqs=False, with_filters=False) master_volume_control = EncoderElement(MIDI_CC_TYPE, MIXER_CHANNEL, MASTER_VOLUME, Live.MidiMap.MapMode.absolute) booth_volume_control = EncoderElement(MIDI_CC_TYPE, MIXER_CHANNEL, MASTER_BOOTH, Live.MidiMap.MapMode.absolute) self.mixer.set_prehear_volume_control(booth_volume_control) self.mixer.master_strip().set_volume_control(master_volume_control) def _setup_transport_control(self): play_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_PLAY) stop_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_STOP) record_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_RECORD) seek_ffwd_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_SEEK_FFWD) seek_rwd_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_SEEK_RWD) tap_tempo_button = ButtonElement(self.is_momentary, MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_TAP_TEMPO) tempo_control = EncoderElement(MIDI_CC_TYPE, TRANSPORT_CHANNEL, TRANSPORT_COARSE_TEMPO, Live.MidiMap.MapMode.absolute) play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' record_button.name = 'Record_Button' seek_ffwd_button.name = 'Seek_FFWD_Button' seek_rwd_button.name = 'Seek_RWD_Button' tap_tempo_button.name = 'Tap_Tempo_Button' self.transport.set_play_button(play_button) self.transport.set_stop_button(stop_button) self.transport.set_record_button(record_button) self.transport.set_tap_tempo_button(tap_tempo_button) self.transport.set_tempo_control(tempo_control) self.transport.set_seek_buttons(seek_ffwd_button, seek_rwd_button) def _set_back_to_arranger_button(self, button): button.add_value_listener(self.back_to_arranger) self.back_to_arranger_button = button def disconnect(self): self.send_midi((240, 0, 66, 89, 69, 247)) #goodbye message in sysex stream def send_midi(self, midi_event_bytes): """ Use this function to send MIDI events through Live to the _real_ MIDI devices that this script is assigned to. """ assert isinstance(midi_event_bytes, tuple) self._send_midi(midi_event_bytes) return True def translateString(self, text): """ Convert a string into a sysex safe string """ result = () length = len(text) for i in range(0, length): charCode = ord(text[i]) if (charCode < 32): charCode = 32 elif (charCode > 127): charCode = 127 result = (result + (charCode,)) return result def sendScreenSysex(self, data, line=1): """ Data must be a tuple of bytes, remember only 7-bit data is allowed for sysex """ if not data: pass if(line==1): self._send_midi(((SYSEX_SCREEN_BEGIN_LINE_1 + data) + SYSEX_SCREEN_END)) else: if(line==2): self._send_midi(((SYSEX_SCREEN_BEGIN_LINE_2 + data) + SYSEX_SCREEN_END)) def send_value(self, msg_type, channel, id, value, force_send = False): assert (value != None) assert isinstance(value, int) assert (value in range(128)) data_byte1 = id data_byte2 = value status_byte = channel if (msg_type == MIDI_NOTE_TYPE): status_byte += MIDI_NOTE_ON_STATUS elif (msg_type == MIDI_CC_TYPE): status_byte += MIDI_CC_STATUS else: assert False self._send_midi((status_byte, data_byte1, data_byte2)) def back_to_arranger(self, *args, **kwargs): self.song().back_to_arranger = False def update_controller(self): """ controller event loop this may also update every 100 miliseconds. decoupling the data updates from live and the controller communication may help keep latency to a minimum. """ def onTempoChange(self): self.bpmBeatTime = self.song().get_current_beats_song_time() def updateTempo(self): if self.song().is_playing: if (self.bpmBeatTime.beats > self.lastBeat): self.updateBPMLightOff() else: self.updateBPMLightOn() def updateBPMLightOn(self): self.transport._play_button.turn_on() #self.send_value(MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_TEMPO, MASCHINE_DISPLAY_BPM) def updateBPMLightOff(self): self.transport._play_button.turn_off() #self.send_value(MIDI_NOTE_TYPE, TRANSPORT_CHANNEL, TRANSPORT_TEMPO, 0)
class Axiom_OJI(AxiomPro): """ Script for the M-Audio Axiom Pro OJI version """ _browser_mode_enabled = False def __init__(self, *a, **k): #super(Axiom_OJI, self).__init__(*a, **k) ControlSurface.__init__(self, *a, **k) with self.component_guard(): is_momentary = True #self.set_pad_translations(PAD_TRANSLATIONS) self._suggested_input_port = u'HyperControl' self._suggested_output_port = u'HyperControl' self._display_on_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 15, 79) self._waiting_for_first_response = True self._mixer1 = DisplayingMixerComponent(0) self._mixer1.set_select_buttons( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 111), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 110)) self._mixer1.set_mute_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 12)) self._mixer1.set_solo_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 13)) self._mixer2 = NotifyingMixerComponent(8) self._mixer2.set_bank_buttons( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 15), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 14)) self._mixer2.master_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, 15, 41)) for index in range(8): self._mixer2.channel_strip(index).set_volume_control( SliderElement(MIDI_CC_TYPE, 15, 33 + index)) self._device = PageableDeviceComponent( device_selection_follows_track_selection=True) self.set_device_component(self._device) self._ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 115) self._rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 114) self._loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 113) self._transport = TransportComponent() self._transport.set_stop_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 116)) self._transport.set_play_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 117)) self._transport.set_record_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 118, name='RecordButton')) self._session = SessionComponent(0, 0) self._transport_view_modes = TransportViewModeSelector( self._transport, self._session, self._ffwd_button, self._rwd_button, self._loop_button) self._select_button_modes = SelectButtonModeSelector( self._mixer2, tuple([ ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 49 + offset) for offset in range(8) ])) self._select_button_modes.set_mode_toggle( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 57)) self._mixer_encoder_modes = EncoderMixerModeSelector(self._mixer2) self._encoders = [] for offset in range(8): self._encoders.append( PeekableEncoderElement( MIDI_CC_TYPE, 15, 17 + offset, Live.MidiMap.MapMode.relative_smooth_two_compliment)) self._encoders[-1].set_feedback_delay(-1) self._mixer_or_device = MixerOrDeviceModeSelector( self._mixer_encoder_modes, self._device, tuple(self._encoders), tuple([ ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 74 + offset) for offset in range(4) ])) self._mixer_or_device.set_mode_toggle( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 109)) self._mixer_or_device.set_peek_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 78)) self._track_display = PhysicalDisplayElement(8, 1) self._track_display.set_clear_all_message(SYSEX_START + (16, 247)) self._track_display.set_message_parts(SYSEX_START + (17, 1, 0, 0), (247, )) #self._track_display.segment(0).set_data_source(mixer1.selected_strip().track_name_data_source()) self._device_display = PhysicalDisplayElement(8, 1) self._device_display.set_message_parts( SYSEX_START + (17, 1, 0, 10), (247, )) self._parameter_display = PhysicalDisplayElement(16, 1) self._parameter_display.set_message_parts( SYSEX_START + (17, 2, 0, 0), (247, )) #self._select_button_modes.set_mode_display(parameter_display) #self._mixer1.set_display(parameter_display) #self._mixer2.set_bank_display(parameter_display) self._page_displays = [] for index in range(4): self._page_displays.append(PhysicalDisplayElement(5, 1)) self._page_displays[-1].set_message_parts( SYSEX_START + (17, 4, index, 0), (247, )) self._encoder_display = PhysicalDisplayElement(80, 8) self._encoder_display.set_message_parts(SYSEX_START + (17, 3), (247, )) for index in range(8): pos_id = tuple() if index != 0: pos_id += (0, ) if index > 3: pos_id += (index % 4, 13) else: pos_id += (index % 4, 0) self._encoder_display.segment(index).set_position_identifier( pos_id) self._data_sources = [ DisplayDataSource(' ') for index in range(7) ] top_display = PhysicalDisplayElement(20, 1) top_display.set_message_parts(SYSEX_START + (17, 1, 0, 0), (247, )) top_display.set_clear_all_message(SYSEX_START + (16, 247)) self._header_display = top_display self._display1 = top_display.segment(0) long_display = PhysicalDisplayElement(80, 4) long_display.set_message_parts(SYSEX_START + ( 17, 3, ), (247, )) self._display2 = long_display.segment(0) pos_id = tuple() pos_id += (0, 0) self._display2.set_position_identifier(pos_id) self._display3 = long_display.segment(1) pos_id = tuple() pos_id += (0, 1, 0) self._display3.set_position_identifier(pos_id) self._display4 = long_display.segment(2) pos_id = tuple() pos_id += (0, 2, 0) self._display4.set_position_identifier(pos_id) self._display5 = long_display.segment(3) pos_id = tuple() pos_id += (0, 3, 0) self._display5.set_position_identifier(pos_id) middle_display = PhysicalDisplayElement(20, 1) middle_display.set_message_parts(SYSEX_START + (17, 2, 0, 0), (247, )) self._display6 = middle_display.segment(0) bottom_display = PhysicalDisplayElement(20, 1) bottom_display.set_message_parts(SYSEX_START + (17, 4, 0, 0), (247, )) self._display7 = bottom_display.segment(0) self._browser_displays = [ self._display1, self._display2, self._display3, self._display4, self._display5, self._display6, self._display7 ] self._drumpads = [ ButtonElement(True, MIDI_NOTE_TYPE, 15, 81 + index, name='Pad_' + str(index)) for index in range(8) ] self._setup_m4l_interface() self.log_message('Axiom_OJI script installed') """ def __init__(self, *a, **k): super(Axiom_OJI, self).__init__(*a, **k) with self.component_guard(): #self._data_sources = (DisplayDataSource('TEST') for index in range(7)) self._display1 = PhysicalDisplayElement(16, 1) self._display1.set_message_parts(SYSEX_START + (17, 1, 0, 0), (247,)) self._header_display = self._display1 self._header_display.set_clear_all_message(SYSEX_START + (16, 247)) self._display2 = PhysicalDisplayElement(16, 1) self._display2.set_message_parts(SYSEX_START + (17, 3, 0, 0), (247,)) self._display3 = PhysicalDisplayElement(16, 1) self._display3.set_message_parts(SYSEX_START + (17, 3, 1, 0), (247,)) self._display4 = PhysicalDisplayElement(16, 1) self._display4.set_message_parts(SYSEX_START + (17, 3, 2, 0), (247,)) self._display5 = PhysicalDisplayElement(16, 1) self._display5.set_message_parts(SYSEX_START + (17, 3, 3, 0), (247,)) self._display6 = PhysicalDisplayElement(16, 1) self._display6.set_message_parts(SYSEX_START + (17, 2, 0, 0), (247,)) self._display7 = PhysicalDisplayElement(16, 1) self._display7 .set_message_parts(SYSEX_START + (17, 4, 0, 0), (247,)) self._browser_displays = [self._display1, self._display2, self._display3, self._display4, self._display5, self._display6, self._display7] """ def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent( controls=self.controls, component_guard=self.component_guard, priority=10) self._m4l_interface.name = "M4LInterface" self.get_control_names = self._m4l_interface.get_control_names self.get_control = self._m4l_interface.get_control self.grab_control = self._m4l_interface.grab_control self.release_control = self._m4l_interface.release_control def handle_sysex(self, midi_bytes): if midi_bytes[0:-2] == SYSEX_START + (32, ): msg_id_byte = midi_bytes[-2] is_setup_response = msg_id_byte in (46, 38) has_sliders = msg_id_byte == 46 if is_setup_response: if self._waiting_for_first_response: self._waiting_for_first_response = False self._display_on_button.send_value(0) if not self._browser_mode_enabled: for component in self.components: component.set_enabled(True) self._display_on_button.send_value(127) self._send_midi(SYSEX_START + (16, 247)) self._send_midi(SYSEX_START + (17, 3, 0, 1, 65, 98, 108, 101, 116, 111, 110, 32, 76, 105, 118, 101, 32, 67, 111, 110, 116, 114, 111, 108, 32, 0, 1, 4, 83, 117, 114, 102, 97, 99, 101, 32, 118, 49, 46, 48, 46, 48, 46, 247)) self._mixer_encoder_modes.set_show_volume_page(not has_sliders) #if not self._browser_mode_enabled: for display in self._displays: display.set_block_messages(False) self.schedule_message(25, self._refresh_displays) #self.schedule_message(30, self._enable_browser) elif msg_id_byte == 43: self._send_midi(SYSEX_START + (16, 247)) #if not self._browser_mode_enabled: for display in self._displays: if display is self._track_display: display.update() else: display.set_block_messages(True) def _enable_browser(self): self.enable_browser_mode(True) def enable_browser_mode(self, enable): self._browser_mode_enabled = enable > 0 debug('enable_browser_mode:' + str(enable)) if enable: for component in self.components: component.set_enabled(False) self._header_display.reset() self._track_display.segment(0).set_data_source(None) for index in range(7): debug('index: ' + str(index)) self._browser_displays[index].set_data_source( self._data_sources[index]) else: self._header_display.reset() for index in range(7): debug('index: ' + str(index)) self._browser_displays[index].set_data_source(None) for component in self.components: component.set_enabled(True) def _enable_browser_mode(self, enable): self._browser_mode_enabled = enable > 0 #debug('enable_browser_mode', enable) if enable: #debug('here 1') for component in self.components: component.set_enabled(False) self._header_display.reset() #debug('here 2') #for index, display in enumerate(self._browser_displays): #debug('index:', index, 'display:', display) #self._data_sources[index].clear() #display.set_data_source(self._data_sources[index]) else: for component in self.components: component.set_enabled(True) def write_to_lcd(self, display, message): if self._browser_mode_enabled and display in range(7): self._data_sources[display].set_display_string(message) def test_browser(self): debug('test_browser') browser = self.application.browser debug('browser is:', browser) user_folders = browser.user_folders debug('user_folders are:', user_folders) for item in user_folders: #debug('item is:', item, item.name) if item.name == 'defaultPresets': inneritems = item.iter_children for inneritem in inneritems: debug('inneritem:', inneritem) if inneritem.name == 'Default.aupreset': browser.load_item(inneritem) break def load_preset(self, target=None, folder=None, directory='defaultPresets'): debug('load_preset()', target, folder, directory) if not target is None: browser = Live.Application.get_application( ).browser ##if not self.application.view.browse_mode else self.application.browser.hotswap_target user_folders = browser.user_folders for item in user_folders: if item.name == directory: if not folder is None: folder_target = None item_iterator = item.iter_children inneritems = [inneritem for inneritem in item_iterator] for inneritem in inneritems: if inneritem.name == folder: folder_target = inneritem break if folder_target: item_iterator = folder_target.iter_children inneritems = [ inneritem for inneritem in item_iterator ] for inneritem in inneritems: if isinstance(target, int): if target < len(inneritems): if inneritems[target].is_loadable: browser.load_item( inneritems[target]) break elif inneritems[target].is_folder: debug(inneritems[target], '.is_folder') innertarget = inneritems[target] innertarget_iterator = innertarget.iter_children innertargetitems = [ innertargetitem for innertargetitem in innertarget_iterator ] #debug('innertargetitems:', innertargetitems) if len(innertargetitems ) > 0 and innertargetitems[ 0].is_loadable: browser.load_item( innertargetitems[0]) break else: debug(innertargetitems[0], 'item isnt loadable 0') break else: debug(inneritems[target], 'item isnt loadable 1') break else: if inneritem.name == target: if inneritem.is_loadable: browser.load_item(inneritem) else: debug(inneritem, 'item isnt loadable 2') break else: item_iterator = item.iter_children inneritems = [inneritem for inneritem in item_iterator] for inneritem in inneritems: if isinstance(target, int): if target < len(inneritems): if inneritems[target].is_loadable: browser.load_item(inneritems[target]) break else: debug(inneritems[target], 'item isnt loadable 3') break else: if inneritem.name == target: if inneritem.is_loadable: browser.load_item(inneritem) break else: debug(inneritem, 'item isnt loadable 4') break def get_preset_names(self, folder=None, directory='defaultPresets'): #debug('get_preset_names', folder, directory) preset_names = [ 'no target', 'no target', 'no target', 'no target', 'no target', 'no target', 'no target', 'no target' ] browser = Live.Application.get_application( ).browser ##if not self.application.view.browse_mode else self.application.browser.hotswap_target user_folders = browser.user_folders for item in user_folders: if item.name == directory: if not folder is None: folder_target = None item_iterator = item.iter_children inneritems = [inneritem for inneritem in item_iterator] for inneritem in inneritems: if inneritem.name == folder: folder_target = inneritem break if folder_target: item_iterator = folder_target.iter_children preset_names = [ inneritem.name for inneritem in item_iterator ] else: item_iterator = item.iter_children preset_names = [ inneritem.name for inneritem in item_iterator ] #debug('names:', preset_names) return preset_names def write_presets_to_lcd(self, folder=None, directory='defaultPresets'): #debug('write_presets_to_lcd') preset_names = self.get_preset_names(folder, directory) #debug('names:', preset_names) for i, name in enumerate(preset_names): if i < 7: #debug('name:', i, name) self.write_to_lcd(i, name[:20])
def _setup_components(self): # Session self._session = SessionComponent(8, len(self._scene_launch_buttons)) self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( self._scene_launch_button) self._session.set_stop_all_clips_button(self._scene_stop_button) for index in range(8): clip_slot = self._session.selected_scene().clip_slot(index) clip_slot.set_launch_button(self._clip_launch_buttons[index]) clip_slot.name = 'Selected_Clip_Slot_' + str(index) self._session.set_stop_track_clip_buttons( tuple(self._clip_stop_buttons)) # Undo self._do_undo.subject = self._clip_undo_button # Transport transport = TransportComponent() transport.name = 'Transport' transport.set_stop_button(self._stop_button) transport.set_play_button(self._play_button) transport.set_record_button(self._rec_button) transport.set_loop_button(self._loop_button) self._transport_view_modes = TransportViewModeSelector( transport, self._session, self._ffwd_button, self._rwd_button) self._transport_view_modes.name = 'Transport_View_Modes' session_recording = SessionRecordingComponent( ClipCreator(), ViewControlComponent(), name='Session_Recording', is_enabled=False, layer=Layer(record_button=self._overdub_button)) # Device # device = DeviceComponent() # device.name = 'Device_Component' # self.set_device_component(device) # device.set_parameter_controls(self._encoders) # Navigation self._session_navigation = SessionNavigationComponent( name='Session_Navigation') self._session_navigation.set_next_track_button(self._next_track_button) self._session_navigation.set_prev_track_button(self._prev_track_button) # Playing # self._session.set_scene_launch_buttons(tuple(self._scene_launch_buttons)) for index in range(len(self._scene_launch_buttons)): scene = self._session.scene(index) scene.set_launch_button(self._scene_launch_buttons[index])
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): is_momentary = True self._device_selection_follows_track_selection = True self.set_pad_translations(PAD_TRANSLATIONS) self._suggested_input_port = 'HyperControl' self._suggested_output_port = 'HyperControl' self._display_on_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 15, 79) self._waiting_for_first_response = True mixer1 = DisplayingMixerComponent(0) mixer1.set_select_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 111), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 110)) mixer1.set_mute_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 12)) mixer1.set_solo_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 13)) mixer2 = NotifyingMixerComponent(8) mixer2.set_bank_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 15), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 14)) mixer2.master_strip().set_volume_control(SliderElement(MIDI_CC_TYPE, 15, 41)) for index in range(8): mixer2.channel_strip(index).set_volume_control(SliderElement(MIDI_CC_TYPE, 15, 33 + index)) device = PageableDeviceComponent() self.set_device_component(device) ffwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 115) rwd_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 114) loop_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 113) transport = TransportComponent() transport.set_stop_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 116)) transport.set_play_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 117)) transport.set_record_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 118)) session = SessionComponent(0, 0) transport_view_modes = TransportViewModeSelector(transport, session, ffwd_button, rwd_button, loop_button) select_button_modes = SelectButtonModeSelector(mixer2, tuple([ ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 49 + offset) for offset in range(8) ])) select_button_modes.set_mode_toggle(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 57)) self._mixer_encoder_modes = EncoderMixerModeSelector(mixer2) encoders = [] for offset in range(8): encoders.append(PeekableEncoderElement(MIDI_CC_TYPE, 15, 17 + offset, Live.MidiMap.MapMode.relative_smooth_two_compliment)) encoders[-1].set_feedback_delay(-1) mixer_or_device = MixerOrDeviceModeSelector(self._mixer_encoder_modes, device, tuple(encoders), tuple([ ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 74 + offset) for offset in range(4) ])) mixer_or_device.set_mode_toggle(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 109)) mixer_or_device.set_peek_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 78)) self._track_display = PhysicalDisplayElement(8, 1) self._track_display.set_clear_all_message(SYSEX_START + (16, 247)) self._track_display.set_message_parts(SYSEX_START + (17, 1, 0, 0), (247,)) self._track_display.segment(0).set_data_source(mixer1.selected_strip().track_name_data_source()) device_display = PhysicalDisplayElement(8, 1) device_display.set_message_parts(SYSEX_START + (17, 1, 0, 10), (247,)) parameter_display = PhysicalDisplayElement(16, 1) parameter_display.set_message_parts(SYSEX_START + (17, 2, 0, 0), (247,)) select_button_modes.set_mode_display(parameter_display) mixer1.set_display(parameter_display) mixer2.set_bank_display(parameter_display) page_displays = [] for index in range(4): page_displays.append(PhysicalDisplayElement(5, 1)) page_displays[-1].set_message_parts(SYSEX_START + (17, 4, index, 0), (247,)) encoder_display = PhysicalDisplayElement(80, 8) encoder_display.set_message_parts(SYSEX_START + (17, 3), (247,)) for index in range(8): pos_id = tuple() if index != 0: pos_id += (0,) if index > 3: pos_id += (index % 4, 13) else: pos_id += (index % 4, 0) encoder_display.segment(index).set_position_identifier(pos_id) mixer_or_device.set_displays(encoder_display, parameter_display, device_display, tuple(page_displays)) for component in self.components: component.set_enabled(False)
class Axiom_AIR_25_49_61(ControlSurface): """ Script for the M-Audio Axiom A.I.R. 25, 49 and 61 """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._alt_device_component = None with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) self._device_selection_follows_track_selection = True self._suggested_input_port = "HyperControl" self._suggested_output_port = "HyperControl" self._single_fader_button_modes = None self._has_faders = True self._display_reset_delay = -1 self._hc_byte = HC_BYTE self._waiting_for_first_response = True self._setup_controls() self._setup_displays() self._setup_mixer() self._setup_session() self._setup_transport() self._setup_device() self._setup_modes() self._drum_group_midi_button = None self._drum_group_hyper_button = None for component in self.components: component.set_enabled(False) def disconnect(self): self._scheduled_messages = [] for encoder in self._encoders: encoder.remove_value_listener(self._encoder_value) for fader in self._faders: fader.remove_value_listener(self._fader_value) for fader_button in self._fader_buttons: fader_button.remove_value_listener(self._fader_button_value) self._master_fader.remove_value_listener(self._fader_value) self._master_fader_button.remove_value_listener(self._fader_button_value) self._select_button.remove_value_listener(self._select_button_value) self._identify_button.remove_value_listener(self._identify_value) self._fader_group_midi_button.remove_value_listener(self._midi_button_value) self._fader_group_mix_button.remove_value_listener(self._hyper_button_value) self._fader_group_fx_button.remove_value_listener(self._hyper_button_value) self._encoder_group_midi_button.remove_value_listener(self._midi_button_value) self._encoder_group_mix_button.remove_value_listener(self._hyper_button_value) self._encoder_group_fx_button.remove_value_listener(self._hyper_button_value) if self._drum_group_midi_button != None: self._drum_group_midi_button.remove_value_listener(self._midi_button_value) if self._drum_group_hyper_button != None: self._drum_group_hyper_button.remove_value_listener(self._hyper_button_value) self._alt_device_component = None self._name_display = None self._value_display = None self._bank_display = None self._pad_display = None self._name_display_data_source = None self._value_display_data_source = None self._bank_display_data_source = None self._pad_display_data_source = None self._select_button = None self._left_button = None self._right_button = None self._up_button = None self._down_button = None self._loop_button = None self._ffwd_button = None self._rwd_button = None self._play_button = None self._stop_button = None self._rec_button = None self._master_fader_button = None self._fader_buttons = None self._faders = None self._encoders = None self._drum_pads = None self._identify_button = None self._main_group_hyper_button = None self._main_group_track_button = None self._main_group_fx_button = None self._encoder_group_midi_button = None self._encoder_group_mix_button = None self._encoder_group_fx_button = None self._fader_group_mode_button = None self._fader_group_midi_button = None self._fader_group_mix_button = None self._fader_group_fx_button = None self._drum_group_midi_button = None self._drum_group_roll_button = None self._drum_group_hyper_button = None self._mixer_for_encoders = None self._mixer_for_faders = None self._device_for_encoders = None self._device_for_faders = None self._transport = None self._session = None ControlSurface.disconnect(self) self._send_midi(SYSEX_START + DISABLE_HYPERCONTROL) def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(5, self._send_midi, IDENTITY_REQUEST) def handle_sysex(self, midi_bytes): if midi_bytes[0:10] == AXIOM_AIR_RESPONSE: if midi_bytes[12:15] < AXIOM_REV4_RESPONSE: self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL) self.schedule_message(2, self._send_midi, SYSEX_START + CLEAR_ALL) self.schedule_message(3, self._name_display.display_message, "Firmware") self.schedule_message(13, self._name_display.display_message, "Update") self.schedule_message(23, self._name_display.display_message, "Required") self.schedule_message(33, self._send_midi, SYSEX_START + DISABLE_HYPERCONTROL) elif midi_bytes[12:15] >= AXIOM_REV4_RESPONSE: if self._waiting_for_first_response == True: self._waiting_for_first_response = False self._has_faders = midi_bytes[10] != 50 self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL) self.schedule_message(2, self._send_midi, SYSEX_START + SPECIAL_HYPERCONTROL) self.schedule_message(3, self._complete_setup) else: self._display_reset_delay = 0 elif midi_bytes[0:8] == REQUEST_HYPERCONTROL: self.schedule_message(5, self._send_midi, IDENTITY_REQUEST) def update_display(self): ControlSurface.update_display(self) if self._display_reset_delay >= 0: self._display_reset_delay -= 1 if self._display_reset_delay == -1: self._set_displays_to_default() def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) self._display_reset_delay = 0 def restore_bank(self, bank_index): ControlSurface.restore_bank(self, bank_index) if self._alt_device_component != None: self._alt_device_component.restore_bank(bank_index) def set_appointed_device(self, device): ControlSurface.set_appointed_device(self, device) with self.component_guard(): if self._alt_device_component != None: self._alt_device_component.set_device(device) def set_alt_device_component(self, device_component): self._alt_device_component = device_component def _update_device_selection(self): track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) if self._alt_device_component != None: self._alt_device_component.set_device(device_to_select) def _setup_controls(self): self._left_button = create_button(99, "Left_Button") self._right_button = create_button(100, "Right_Button") self._up_button = create_button(101, "Up_Button") self._down_button = create_button(102, "Down_Button") self._loop_button = create_button(113, "Loop_Button") self._rwd_button = create_button(114, "Rwd_Button") self._ffwd_button = create_button(115, "FFwd_Button") self._stop_button = create_button(116, "Stop_Button") self._play_button = create_button(117, "Play_Button") self._rec_button = create_button(118, "Record_Button") self._select_button = ConfigurableButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, GLOBAL_CHANNEL, 98) self._select_button.name = "Select_Button" self._select_button.add_value_listener(self._select_button_value) self._main_group_hyper_button = create_configurable_button(104, "Fader_Group_HyperControl_Button", 2, 14) self._main_group_track_button = create_configurable_button(105, "Main_Group_Track_Button", 2, 11) self._main_group_fx_button = create_configurable_button(106, "Main_Group_Inst_FX_Button", 2, 11) self._identify_button = create_configurable_button(97, "Identify_Button", 2, 16) self._identify_button.add_value_listener(self._identify_value) self._fader_buttons = [] for index in range(8): self._fader_buttons.append(create_configurable_button(49 + index, "Fader_Button_%d" % index)) self._fader_buttons[-1].add_value_listener(self._fader_button_value, identify_sender=True) self._faders = [] for index in range(8): self._faders.append(create_slider(33 + index, "Fader_%d" % index)) self._faders[-1].add_value_listener(self._fader_value, identify_sender=True) self._master_fader_button = create_configurable_button(57, "Master_Fader_Button") self._master_fader_button.add_value_listener(self._fader_button_value, identify_sender=True) self._master_fader = create_slider(41, "Master_Fader") self._master_fader.add_value_listener(self._fader_value, identify_sender=True) self._fader_group_mode_button = create_configurable_button(61, "Fader_Group_Mode_Button") self._fader_group_midi_button = create_configurable_button(60, "Fader_Group_MIDI_Button") self._fader_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True) self._fader_group_mix_button = create_configurable_button(58, "Fader_Group_Mix_Button", 0, 1) self._fader_group_mix_button.add_value_listener(self._hyper_button_value, identify_sender=True) self._fader_group_fx_button = create_configurable_button(59, "Fader_Group_Inst_FX_Button", 0, -1) self._fader_group_fx_button.add_value_listener(self._hyper_button_value, identify_sender=True) self._encoders = [] for index in range(8): self._encoders.append(create_encoder(17 + index, "Encoder_%d" % index)) self._encoders[-1].add_value_listener(self._encoder_value, identify_sender=True) self._encoder_group_midi_button = create_configurable_button(27, "Encoder_Group_MIDI_Button", 0, 72) self._encoder_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True) self._encoder_group_mix_button = create_configurable_button(25, "Encoder_Group_Mix_Button", 0, 72) self._encoder_group_mix_button.add_value_listener(self._hyper_button_value, identify_sender=True) self._encoder_group_fx_button = create_configurable_button(26, "Encoder_Group_Inst_FX_Button", 0, 72) self._encoder_group_fx_button.add_value_listener(self._hyper_button_value, identify_sender=True) def _setup_drum_pads(self): self._drum_pads = [] num_pads = 12 if self._has_faders else 16 for index in range(8): self._drum_pads.append(create_configurable_button(81 + index, "Pad_%d" % index, 0, 0, MIDI_CC_TYPE)) for index in range(num_pads - 8): self._drum_pads.append( ConfigurableButtonElement( IS_MOMENTARY, MIDI_NOTE_TYPE, GLOBAL_CHANNEL - 1, 81 + index, GLOBAL_SEND_CHANNEL, 8, MIDI_CC_TYPE ) ) self._drum_pads[-1].name = "Pad_" + str(index + 8) self._drum_group_midi_button = create_configurable_button(91, "Drum_Group_MIDI_Button", 2, -2) self._drum_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True) self._drum_group_roll_button = create_configurable_button(90, "Drum_Group_Roll_Button", -1) self._drum_group_hyper_button = create_configurable_button(89, "Drum_Group_HyperControl_Button", 2, 2) self._drum_group_hyper_button.add_value_listener(self._hyper_button_value, identify_sender=True) def _setup_displays(self): self._name_display = PhysicalDisplayElement(12, 1) self._name_display.name = "Name_Display" self._name_display.set_message_parts(SYSEX_START + (21,), (0, 247)) self._name_display.set_clear_all_message(CLEAR_NAME) self._name_display_data_source = DisplayDataSource() self._name_display.segment(0).set_data_source(self._name_display_data_source) self._value_display = NumericalDisplayElement(3, 1) self._value_display.name = "Value_Display" self._value_display.set_message_parts(SYSEX_START + (20, 48), (0, 247)) self._value_display.set_clear_all_message(CLEAR_VALUE) self._value_display_data_source = DisplayDataSource() self._value_display.segment(0).set_data_source(self._value_display_data_source) self._bank_display = NumericalDisplayElement(3, 1) self._bank_display.name = "Bank_Display" self._bank_display.set_message_parts(SYSEX_START + (19,), (0, 247)) self._bank_display.set_clear_all_message(CLEAR_BANK) self._bank_display_data_source = DisplayDataSource() self._bank_display.segment(0).set_data_source(self._bank_display_data_source) self._pad_display = NumericalDisplayElement(2, 1) self._pad_display.name = "Pad_Display" self._pad_display.set_message_parts(SYSEX_START + (18,), (0, 247)) self._pad_display.set_clear_all_message(CLEAR_PAD) self._pad_display_data_source = DisplayDataSource() self._pad_display.segment(0).set_data_source(self._pad_display_data_source) def _setup_mixer(self): self._mixer_for_encoders = SpecialMixerComponent(self._name_display, self._value_display, 8) self._mixer_for_encoders.name = "Mixer_for_encoders" self._mixer_for_faders = SpecialMixerComponent(self._name_display, self._value_display, 8) self._mixer_for_faders.name = "Mixer_for_faders" def _setup_session(self): self._session = SpecialSessionComponent(8, 0) self._session.name = "Session_Control" self._session.selected_scene().name = "Selected_Scene" self._session.set_mixer(self._mixer_for_encoders) self._session.set_alt_mixer(self._mixer_for_faders) self._session.add_offset_listener(self._update_bank_value) def _setup_transport(self): self._transport = TransportComponent() self._transport.name = "Transport" self._transport.set_stop_button(self._stop_button) self._transport.set_play_button(self._play_button) self._transport.set_record_button(self._rec_button) transport_view_modes = TransportViewModeSelector( self._transport, self._session, self._ffwd_button, self._rwd_button, self._loop_button ) transport_view_modes.name = "Transport_View_Modes" def _setup_device(self): self._device_for_encoders = BestBankDeviceComponent() self._device_for_encoders.name = "Device_Component_for_encoders" self._device_for_faders = BestBankDeviceComponent() self._device_for_faders.name = "Device_Component_for_faders" self.set_device_component(self._device_for_encoders) self.set_alt_device_component(self._device_for_faders) self._device_nav = DeviceNavComponent() self._device_nav.name = "Device_Nav_Component" def _setup_modes(self): self._fader_button_modes = FaderButtonModeSelector(self._mixer_for_faders, tuple(self._fader_buttons)) self._fader_button_modes.name = "Fader_Button_Modes" self._fader_button_modes.set_mode_toggle(self._fader_group_mode_button) self._fader_modes = FaderModeSelector( self._mixer_for_faders, self._device_for_faders, tuple(self._faders), self._fader_button_modes, self._master_fader_button, ) self._fader_modes.name = "Fader_Modes" self._fader_modes.set_mode_buttons((self._fader_group_mix_button, self._fader_group_fx_button)) self._encoder_modes = EncoderModeSelector( self._mixer_for_encoders, self._device_for_encoders, tuple(self._encoders) ) self._encoder_modes.name = "Encoder_Modes" self._encoder_modes.set_mode_buttons((self._encoder_group_mix_button, self._encoder_group_fx_button)) main_modes = MainModeSelector( self._device_for_encoders, self._device_for_faders, self._session, self._mixer_for_faders, self._device_nav, self._up_button, self._down_button, self._left_button, self._right_button, self._select_button, ) main_modes.name = "Main_Modes" main_modes.set_mode_buttons((self._main_group_track_button, self._main_group_fx_button)) def _setup_master_fader(self): if self._has_faders: self._mixer_for_encoders.master_strip().set_volume_control(self._master_fader) else: self._mixer_for_encoders.selected_strip().set_volume_control(self._master_fader) def _setup_single_fader_button_modes(self): self._single_fader_button_modes = SingleFaderButtonModeSelector( self._mixer_for_encoders, self._fader_group_midi_button ) self._single_fader_button_modes.name = "Single_Fader_Button_Modes" self._single_fader_button_modes.set_mode_toggle(self._fader_group_mode_button) def _complete_setup(self): self._setup_drum_pads() self._set_drum_pads_to_hc() self._setup_master_fader() if not self._has_faders: self._setup_single_fader_button_modes() for control in self.controls: if isinstance(control, InputControlElement): control.clear_send_cache() for component in self.components: component.set_enabled(True) self._fader_group_midi_button.send_value(LED_OFF, True) self._encoder_group_midi_button.send_value(LED_OFF, True) self._main_group_hyper_button.send_value(AMB_FULL, True) self.request_rebuild_midi_map() self._on_selected_track_changed() self.schedule_message(1, self._show_startup_message) def _show_startup_message(self): self._send_midi(SYSEX_START + CLEAR_ALL) self._name_display.display_message("Ableton Live") self._display_reset_delay = INITIAL_DISPLAY_DELAY def _select_button_value(self, value): self._display_reset_delay = STANDARD_DISPLAY_DELAY def _identify_value(self, value): for encoder in self._encoders: encoder.set_identify_mode(value > 0) for fader in self._faders: fader.set_identify_mode(value > 0) self._master_fader.set_identify_mode(value > 0) self._display_reset_delay = 0 self._identify_button.turn_on() if value > 0 else self._identify_button.turn_off() def _midi_button_value(self, value, sender): if value > 0: if sender is self._drum_group_midi_button: hc_byte = self._hc_byte ^ PADS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._drum_group_hyper_button.send_value(LED_OFF, True) self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) elif sender is self._encoder_group_midi_button: hc_byte = self._hc_byte ^ ENCODERS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._encoder_group_mix_button.send_value(LED_OFF, True) self._encoder_group_fx_button.send_value(LED_OFF, True) if self._encoder_modes.mode_index < 3: self._encoder_modes.set_enabled(False) self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) elif sender is self._fader_group_midi_button: if self._has_faders: hc_byte = self._hc_byte ^ FADERS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._fader_group_mix_button.send_value(LED_OFF, True) self._fader_group_fx_button.send_value(LED_OFF, True) self._fader_group_mode_button.send_value(LED_OFF, True) if self._fader_modes.mode_index < 2: self._fader_modes.set_enabled(False) self._fader_button_modes.set_enabled(False) self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) else: self._display_reset_delay = STANDARD_DISPLAY_DELAY def _hyper_button_value(self, value, sender): if value > 0: if sender is self._drum_group_hyper_button: if self._hc_byte | PADS != self._hc_byte: self._hc_byte = self._hc_byte | PADS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self.schedule_message(1, self._set_drum_pads_to_hc) elif sender is self._encoder_group_fx_button or sender is self._encoder_group_mix_button: if self._hc_byte | ENCODERS != self._hc_byte: self._hc_byte = self._hc_byte | ENCODERS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self._encoder_group_midi_button.turn_off() if sender is self._encoder_group_fx_button: self._encoder_modes.set_enabled(True) self._display_reset_delay = 0 return else: self.schedule_message(1, self._encoder_modes.set_enabled, True) self.schedule_message(1, self._encoder_modes.update) self._display_reset_delay = 2 return elif sender is self._fader_group_fx_button or sender is self._fader_group_mix_button: if self._hc_byte | FADERS != self._hc_byte: self._hc_byte = self._hc_byte | FADERS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self._fader_group_midi_button.turn_off() self._fader_button_modes.set_enabled(True) if sender is self._fader_group_fx_button: self._fader_modes.set_enabled(True) self._fader_button_modes.set_enabled(True) self._display_reset_delay = 0 return else: self.schedule_message(1, self._fader_modes.set_enabled, True) self.schedule_message(1, self._fader_modes.update) self.schedule_message(1, self._fader_button_modes.set_enabled, True) self.schedule_message(1, self._fader_button_modes.update) self._display_reset_delay = 2 return self._display_reset_delay = 0 def _set_drum_pads_to_hc(self): self._drum_group_midi_button.send_value(LED_OFF, True) self._drum_group_hyper_button.send_value(RED_FULL, True) for index in range(len(self._drum_pads)): self._drum_pads[index].send_value(RED_LOW, True) def _fader_button_value(self, value, sender): self._display_reset_delay = STANDARD_DISPLAY_DELAY def _fader_value(self, value, sender): param = sender.mapped_parameter() if param != None: param_range = param.max - param.min if param.name == "Track Volume": if sender == self._master_fader: if self._has_faders: name_string = "Master Vol" else: name_string = ( self._mixer_for_faders.selected_strip().track_name_data_source().display_string() + " Vol" ) else: name_string = ( self._mixer_for_faders.channel_strip(self._faders.index(sender)) .track_name_data_source() .display_string() + " Vol" ) else: name_string = param.name value = int((param.value - param.min) / param_range * 127) value_string = str(value) else: name_string = "<unmapped>" value_string = None self.schedule_message(1, self._set_value_string) self._set_name_string(name_string) self._set_value_string(value_string) def _encoder_value(self, value, sender): param = sender.mapped_parameter() if param != None: param_range = param.max - param.min if param.name == "Track Volume": name_string = ( self._mixer_for_encoders.channel_strip(self._encoders.index(sender)) .track_name_data_source() .display_string() + " Vol" ) value = int((param.value - param.min) / param_range * 127) elif param.name == "Track Panning": name_string = ( self._mixer_for_encoders.channel_strip(self._encoders.index(sender)) .track_name_data_source() .display_string() + " Pan" ) value = int(param.value / param_range * 127) if value < 0: name_string += " L" elif value > 0: name_string += " R" else: name_string += " C" else: name_string = param.name value = int((param.value - param.min) / param_range * 127) value_string = str(value) else: name_string = "<unmapped>" value_string = None self.schedule_message(1, self._set_value_string) self._set_name_string(name_string) self._set_value_string(value_string) def _set_displays_to_default(self): self._name_display.segment(0).set_data_source( self._mixer_for_encoders.selected_strip().track_name_data_source() ) self._name_display.update() self._update_bank_value() self._set_value_string(None) self._send_midi(SYSEX_START + LCD_HC_DEFAULT) def _set_name_string(self, name_string): self._name_display.segment(0).set_data_source(self._name_display_data_source) self._name_display_data_source.set_display_string(name_string) self._display_reset_delay = STANDARD_DISPLAY_DELAY def _set_value_string(self, value_string=None): if value_string != None: self._value_display_data_source.set_display_string(value_string) else: self._value_display.reset() def _set_bank_string(self, bank_string=None): if bank_string != None: self._bank_display_data_source.set_display_string(bank_string) else: self._bank_display.reset() def _update_bank_value(self): bank = (self._session.track_offset() + 1) / self._session.width() + 1 self._set_bank_string(str(bank)) def _install_mapping(self, midi_map_handle, control, parameter, feedback_delay, feedback_map): if not self._in_build_midi_map: raise AssertionError raise midi_map_handle != None or AssertionError raise control != None and parameter != None or AssertionError raise isinstance(parameter, Live.DeviceParameter.DeviceParameter) or AssertionError raise isinstance(control, InputControlElement) or AssertionError raise isinstance(feedback_delay, int) or AssertionError if not isinstance(feedback_map, tuple): raise AssertionError success = False feedback_rule = None feedback_rule = control.message_type() is MIDI_NOTE_TYPE and Live.MidiMap.NoteFeedbackRule() feedback_rule.note_no = 0 feedback_rule.vel_map = (0,) elif control.message_type() is MIDI_CC_TYPE: feedback_rule = Live.MidiMap.CCFeedbackRule() feedback_rule.cc_no = 0 feedback_rule.cc_value_map = (0,) elif control.message_type() is MIDI_PB_TYPE: feedback_rule = Live.MidiMap.PitchBendFeedbackRule() feedback_rule.value_pair_map = feedback_map raise feedback_rule != None or AssertionError feedback_rule.channel = control.message_channel() feedback_rule.delay_in_ms = feedback_delay success = control.message_type() is MIDI_NOTE_TYPE and Live.MidiMap.map_midi_note_with_feedback_map( midi_map_handle, parameter, control.message_channel(), control.message_identifier(), feedback_rule ) elif control.message_type() is MIDI_CC_TYPE: success = Live.MidiMap.map_midi_cc_with_feedback_map( midi_map_handle, parameter, control.message_channel(), control.message_identifier(), control.message_map_mode(), feedback_rule, not control.needs_takeover(), ) elif control.message_type() is MIDI_PB_TYPE: success = Live.MidiMap.map_midi_pitchbend_with_feedback_map( midi_map_handle, parameter, control.message_channel(), feedback_rule, not control.needs_takeover() ) return success
class Axiom_AIR_25_49_61(ControlSurface): """ Script for the M-Audio Axiom A.I.R. 25, 49 and 61 """ def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._alt_device_component = None with self.component_guard(): self.set_pad_translations(PAD_TRANSLATIONS) self._device_selection_follows_track_selection = True self._suggested_input_port = 'HyperControl' self._suggested_output_port = 'HyperControl' self._single_fader_button_modes = None self._has_faders = True self._display_reset_delay = -1 self._hc_byte = HC_BYTE self._waiting_for_first_response = True self._setup_controls() self._setup_displays() self._setup_mixer() self._setup_session() self._setup_transport() self._setup_device() self._setup_modes() self._drum_group_midi_button = None self._drum_group_hyper_button = None for component in self.components: component.set_enabled(False) return def disconnect(self): self._scheduled_messages = [] for encoder in self._encoders: encoder.remove_value_listener(self._encoder_value) for fader in self._faders: fader.remove_value_listener(self._fader_value) for fader_button in self._fader_buttons: fader_button.remove_value_listener(self._fader_button_value) self._master_fader.remove_value_listener(self._fader_value) self._master_fader_button.remove_value_listener( self._fader_button_value) self._select_button.remove_value_listener(self._select_button_value) self._identify_button.remove_value_listener(self._identify_value) self._fader_group_midi_button.remove_value_listener( self._midi_button_value) self._fader_group_mix_button.remove_value_listener( self._hyper_button_value) self._fader_group_fx_button.remove_value_listener( self._hyper_button_value) self._encoder_group_midi_button.remove_value_listener( self._midi_button_value) self._encoder_group_mix_button.remove_value_listener( self._hyper_button_value) self._encoder_group_fx_button.remove_value_listener( self._hyper_button_value) if self._drum_group_midi_button != None: self._drum_group_midi_button.remove_value_listener( self._midi_button_value) if self._drum_group_hyper_button != None: self._drum_group_hyper_button.remove_value_listener( self._hyper_button_value) self._alt_device_component = None self._name_display = None self._value_display = None self._bank_display = None self._pad_display = None self._name_display_data_source = None self._value_display_data_source = None self._bank_display_data_source = None self._pad_display_data_source = None self._select_button = None self._left_button = None self._right_button = None self._up_button = None self._down_button = None self._loop_button = None self._ffwd_button = None self._rwd_button = None self._play_button = None self._stop_button = None self._rec_button = None self._master_fader_button = None self._fader_buttons = None self._faders = None self._encoders = None self._drum_pads = None self._identify_button = None self._main_group_hyper_button = None self._main_group_track_button = None self._main_group_fx_button = None self._encoder_group_midi_button = None self._encoder_group_mix_button = None self._encoder_group_fx_button = None self._fader_group_mode_button = None self._fader_group_midi_button = None self._fader_group_mix_button = None self._fader_group_fx_button = None self._drum_group_midi_button = None self._drum_group_roll_button = None self._drum_group_hyper_button = None self._mixer_for_encoders = None self._mixer_for_faders = None self._device_for_encoders = None self._device_for_faders = None self._transport = None self._session = None ControlSurface.disconnect(self) self._send_midi(SYSEX_START + DISABLE_HYPERCONTROL) return def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(5, self._send_midi, IDENTITY_REQUEST) def handle_sysex(self, midi_bytes): if midi_bytes[0:10] == AXIOM_AIR_RESPONSE: if midi_bytes[12:15] < AXIOM_REV4_RESPONSE: self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL) self.schedule_message(2, self._send_midi, SYSEX_START + CLEAR_ALL) self.schedule_message(3, self._name_display.display_message, 'Firmware') self.schedule_message(13, self._name_display.display_message, 'Update') self.schedule_message(23, self._name_display.display_message, 'Required') self.schedule_message(33, self._send_midi, SYSEX_START + DISABLE_HYPERCONTROL) elif midi_bytes[12:15] >= AXIOM_REV4_RESPONSE: if self._waiting_for_first_response == True: self._waiting_for_first_response = False self._has_faders = midi_bytes[10] != 50 self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL) self.schedule_message(2, self._send_midi, SYSEX_START + SPECIAL_HYPERCONTROL) self.schedule_message(3, self._complete_setup) else: self._display_reset_delay = 0 elif midi_bytes[0:8] == REQUEST_HYPERCONTROL: self.schedule_message(5, self._send_midi, IDENTITY_REQUEST) def update_display(self): ControlSurface.update_display(self) if self._display_reset_delay >= 0: self._display_reset_delay -= 1 if self._display_reset_delay == -1: self._set_displays_to_default() def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) self._display_reset_delay = 0 def restore_bank(self, bank_index): ControlSurface.restore_bank(self, bank_index) if self._alt_device_component != None: self._alt_device_component.restore_bank(bank_index) return def set_appointed_device(self, device): ControlSurface.set_appointed_device(self, device) with self.component_guard(): if self._alt_device_component != None: self._alt_device_component.set_device(device) return def set_alt_device_component(self, device_component): self._alt_device_component = device_component def _update_device_selection(self): track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) if self._alt_device_component != None: self._alt_device_component.set_device(device_to_select) return def _setup_controls(self): self._left_button = create_button(99, 'Left_Button') self._right_button = create_button(100, 'Right_Button') self._up_button = create_button(101, 'Up_Button') self._down_button = create_button(102, 'Down_Button') self._loop_button = create_button(113, 'Loop_Button') self._rwd_button = create_button(114, 'Rwd_Button') self._ffwd_button = create_button(115, 'FFwd_Button') self._stop_button = create_button(116, 'Stop_Button') self._play_button = create_button(117, 'Play_Button') self._rec_button = create_button(118, 'Record_Button') self._select_button = ConfigurableButtonElement( IS_MOMENTARY, MIDI_CC_TYPE, GLOBAL_CHANNEL, 98) self._select_button.name = 'Select_Button' self._select_button.add_value_listener(self._select_button_value) self._main_group_hyper_button = create_configurable_button( 104, 'Fader_Group_HyperControl_Button', 2, 14) self._main_group_track_button = create_configurable_button( 105, 'Main_Group_Track_Button', 2, 11) self._main_group_fx_button = create_configurable_button( 106, 'Main_Group_Inst_FX_Button', 2, 11) self._identify_button = create_configurable_button( 97, 'Identify_Button', 2, 16) self._identify_button.add_value_listener(self._identify_value) self._fader_buttons = [] for index in range(8): self._fader_buttons.append( create_configurable_button(49 + index, 'Fader_Button_%d' % index)) self._fader_buttons[-1].add_value_listener( self._fader_button_value, identify_sender=True) self._faders = [] for index in range(8): self._faders.append(create_slider(33 + index, 'Fader_%d' % index)) self._faders[-1].add_value_listener(self._fader_value, identify_sender=True) self._master_fader_button = create_configurable_button( 57, 'Master_Fader_Button') self._master_fader_button.add_value_listener(self._fader_button_value, identify_sender=True) self._master_fader = create_slider(41, 'Master_Fader') self._master_fader.add_value_listener(self._fader_value, identify_sender=True) self._fader_group_mode_button = create_configurable_button( 61, 'Fader_Group_Mode_Button') self._fader_group_midi_button = create_configurable_button( 60, 'Fader_Group_MIDI_Button') self._fader_group_midi_button.add_value_listener( self._midi_button_value, identify_sender=True) self._fader_group_mix_button = create_configurable_button( 58, 'Fader_Group_Mix_Button', 0, 1) self._fader_group_mix_button.add_value_listener( self._hyper_button_value, identify_sender=True) self._fader_group_fx_button = create_configurable_button( 59, 'Fader_Group_Inst_FX_Button', 0, -1) self._fader_group_fx_button.add_value_listener( self._hyper_button_value, identify_sender=True) self._encoders = [] for index in range(8): self._encoders.append( create_encoder(17 + index, 'Encoder_%d' % index)) self._encoders[-1].add_value_listener(self._encoder_value, identify_sender=True) self._encoder_group_midi_button = create_configurable_button( 27, 'Encoder_Group_MIDI_Button', 0, 72) self._encoder_group_midi_button.add_value_listener( self._midi_button_value, identify_sender=True) self._encoder_group_mix_button = create_configurable_button( 25, 'Encoder_Group_Mix_Button', 0, 72) self._encoder_group_mix_button.add_value_listener( self._hyper_button_value, identify_sender=True) self._encoder_group_fx_button = create_configurable_button( 26, 'Encoder_Group_Inst_FX_Button', 0, 72) self._encoder_group_fx_button.add_value_listener( self._hyper_button_value, identify_sender=True) def _setup_drum_pads(self): self._drum_pads = [] num_pads = 12 if self._has_faders else 16 for index in range(8): self._drum_pads.append( create_configurable_button(81 + index, 'Pad_%d' % index, 0, 0, MIDI_CC_TYPE)) for index in range(num_pads - 8): self._drum_pads.append( ConfigurableButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, GLOBAL_CHANNEL - 1, 81 + index, GLOBAL_SEND_CHANNEL, 8, MIDI_CC_TYPE)) self._drum_pads[-1].name = 'Pad_' + str(index + 8) self._drum_group_midi_button = create_configurable_button( 91, 'Drum_Group_MIDI_Button', 2, -2) self._drum_group_midi_button.add_value_listener( self._midi_button_value, identify_sender=True) self._drum_group_roll_button = create_configurable_button( 90, 'Drum_Group_Roll_Button', -1) self._drum_group_hyper_button = create_configurable_button( 89, 'Drum_Group_HyperControl_Button', 2, 2) self._drum_group_hyper_button.add_value_listener( self._hyper_button_value, identify_sender=True) def _setup_displays(self): self._name_display = PhysicalDisplayElement(12, 1) self._name_display.name = 'Name_Display' self._name_display.set_message_parts(SYSEX_START + (21, ), (0, 247)) self._name_display.set_clear_all_message(CLEAR_NAME) self._name_display_data_source = DisplayDataSource() self._name_display.segment(0).set_data_source( self._name_display_data_source) self._value_display = NumericalDisplayElement(3, 1) self._value_display.name = 'Value_Display' self._value_display.set_message_parts(SYSEX_START + (20, 48), (0, 247)) self._value_display.set_clear_all_message(CLEAR_VALUE) self._value_display_data_source = DisplayDataSource() self._value_display.segment(0).set_data_source( self._value_display_data_source) self._bank_display = NumericalDisplayElement(3, 1) self._bank_display.name = 'Bank_Display' self._bank_display.set_message_parts(SYSEX_START + (19, ), (0, 247)) self._bank_display.set_clear_all_message(CLEAR_BANK) self._bank_display_data_source = DisplayDataSource() self._bank_display.segment(0).set_data_source( self._bank_display_data_source) self._pad_display = NumericalDisplayElement(2, 1) self._pad_display.name = 'Pad_Display' self._pad_display.set_message_parts(SYSEX_START + (18, ), (0, 247)) self._pad_display.set_clear_all_message(CLEAR_PAD) self._pad_display_data_source = DisplayDataSource() self._pad_display.segment(0).set_data_source( self._pad_display_data_source) def _setup_mixer(self): self._mixer_for_encoders = SpecialMixerComponent( self._name_display, self._value_display, 8) self._mixer_for_encoders.name = 'Mixer_for_encoders' self._mixer_for_faders = SpecialMixerComponent(self._name_display, self._value_display, 8) self._mixer_for_faders.name = 'Mixer_for_faders' def _setup_session(self): self._session = SpecialSessionComponent(8, 0) self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.set_mixer(self._mixer_for_encoders) self._session.set_alt_mixer(self._mixer_for_faders) self._session.add_offset_listener(self._update_bank_value) def _setup_transport(self): self._transport = TransportComponent() self._transport.name = 'Transport' self._transport.set_stop_button(self._stop_button) self._transport.set_play_button(self._play_button) self._transport.set_record_button(self._rec_button) transport_view_modes = TransportViewModeSelector( self._transport, self._session, self._ffwd_button, self._rwd_button, self._loop_button) transport_view_modes.name = 'Transport_View_Modes' def _setup_device(self): self._device_for_encoders = BestBankDeviceComponent() self._device_for_encoders.name = 'Device_Component_for_encoders' self._device_for_faders = BestBankDeviceComponent() self._device_for_faders.name = 'Device_Component_for_faders' self.set_device_component(self._device_for_encoders) self.set_alt_device_component(self._device_for_faders) self._device_nav = DeviceNavComponent() self._device_nav.name = 'Device_Nav_Component' def _setup_modes(self): self._fader_button_modes = FaderButtonModeSelector( self._mixer_for_faders, tuple(self._fader_buttons)) self._fader_button_modes.name = 'Fader_Button_Modes' self._fader_button_modes.set_mode_toggle(self._fader_group_mode_button) self._fader_modes = FaderModeSelector(self._mixer_for_faders, self._device_for_faders, tuple(self._faders), self._fader_button_modes, self._master_fader_button) self._fader_modes.name = 'Fader_Modes' self._fader_modes.set_mode_buttons( (self._fader_group_mix_button, self._fader_group_fx_button)) self._encoder_modes = EncoderModeSelector(self._mixer_for_encoders, self._device_for_encoders, tuple(self._encoders)) self._encoder_modes.name = 'Encoder_Modes' self._encoder_modes.set_mode_buttons( (self._encoder_group_mix_button, self._encoder_group_fx_button)) main_modes = MainModeSelector(self._device_for_encoders, self._device_for_faders, self._session, self._mixer_for_faders, self._device_nav, self._up_button, self._down_button, self._left_button, self._right_button, self._select_button) main_modes.name = 'Main_Modes' main_modes.set_mode_buttons( (self._main_group_track_button, self._main_group_fx_button)) def _setup_master_fader(self): if self._has_faders: self._mixer_for_encoders.master_strip().set_volume_control( self._master_fader) else: self._mixer_for_encoders.selected_strip().set_volume_control( self._master_fader) def _setup_single_fader_button_modes(self): self._single_fader_button_modes = SingleFaderButtonModeSelector( self._mixer_for_encoders, self._fader_group_midi_button) self._single_fader_button_modes.name = 'Single_Fader_Button_Modes' self._single_fader_button_modes.set_mode_toggle( self._fader_group_mode_button) def _complete_setup(self): self._setup_drum_pads() self._set_drum_pads_to_hc() self._setup_master_fader() if not self._has_faders: self._setup_single_fader_button_modes() for control in self.controls: if isinstance(control, InputControlElement): control.clear_send_cache() for component in self.components: component.set_enabled(True) self._fader_group_midi_button.send_value(LED_OFF, True) self._encoder_group_midi_button.send_value(LED_OFF, True) self._main_group_hyper_button.send_value(AMB_FULL, True) self.request_rebuild_midi_map() self._on_selected_track_changed() self.schedule_message(1, self._show_startup_message) def _show_startup_message(self): self._send_midi(SYSEX_START + CLEAR_ALL) self._name_display.display_message('Ableton Live') self._display_reset_delay = INITIAL_DISPLAY_DELAY def _select_button_value(self, value): self._display_reset_delay = STANDARD_DISPLAY_DELAY def _identify_value(self, value): for encoder in self._encoders: encoder.set_identify_mode(value > 0) for fader in self._faders: fader.set_identify_mode(value > 0) self._master_fader.set_identify_mode(value > 0) self._display_reset_delay = 0 self._identify_button.turn_on( ) if value > 0 else self._identify_button.turn_off() def _midi_button_value(self, value, sender): if value > 0: if sender is self._drum_group_midi_button: hc_byte = self._hc_byte ^ PADS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._drum_group_hyper_button.send_value(LED_OFF, True) self.schedule_message( 1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) elif sender is self._encoder_group_midi_button: hc_byte = self._hc_byte ^ ENCODERS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._encoder_group_mix_button.send_value(LED_OFF, True) self._encoder_group_fx_button.send_value(LED_OFF, True) if self._encoder_modes.mode_index < 3: self._encoder_modes.set_enabled(False) self.schedule_message( 1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) elif sender is self._fader_group_midi_button: if self._has_faders: hc_byte = self._hc_byte ^ FADERS if hc_byte != self._hc_byte: self._hc_byte = hc_byte self._fader_group_mix_button.send_value(LED_OFF, True) self._fader_group_fx_button.send_value(LED_OFF, True) self._fader_group_mode_button.send_value(LED_OFF, True) if self._fader_modes.mode_index < 2: self._fader_modes.set_enabled(False) self._fader_button_modes.set_enabled(False) self.schedule_message( 1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247)) else: self._display_reset_delay = STANDARD_DISPLAY_DELAY def _hyper_button_value(self, value, sender): if value > 0: if sender is self._drum_group_hyper_button: if self._hc_byte | PADS != self._hc_byte: self._hc_byte = self._hc_byte | PADS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self.schedule_message(1, self._set_drum_pads_to_hc) elif sender is self._encoder_group_fx_button or sender is self._encoder_group_mix_button: if self._hc_byte | ENCODERS != self._hc_byte: self._hc_byte = self._hc_byte | ENCODERS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self._encoder_group_midi_button.turn_off() if sender is self._encoder_group_fx_button: self._encoder_modes.set_enabled(True) self._display_reset_delay = 0 return else: self.schedule_message(1, self._encoder_modes.set_enabled, True) self.schedule_message(1, self._encoder_modes.update) self._display_reset_delay = 2 return elif sender is self._fader_group_fx_button or sender is self._fader_group_mix_button: if self._hc_byte | FADERS != self._hc_byte: self._hc_byte = self._hc_byte | FADERS self._send_midi(SYSEX_START + (32, self._hc_byte, 247)) self._fader_group_midi_button.turn_off() self._fader_button_modes.set_enabled(True) if sender is self._fader_group_fx_button: self._fader_modes.set_enabled(True) self._fader_button_modes.set_enabled(True) self._display_reset_delay = 0 return else: self.schedule_message(1, self._fader_modes.set_enabled, True) self.schedule_message(1, self._fader_modes.update) self.schedule_message( 1, self._fader_button_modes.set_enabled, True) self.schedule_message(1, self._fader_button_modes.update) self._display_reset_delay = 2 return self._display_reset_delay = 0 def _set_drum_pads_to_hc(self): self._drum_group_midi_button.send_value(LED_OFF, True) self._drum_group_hyper_button.send_value(RED_FULL, True) for index in range(len(self._drum_pads)): self._drum_pads[index].send_value(RED_LOW, True) def _fader_button_value(self, value, sender): self._display_reset_delay = STANDARD_DISPLAY_DELAY def _fader_value(self, value, sender): param = sender.mapped_parameter() if param != None: param_range = param.max - param.min if param.name == 'Track Volume': if sender == self._master_fader: if self._has_faders: name_string = 'Master Vol' else: name_string = self._mixer_for_faders.selected_strip( ).track_name_data_source().display_string() + ' Vol' else: name_string = self._mixer_for_faders.channel_strip( self._faders.index(sender)).track_name_data_source( ).display_string() + ' Vol' else: name_string = param.name value = int((param.value - param.min) / param_range * 127) value_string = str(value) else: name_string = '<unmapped>' value_string = None self.schedule_message(1, self._set_value_string) self._set_name_string(name_string) self._set_value_string(value_string) return def _encoder_value(self, value, sender): param = sender.mapped_parameter() if param != None: param_range = param.max - param.min if param.name == 'Track Volume': name_string = self._mixer_for_encoders.channel_strip( self._encoders.index(sender)).track_name_data_source( ).display_string() + ' Vol' value = int((param.value - param.min) / param_range * 127) elif param.name == 'Track Panning': name_string = self._mixer_for_encoders.channel_strip( self._encoders.index(sender)).track_name_data_source( ).display_string() + ' Pan' value = int(param.value / param_range * 127) if value < 0: name_string += ' L' elif value > 0: name_string += ' R' else: name_string += ' C' else: name_string = param.name value = int((param.value - param.min) / param_range * 127) value_string = str(value) else: name_string = '<unmapped>' value_string = None self.schedule_message(1, self._set_value_string) self._set_name_string(name_string) self._set_value_string(value_string) return def _set_displays_to_default(self): self._name_display.segment(0).set_data_source( self._mixer_for_encoders.selected_strip().track_name_data_source()) self._name_display.update() self._update_bank_value() self._set_value_string(None) self._send_midi(SYSEX_START + LCD_HC_DEFAULT) return def _set_name_string(self, name_string): self._name_display.segment(0).set_data_source( self._name_display_data_source) self._name_display_data_source.set_display_string(name_string) self._display_reset_delay = STANDARD_DISPLAY_DELAY def _set_value_string(self, value_string=None): if value_string != None: self._value_display_data_source.set_display_string(value_string) else: self._value_display.reset() return def _set_bank_string(self, bank_string=None): if bank_string != None: self._bank_display_data_source.set_display_string(bank_string) else: self._bank_display.reset() return def _update_bank_value(self): bank = (self._session.track_offset() + 1) / self._session.width() + 1 self._set_bank_string(str(bank)) def _install_mapping(self, midi_map_handle, control, parameter, feedback_delay, feedback_map): if not self._in_build_midi_map: raise AssertionError raise midi_map_handle != None or AssertionError raise control != None and parameter != None or AssertionError raise isinstance( parameter, Live.DeviceParameter.DeviceParameter) or AssertionError raise isinstance(control, InputControlElement) or AssertionError raise isinstance(feedback_delay, int) or AssertionError if not isinstance(feedback_map, tuple): raise AssertionError success = False feedback_rule = None feedback_rule = control.message_type( ) is MIDI_NOTE_TYPE and Live.MidiMap.NoteFeedbackRule() feedback_rule.note_no = 0 feedback_rule.vel_map = (0, ) elif control.message_type() is MIDI_CC_TYPE: feedback_rule = Live.MidiMap.CCFeedbackRule() feedback_rule.cc_no = 0 feedback_rule.cc_value_map = (0, ) elif control.message_type() is MIDI_PB_TYPE: feedback_rule = Live.MidiMap.PitchBendFeedbackRule() feedback_rule.value_pair_map = feedback_map raise feedback_rule != None or AssertionError feedback_rule.channel = control.message_channel() feedback_rule.delay_in_ms = feedback_delay success = control.message_type( ) is MIDI_NOTE_TYPE and Live.MidiMap.map_midi_note_with_feedback_map( midi_map_handle, parameter, control.message_channel(), control.message_identifier(), feedback_rule) elif control.message_type() is MIDI_CC_TYPE: success = Live.MidiMap.map_midi_cc_with_feedback_map( midi_map_handle, parameter, control.message_channel(), control.message_identifier(), control.message_map_mode(), feedback_rule, not control.needs_takeover()) elif control.message_type() is MIDI_PB_TYPE: success = Live.MidiMap.map_midi_pitchbend_with_feedback_map( midi_map_handle, parameter, control.message_channel(), feedback_rule, not control.needs_takeover()) return success
class QuNexus_Basic(ControlSurface): __module__ = __name__ __doc__ = "QuNexus Keyboard controller script" def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) #Turn off rebuild MIDI map until after we're done setting up self.set_suppress_rebuild_requests(True) #set up some variables I want to use in multiple functions self.mixer = None self.session = None #Setup the mixer and session object self._setup_session_control() self._setup_mixer_control() self._setup_device_control() self._setup_transport_control() self.set_suppress_rebuild_requests(False) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.set_stop_button(ButtonElement(is_momentary,MIDI_NOTE_TYPE,CHANNEL,68)) self._transport.set_record_button(ButtonElement(is_momentary,MIDI_NOTE_TYPE,CHANNEL,66)) self._transport.set_play_button(ButtonElement(is_momentary,MIDI_NOTE_TYPE,CHANNEL,70)) #note that we have split the mixer functions across two scripts, in order to have two session highlight boxes (one red, one yellow), so there are a few things which we are not doing here... def _setup_session_control(self): num_tracks = 1 #one column (track) num_scenes = 8 #eight rows, which will be mapped to eight "white" notes #(num_tracks, num_scenes) a session highlight ("red box") will appear with any two non-zero values self.session = QuNexusSessionComponent(num_tracks,num_scenes) #(track_offset, scene_offset) Sets the initial offset of the "red box" from top left self.session.set_offsets(0,0) self.session.set_select_buttons(ButtonElement(is_momentary,MIDI_NOTE_TYPE,CHANNEL,63), ButtonElement(is_momentary,MIDI_NOTE_TYPE,CHANNEL,61)) self.session.set_scene_bank_buttons(ButtonElement(is_momentary,MIDI_NOTE_TYPE,CHANNEL,51), ButtonElement(is_momentary,MIDI_NOTE_TYPE,CHANNEL,49)) self.session.set_track_bank_buttons(ButtonElement(is_momentary,MIDI_NOTE_TYPE,CHANNEL,56), ButtonElement(is_momentary,MIDI_NOTE_TYPE,CHANNEL,54)) self.session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 62)) self.session.set_stop_all_clips_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 58)) for row in range(8): for col in range(1): self.session.scene(row).clip_slot(col).set_started_value(127) self.session.scene(row).clip_slot(col).set_stopped_value(0) #here we set up the clip launch assignments for the session clip_launch_notes = [48,50,52,53,55,57,59,60] #set of eight white notes starting at C3/C4 for index in range(num_scenes): #step though scenes and assign a note to first slot of each self.session.scene(index).clip_slot(0).set_started_value(127) self.session.scene(index).clip_slot(0).set_stopped_value(3) #self.session.scene(index).clip_slot(0).set_recording_value(64) self.session.scene(index).clip_slot(0).set_launch_button(ButtonElement(is_momentary,MIDI_NOTE_TYPE,CHANNEL,clip_launch_notes[index])) #here we set up a mixer and channel strip(s) which move with the session self.session.set_mixer(self.mixer) #bind the mixer to the session so that they move together def _setup_mixer_control(self): is_momentary = True #A mixer is one-dimensional; here we define the width in tracks - seven columns, which we will map to the seven "white" notes num_tracks = 1 #set up the mixer self.mixer = MixerComponent(num_tracks, 2, with_eqs=True, with_filters=True) #(num_tracks, num_returns, with_eqs, with_filters) self.mixer.set_track_offset(0) #sets start point for mixer strip (offset from left) #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error self.song().view.selected_track = self.mixer.channel_strip(0)._track #set up the mixer buttons #self.mixer.set_select_buttons() #left, right track select def _setup_device_control(self): sliders = [] pressures = [92,94,98,102,106,108] for index in range(6): sliders.append(SliderElement(MIDI_CC_TYPE, CHANNEL, pressures[index])) self._sliders = tuple(sliders) device = DeviceComponent() device.name = 'Device_Component' self.set_device_component(device) device.set_parameter_controls(self._sliders) def disconnect(self): #clean things up on disconnect #create entry in log file self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "----------QuNexus Basic log closed----------") ControlSurface.disconnect(self) return None
class DC1(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) is_momentary = True self._timer = 0 #used for flashing states, and is incremented by each call from self._update_display() self._touched = 0 self.flash_status = 1 # Used in FlashingButtonElement (kludge for our purposes) self._device_selection_follows_track_selection = True with self.component_guard(): self._setup_transport_control() if USE_MIXER_CONTROLS == True: self.mixer_control() if USE_SESSION_VIEW == True: self.session_control() self.setup_device_control() def _setup_transport_control(self): is_momentary = True # We'll only be using momentary buttons here self.transport = TransportComponent() #Instantiate a Transport Component """set up the buttons""" self.transport.set_play_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 60)) #ButtonElement(is_momentary, msg_type, channel, identifier) Note that the MIDI_NOTE_TYPE constant is defined in the InputControlElement module self.transport.set_stop_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 61)) self.transport.set_record_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 62)) def mixer_control(self): is_momentary = True self.num_tracks = N_TRACKS if(USE_SENDS == True): self.mixer = MixerComponent(N_TRACKS, N_SENDS_PER_TRACK, USE_MIXER_EQ, USE_MIXER_FILTERS) else: self.mixer = MixerComponent(N_TRACKS,0, USE_MIXER_EQ, USE_MIXER_FILTERS) self.mixer.name = 'Mixer' self.mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(N_TRACKS): self.mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) self.mixer.channel_strip(index)._invert_mute_feedback = True if(USE_SELECT_BUTTONS == True): self.selectbuttons = [None for index in range(N_TRACKS)] for index in range(len(SELECT_BUTTONS)): self.selectbuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,SELECT_BUTTONS[index], 'Select_Button', self) self.mixer.channel_strip(index).set_select_button(self.selectbuttons[index]) self.selectbuttons[index].set_on_value(SELECT_BUTTON_ON_COLOR) self.selectbuttons[index].set_off_value(SELECT_BUTTON_OFF_COLOR) if(USE_SOLO_BUTTONS == True): self.solobuttons = [None for index in range(N_TRACKS)] for index in range(len(SOLO_BUTTONS)): self.solobuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,SOLO_BUTTONS[index], 'Solo_Button', self) self.mixer.channel_strip(index).set_solo_button(self.solobuttons[index]) self.solobuttons[index].set_on_value(SOLO_BUTTON_ON_COLOR) self.solobuttons[index].set_off_value(SOLO_BUTTON_OFF_COLOR) if(USE_ARM_BUTTONS == True): self.armbuttons = [None for index in range(N_TRACKS)] for index in range(len(ARM_BUTTONS)): self.armbuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,ARM_BUTTONS[index], 'Arm_Button', self) self.mixer.channel_strip(index).set_arm_button(self.armbuttons[index]) self.armbuttons[index].set_on_value(ARM_BUTTON_ON_COLOR) self.armbuttons[index].set_off_value(ARM_BUTTON_OFF_COLOR) if(USE_MUTE_BUTTONS == True): self.mutebuttons = [None for index in range(N_TRACKS)] for index in range(len(MUTE_BUTTONS)): self.mutebuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,MUTE_BUTTONS[index], 'Mute_Button', self) self.mixer.channel_strip(index).set_mute_button(self.mutebuttons[index]) self.mutebuttons[index].set_on_value(MUTE_BUTTON_ON_COLOR) self.mutebuttons[index].set_off_value(MUTE_BUTTON_OFF_COLOR) if(USE_SENDS == True): self.sendencoders = [None for index in range(len(SEND_ENCODERS))] for index in range(len(SEND_ENCODERS)): self.sendencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, SEND_ENCODERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(SEND_ENCODERS)/N_SENDS_PER_TRACK): self.mixer.channel_strip(index).set_send_controls(tuple(self.sendencoders[(index*N_SENDS_PER_TRACK):((index*N_SENDS_PER_TRACK)+N_SENDS_PER_TRACK-1)])) if(USE_VOLUME_CONTROLS == True): self.volencoders = [None for index in range(len(VOLUME_ENCODERS))] for index in range (len(VOLUME_ENCODERS)): self.volencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, VOLUME_ENCODERS[index], Live.MidiMap.MapMode.absolute) self.mixer.channel_strip(index).set_volume_control(self.volencoders[index]) def session_control(self): is_momentary = True self._timer = 0 self.flash_status = 1 self.grid = [None for index in range(N_TRACKS*N_SCENES)] for index in range(N_TRACKS*N_SCENES): self.grid[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,TRACK_CLIP_BUTTONS[index], 'Grid' + str(index), self) self.grid[index].set_off_value(0) self.grid[index].turn_off() self.matrix = ButtonMatrixElement() for row in range(N_SCENES): button_row = [] for column in range(N_TRACKS): button_row.append(self.grid[row+(column*N_SCENES)]) self.matrix.add_row(tuple(button_row)) self.session = SessionComponent(N_TRACKS,N_SCENES) self.session.name = "Session" self.session.set_offsets(0,0) self.scene = [None for index in range(N_SCENES)] for row in range(N_SCENES): self.scene[row] = self.session.scene(row) self.scene[row].name = 'Scene_'+str(row) for column in range(N_TRACKS): clip_slot = self.scene[row].clip_slot(column) clip_slot.name = str(column)+'_Clip_Slot'+str(row) self.scene[row].clip_slot(column).set_triggered_to_play_value(CLIP_TRG_PLAY_COLOR) self.scene[row].clip_slot(column).set_stopped_value(CLIP_STOP_COLOR) self.scene[row].clip_slot(column).set_started_value(CLIP_STARTED_COLOR) self.set_highlighting_session_component(self.session) self.session_zoom = DeprecatedSessionZoomingComponent(self.session) #this creates the ZoomingComponent that allows navigation when the shift button is pressed self.session_zoom.name = 'Session_Overview' #name it so we can access it in m4l self.session_zoom.set_stopped_value(ZOOM_STOPPED) #set the zooms stopped color self.session_zoom.set_playing_value(ZOOM_PLAYING) #set the zooms playing color self.session_zoom.set_selected_value(ZOOM_SELECTED) #set the zooms selected color self.session_zoom.set_button_matrix(self.matrix) #assign the ButtonMatrixElement that we created in _setup_controls() to the zooming component so that we can control it self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 63) self.session_zoom.set_zoom_button(self._shift_button) #assign a shift button so that we can switch states between the SessionComponent and the SessionZoomingComponent self.looper = LooperComponent(self) self.log_message(str(len(STOP_BUTTONS))) if(USE_STOP_BUTTONS == True): self.stopbuttons = [None for index in range(N_TRACKS)] for index in range(len(STOP_BUTTONS)): self.stopbuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,STOP_BUTTONS[index], 'Stop_Button', self) self.session.set_stop_track_clip_buttons(self.stopbuttons) self.stopbuttons[index].set_on_value(STOP_BUTTON_ON_COLOR) self.stopbuttons[index].set_off_value(STOP_BUTTON_OFF_COLOR) self.scrollencoder = ScrollEncoderElement(MIDI_CC_TYPE, CHANNEL, 32, Live.MidiMap.MapMode.absolute, self.session, self.transport, self.mixer, self.looper) self.scrollencoder.set_nav_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 0)) self.scrollencoder.set_transport_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 7)) self.scrollencoder.set_scene_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 3)) self.scrollencoder.set_library_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 4)) self.scrollencoder.set_button1(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 1)) self.scrollencoder.set_button2(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 2)) self.scrollencoder.set_button3(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 5)) self.scrollencoder.set_button4(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 6)) self.scrollencoder.set_encoder_button(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 32)) for column in range(N_TRACKS): for row in range(N_SCENES): self.scene[row].clip_slot(column).set_launch_button(self.grid[row+(column*N_SCENES)]) for index in range(N_TRACKS*N_SCENES): self.grid[index].clear_send_cache() if USE_MIXER_CONTROLS == True: self.session.set_mixer(self.mixer) self.refresh_state() self.session.set_enabled(True) self.session.update() def setup_device_control(self): is_momentary = True device_bank_buttons = [] device_param_controls = [] bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button') for index in range(4): device_bank_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 16 + index)) device_bank_buttons[-1].name = bank_button_labels[index] for index in range(8): #ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, 21 + index) ringed_encoder = CMDEncoderElement(MIDI_CC_TYPE, CHANNEL, 16 + index, Live.MidiMap.MapMode.relative_binary_offset, 20) #ringed_encoder.set_ring_mode_button(ring_mode_button) ringed_encoder.name = 'Device_Control_' + str(index) #ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button' device_param_controls.append(ringed_encoder) device = ShiftableDeviceComponent() device.name = 'Device_Component' device.set_bank_buttons(tuple(device_bank_buttons)) device.set_shift_button(self._shift_button) device.set_parameter_controls(tuple(device_param_controls)) device.set_on_off_button(device_bank_buttons[1]) self.set_device_component(device) detail_view_toggler = DetailViewControllerComponent(self) detail_view_toggler.name = 'Detail_View_Control' detail_view_toggler.set_shift_button(self._shift_button) detail_view_toggler.set_device_clip_toggle_button(device_bank_buttons[0]) detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3]) def update_display(self): ControlSurface.update_display(self) self._timer = (self._timer + 1) % 256 def disconnect(self): self._hosts = [] ControlSurface.disconnect(self) return None
class DV1(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) is_momentary = True self._timer = 0 #used for flashing states, and is incremented by each call from self._update_display() self._touched = 0 self.flash_status = 1 # Used in FlashingButtonElement (kludge for our purposes) self._device_selection_follows_track_selection = True with self.component_guard(): self._setup_transport_control() if USE_MIXER_CONTROLS == True: self.mixer_control() if USE_SESSION_VIEW == True: self.session_control() # self.setup_device_control() def _setup_transport_control(self): is_momentary = True # We'll only be using momentary buttons here self.transport = TransportComponent( ) #Instantiate a Transport Component """set up the buttons""" self.transport.set_play_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 60) ) #ButtonElement(is_momentary, msg_type, channel, identifier) Note that the MIDI_NOTE_TYPE constant is defined in the InputControlElement module self.transport.set_stop_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 61)) self.transport.set_record_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 62)) def mixer_control(self): is_momentary = True self.num_tracks = N_TRACKS if (USE_SENDS == True): self.mixer = MixerComponent(N_TRACKS, N_SENDS_PER_TRACK, USE_MIXER_EQ, USE_MIXER_FILTERS) else: self.mixer = MixerComponent(N_TRACKS, 0, USE_MIXER_EQ, USE_MIXER_FILTERS) self.mixer.name = 'Mixer' self.mixer.set_track_offset( 0) #Sets start point for mixer strip (offset from left) for index in range(N_TRACKS): self.mixer.channel_strip( index).name = 'Mixer_ChannelStrip_' + str(index) self.mixer.channel_strip(index)._invert_mute_feedback = True if (USE_SELECT_BUTTONS == True): self.selectbuttons = [None for index in range(N_TRACKS)] for index in range(len(SELECT_BUTTONS)): self.selectbuttons[index] = FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, SELECT_BUTTONS[index], 'Select_Button', self) self.mixer.channel_strip(index).set_select_button( self.selectbuttons[index]) self.selectbuttons[index].set_on_value(SELECT_BUTTON_ON_COLOR) self.selectbuttons[index].set_off_value( SELECT_BUTTON_OFF_COLOR) if (USE_SOLO_BUTTONS == True): self.solobuttons = [None for index in range(N_TRACKS)] for index in range(len(SOLO_BUTTONS)): self.solobuttons[index] = FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, SOLO_BUTTONS[index], 'Solo_Button', self) self.mixer.channel_strip(index).set_solo_button( self.solobuttons[index]) self.solobuttons[index].set_on_value(SOLO_BUTTON_ON_COLOR) self.solobuttons[index].set_off_value(SOLO_BUTTON_OFF_COLOR) if (USE_ARM_BUTTONS == True): self.armbuttons = [None for index in range(N_TRACKS)] for index in range(len(ARM_BUTTONS)): self.armbuttons[index] = FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, ARM_BUTTONS[index], 'Arm_Button', self) self.mixer.channel_strip(index).set_arm_button( self.armbuttons[index]) self.armbuttons[index].set_on_value(ARM_BUTTON_ON_COLOR) self.armbuttons[index].set_off_value(ARM_BUTTON_OFF_COLOR) if (USE_MUTE_BUTTONS == True): self.mutebuttons = [None for index in range(N_TRACKS)] for index in range(len(MUTE_BUTTONS)): self.mutebuttons[index] = FlashingButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, MUTE_BUTTONS[index], 'Mute_Button', self) self.mixer.channel_strip(index).set_mute_button( self.mutebuttons[index]) self.mutebuttons[index].set_on_value(MUTE_BUTTON_ON_COLOR) self.mutebuttons[index].set_off_value(MUTE_BUTTON_OFF_COLOR) if (USE_SENDS == True): self.sendencoders = [None for index in range(len(SEND_ENCODERS))] for index in range(len(SEND_ENCODERS)): # self.sendencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, SEND_ENCODERS[index], Live.MidiMap.MapMode.absolute) self.sendencoders[index] = CMDEncoderElement( MIDI_CC_TYPE, CHANNEL, SEND_ENCODERS[index], Live.MidiMap.MapMode.relative_smooth_binary_offset, 20) for index in range(len(SEND_ENCODERS) / N_SENDS_PER_TRACK): self.mixer.channel_strip(index).set_send_controls( tuple(self.sendencoders[(index * N_SENDS_PER_TRACK):( (index * N_SENDS_PER_TRACK) + N_SENDS_PER_TRACK)]) ) # Pas -1, car tuple() fonctionne etrangement en Python ;) if (USE_VOLUME_CONTROLS == True): self.volencoders = [None for index in range(len(VOLUME_ENCODERS))] for index in range(len(VOLUME_ENCODERS)): #self.volencoders[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, VOLUME_ENCODERS[index], Live.MidiMap.MapMode.absolute) self.volencoders[index] = CMDEncoderElement( MIDI_CC_TYPE, CHANNEL, VOLUME_ENCODERS[index], Live.MidiMap.MapMode.relative_smooth_binary_offset, 20) self.mixer.channel_strip(index).set_volume_control( self.volencoders[index]) def session_control(self): is_momentary = True self._timer = 0 self.flash_status = 1 self.grid = [None for index in range(N_TRACKS * N_SCENES)] for index in range(N_TRACKS * N_SCENES): self.grid[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TRACK_CLIP_BUTTONS[index], 'Grid' + str(index), self) self.grid[index].set_off_value(0) self.grid[index].turn_off() self.matrix = ButtonMatrixElement() for row in range(N_SCENES): button_row = [] for column in range(N_TRACKS): button_row.append(self.grid[row + (column * N_SCENES)]) self.matrix.add_row(tuple(button_row)) self.session = SessionComponent(N_TRACKS, N_SCENES) self.session.name = "Session" self.session.set_offsets(0, 0) self.scene = [None for index in range(N_SCENES)] for row in range(N_SCENES): self.scene[row] = self.session.scene(row) self.scene[row].name = 'Scene_' + str(row) for column in range(N_TRACKS): clip_slot = self.scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot' + str(row) self.scene[row].clip_slot(column).set_triggered_to_play_value( CLIP_TRG_PLAY_COLOR) self.scene[row].clip_slot(column).set_stopped_value( CLIP_STOP_COLOR) self.scene[row].clip_slot(column).set_started_value( CLIP_STARTED_COLOR) self.set_highlighting_session_component(self.session) #self.session_zoom = DeprecatedSessionZoomingComponent(self.session) #this creates the ZoomingComponent that allows navigation when the shift button is pressed #self.session_zoom.name = 'Session_Overview' #name it so we can access it in m4l #self.session_zoom.set_stopped_value(ZOOM_STOPPED) #set the zooms stopped color #self.session_zoom.set_playing_value(ZOOM_PLAYING) #set the zooms playing color #self.session_zoom.set_selected_value(ZOOM_SELECTED) #set the zooms selected color #self.session_zoom.set_button_matrix(self.matrix) #assign the ButtonMatrixElement that we created in _setup_controls() to the zooming component so that we can control it #self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 84) #self.session_zoom.set_zoom_button(self._shift_button) #assign a shift button so that we can switch states between the SessionComponent and the SessionZoomingComponent #self.looper = LooperComponent(self) #self.log_message(str(len(STOP_BUTTONS))) #if(USE_STOP_BUTTONS == True): #self.stopbuttons = [None for index in range(N_TRACKS)] #for index in range(len(STOP_BUTTONS)): #self.stopbuttons[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL,STOP_BUTTONS[index], 'Stop_Button', self) #self.session.set_stop_track_clip_buttons(self.stopbuttons) #self.stopbuttons[index].set_on_value(STOP_BUTTON_ON_COLOR) #self.stopbuttons[index].set_off_value(STOP_BUTTON_OFF_COLOR) #self.scrollencoder = ScrollEncoderElement(MIDI_CC_TYPE, CHANNEL, 32, Live.MidiMap.MapMode.absolute, self.session, self.transport, self.mixer, self.looper) #self.scrollencoder.set_nav_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 80)) #self.scrollencoder.set_transport_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 81)) #self.scrollencoder.set_scene_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 82)) #self.scrollencoder.set_library_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 83)) #self.scrollencoder.set_button1(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 66)) #self.scrollencoder.set_button2(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 67)) #self.scrollencoder.set_button3(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 64)) #self.scrollencoder.set_button4(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 65)) #self.scrollencoder.set_encoder_button(SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 32)) self.button_left = SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, NAVBOX_LEFT_BUTTON) self.button_right = SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, NAVBOX_RIGHT_BUTTON) self.button_up = SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, NAVBOX_UP_BUTTON) self.button_down = SimpleButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, NAVBOX_DOWN_BUTTON) self.session.set_track_bank_buttons(self.button_right, self.button_left) self.session.set_scene_bank_buttons(self.button_down, self.button_up) for column in range(N_TRACKS): for row in range(N_SCENES): self.scene[row].clip_slot(column).set_launch_button( self.grid[row + (column * N_SCENES)]) for index in range(N_TRACKS * N_SCENES): self.grid[index].clear_send_cache() if USE_MIXER_CONTROLS == True: self.session.set_mixer(self.mixer) self.refresh_state() self.session.set_enabled(True) self.session.update() #def setup_device_control(self): #is_momentary = True #device_bank_buttons = [] #device_param_controls = [] #bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button') #for index in range(4): #device_bank_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 16 + index)) #device_bank_buttons[-1].name = bank_button_labels[index] #for index in range(8): ##ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, 21 + index) #ringed_encoder = CMDEncoderElement(MIDI_CC_TYPE, CHANNEL, 16 + index, Live.MidiMap.MapMode.relative_binary_offset, 20) ##ringed_encoder.set_ring_mode_button(ring_mode_button) #ringed_encoder.name = 'Device_Control_' + str(index) ##ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button' #device_param_controls.append(ringed_encoder) #device = ShiftableDeviceComponent() #device.name = 'Device_Component' #device.set_bank_buttons(tuple(device_bank_buttons)) ##device.set_shift_button(self._shift_button) #device.set_parameter_controls(tuple(device_param_controls)) #device.set_on_off_button(device_bank_buttons[1]) #self.set_device_component(device) #detail_view_toggler = DetailViewControllerComponent(self) #detail_view_toggler.name = 'Detail_View_Control' ##detail_view_toggler.set_shift_button(self._shift_button) #detail_view_toggler.set_device_clip_toggle_button(device_bank_buttons[0]) #detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3]) def update_display(self): ControlSurface.update_display(self) self._timer = (self._timer + 1) % 256 def disconnect(self): self._hosts = [] ControlSurface.disconnect(self) return None
class ProjectX(ControlSurface): __module__ = __name__ __doc__ = " ProjectX keyboard 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.log_message( time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= ProjectX log opened =--------------") with self.component_guard(): self._create_transport_control() self._create_mixer_control() self._create_session_control() self.request_rebuild_midi_map() self.log_message("Captain's last log stardate ****") def _create_transport_control(self): is_momentary = True self._transport = TransportComponent(is_enabled=True, name='Transport') """set up the buttons""" self._transport.set_play_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 61)) self._transport.set_stop_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 63)) self._transport.set_record_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 66)) self._transport.set_overdub_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 68)) self._transport.set_nudge_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 75), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 73)) self._transport.set_tap_tempo_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 78)) self._transport.set_metronome_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 80)) self._transport.set_loop_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 82)) self._transport.set_punch_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 85), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 87)) self._transport.set_seek_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 90), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 92)) """set up the sliders""" self._transport.set_tempo_control( SliderElement(MIDI_CC_TYPE, CHANNEL, 26), SliderElement(MIDI_CC_TYPE, CHANNEL, 25)) self._transport.set_song_position_control( SliderElement(MIDI_CC_TYPE, CHANNEL, 24)) self.log_message("Captain's log stardate 1") def _create_mixer_control(self): is_momentary = True num_tracks = 7 """Here we set up the global mixer""" global mixer mixer = MixerComponent(name='Mixer', num_tracks=num_tracks, is_enabled=False, num_returns=2) mixer.set_enabled(True) mixer.set_track_offset(0) self.song().view.selected_track = mixer.channel_strip(0)._track mixer.channel_strip(0) """set up the mixer buttons""" mixer.set_select_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 56), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 54)) mixer.master_strip().set_select_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 94)) mixer.selected_strip().set_mute_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 42)) mixer.selected_strip().set_solo_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 44)) mixer.selected_strip().set_arm_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 46)) """set up the mixer sliders""" mixer.selected_strip().set_volume_control( SliderElement(MIDI_CC_TYPE, CHANNEL, 14)) """note that we have split the mixer functions across two scripts, in order to have two session highlight boxes (one red, one yellow), so there are a few things which we are not doing here... """ self.log_message("Captain's log stardate 2") def _create_session_control(self): is_momentary = True num_tracks = 1 num_scenes = 7 global session session = SessionComponent(num_tracks, num_scenes) session.set_offsets(0, 0) """set up the session navigation buttons""" session.set_select_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 25), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 27)) session.set_scene_bank_buttons( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 51), ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 49)) session.set_stop_all_clips_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 70)) session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 30)) """Here we set up the scene launch assignments for the session""" launch_notes = [60, 62, 64, 65, 67, 69, 71] for index in range(num_scenes): session.scene(index).set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, launch_notes[index])) """Here we set up the track stop launch assignment(s) for the session""" stop_track_buttons = [] for index in range(num_tracks): stop_track_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, 58 + index)) session.set_stop_track_clip_buttons(tuple(stop_track_buttons)) """Here we set up the clip launch assignments for the session""" clip_launch_notes = [48, 50, 52, 53, 55, 57, 59] for index in range(num_scenes): session.scene(index).clip_slot(0).set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, clip_launch_notes[index])) """Here we set up a mixer and channel strip(s) which move with the session""" self.log_message("Captain's log stardate 3") def _on_selected_track_changed(self): """This is an override, to add special functionality (we want to move the session to the selected track, when it changes) Note that it is sometimes necessary to reload Live (not just the script) when making changes to this function""" ControlSurface._on_selected_track_changed(self) """here we set the mixer and session to the selected track, when the selected track changes""" selected_track = self.song().view.selected_track mixer.channel_strip(0).set_track(selected_track) all_tracks = ((self.song().tracks + self.song().return_tracks) + (self.song().master_track, )) index = list(all_tracks).index(selected_track) session.set_offsets(index, session._scene_offset) def disconnect(self): """clean things up on disconnect""" self.log_message( time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= ProjectX log closed =--------------") ControlSurface.disconnect(self) return None
class OP1(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self.c_instance = c_instance self.retries_count = 0 self.device_connected = False self.clip_color_callbacks = {} self.slot_callbacks = {} self.text_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x03) self.text_end_sequence = (0xf7, ) self.enable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x02, 0xf7) self.disable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x00, 0xf7) self.id_sequence = (0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7) self.text_color_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x04) self.log('INITIALIZING') self.app = Live.Application.get_application() #maj = self.app.get_major_version() #min = self.app.get_minor_version() #bug = self.app.get_bugfix_version() #self.show_message(str(1) + "." + str(0) + "." + str(9)) self.show_message("Version " + VERSION) # reseting text self.write_text(' ') # reset display clips self.reset_display_clips() # getting browser visible state self.session_browser_visible = self.app.view.is_view_visible("Browser") # getting browser visible state self.arrange_browser_visible = self.app.view.is_view_visible("Browser") # getting session view visible state self.session_visible = self.app.view.is_view_visible("Session") # getting arrange view visible state self.arrange_visible = self.app.view.is_view_visible("Arranger") # getting detail view visible state self.detail_visible = self.app.view.is_view_visible("Detail") # getting back to arranger state self.back_to_arranger_state = self.song().back_to_arranger # initializing channel strip to null self._channel_strip = None # initializing transport component self._transport = TransportComponent() # initializing mixer component self._mixer = MixerComponent(NUM_TRACKS, 2) # initializing session component self._session = SessionComponent(NUM_TRACKS, NUM_ROWS) self._session.add_offset_listener(self.session_offset_changed) # configuring operation mode selector buttons self._operation_mode_buttons = ButtonElement( True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_1_BUTTON), ButtonElement( True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_2_BUTTON), ButtonElement( True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_3_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_4_BUTTON), # initializing operation mode selector self._operation_mode_selector = OP1ModeSelectorComponent( self, self._transport, self._mixer, self._session) # setting operation mode selector buttons self._operation_mode_selector.set_mode_buttons( self._operation_mode_buttons) # adding value listener for operation mode index self._operation_mode_selector.add_mode_index_listener( self.mode_index_changed) # setting global transport assignments self._transport.set_record_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_REC_BUTTON)) self._transport.set_play_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_PLAY_BUTTON)) self._transport.set_stop_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_STOP_BUTTON)) self._transport.set_metronome_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_METRONOME_BUTTON)) self._transport.set_tap_tempo_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_HELP_BUTTON)) self._transport.set_punch_buttons( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS1_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS2_BUTTON)) self._transport.set_loop_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS3_BUTTON)) self._transport.set_overdub_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS4_BUTTON)) # setting global session assignments self._session.set_scene_bank_buttons( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_COM), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MICRO)) # setting misc listeners self.browser_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 15) self.browser_toggle_button.add_value_listener( self.browser_toggle_button_callback) self.mainview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 16) self.mainview_toggle_button.add_value_listener( self.mainview_toggle_button_callback) self.detailview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 17) self.detailview_toggle_button.add_value_listener( self.detailview_toggle_button_callback) self.clear_track_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 25) self.clear_track_button.add_value_listener( self.clear_track_button_callback) self.back_to_arranger_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 26) self.back_to_arranger_button.add_value_listener( self.back_to_arranger_button_callback) # adding value listener for selected track change self.song().view.add_selected_track_listener( self.selected_track_changed) # adding value listener for selected scene change self.song().view.add_selected_scene_listener( self.selected_scene_changed) # setting assignments for currently selected track self.selected_track_changed() # setting assignments for currently selected scene self.selected_scene_changed() def handle_sysex(self, midi_bytes): if ((midi_bytes[6] == 32) and (midi_bytes[7] == 118)): self.device_connected = True self.log("OP-1 CONNECTED. SENDING ABLETON LIVE MODE INIT SEQUENCE") self._send_midi(self.enable_sequence) def add_clip_slot_listeners(self): #self.log('ADDING CLIP SLOT LISTENERS') # creating an empty list for all clip slots clip_slots = [] # getting a reference to all tracks tracks = self.song().tracks # appending all tracks clip slots to clip_slots for track in tracks: clip_slots.append(track.clip_slots) # iterating over all clip slots for t in range(len(clip_slots)): for c in range(len(clip_slots[t])): clip_slot = clip_slots[t][c] # adding has clip listener to clip slot self.add_slot_listener(clip_slot) # if clip slot has clip if clip_slot.has_clip: # adding clip listeners self.add_clip_listener(clip_slot.clip) def rem_clip_slot_listeners(self): #self.log('REMOVING CLIP SLOT LISTENERS') # iterate over all clip color change callbacks for c in self.clip_color_callbacks: # if clip still exists if c != None: # and it has a has clip listener if c.color_has_listener(self.clip_color_callbacks[c]) == 1: # remove it c.remove_color_listener(self.clip_color_callbacks[c]) # iterate over all clip slot callbacks for cs in self.slot_callbacks: # if clip slot still exists if cs != None: # and it has a has clip listener if cs.has_clip_has_listener(self.slot_callbacks[cs]) == 1: # remove it cs.remove_has_clip_listener(self.slot_callbacks[cs]) def add_slot_listener(self, cs): # setting has clip listener callback = lambda: self.has_clip_listener(cs) # if we don't have a clip slot has clip listener for this clip slot yet if not (self.slot_callbacks.has_key(cs)): # adding has clip callback to clip slot cs.add_has_clip_listener(callback) # saving callback for future release self.slot_callbacks[cs] = callback def add_clip_listener(self, clip): # setting callback for clip color change color_callback = lambda: self.update_display_clips() # if we don't have a clip color change callback for this clip yet if not (self.clip_color_callbacks.has_key(clip)): # adding clip color change callback clip.add_color_listener(color_callback) # saving callback for future release self.clip_color_callbacks[clip] = color_callback def has_clip_listener(self, cs): # clip slot has clip listener callback if cs.has_clip: # add clip listener self.add_clip_listener(cs.clip) else: # update display if clip slot was removed self.update_display_clips() def session_offset_changed(self): # if session component offset changes, update display self.update_display_clips() def selected_scene_changed(self): # if on clip mode update display if (self._operation_mode_selector.mode_index == OP1_MODE_CLIP): self.update_display_clip_mode() def mode_index_changed(self): # update display to current mode info if (self._operation_mode_selector.mode_index == OP1_MODE_PERFORM): self.update_display_perform_mode() elif (self._operation_mode_selector.mode_index == OP1_MODE_CLIP): self.update_display_clip_mode() elif (self._operation_mode_selector.mode_index == OP1_MODE_TRANSPORT): self.update_display_transport_mode() elif (self._operation_mode_selector.mode_index == OP1_MODE_MIXER): self.update_display_mixer_mode() def clear_track_button_callback(self, value): # if clear track button was called, reset track if (value == 127): for i in range(len(self.song().tracks)): self.song().tracks[i].arm = 0 self.song().tracks[i].solo = 0 self.song().tracks[i].mute = 0 for i in range(len(self.song().return_tracks)): self.song().tracks[i].solo = 0 self.song().tracks[i].mute = 0 def clear_return_track_assignment(self, strip): # clear return track assingments strip.set_volume_control(None) strip.set_pan_control(None) strip.set_mute_button(None) strip.set_solo_button(None) def clear_track_assignment(self, strip): # clear track assignments strip.set_volume_control(None) strip.set_pan_control(None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) def clear_tracks_assigments(self): # for all normal tracks, clear assignments for i in range(NUM_TRACKS): strip = self._mixer.channel_strip(i) if (strip != None): self.clear_track_assignment(strip) # for all return tracks, clear assignments for i in range(2): return_strip = self._mixer.return_strip(i) if (return_strip != None): self.clear_return_track_assignment(return_strip) def selected_track_changed(self): # if on mixer mode update display if (self._operation_mode_selector.mode_index == OP1_MODE_MIXER): self.update_display_mixer_mode() # clear track assignments self.clear_tracks_assigments() # getting selected strip self._channel_strip = self._mixer.selected_strip() # perform track assignments self._channel_strip.set_volume_control( EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_1, Live.MidiMap.MapMode.relative_two_compliment)) self._channel_strip.set_pan_control( EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_2, Live.MidiMap.MapMode.relative_two_compliment)) # setting a tuple of encoders to control sends send_controls = EncoderElement( MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_3, Live.MidiMap.MapMode.relative_two_compliment), EncoderElement( MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_4, Live.MidiMap.MapMode.relative_two_compliment), # setting send encoders self._channel_strip.set_send_controls(tuple(send_controls)) # setting solo button self._channel_strip.set_solo_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS6_BUTTON)) # if track can be armed, set arm button if (self._channel_strip._track.can_be_armed): self._channel_strip.set_arm_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS7_BUTTON)) # if track is no master, set mute button if (self._channel_strip._track != self.song().master_track): self._channel_strip.set_mute_button( ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS5_BUTTON)) def browser_toggle_button_callback(self, value): if (value == 127): if (self.session_visible): if (self.session_browser_visible == True): self.session_browser_visible = False self.app.view.hide_view("Browser") else: self.session_browser_visible = True self.app.view.show_view("Browser") if (self.arrange_visible): if (self.arrange_browser_visible == True): self.arrange_browser_visible = False self.app.view.hide_view("Browser") else: self.arrange_browser_visible = True self.app.view.show_view("Browser") def back_to_arranger_button_callback(self, value): if (value == 127): self.song().back_to_arranger = False def mainview_toggle_button_callback(self, value): if (value == 127): if (self.session_visible == True): self.session_visible = False self.arrange_visible = True self.app.view.show_view("Arranger") self.arrange_browser_visible = self.app.view.is_view_visible( "Browser") else: self.session_visible = True self.arrange_visible = False self.app.view.show_view("Session") self.session_browser_visible = self.app.view.is_view_visible( "Browser") def detailview_toggle_button_callback(self, value): if (value == 127): if (self.detail_visible == True): self.detail_visible = False self.app.view.hide_view("Detail") else: self.detail_visible = True self.app.view.show_view("Detail") def write_text(self, msg): text_list = [] sequence = () text_list.append(len(msg.strip())) for i in msg.strip(): text_list.append(ord(i)) sequence = self.text_start_sequence + tuple( text_list) + self.text_end_sequence self._send_midi(sequence) def suggest_input_port(self): return "OP-1 Midi Device" def suggest_output_port(self): return "OP-1 Midi Device" def update_display_perform_mode(self): self.write_text("perform\rmode") def reset_display_clips(self): count = 0 colors = [] length = [] sequence = () for i in range(NUM_TRACKS): count += 1 colors.append(0x00) colors.append(0x00) colors.append(0x00) length.append(count) sequence = self.text_color_start_sequence + tuple(length) + tuple( colors) + self.text_end_sequence self._send_midi(sequence) def update_display_clips(self): #self.log("UPDATING DISPLAY CLIPS") count = 0 colors = [] length = [] sequence = () tracks_len = len(self.song().tracks) - self._session._track_offset if (tracks_len > NUM_TRACKS): tracks_len = NUM_TRACKS for i in range(tracks_len): count += 1 clip_slot = self._session.scene(0).clip_slot(i) if (clip_slot != None): if (clip_slot.has_clip() != False): clip_color = clip_slot._clip_slot.clip.color colors.append(((clip_color >> 16) & 0x000000ff) >> 1) colors.append(((clip_color >> 8) & 0x000000ff) >> 1) colors.append((clip_color & 0x000000ff) >> 1) else: colors.append(0x00) colors.append(0x00) colors.append(0x00) else: colors.append(0x00) colors.append(0x00) colors.append(0x00) length.append(count) sequence = self.text_color_start_sequence + tuple(length) + tuple( colors) + self.text_end_sequence self._send_midi(sequence) def update_display_clip_mode(self): self.write_text( "sel. scene\r" + str(self.song().view.selected_scene.name.lower().strip())) def update_display_transport_mode(self): song_time = str(self.song().get_current_beats_song_time()) self.write_text("song pos.\r" + song_time[:len(song_time) - 4]) def update_display_mixer_mode(self): self.write_text("sel. track\r" + str(self.song().view.selected_track.name.lower())) def update_display(self): if not (self.device_connected): if (self.retries_count < 5): self.log("TRYING OP-1 CONNECTION") self.retries_count += 1 self._send_midi(self.id_sequence) time.sleep(1) # if in transport mode, update display with song position if (self._operation_mode_selector.mode_index == OP1_MODE_TRANSPORT): self.update_display_transport_mode() # checking if app current view is session if (self.app.view.is_view_visible("Session")): # checking if session browser state is diferent from the internal if (self.session_browser_visible != self.app.view.is_view_visible("Browser")): self.session_browser_visible = self.app.view.is_view_visible( "Browser") # checking if app current view is arrange if (self.app.view.is_view_visible("Arranger")): # checking if arrange browser state is diferent from the internal if (self.arrange_browser_visible != self.app.view.is_view_visible("Browser")): self.arrange_browser_visible = self.app.view.is_view_visible( "Browser") # checking if app current view is detail if (self.app.view.is_view_visible("Detail")): # checking if detail state is diferent from the internal if (self.detail_visible != self.app.view.is_view_visible("Detail")): self.detail_visible = self.app.view.is_view_visible("Detail") def refresh_state(self): self.log("REFRESH STATE") self.retries_count = 0 self.device_connected = False def build_midi_map(self, midi_map_handle): #self.log("BUILD MIDI MAP") assert (self._suppress_requests_counter == 0) self._in_build_midi_map = True self._midi_map_handle = midi_map_handle self._forwarding_registry = {} for control in self.controls: if isinstance(control, InputControlElement): control.install_connections() self._midi_map_handle = None self._in_build_midi_map = False if (self._pad_translations != None): self._c_instance.set_pad_translation(self._pad_translations) # remove clip listeners self.rem_clip_slot_listeners() # add clip listeners self.add_clip_slot_listeners() # update display self.update_display_clips() def log(self, msg): self.c_instance.log_message("[TE OP-1] " + msg) def disconnect(self): # removing clip slots listeners self.rem_clip_slot_listeners() # removing value listener for track changed self.song().view.remove_selected_track_listener( self.selected_track_changed) # removing value listener for scene changed self.song().view.remove_selected_scene_listener( self.selected_scene_changed) # removing value listener for operation mode index self._operation_mode_selector.remove_mode_index_listener( self.mode_index_changed) # removing global transport assignments self._transport.set_punch_buttons(None, None) self._transport.set_loop_button(None) self._transport.set_overdub_button(None) self._transport.set_record_button(None) self._transport.set_play_button(None) self._transport.set_stop_button(None) self._transport.set_metronome_button(None) self._transport.set_tap_tempo_button(None) # removing global session assignments self._session.set_scene_bank_buttons(None, None) # removing misc listeners self.browser_toggle_button.remove_value_listener( self.browser_toggle_button_callback) self.mainview_toggle_button.remove_value_listener( self.mainview_toggle_button_callback) self.detailview_toggle_button.remove_value_listener( self.detailview_toggle_button_callback) self.clear_track_button.remove_value_listener( self.clear_track_button_callback) self.back_to_arranger_button.remove_value_listener( self.back_to_arranger_button_callback) # sending special ableton mode disable sequence self._send_midi(self.disable_sequence) # disconnecting control surface ControlSurface.disconnect(self) self.log("DISCONNECTED")
class OP1(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self.c_instance = c_instance self.retries_count = 0 self.device_connected = False self.clip_color_callbacks = {} self.slot_callbacks = {} self.text_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x03) self.text_end_sequence = (0xf7,) self.enable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x02, 0xf7) self.disable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x00, 0xf7) self.id_sequence = (0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7) self.text_color_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x04) self.log('INITIALIZING') self.app = Live.Application.get_application() #maj = self.app.get_major_version() #min = self.app.get_minor_version() #bug = self.app.get_bugfix_version() #self.show_message(str(1) + "." + str(0) + "." + str(9)) self.show_message("Version " + VERSION) # reseting text self.write_text(' ') # reset display clips self.reset_display_clips() # getting browser visible state self.session_browser_visible = self.app.view.is_view_visible("Browser") # getting browser visible state self.arrange_browser_visible = self.app.view.is_view_visible("Browser") # getting session view visible state self.session_visible = self.app.view.is_view_visible("Session") # getting arrange view visible state self.arrange_visible = self.app.view.is_view_visible("Arranger") # getting detail view visible state self.detail_visible = self.app.view.is_view_visible("Detail") # getting back to arranger state self.back_to_arranger_state = self.song().back_to_arranger # initializing channel strip to null self._channel_strip = None # initializing transport component self._transport = TransportComponent() # initializing mixer component self._mixer = MixerComponent(NUM_TRACKS,2) # initializing session component self._session = SessionComponent(NUM_TRACKS,NUM_ROWS) self._session.add_offset_listener(self.session_offset_changed) # configuring operation mode selector buttons self._operation_mode_buttons = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_1_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_2_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_3_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_4_BUTTON), # initializing operation mode selector self._operation_mode_selector = OP1ModeSelectorComponent(self, self._transport, self._mixer, self._session) # setting operation mode selector buttons self._operation_mode_selector.set_mode_buttons(self._operation_mode_buttons) # adding value listener for operation mode index self._operation_mode_selector.add_mode_index_listener(self.mode_index_changed) # setting global transport assignments self._transport.set_record_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_REC_BUTTON)) self._transport.set_play_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_PLAY_BUTTON)) self._transport.set_stop_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_STOP_BUTTON)) self._transport.set_metronome_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_METRONOME_BUTTON)) self._transport.set_tap_tempo_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_HELP_BUTTON)) self._transport.set_punch_buttons(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS1_BUTTON), ButtonElement(True,MIDI_CC_TYPE, CHANNEL, OP1_SS2_BUTTON)) self._transport.set_loop_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS3_BUTTON)) self._transport.set_overdub_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS4_BUTTON)) # setting global session assignments self._session.set_scene_bank_buttons(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_COM),ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MICRO)) # setting misc listeners self.browser_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 15) self.browser_toggle_button.add_value_listener(self.browser_toggle_button_callback) self.mainview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 16) self.mainview_toggle_button.add_value_listener(self.mainview_toggle_button_callback) self.detailview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 17) self.detailview_toggle_button.add_value_listener(self.detailview_toggle_button_callback) self.clear_track_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 25) self.clear_track_button.add_value_listener(self.clear_track_button_callback) self.back_to_arranger_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 26) self.back_to_arranger_button.add_value_listener(self.back_to_arranger_button_callback) # adding value listener for selected track change self.song().view.add_selected_track_listener(self.selected_track_changed) # adding value listener for selected scene change self.song().view.add_selected_scene_listener(self.selected_scene_changed) # setting assignments for currently selected track self.selected_track_changed() # setting assignments for currently selected scene self.selected_scene_changed() def handle_sysex(self, midi_bytes): if ((midi_bytes[6]==32) and (midi_bytes[7]==118)): self.device_connected = True self.log("OP-1 CONNECTED. SENDING ABLETON LIVE MODE INIT SEQUENCE") self._send_midi(self.enable_sequence) def add_clip_slot_listeners(self): #self.log('ADDING CLIP SLOT LISTENERS') # creating an empty list for all clip slots clip_slots = [] # getting a reference to all tracks tracks = self.song().tracks # appending all tracks clip slots to clip_slots for track in tracks: clip_slots.append(track.clip_slots) # iterating over all clip slots for t in range(len(clip_slots)): for c in range(len(clip_slots[t])): clip_slot = clip_slots[t][c] # adding has clip listener to clip slot self.add_slot_listener(clip_slot) # if clip slot has clip if clip_slot.has_clip: # adding clip listeners self.add_clip_listener(clip_slot.clip) def rem_clip_slot_listeners(self): #self.log('REMOVING CLIP SLOT LISTENERS') # iterate over all clip color change callbacks for c in self.clip_color_callbacks: # if clip still exists if c != None: # and it has a has clip listener if c.color_has_listener(self.clip_color_callbacks[c]) == 1: # remove it c.remove_color_listener(self.clip_color_callbacks[c]) # iterate over all clip slot callbacks for cs in self.slot_callbacks: # if clip slot still exists if cs != None: # and it has a has clip listener if cs.has_clip_has_listener(self.slot_callbacks[cs]) == 1: # remove it cs.remove_has_clip_listener(self.slot_callbacks[cs]) def add_slot_listener(self, cs): # setting has clip listener callback = lambda :self.has_clip_listener(cs) # if we don't have a clip slot has clip listener for this clip slot yet if not(self.slot_callbacks.has_key(cs)): # adding has clip callback to clip slot cs.add_has_clip_listener(callback) # saving callback for future release self.slot_callbacks[cs] = callback def add_clip_listener(self, clip): # setting callback for clip color change color_callback = lambda :self.update_display_clips() # if we don't have a clip color change callback for this clip yet if not(self.clip_color_callbacks.has_key(clip)): # adding clip color change callback clip.add_color_listener(color_callback) # saving callback for future release self.clip_color_callbacks[clip] = color_callback def has_clip_listener(self, cs): # clip slot has clip listener callback if cs.has_clip: # add clip listener self.add_clip_listener(cs.clip) else: # update display if clip slot was removed self.update_display_clips() def session_offset_changed(self): # if session component offset changes, update display self.update_display_clips() def selected_scene_changed(self): # if on clip mode update display if (self._operation_mode_selector.mode_index==OP1_MODE_CLIP): self.update_display_clip_mode() def mode_index_changed(self): # update display to current mode info if (self._operation_mode_selector.mode_index==OP1_MODE_PERFORM): self.update_display_perform_mode() elif (self._operation_mode_selector.mode_index==OP1_MODE_CLIP): self.update_display_clip_mode() elif (self._operation_mode_selector.mode_index==OP1_MODE_TRANSPORT): self.update_display_transport_mode() elif (self._operation_mode_selector.mode_index==OP1_MODE_MIXER): self.update_display_mixer_mode() def clear_track_button_callback(self, value): # if clear track button was called, reset track if (value==127): for i in range(len(self.song().tracks)): self.song().tracks[i].arm = 0 self.song().tracks[i].solo = 0 self.song().tracks[i].mute = 0 for i in range(len(self.song().return_tracks)): self.song().tracks[i].solo = 0 self.song().tracks[i].mute = 0 def clear_return_track_assignment(self, strip): # clear return track assingments strip.set_volume_control(None) strip.set_pan_control(None) strip.set_mute_button(None) strip.set_solo_button(None) def clear_track_assignment(self, strip): # clear track assignments strip.set_volume_control(None) strip.set_pan_control(None) strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(None) def clear_tracks_assigments(self): # for all normal tracks, clear assignments for i in range(NUM_TRACKS): strip = self._mixer.channel_strip(i) if (strip!=None): self.clear_track_assignment(strip) # for all return tracks, clear assignments for i in range(2): return_strip = self._mixer.return_strip(i) if (return_strip!=None): self.clear_return_track_assignment(return_strip) def selected_track_changed(self): # if on mixer mode update display if (self._operation_mode_selector.mode_index==OP1_MODE_MIXER): self.update_display_mixer_mode() # clear track assignments self.clear_tracks_assigments() # getting selected strip self._channel_strip = self._mixer.selected_strip() # perform track assignments self._channel_strip.set_volume_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_1, Live.MidiMap.MapMode.relative_two_compliment)) self._channel_strip.set_pan_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_2, Live.MidiMap.MapMode.relative_two_compliment)) # setting a tuple of encoders to control sends send_controls = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_3, Live.MidiMap.MapMode.relative_two_compliment), EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_4, Live.MidiMap.MapMode.relative_two_compliment), # setting send encoders self._channel_strip.set_send_controls(tuple(send_controls)) # setting solo button self._channel_strip.set_solo_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS6_BUTTON)) # if track can be armed, set arm button if (self._channel_strip._track.can_be_armed): self._channel_strip.set_arm_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS7_BUTTON)) # if track is no master, set mute button if (self._channel_strip._track!=self.song().master_track): self._channel_strip.set_mute_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS5_BUTTON)) def browser_toggle_button_callback(self, value): if (value==127): if (self.session_visible): if (self.session_browser_visible==True): self.session_browser_visible=False self.app.view.hide_view("Browser") else: self.session_browser_visible=True self.app.view.show_view("Browser") if (self.arrange_visible): if (self.arrange_browser_visible==True): self.arrange_browser_visible=False self.app.view.hide_view("Browser") else: self.arrange_browser_visible=True self.app.view.show_view("Browser") def back_to_arranger_button_callback(self, value): if (value==127): self.song().back_to_arranger = False def mainview_toggle_button_callback(self, value): if (value==127): if (self.session_visible==True): self.session_visible=False self.arrange_visible=True self.app.view.show_view("Arranger") self.arrange_browser_visible = self.app.view.is_view_visible("Browser"); else: self.session_visible=True self.arrange_visible=False self.app.view.show_view("Session") self.session_browser_visible = self.app.view.is_view_visible("Browser"); def detailview_toggle_button_callback(self, value): if (value==127): if (self.detail_visible==True): self.detail_visible=False self.app.view.hide_view("Detail") else: self.detail_visible=True self.app.view.show_view("Detail") def write_text(self, msg): text_list = [] sequence = () text_list.append(len(msg.strip())) for i in msg.strip(): text_list.append(ord(i)) sequence = self.text_start_sequence + tuple(text_list) + self.text_end_sequence self._send_midi(sequence) def suggest_input_port(self): return "OP-1 Midi Device" def suggest_output_port(self): return "OP-1 Midi Device" def update_display_perform_mode(self): self.write_text("perform\rmode") def reset_display_clips(self): count = 0 colors = [] length = [] sequence = () for i in range (NUM_TRACKS): count+=1 colors.append(0x00) colors.append(0x00) colors.append(0x00) length.append(count) sequence = self.text_color_start_sequence + tuple(length) + tuple(colors) + self.text_end_sequence self._send_midi(sequence) def update_display_clips(self): #self.log("UPDATING DISPLAY CLIPS") count = 0 colors = [] length = [] sequence = () tracks_len = len(self.song().tracks)-self._session._track_offset if (tracks_len>NUM_TRACKS): tracks_len = NUM_TRACKS for i in range (tracks_len): count+=1 clip_slot = self._session.scene(0).clip_slot(i) if (clip_slot!=None): if (clip_slot.has_clip()!=False): clip_color = clip_slot._clip_slot.clip.color colors.append(((clip_color>>16)&0x000000ff)>>1) colors.append(((clip_color>>8)&0x000000ff)>>1) colors.append((clip_color&0x000000ff)>>1) else: colors.append(0x00) colors.append(0x00) colors.append(0x00) else: colors.append(0x00) colors.append(0x00) colors.append(0x00) length.append(count) sequence = self.text_color_start_sequence + tuple(length) + tuple(colors) + self.text_end_sequence self._send_midi(sequence) def update_display_clip_mode(self): self.write_text("sel. scene\r" + str(self.song().view.selected_scene.name.lower().strip())) def update_display_transport_mode(self): song_time = str(self.song().get_current_beats_song_time()) self.write_text("song pos.\r" + song_time[:len(song_time)-4]) def update_display_mixer_mode(self): self.write_text("sel. track\r" + str(self.song().view.selected_track.name.lower())) def update_display(self): if not(self.device_connected): if (self.retries_count<5): self.log("TRYING OP-1 CONNECTION") self.retries_count+=1 self._send_midi(self.id_sequence) time.sleep(1) # if in transport mode, update display with song position if (self._operation_mode_selector.mode_index==OP1_MODE_TRANSPORT): self.update_display_transport_mode() # checking if app current view is session if (self.app.view.is_view_visible("Session")): # checking if session browser state is diferent from the internal if (self.session_browser_visible != self.app.view.is_view_visible("Browser")): self.session_browser_visible = self.app.view.is_view_visible("Browser") # checking if app current view is arrange if (self.app.view.is_view_visible("Arranger")): # checking if arrange browser state is diferent from the internal if (self.arrange_browser_visible != self.app.view.is_view_visible("Browser")): self.arrange_browser_visible = self.app.view.is_view_visible("Browser") # checking if app current view is detail if (self.app.view.is_view_visible("Detail")): # checking if detail state is diferent from the internal if (self.detail_visible != self.app.view.is_view_visible("Detail")): self.detail_visible = self.app.view.is_view_visible("Detail") def refresh_state(self): self.log("REFRESH STATE") self.retries_count = 0 self.device_connected = False def build_midi_map(self, midi_map_handle): #self.log("BUILD MIDI MAP") assert (self._suppress_requests_counter == 0) self._in_build_midi_map = True self._midi_map_handle = midi_map_handle self._forwarding_registry = {} for control in self.controls: if isinstance(control, InputControlElement): control.install_connections() self._midi_map_handle = None self._in_build_midi_map = False if (self._pad_translations != None): self._c_instance.set_pad_translation(self._pad_translations) # remove clip listeners self.rem_clip_slot_listeners() # add clip listeners self.add_clip_slot_listeners() # update display self.update_display_clips() def log(self, msg): self.c_instance.log_message("[TE OP-1] " + msg) def disconnect(self): # removing clip slots listeners self.rem_clip_slot_listeners() # removing value listener for track changed self.song().view.remove_selected_track_listener(self.selected_track_changed) # removing value listener for scene changed self.song().view.remove_selected_scene_listener(self.selected_scene_changed) # removing value listener for operation mode index self._operation_mode_selector.remove_mode_index_listener(self.mode_index_changed) # removing global transport assignments self._transport.set_punch_buttons(None, None) self._transport.set_loop_button(None) self._transport.set_overdub_button(None) self._transport.set_record_button(None) self._transport.set_play_button(None) self._transport.set_stop_button(None) self._transport.set_metronome_button(None) self._transport.set_tap_tempo_button(None) # removing global session assignments self._session.set_scene_bank_buttons(None, None) # removing misc listeners self.browser_toggle_button.remove_value_listener(self.browser_toggle_button_callback) self.mainview_toggle_button.remove_value_listener(self.mainview_toggle_button_callback) self.detailview_toggle_button.remove_value_listener(self.detailview_toggle_button_callback) self.clear_track_button.remove_value_listener(self.clear_track_button_callback) self.back_to_arranger_button.remove_value_listener(self.back_to_arranger_button_callback) # sending special ableton mode disable sequence self._send_midi(self.disable_sequence) # disconnecting control surface ControlSurface.disconnect(self) self.log("DISCONNECTED")