def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._monomod_version = 'b994' self.hosts = [] self._host_name = 'BlockPad' self._color_type = 'Monochrome' self._timer = 0 is_momentary = True self._suggested_input_port = 'block (Controls)' self._suggested_output_port = 'block (Controls)' self._wrote_user_byte = False matrix = ButtonMatrixElement() for row in range(8): button_row = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((column * 8) + row), 'Button_'+str(column)+'_'+str(row), self) for column in range(8) ] matrix.add_row(tuple(button_row)) knobs = [ EncoderElement(MIDI_CC_TYPE, 0, KNOB_CC[index], Live.MidiMap.MapMode.absolute) for index in range(8) ] sliders = [ EncoderElement(MIDI_CC_TYPE, 0, SLIDER_CC[index], Live.MidiMap.MapMode.absolute) for index in range(2) ] self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0) self._config_button.add_value_listener(self._config_value) top_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, TOP_NOTES[index], 'Top_Button'+str(index), self) for index in range(8) ] side_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index], 'Side_Button'+str(index), self) for index in range(8) ] self._setup_monobridge() self._setup_monomod() self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, tuple(knobs), tuple(sliders), self) self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self.set_enabled(True) self.log_message("--------------= BlockPad log opened =--------------") #Create entry in log file self.refresh_state()
def _setup_session_control(self): is_momentary = True self._shift_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98, 'Shift_Button', self) right_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96, 'Right_Button', self) self._right_button = right_button left_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97, 'Left_Button', self) self._left_button = left_button up_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94, 'Up_Button', self) self._up_button = up_button down_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95, 'Down_Button', self) self._down_button = down_button self._session = PedaledSessionComponent(8, 5) self._session.name = 'Session_Control' self._session.set_track_bank_buttons(right_button, left_button) self._session.set_scene_bank_buttons(down_button, up_button) matrix = ButtonMatrixElement() self._matrix = matrix # added a matrix.name = 'Button_Matrix' scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82)) for index in range(5) ] track_stop_buttons = [ AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52, 'Track_' + str(index) + '_Stop_Button', self) for index in range(8) ] self._track_stop_buttons = track_stop_buttons # added a for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_'+ str(index) + '_Launch_Button' stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) stop_all_button.name = 'Stop_All_Clips_Button' self._session.set_stop_all_clips_button(stop_all_button) self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session.set_stop_track_clip_value(2) for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53), str(track_index) + '_Clip_' + str(scene_index) + '_Button', self) #button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(5) clip_slot.set_started_value(1) clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) matrix.add_row(tuple(button_row)) self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = SessionZoomingComponent(self._session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button) self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5)
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._suppress_send_midi = True self._suppress_session_highlight = True is_momentary = True self._suggested_input_port = 'Launchpad' self._suggested_output_port = 'Launchpad' self._control_is_with_automap = False self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = 'User_Byte_Button' self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self._wrote_user_byte = False self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143 matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' for row in range(8): button_row = [] for column in range(8): button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, row * 16 + column) button.name = str(column) + '_Clip_' + str(row) + '_Button' button_row.append(button) matrix.add_row(tuple(button_row)) self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False) self._config_button.add_value_listener(self._config_value) top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index) for index in range(8) ] side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index]) for index in range(8) ] top_buttons[0].name = 'Bank_Select_Up_Button' top_buttons[1].name = 'Bank_Select_Down_Button' top_buttons[2].name = 'Bank_Select_Left_Button' top_buttons[3].name = 'Bank_Select_Right_Button' top_buttons[4].name = 'Session_Button' top_buttons[5].name = 'User1_Button' top_buttons[6].name = 'User2_Button' top_buttons[7].name = 'Mixer_Button' side_buttons[0].name = 'Vol_Button' side_buttons[1].name = 'Pan_Button' side_buttons[2].name = 'SndA_Button' side_buttons[3].name = 'SndB_Button' side_buttons[4].name = 'Stop_Button' side_buttons[5].name = 'Trk_On_Button' side_buttons[6].name = 'Solo_Button' side_buttons[7].name = 'Arm_Button' self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self) self._selector.name = 'Main_Modes' self._do_combine() for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.add_value_listener(self._button_value) self.set_highlighting_session_component(self._selector.session_component()) self._suppress_session_highlight = False #self.set_suppress_rebuild_requests(False) self.log_message("LaunchPad95 Loaded !")
def __init__(self, *a, **k): ControlSurface.__init__(self, *a, **k) with self.component_guard(): self._monomod_version = 'b996' self._host_name = 'LaunchMod' self._color_type = 'Launchpad' self._timer = 0 self._suppress_send_midi = True self._suppress_session_highlight = True self._suppress_highlight = False is_momentary = True self._suggested_input_port = 'Launchpad' self._suggested_output_port = 'Launchpad' self._control_is_with_automap = False self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = 'User_Byte_Button' self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self._wrote_user_byte = False self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143 matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' for row in range(8): button_row = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, row * 16 + column, str(column) + '_Clip_' + str(row) + '_Button', self) for column in range(8) ] matrix.add_row(tuple(button_row)) self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False) self._config_button.add_value_listener(self._config_value) top_button_names = ['Bank_Select_Up_Button', 'Bank_Select_Down_Button', 'Bank_Select_Left_Button', 'Bank_Select_Right_Button', 'Session_Button', 'User1_Button', 'User2_Button', 'Mixer_Button'] side_button_names = ['Vol_Button', 'Pan_Button', 'SndA_Button', 'SndB_Button', 'Stop_Button', 'Trk_On_Button', 'Solo_Button', 'Arm_Button'] top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, top_button_names[index], self) for index in range(8) ] side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index], side_button_names[index], self) for index in range(8) ] self._side_buttons = ButtonMatrixElement() self._side_buttons.add_row(side_buttons) self._setup_monobridge() self._setup_mod() self._selector = MainSelectorComponent(self, matrix, tuple(top_buttons), tuple(side_buttons), self._config_button) self._selector.name = 'Main_Modes' for control in self.controls: isinstance(control, MonoButtonElement) and control.add_value_listener(self._button_value) self.set_highlighting_session_component(self._selector.session_component()) self._suppress_session_highlight = False self.log_message('--------------= ' + str(self._monomod_version) + ' log opened =--------------')
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self.set_suppress_rebuild_requests(True) self._suppress_send_midi = True self._suppress_session_highlight = True is_momentary = True self._suggested_input_port = "Launchpad" self._suggested_output_port = "Launchpad" self._control_is_with_automap = False self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = "User_Byte_Button" self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self._wrote_user_byte = False self._challenge = (Live.Application.get_random_int(0, 400000000) & 2139062143) matrix = ButtonMatrixElement() matrix.name = "Button_Matrix" for row in range(8): button_row = [] for column in range(8): button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((row * 16) + column)) button.name = (((str(column) + "_Clip_") + str(row)) + "_Button") button_row.append(button) matrix.add_row(tuple(button_row)) self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0) self._config_button.add_value_listener(self._config_value) top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, (104 + index)) for index in range(8) ] side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index]) for index in range(8) ] top_buttons[0].name = "Bank_Select_Up_Button" top_buttons[1].name = "Bank_Select_Down_Button" top_buttons[2].name = "Bank_Select_Left_Button" top_buttons[3].name = "Bank_Select_Right_Button" top_buttons[4].name = "Session_Button" top_buttons[5].name = "User1_Button" top_buttons[6].name = "User2_Button" top_buttons[7].name = "Mixer_Button" side_buttons[0].name = "Vol_Button" side_buttons[1].name = "Pan_Button" side_buttons[2].name = "SndA_Button" side_buttons[3].name = "SndB_Button" side_buttons[4].name = "Stop_Button" side_buttons[5].name = "Trk_On_Button" side_buttons[6].name = "Solo_Button" side_buttons[7].name = "Arm_Button" self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self) self._selector.name = "Main_Modes" for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.add_value_listener(self._button_value) self._suppress_session_highlight = False self.set_suppress_rebuild_requests(False) self.log_message("LaunchPad85 Loaded !")
def _setup_session_control(self): is_momentary = True num_tracks = 4 num_scenes = 4 self.session = SessionComponent(num_tracks, num_scenes) self.session.name = 'MaschinAble_session_control' matrix = ButtonMatrixElement() self.session.set_offsets(0, 0) up_button = ButtonElement(is_momentary, 1, 1, 108) down_button = ButtonElement(is_momentary, 1, 1, 109) left_button = ButtonElement(is_momentary, 1, 1, 110) right_button = ButtonElement(is_momentary, 1, 1, 111) self.session.set_track_bank_buttons(right_button, left_button) self.session.set_scene_bank_buttons(down_button, up_button) launch_notes_start_from = 112 launch_notes = range(launch_notes_start_from, launch_notes_start_from + 16) current_scene = list( self.song().scenes).index(self.song().view.selected_scene) current_track = list( self.song().tracks).index(self.song().view.selected_track) for scene_index in range(num_scenes): button_row = [] for track_index in range(num_tracks): clip_slot = self.session.scene(num_scenes - 1 - scene_index + current_scene).clip_slot(track_index + current_track) button = ButtonElement(is_momentary, 0, 1, launch_notes[track_index+(4*scene_index)]) button_row.append(button) if clip_slot.has_clip: clip_slot.set_stopped_value(1) else: clip_slot.set_stopped_value(0) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(2) clip_slot.set_launch_button(button) matrix.add_row(tuple(button_row))
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._monomod_version = 'b994' self._host_name = 'LaunchMod' self._color_type = 'Launchpad' self.hosts = [] self._timer = 0 self.set_suppress_rebuild_requests(True) self._suppress_send_midi = True self._suppress_session_highlight = True is_momentary = True self._suggested_input_port = 'Launchpad' self._suggested_output_port = 'Launchpad' self._wrote_user_byte = False self._control_is_with_automap = False self._challenge = (Live.Application.get_random_int(0, 400000000) & 2139062143) matrix = ButtonMatrixElement() matrix.name = 'ButtonMatrix' for row in range(8): #button_row = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((row * 16) + column)) for column in range(8) ] button_row = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((row * 16) + column), 'Button_'+str(row)+'_'+str(column), self) for column in range(8) ] matrix.add_row(tuple(button_row)) self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0) self._config_button.add_value_listener(self._config_value) top_buttons = [ FlashingButtonElement(is_momentary, MIDI_CC_TYPE, 0, (104 + index), 'Top_Button'+str(index), self) for index in range(8) ] side_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index], 'Side_Button'+str(index), self) for index in range(8) ] self._setup_monobridge() self._setup_monomod() self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self) self._suppress_session_highlight = False self._suppress_send_midi = False self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self._suppress_send_midi = True self.set_suppress_rebuild_requests(False) self.log_message("--------------= LaunchMod log opened =--------------") #Create entry in log file self.refresh_state()
class Maschine(ControlSurface): __module__ = __name__ '''Basic Control Script for All Maschine Modell Mikro, Mikro Mk2, Mk1, Mk2, Studio''' def __init__(self, c_instance): super(Maschine, self).__init__(c_instance) self.component_guard().__enter__() try: register_sender(self) self._diplay_cache = ['', '', '', ''] self._suppress_send_midi = True is_momentary = True self._c_ref = c_instance self.display_task = DisplayTask() self._challenge = Live.Application.get_random_int( 0, 400000000) & 2139062143 self._active = False self._midi_pause_count = 0 self.blink_state = 0 self.send_slider_index = 0 self.nav_index = 0 self.arm_selected_track = False self.undo_state = 0 self.redo_state = 0 self._set_suppress_rebuild_requests(True) self._modeselect = ModeSelector(self.is_monochrome()) self._device = self._set_up_device_control() self._set_up_session(self._modeselect) self._set_up_mixer() self._setup_transport() self._set_global_buttons() self._editsection = EditSection() self._editsection.connect_session(self._session) self._editsection.set_mode_selector(self._modeselect) self._session.set_mode(self._modeselect._clip_mode) self._audio_clip_editor = AudioClipEditComponent() self._note_repeater = NoteRepeatComponent(c_instance.note_repeat) self._midi_edit = MidiEditSection() self._init_settings() self._init_maschine() self.set_highlighting_session_component(self._session) self.set_pad_translations(PAD_TRANSLATIONS) self._on_selected_track_changed() self.set_up_function_buttons() self.show_message(str('')) self.request_rebuild_midi_map() self._set_suppress_rebuild_requests(False) self._active = True self._display_device_param = False self.set_feedback_channels(FEEDBACK_CHANNELS) self._final_init() self._suppress_send_midi = False self.apply_preferences() self.init_text_display() self._on_appointed_device_changed.subject = self.song() finally: pass def _init_maschine(self): pass def _final_init(self): pass def create_pad_button(self, scene_index, track_index, color_source): pass def create_gated_button(self, identifier, hue): pass def apply_preferences(self): pref_dict = self._pref_dict if 'step_advance' in pref_dict: self._session.set_step_advance(pref_dict['step_advance']) if 'solo_exclusive' in pref_dict: self._modeselect.set_solo_exclusive(pref_dict['solo_exclusive']) else: self._modeselect.set_solo_exclusive(True) if 'arm_exclusive' in pref_dict: self._modeselect.set_arm_exclusive(pref_dict['arm_exclusive']) else: self._modeselect.set_arm_exclusive(True) if 'quantize_val' in pref_dict: self._editsection.quantize = pref_dict['quantize_val'] else: self._editsection.quantize = 5 if 'initial_cliplen' in pref_dict: self._editsection.initial_clip_len = pref_dict['initial_cliplen'] else: self._editsection.initial_clip_len = 4 if 'auto_arm_sel_track' in pref_dict: self.arm_selected_track = pref_dict['auto_arm_sel_track'] else: self.arm_selected_track = False if 'note_color_mode' in pref_dict: self._modeselect._pad_mode._note_display_mode = pref_dict[ 'note_color_mode'] else: self._modeselect._pad_mode._note_display_mode = ND_KEYBOARD1 self._pref_dict[ 'note_color_mode'] = self._modeselect._pad_mode._note_display_mode if not self.arm_selected_track or 127: pass self.set_sel_arm_button.send_value(0, True) self._note_repeater.recall_values(self._pref_dict) def store_preferences(self): self._pref_dict['step_advance'] = self._session.get_step_advance() self._pref_dict['solo_exclusive'] = self._modeselect.is_solo_exclusive( ) self._pref_dict['arm_exclusive'] = self._modeselect.is_arm_exclusive() self._pref_dict['quantize_val'] = self._editsection.quantize self._pref_dict['initial_cliplen'] = self._editsection.initial_clip_len self._pref_dict['auto_arm_sel_track'] = self.arm_selected_track self._pref_dict[ 'note_color_mode'] = self._modeselect._pad_mode._note_display_mode self._note_repeater.store_values(self._pref_dict) def _init_settings(self): loads = loads dumps = dumps import pickle ascii = ascii import encodings nop(ascii) preferences = self._c_instance.preferences(self.preferences_name()) self._pref_dict = {} try: self._pref_dict = loads(str(preferences)) except Exception: pass pref_dict = self._pref_dict (None, preferences.set_serializer)(lambda: dumps(pref_dict)) def preferences_name(self): return 'Maschine' def _pre_serialize(self): dumps = dumps import pickle ascii = ascii import encodings nop(ascii) preferences = self._c_instance.preferences('Maschine') self.store_preferences() dump = dumps(self._pref_dict) (preferences.set_serializer, )(lambda: dump) def toggle_nav_mode(self): self._session.switch_step_advance() self.show_message(' View Navigation in steps of ' + str(self._session.get_step_advance())) def _set_up_session(self, mode_selector): is_momentary = True self._session = MaschineSessionComponent() self._session.set_color_manager(mode_selector.get_color_manager()) self.nav_buttons = (self.create_gated_button(92, COLOR_HUE_NAV), self.create_gated_button(81, COLOR_HUE_NAV), self.create_gated_button(93, COLOR_HUE_NAV), self.create_gated_button(91, COLOR_HUE_NAV)) self._session.set_scene_bank_buttons(self.nav_buttons[0], self.nav_buttons[1]) self._session.set_track_bank_buttons(self.nav_buttons[2], self.nav_buttons[3]) continue track_stop_buttons = [ StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, index + STOP_CC_OFF) for index in range(4) ] self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._matrix = [] self._bmatrix = ButtonMatrixElement() for scene_index in range(4): button_row = [] for track_index in range(4): button = self.create_pad_button(scene_index, track_index, mode_selector) button_row.append(button) self._matrix.append(tuple(button_row)) self._bmatrix.add_row(tuple(button_row)) self._session.set_matrix(self._matrix) for (track_index, scene_index) in self._bmatrix.iterbuttons(): if button: scene = self._session.scene(scene_index) clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(button) clip_slot.set_triggered_to_play_value(1) clip_slot.set_triggered_to_record_value(1) clip_slot.set_started_value(1) clip_slot.set_recording_value(1) clip_slot.set_stopped_value(1) continue self._session._link() def _set_up_mixer(self): is_momentary = True self._mixer = MaschineMixerComponent(8) self.send_sliders = [] for track in range(8): self.send_sliders.append( SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, SEND_CC_OFF + track)) for track in range(8): strip = self._mixer.channel_strip(track) strip.set_arm_button( StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, ARM_CC_OFF + track)) strip.set_solo_button( StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SOLO_CC_OFF + track)) strip.set_mute_button( StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, MUTE_CC_OFF + track)) strip.set_volume_control( SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, LEVEL_CC_OFF + track)) strip.set_pan_control( SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, PAN_CC_OFF + track)) strip.set_select_button( StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SELECT_CC_OFF + track)) st = tuple([self.send_sliders[track]]) strip.set_send_controls(st) self.send_slider_toggle_button = StateButton(False, MIDI_CC_TYPE, 0, 90) self._do_toggle_send.subject = self.send_slider_toggle_button self._session.set_mixer(self._mixer) def _set_global_buttons(self): is_momentary = True self._undo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 85) self._do_undo.subject = self._undo_button self._redo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 87) self._do_redo.subject = self._redo_button self._stop_all_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 111) self._do_stop_all.subject = self._stop_all_button self._toggle_detail_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 121) self._action_toogle_detail_view.subject = self._toggle_detail_button self._fire_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 9) self._do_fire_button.subject = self._fire_button self._g_clear_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 106) self._hold_clear_action.subject = self._g_clear_button self._g_duplicate_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 107) self._hold_duplicate_action.subject = self._g_duplicate_button self.track_left_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 120) self.track_right_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 121) self.set_sel_arm_button = StateButton(is_momentary, MIDI_CC_TYPE, 2, 56) self._reenable_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 120) self._do_auto_reenable.subject = self._reenable_button self._on_change_reenabled.subject = self.song() self._on_change_reenabled() self._a_trk_left.subject = self.track_left_button self._a_trk_right.subject = self.track_right_button self._a_sel_arm.subject = self.set_sel_arm_button def _set_up_device_control(self): is_momentary = True device = MaschineDeviceComponent() param_controls = [] for index in range(8): param_controls.append( SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_CC_OFF + index)) device.set_parameter_controls(tuple(param_controls)) self.device_control = param_controls device.set_on_off_button( StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF)) device.set_bank_nav_buttons( StateButton(is_momentary, MIDI_CC_TYPE, 3, 104), ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 105)) self._device_nav_button_left = StateButton(is_momentary, MIDI_CC_TYPE, 3, 106) self._device_nav_button_right = StateButton(is_momentary, MIDI_CC_TYPE, 3, 107) self._navigate_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 127) self._nav_value_left.subject = self._device_nav_button_left self._nav_value_right.subject = self._device_nav_button_right self._do_focus_navigate.subject = self._navigate_button self.set_device_component(device) return device 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 set_up_function_buttons(self): is_momentary = True self.keycolor_mod_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 73) self._do_key_color.subject = self.keycolor_mod_button self._update_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 86) self._do_update_display.subject = self._update_button def _on_appointed_device_changed(self): self._modeselect._device_changed() _on_appointed_device_changed = subject_slot('appointed_device')( _on_appointed_device_changed) def _update_hardware(self): self._session.update() self._modeselect.refresh() self.update_undo_redo(True) def refresh_state(self): ControlSurface.refresh_state(self) self._update_hardware() def _send_midi(self, midi_bytes, **keys): self._c_ref.send_midi(midi_bytes) return True def init_text_display(self): if USE_DISPLAY: self._modeselect._pad_mode.update_text_display() def _on_selected_track_changed(self): super(Maschine, self)._on_selected_track_changed() self.set_controlled_track(self.song().view.selected_track) self._on_devices_changed.subject = self.song().view.selected_track def _on_devices_changed(self): pass _on_devices_changed = subject_slot('devices')(_on_devices_changed) def update(self): self.set_feedback_channels(FEEDBACK_CHANNELS) super(Maschine, self).update() def is_monochrome(self): return False def _deassign_matrix(self): for scene_index in range(4): scene = self._session.scene(scene_index) for track_index in range(4): clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(None) def update_display(self): self.component_guard().__enter__() try: self._is_sending_scheduled_messages().__enter__() try: self._task_group.update(0.1) finally: pass self._modeselect.notify(self.blink_state) self.blink_state = (self.blink_state + 1) % 4 self.display_task.tick() self.update_undo_redo(False) finally: pass def update_undo_redo(self, force=False): if force: self.undo_state = self.song().can_undo self.redo_state = self.song().can_redo if self.song().can_undo != self.undo_state: self.undo_state = self.song().can_undo if not self.undo_state == 1 or 127: pass self._undo_button.send_value(0) if self.song().can_redo != self.redo_state: self.redo_state = self.song().can_redo if not self.redo_state == 1 or 127: pass self._redo_button.send_value(0) def adjust_loop_start(self, delta): loopval = self.song().loop_start self.song().loop_start = min(self.song().song_length, max(0, loopval + delta)) def adjust_loop_length(self, delta): loopval = self.song().loop_length self.song().loop_length = min(self.song().song_length, max(abs(delta), loopval + delta)) def _do_armsolo_mode(self, value): pass def _do_fire_button(self, value): if not self._fire_button != None: raise AssertionError if not value in range(128): raise AssertionError if value != 0: if self.isShiftDown(): self.song().tap_tempo() else: clip_slot = self.song().view.highlighted_clip_slot if clip_slot: clip_slot.fire() _do_fire_button = subject_slot('value')(_do_fire_button) def _do_undo(self, value): if value != 0: if self.use_layered_buttons() and self.isShiftDown(): if self.song().can_redo == 1: self.song().redo() self.show_message(str('REDO')) elif self.song().can_undo == 1: self.song().undo() self.show_message(str('UNDO')) _do_undo = subject_slot('value')(_do_undo) def _do_redo(self, value): if value != 0: if self.song().can_redo == 1: self.song().redo() self.show_message(str('REDO')) _do_redo = subject_slot('value')(_do_redo) def _do_stop_all(self, value): if value != 0: if self.use_layered_buttons() and self.isShiftDown(): self.song().stop_all_clips(0) else: self.song().stop_all_clips(1) _do_stop_all = subject_slot('value')(_do_stop_all) def isShiftDown(self): return self._editsection.isShiftdown() def modifiers(self): return self._editsection.modifiers() def use_layered_buttons(self): return False def _handle_base_note(self, diff): self._modeselect._pad_mode.inc_base_note(diff) def _handle_octave(self, diff): self._modeselect._pad_mode.inc_octave(diff) octave_val = self._modeselect._pad_mode def _handle_scale(self, diff): self._modeselect._pad_mode.inc_scale(diff) def _do_update_display(self, value): if value != 0: self.refresh_state() _do_update_display = subject_slot('value')(_do_update_display) def _do_key_color(self, value): if not value in range(128): raise AssertionError if value != 0: self._modeselect._pad_mode.step_key_color_mode() _do_key_color = subject_slot('value')(_do_key_color) def _do_tap_tempo(self, value): if not value in range(128): raise AssertionError if value != 0: self.song().tap_tempo() _do_tap_tempo = subject_slot('value')(_do_tap_tempo) def _do_toggle_cue(self, value): if not value in range(128): raise AssertionError if value != 0: self.song().set_or_delete_cue() _do_toggle_cue = subject_slot('value')(_do_toggle_cue) def _do_toggle_prev_cue(self, value): if not value in range(128): raise AssertionError if value != 0: self.song().jump_to_prev_cue() _do_toggle_prev_cue = subject_slot('value')(_do_toggle_prev_cue) def _do_toggle_next_cue(self, value): if not value in range(128): raise AssertionError if value != 0: self.song().jump_to_next_cue() _do_toggle_next_cue = subject_slot('value')(_do_toggle_next_cue) def _do_toggle_send(self, value): if not value in range(128): raise AssertionError if self.isShiftDown(): if value != 0: self.refresh_state() self.show_message('Refresh Display') else: nr_of_tracks = len(self.song().return_tracks) if value == 0 or nr_of_tracks < 1: return None prev = self.send_slider_index self.send_slider_index += 1 if self.send_slider_index >= nr_of_tracks: self.send_slider_index = 0 self.show_message(' Set Send ' + str(SENDS[self.send_slider_index])) self.timed_message( 2, ' Set Send ' + str(SENDS[self.send_slider_index])) if prev != self.send_slider_index: for track in range(8): strip = self._mixer.channel_strip(track) slider_list = [] for index in range(self.send_slider_index + 1): if index < self.send_slider_index - 1: slider_list.append(None) else: slider_list.append(self.send_sliders[track]) strip.set_send_controls(tuple(slider_list)) _do_toggle_send = subject_slot('value')(_do_toggle_send) def _a_trk_left(self, value): if not value in range(128): raise AssertionError if value != 0: if self.application().view.is_view_visible('Session'): direction = Live.Application.Application.View.NavDirection.left self.application().view.scroll_view(direction, 'Session', True) track = self.song().view.selected_track self.timed_message(2, 'T:' + track.name, False) if self.arm_selected_track and track.can_be_armed: arm_exclusive(self.song(), track) _a_trk_left = subject_slot('value')(_a_trk_left) def _a_trk_right(self, value): if not value in range(128): raise AssertionError if value != 0: if self.application().view.is_view_visible('Session'): direction = Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Session', True) track = self.song().view.selected_track self.timed_message(2, 'T:' + track.name, False) if self.arm_selected_track and track.can_be_armed: arm_exclusive(self.song(), track) _a_trk_right = subject_slot('value')(_a_trk_right) def _a_sel_arm(self, value): if value != 0: if self.arm_selected_track: self.arm_selected_track = False self.set_sel_arm_button.send_value(0, True) else: self.arm_selected_track = True self.set_sel_arm_button.send_value(127, True) _a_sel_arm = subject_slot('value')(_a_sel_arm) def _nav_value_left(self, value): if not self._device_nav_button_left != None: raise AssertionError if not value in range(128): raise AssertionError modifier_pressed = True if value != 0: if not self.application().view.is_view_visible( 'Detail') or not self.application().view.is_view_visible( 'Detail/DeviceChain'): self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: direction = Live.Application.Application.View.NavDirection.left self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed) _nav_value_left = subject_slot('value')(_nav_value_left) def _nav_value_right(self, value): if not self._device_nav_button_right != None: raise AssertionError if not value in range(128): raise AssertionError if value != 0: modifier_pressed = True if not self.application().view.is_view_visible( 'Detail') or not self.application().view.is_view_visible( 'Detail/DeviceChain'): self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: direction = Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed) _nav_value_right = subject_slot('value')(_nav_value_right) def _do_focus_navigate(self, value): if not self._navigate_button != None: raise AssertionError if not value in range(128): raise AssertionError if value != 0: self.nav_index = (self.nav_index + 1) % len(VIEWS_ALL) self.application().view.focus_view(VIEWS_ALL[self.nav_index]) self.show_message('Focus on : ' + str(VIEWS_ALL[self.nav_index])) _do_focus_navigate = subject_slot('value')(_do_focus_navigate) def focus_clip_detail(self): self.application().view.focus_view('Detail/Clip') def _song_follow_changed(self): view = self.song().view if view.follow_song: self.song_follow_button.send_value(1, True) else: self.song_follow_button.send_value(0, True) _song_follow_changed = subject_slot('follow_song')(_song_follow_changed) def _do_song_follow(self, value): if value != 0: view = self.song().view if view.follow_song: view.follow_song = False self.song_follow_button.send_value(0, True) else: view.follow_song = True self.song_follow_button.send_value(1, True) _do_song_follow = subject_slot('value')(_do_song_follow) def _hold_duplicate_action(self, value): if value != 0: pass 1 _hold_duplicate_action = subject_slot('value')(_hold_duplicate_action) def _hold_clear_action(self, value): if value != 0: self._mixer.enter_clear_mode() self._device_component.enter_clear_mode() else: self._mixer.exit_clear_mode() self._device_component.exit_clear_mode() _hold_clear_action = subject_slot('value')(_hold_clear_action) def _action_toogle_main_view(self, value): if value != 0: appv = self.application().view if appv.is_view_visible('Arranger'): appv.show_view('Session') else: appv.show_view('Arranger') _action_toogle_main_view = subject_slot('value')(_action_toogle_main_view) def _action_toogle_detail_view(self, value): if value != 0: appv = self.application().view if self.isShiftDown(): if appv.is_view_visible('Arranger'): appv.show_view('Session') else: appv.show_view('Arranger') elif appv.is_view_visible('Detail/Clip'): appv.show_view('Detail/DeviceChain') else: appv.show_view('Detail/Clip') _action_toogle_detail_view = subject_slot('value')( _action_toogle_detail_view) def _on_change_reenabled(self): if self.song().re_enable_automation_enabled: self._reenable_button.turn_on() else: self._reenable_button.turn_off() _on_change_reenabled = subject_slot('re_enable_automation_enabled')( _on_change_reenabled) def _do_auto_reenable(self, value): if value != 0: self.song().re_enable_automation() _do_auto_reenable = subject_slot('value')(_do_auto_reenable) def to_color_edit_mode(self, active): pass def clear_display_all(self): self.send_to_display('', 0) self.send_to_display('', 1) self.send_to_display('', 2) self.send_to_display('', 3) def clear_display(self, grid): self.send_to_display('', grid) def timed_message(self, grid, text, hold=False): if USE_DISPLAY == False: self.show_message(text) else: self.display_task.set_func(self.clear_display, grid) self.send_to_display(text, grid) if hold: self.display_task.hold() self.display_task.start() def timed_message_release(self): self.display_task.release() def update_bank_display(self): if USE_DISPLAY: (name, bank) = self._device._current_bank_details() if self._display_device_param: prms = len(bank) d1 = '' for i in range(4): parm = bank[i] if parm: name = parm.name if not i < 3 or '|': pass d1 += name[:6] + '' continue if not i < 3 or '|': pass d1 += ' ' + '' self.send_to_display(d1, 2) d1 = '' for i in range(4): parm = bank[i + 4] if parm: name = parm.name if not i < 3 or '|': pass d1 += name[:6] + '' continue if not i < 3 or '|': pass d1 += ' ' + '' self.send_to_display(d1, 4) else: self.timed_message(2, 'Bank: ' + name) def display_parameters(self, paramlist): if USE_DISPLAY == False: return None def send_to_display(self, text, grid=0): if USE_DISPLAY == False: return None if self._diplay_cache[grid] == text: return None self._diplay_cache[grid] = text if len(text) > 28: text = text[:27] msgsysex = [240, 0, 0, 102, 23, 18, min(grid, 3) * 28] filled = text.ljust(28) for c in filled: msgsysex.append(ord(c)) msgsysex.append(247) self._send_midi(tuple(msgsysex)) def cleanup(self): pass def disconnect(self): self._pre_serialize() self.clear_display_all() for (track_index, scene_index) in self._bmatrix.iterbuttons(): if button: button.send_color_direct(PColor.OFF[0]) continue time.sleep(0.2) self._active = False self._suppress_send_midi = True super(Maschine, self).disconnect()
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self._device_selection_follows_track_selection = True with self.component_guard(): self._suppress_send_midi = True self._suppress_session_highlight = True self._control_is_with_automap = False is_momentary = True self._suggested_input_port = 'Akai MPK26' self._suggested_output_port = 'Akai MPK26' # self.log("BEFORE mixer") self._setup_mixer_control() self._setup_device_control() # self.clipcontrol(8) # self.log("AFTER MIXER") """SESSION ViEW""" global session session = SessionComponent(GRIDSIZE[0], GRIDSIZE[1]) session.name = 'Session_Control' matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' up_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, UP_BUTTON) down_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, DOWN_BUTTON) left_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, LEFT_BUTTON) right_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL_MIXER, RIGHT_BUTTON) session.set_scene_bank_buttons(down_button, up_button) session.set_track_bank_buttons(right_button, left_button) # session_zoom = SessionZoomingComponent(session) # session_zoom.set_nav_buttons(up_button,down_button,left_button,right_button) session_stop_buttons = [] # self.log("SETTING UP GRID") for row in range(GRIDSIZE[1]): button_row = [] # self.log("CZ ROW") # self.log(str(row)) scene = session.scene(row) scene.name = 'Scene_' + str(row) scene.set_launch_button( ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL, SCENE_BUTTONS[row])) scene.set_triggered_value(2) for column in range(GRIDSIZE[0]): # self.log("CZ COLUMN") # self.log(str(column)) button = ConfigurableButtonElement( True, MIDI_NOTE_TYPE, CHANNEL_MIXER, LAUNCH_BUTTONS[row][column]) button.name = str(column) + '_Clip_' + str(row) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_' + str(row) clip_slot.set_launch_button(button) matrix.add_row(tuple(button_row)) for column in range(GRIDSIZE[0]): session_stop_buttons.append( (ButtonElement(True, MIDI_NOTE_TYPE, CHANNEL_MIXER, TRACK_STOPS[column]))) self._suppress_session_highlight = False self._suppress_send_midi = False self.set_highlighting_session_component(session) session.set_stop_track_clip_buttons(tuple(session_stop_buttons)) session.set_mixer(mixer)
class APC40plus22(APC): __doc__ = " Script for Akai's APC40 Controller with extra features added " def __init__(self, c_instance): self._c_instance = c_instance self._shift_modes = None #added from APC20 script self._encoder_modes = None #added self._slider_modes = None #added APC.__init__(self, c_instance) self.show_message("APC40_22 script loaded") # Disabling the scene launch buttons and assigning them to the first 5 repeats on Master self._device_buttons = [] self.setup_device_buttons() def disconnect(self): #this is from the APC20 script for button in self._device_buttons: button.remove_value_listener(self._device_toggle) self._device_buttons = None self._shift_modes = None self._encoder_modes = None self._slider_modes = None APC.disconnect(self) def setup_device_buttons(self): repeat = RepeatComponent(self) repeat.set_shift_button(self._shift_button) def _setup_session_control(self): is_momentary = True self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98) right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96) left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97) up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94) down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95) right_button.name = 'Bank_Select_Right_Button' left_button.name = 'Bank_Select_Left_Button' up_button.name = 'Bank_Select_Up_Button' down_button.name = 'Bank_Select_Down_Button' self._session = PedaledSessionComponent(8, 5) self._session.name = 'Session_Control' self._session.set_track_bank_buttons(right_button, left_button) self._session.set_scene_bank_buttons(down_button, up_button) self._matrix = ButtonMatrixElement() #was: matrix = ButtonMatrixElement() self._matrix.name = 'Button_Matrix' #was: matrix.name = 'Button_Matrix' scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82)) for index in range(5) ] #self._track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ] self._track_stop_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ] for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_'+ str(index) + '_Launch_Button' for index in range(len(self._track_stop_buttons)): self._track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button' stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) stop_all_button.name = 'Stop_All_Clips_Button' self._session.set_stop_all_clips_button(stop_all_button) self._session.set_stop_track_clip_buttons(tuple(self._track_stop_buttons)) self._session.set_stop_track_clip_value(2) for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): #button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53)) button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53)) #use Launchpad configurable button instead button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(3) clip_slot.set_started_value(1) clip_slot.set_recording_value(5) clip_slot.set_launch_button(button) self._matrix.add_row(tuple(button_row)) #matrix.add_row(tuple(button_row)) # Removing the launch selected clip footpedal option #self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = SessionZoomingComponent(self._session) #use APC20 Zooming instead self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(self._matrix) #was: self._session_zoom.set_button_matrix(matrix) self._session_zoom.set_zoom_button(self._shift_button) #set in MatrixModesComponent instead self._session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button) self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5) return None def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(self, 8) #added self for parent self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) master_select_button.name = 'Master_Select_Button' self._mixer.master_strip().set_select_button(master_select_button) #set in ShiftableSelectorComponent instead if used for Note Mode self._mixer.selected_strip().name = 'Selected_Channel_Strip' select_buttons = [] #added arm_buttons = [] #added sliders = [] #added for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) #volume_control = SliderElement(MIDI_CC_TYPE, track, 7) #set in ShiftableSelectorComponent instead #arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) #see below solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) solo_button.name = str(track) + '_Solo_Button' strip.set_solo_button(solo_button) if track < 4: mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) mute_button.name = str(track) + '_Mute_Button' strip.set_mute_button(mute_button) strip.set_invert_mute_feedback(True) strip.set_shift_button(self._shift_button) select_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) #added select_buttons[-1].name = str(track) + '_Select_Button' #added #strip.set_select_button(select_buttons[-1]) #added arm_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) #added arm_buttons[-1].name = str(track) + '_Arm_Button' #added sliders.append(SliderElement(MIDI_CC_TYPE, track, 7)) #added sliders[-1].name = str(track) + '_Volume_Control' #added self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) self._prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) self._crossfader.name = 'Crossfader' #not used in APC20 master_volume_control.name = 'Master_Volume_Control' self._prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_shift_button(self._shift_button) #added for shifting prehear self._mixer.set_crossfader_control(self._crossfader) #not used in APC20 self._mixer.set_prehear_volume_control(self._prehear_control) #functionality overridden in SpecialMixerComponent self._mixer.master_strip().set_volume_control(master_volume_control) self._slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) #added from APC20 script self._slider_modes.name = 'Slider_Modes' #added from APC20 script matrix_modes = MatrixModesComponent(self._matrix, self._session, self._session_zoom, tuple(self._track_stop_buttons), self) #added new matrix_modes.name = 'Matrix_Modes' #added new # Original method args for ShiftableSelectorComponent: (self, select_buttons, master_button, arm_buttons, matrix, session, zooming, mixer, transport, slider_modes, mode_callback) #self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message) self._shift_modes = ShiftableSelectorComponent(self, tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, self._slider_modes, matrix_modes) #, self._send_introduction_message) #also added self for _parent self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button) def _setup_custom_components(self): self._setup_looper_control() self._setup_device_and_transport_control() self._setup_global_control() def _setup_looper_control(self): is_momentary = True #pedal = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67) loop_on = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 4, 50) loop_start = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 5, 50) halve = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 6, 50) double = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 7, 50) looper = LooperComponent(self) looper.set_shift_button(self._shift_button) looper.set_loop_toggle_button(loop_on) looper.set_loop_start_button(loop_start) looper.set_loop_double_button(double) looper.set_loop_halve_button(halve) def _setup_device_and_transport_control(self): is_momentary = True device_bank_buttons = [] device_param_controls = [] bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Device_Lock_Button', 'Metronome_Button') for index in range(8): device_bank_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 58 + index)) device_bank_buttons[-1].name = bank_button_labels[index] ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 24 + index) ringed_encoder = RingedEncoderElement(MIDI_CC_TYPE, 0, 16 + index, Live.MidiMap.MapMode.absolute) ringed_encoder.set_ring_mode_button(ring_mode_button) ringed_encoder.set_feedback_delay(-1) #added from Axiom DirectLink example ringed_encoder.name = 'Device_Control_' + str(index) ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button' device_param_controls.append(ringed_encoder) self._device = ShiftableDeviceComponent() self._device.name = 'Device_Component' self._device.set_bank_buttons(tuple(device_bank_buttons)) self._device.set_shift_button(self._shift_button) self._device.set_parameter_controls(tuple(device_param_controls)) self._device.set_on_off_button(device_bank_buttons[1]) self.set_device_component(self._device) detail_view_toggler = DetailViewControllerComponent() detail_view_toggler.name = 'Detail_View_Control' detail_view_toggler.set_shift_button(self._shift_button) detail_view_toggler.set_device_clip_toggle_button(device_bank_buttons[0]) detail_view_toggler.set_detail_toggle_button(device_bank_buttons[4]) detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3]) transport = ShiftableTransportComponent() transport.name = 'Transport' play_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 91) stop_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 92) record_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 93) nudge_up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 100) nudge_down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 101) tap_tempo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99) play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' record_button.name = 'Record_Button' nudge_up_button.name = 'Nudge_Up_Button' nudge_down_button.name = 'Nudge_Down_Button' tap_tempo_button.name = 'Tap_Tempo_Button' transport.set_shift_button(self._shift_button) transport.set_play_button(play_button) transport.set_stop_button(stop_button) transport.set_record_button(record_button) transport.set_nudge_buttons(nudge_up_button, nudge_down_button) transport.set_undo_button(nudge_down_button) #shifted nudge transport.set_redo_button(nudge_up_button) #shifted nudge transport.set_tap_tempo_button(tap_tempo_button) self._device.set_lock_button(tap_tempo_button) #shifted tap tempo transport.set_quant_toggle_button(device_bank_buttons[5]) transport.set_overdub_button(device_bank_buttons[6]) transport.set_metronome_button(device_bank_buttons[7]) transport.set_tempo_encoder(self._prehear_control) #shifted prehear bank_button_translator = ShiftableTranslatorComponent() bank_button_translator.set_controls_to_translate(tuple(device_bank_buttons)) bank_button_translator.set_shift_button(self._shift_button) def _setup_global_control(self): is_momentary = True self._global_bank_buttons = [] self._global_param_controls = [] for index in range(8): ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 56 + index) ringed_encoder = RingedEncoderElement(MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute) ringed_encoder.name = 'Track_Control_' + str(index) ringed_encoder.set_feedback_delay(-1) ring_button.name = ringed_encoder.name + '_Ring_Mode_Button' ringed_encoder.set_ring_mode_button(ring_button) self._global_param_controls.append(ringed_encoder) self._global_bank_buttons = [] global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button') for index in range(4): self._global_bank_buttons.append(ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87 + index))#(not is_momentary, MIDI_NOTE_TYPE, 0, 87 + index)) self._global_bank_buttons[-1].name = global_bank_labels[index] self._encoder_modes = EncoderMixerModeSelectorComponent(self._mixer) self._encoder_modes.name = 'Track_Control_Modes' #self._encoder_modes.set_modes_buttons(self._global_bank_buttons) # set in ShiftableEncoderSelectorComponent self._encoder_modes.set_controls(tuple(self._global_param_controls)) #self._encoder_device_modes = EncoderDeviceModeSelectorComponent(self._mixer, self._device) #new self._encoder_device_modes = EncoderDeviceComponent(self._mixer, self._device, self) self._encoder_device_modes.name = 'Alt_Device_Control_Modes' #new self._encoder_eq_modes = EncoderEQComponent(self._mixer, self)#EncoderEQModeSelectorComponent(self._mixer) #new self._encoder_eq_modes.name = 'EQ_Control_Modes' #new global_translation_selector = ChannelTranslationSelector() #translate track encoders to channels 1 through 4, based on button selection (pan = 1, send A = 2, send B = 3, send C = 4) global_translation_selector.name = 'Global_Translations' global_translation_selector.set_controls_to_translate(tuple(self._global_param_controls)) global_translation_selector.set_mode_buttons(tuple(self._global_bank_buttons)) encoder_user_modes = EncoderUserModesComponent(self, self._encoder_modes, tuple(self._global_param_controls), tuple(self._global_bank_buttons), self._mixer, self._device, self._encoder_device_modes, self._encoder_eq_modes) #self._mixer, tuple(sliders)) #added encoder_user_modes.name = 'Encoder_User_Modes' #added self._encoder_shift_modes = ShiftableEncoderSelectorComponent(self, tuple(self._global_bank_buttons), encoder_user_modes, self._encoder_modes, self._encoder_eq_modes, self._encoder_device_modes) #tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, slider_modes, matrix_modes) #, self._send_introduction_message) #also added self for _parent self._encoder_shift_modes.name = 'Encoder_Shift_Modes' self._encoder_shift_modes.set_mode_toggle(self._shift_button) def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) #self._slider_modes.update() #added to update alternate slider assignments track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) return None def _product_model_id_byte(self): return 115
class Serato(ControlSurface): def __init__(self, c_instance): publish_in_cs_list = True ControlSurface.__init__(self, c_instance, not publish_in_cs_list) self._device_selection_follows_track_selection = True with self.component_guard(): self._matrix = None self._session = None self._mixer = None self._device = None self._scene_launch_buttons = None self._track_arm_buttons = None self._track_solo_buttons = None self._track_mute_buttons = None self._track_stop_buttons = None self._track_select_buttons = None self._device_on_off_button = None self._shift_button = None self._serato_interface = PySCAClipControl() self._serato_interface.PySCA_InitializeClipControl() self._setup_session_control() self._setup_mixer_control() self._setup_device_control() self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) return def disconnect(self): ControlSurface.disconnect(self) self._serato_interface.PySCA_DeinitializeClipControl() self._serato_interface = None return def connect_script_instances(self, instanciated_scripts): """ Called by the Application as soon as all scripts are initialized. You can connect yourself to other running scripts here, as we do it connect the extension modules (MackieControlXTs). """ for control_surface in self._control_surfaces(): control_surface_session = control_surface.highlighting_session_component() if control_surface_session: self._session.sync_to(control_surface_session) self._on_track_list_changed() break def build_midi_map(self, midi_map_handle): pass def update_display(self): ControlSurface.update_display(self) while self._serato_interface.PySCA_HasIncomingEvent(): new_event = self._serato_interface.PySCA_GetIncomingEvent() if not self._handle_session_event(new_event): if not self._handle_mixer_event(new_event): if not self._handle_device_event(new_event): print 'Unhandled Event: ' + str(new_event) def _setup_session_control(self): is_momentary = True self._session = SpecialSessionComponent(NUM_TRACKS, NUM_SCENES) self._session.set_serato_interface(self._serato_interface) self._matrix = ButtonMatrixElement() self._scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_SCENES) ] self._track_stop_buttons = [ ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_TRACKS) ] stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) self._session.set_stop_all_clips_button(stop_all_button) self._session.set_stop_track_clip_buttons(tuple(self._track_stop_buttons)) for scene_index in range(NUM_SCENES): scene = self._session.scene(scene_index) button_row = [] scene.set_launch_button(self._scene_launch_buttons[scene_index]) scene.set_index(scene_index) scene.set_serato_interface(self._serato_interface) for track_index in range(NUM_TRACKS): button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(button) clip_slot.set_serato_interface(self._serato_interface) self._matrix.add_row(tuple(button_row)) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(NUM_TRACKS) self._mixer.set_serato_interface(self._serato_interface) self._mixer.master_strip().set_serato_interface(self._serato_interface) self._track_arm_buttons = [] self._track_solo_buttons = [] self._track_mute_buttons = [] self._track_select_buttons = [] self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for track in range(NUM_TRACKS): strip = self._mixer.channel_strip(track) strip.set_serato_interface(self._serato_interface) self._track_arm_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_solo_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_mute_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_select_buttons.append(ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) strip.set_arm_button(self._track_arm_buttons[-1]) strip.set_solo_button(self._track_solo_buttons[-1]) strip.set_mute_button(self._track_mute_buttons[-1]) strip.set_select_button(self._track_select_buttons[-1]) strip.set_shift_button(self._shift_button) def _setup_device_control(self): is_momentary = True self._device_on_off_button = ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0) self._device = SpecialDeviceComponent() self._device.set_serato_interface(self._serato_interface) self._device.set_parameter_controls(tuple([ SliderElement(MIDI_CC_TYPE, 0, 0) for index in range(NUM_PARAMS) ])) self._device.set_on_off_button(self._device_on_off_button) self.set_device_component(self._device) def _handle_session_event(self, event): result = False if event.type in CLIP_EVENTS: value = 127 * int(event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventClipPlayedDown) track_index = event.key1 - 1 scene_index = event.key2 - 1 if track_index in range(NUM_TRACKS) and scene_index in range(NUM_SCENES): self._matrix.get_button(track_index, scene_index).receive_value(value) result = True elif event.type in SCENE_EVENTS: value = 127 * int(event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventScenePlayedDown) scene_index = event.key1 - 1 if scene_index in range(NUM_SCENES): self._scene_launch_buttons[scene_index].receive_value(value) result = True elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixSizeChanged: new_width = event.key1 new_height = event.key2 self._session.set_size(new_width, new_height) result = True elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixOffsetChanged: x_increment = event.key1 y_increment = event.key2 self._session.move_by(x_increment, y_increment) result = True return result def _handle_mixer_event(self, event): result = True track_index = event.key1 - 1 value = event.key2 if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackMasterGainChange: self._mixer.master_strip().set_track_volume(fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackStopped: self.song().stop_all_clips() elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackSelect: self.song().view.selected_track = self.song().master_track else: result = track_index in range(NUM_TRACKS) and self._handle_strip_event(event) return result def _handle_strip_event(self, event): result = True track_index = event.key1 - 1 value = event.key2 if value == 0: self._shift_button.receive_value(127) if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSolo: self._track_solo_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackRecord: self._track_arm_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackActive: self._track_mute_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackStopped: self._track_stop_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSelect: self._track_select_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackGainChange: self._mixer.channel_strip(track_index).set_track_volume(fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendAChange: self._mixer.channel_strip(track_index).set_send(0, fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendBChange: self._mixer.channel_strip(track_index).set_send(1, fixed_value(value)) else: result = False self._shift_button.receive_value(0) return result def _handle_device_event(self, event): result = True if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceValueChanged: self._device.set_parameter_value(event.key1 - 1, fixed_value(event.key2)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceActivate: self._device_on_off_button.receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceFocusMove: self._move_device_focus(event.key1) else: result = False return result def _move_device_focus(self, increment): if not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain'): self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: modifier_pressed = True direction = Live.Application.Application.View.NavDirection.left if increment > 0: direction = Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)
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 APC20(APC): """ Script for Akai's APC20 Controller """ def __init__(self, c_instance): self._shift_modes = None APC.__init__(self, c_instance) def disconnect(self): self._shift_modes = None APC.disconnect(self) def _activate_combination_mode(self, track_offset, support_devices): APC._activate_combination_mode(self, track_offset, support_devices) if support_devices: self._shift_modes.invert_assignment() def _setup_session_control(self): is_momentary = True self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) self._session = APCSessionComponent(8, 5) self._session.name = 'Session_Control' self._matrix = ButtonMatrixElement() self._matrix.name = 'Button_Matrix' scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, index + 82) for index in range(5) ] track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ] for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_' + str(index) + '_Launch_Button' for index in range(len(track_stop_buttons)): track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button' self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session.set_stop_track_clip_value(2) for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, scene_index + 53) button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(5) clip_slot.set_started_value(1) clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) self._matrix.add_row(tuple(button_row)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = ShiftableZoomingComponent(self._session, tuple(track_stop_buttons)) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(self._matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.selected_strip().name = 'Selected_Channel_Strip' for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) master_volume_control.name = 'Master_Volume_Control' prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_prehear_volume_control(prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) def _setup_custom_components(self): is_momentary = True master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) master_select_button.name = 'Master_Select_Button' select_buttons = [] arm_buttons = [] sliders = [] for track in range(8): select_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) arm_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) sliders.append(SliderElement(MIDI_CC_TYPE, track, 7)) select_buttons[-1].name = str(track) + '_Select_Button' arm_buttons[-1].name = str(track) + '_Arm_Button' sliders[-1].name = str(track) + '_Volume_Control' transport = TransportComponent() transport.name = 'Transport' slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) slider_modes.name = 'Slider_Modes' self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message) self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button) def _product_model_id_byte(self): return 123
class APC40(APC, OptimizedControlSurface): """ Script for Akai's APC40 Controller """ def __init__(self, *a, **k): super(APC40, self).__init__(*a, **k) self._color_skin = make_biled_skin() self._default_skin = make_default_skin() with self.component_guard(): self._create_controls() self._create_session() self._create_mixer() self._create_device() self._create_detail_view_control() self._create_transport() self._create_global_control() self._create_fallback_control_owner() self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) self.set_device_component(self._device) for component in self.components: component.set_enabled(False) self._device_selection_follows_track_selection = True def _with_shift(self, button): return ComboElement(button, modifiers=[self._shift_button]) def _create_controls(self): make_on_off_button = partial(make_button, skin=self._default_skin) make_color_button = partial(make_button, skin=self._color_skin) self._shift_button = make_button(0, 98, resource_type=PrioritizedResource, name='Shift_Button') self._right_button = make_button(0, 96, name='Bank_Select_Right_Button') self._left_button = make_button(0, 97, name='Bank_Select_Left_Button') self._up_button = make_button(0, 94, name='Bank_Select_Up_Button') self._down_button = make_button(0, 95, name='Bank_Select_Down_Button') self._session_matrix = ButtonMatrixElement(name='Button_Matrix') self._scene_launch_buttons_raw = [ make_color_button(0, index + 82, name='Scene_%d_Launch_Button' % index) for index in xrange(SESSION_HEIGHT) ] self._track_stop_buttons = [ make_color_button(index, 52, name='Track_%d_Stop_Button' % index) for index in xrange(SESSION_WIDTH) ] self._stop_all_button = make_color_button(0, 81, name='Stop_All_Clips_Button') self._matrix_rows_raw = [ [ make_color_button(track_index, scene_index + 53, name='%d_Clip_%d_Button' % (track_index, scene_index)) for track_index in xrange(SESSION_WIDTH) ] for scene_index in xrange(SESSION_HEIGHT) ] for row in self._matrix_rows_raw: self._session_matrix.add_row(row) self._selected_slot_launch_button = make_pedal_button(67, name='Selected_Slot_Launch_Button') self._selected_scene_launch_button = make_pedal_button(64, name='Selected_Scene_Launch_Button') self._volume_controls = [] self._arm_buttons = [] self._solo_buttons = [] self._mute_buttons = [] self._select_buttons = [] for index in xrange(MIXER_SIZE): self._volume_controls.append(make_slider(index, 7, name='%d_Volume_Control' % index)) self._arm_buttons.append(make_on_off_button(index, 48, name='%d_Arm_Button' % index)) self._solo_buttons.append(make_on_off_button(index, 49, name='%d_Solo_Button' % index)) self._mute_buttons.append(make_on_off_button(index, 50, name='%d_Mute_Button' % index)) self._select_buttons.append(make_on_off_button(index, 51, name='%d_Select_Button' % index)) self._crossfader_control = make_slider(0, 15, name='Crossfader') self._master_volume_control = make_slider(0, 14, name='Master_Volume_Control') self._master_select_button = make_on_off_button(0, 80, name='Master_Select_Button') self._prehear_control = make_encoder(0, 47, name='Prehear_Volume_Control') self._device_bank_buttons = [] self._device_param_controls_raw = [] bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Metronome_Button') for index in range(8): self._device_bank_buttons.append(make_on_off_button(0, 58 + index, name=bank_button_labels[index])) encoder_name = 'Device_Control_%d' % index ringed_encoder = make_ring_encoder(16 + index, 24 + index, name=encoder_name) self._device_param_controls_raw.append(ringed_encoder) self._play_button = make_button(0, 91, name='Play_Button') self._stop_button = make_button(0, 92, name='Stop_Button') self._record_button = make_button(0, 93, name='Record_Button') self._nudge_up_button = make_button(0, 100, name='Nudge_Up_Button') self._nudge_down_button = make_button(0, 101, name='Nudge_Down_Button') self._tap_tempo_button = make_button(0, 99, name='Tap_Tempo_Button') self._global_bank_buttons = [] self._global_param_controls = [] for index in range(8): encoder_name = 'Track_Control_%d' % index ringed_encoder = make_ring_encoder(48 + index, 56 + index, name=encoder_name) self._global_param_controls.append(ringed_encoder) self._global_bank_buttons = [ make_on_off_button(0, 87 + index, name=name) for index, name in enumerate(('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button')) ] self._device_clip_toggle_button = self._device_bank_buttons[0] self._device_on_off_button = self._device_bank_buttons[1] self._detail_left_button = self._device_bank_buttons[2] self._detail_right_button = self._device_bank_buttons[3] self._detail_toggle_button = self._device_bank_buttons[4] self._rec_quantization_button = self._device_bank_buttons[5] self._overdub_button = self._device_bank_buttons[6] self._metronome_button = self._device_bank_buttons[7] def wrap_matrix(control_list, wrapper = nop): return ButtonMatrixElement(rows=[map(wrapper, control_list)]) self._scene_launch_buttons = wrap_matrix(self._scene_launch_buttons_raw) self._track_stop_buttons = wrap_matrix(self._track_stop_buttons) self._volume_controls = wrap_matrix(self._volume_controls) self._arm_buttons = wrap_matrix(self._arm_buttons) self._solo_buttons = wrap_matrix(self._solo_buttons) self._mute_buttons = wrap_matrix(self._mute_buttons) self._select_buttons = wrap_matrix(self._select_buttons) self._device_param_controls = wrap_matrix(self._device_param_controls_raw) self._device_bank_buttons = wrap_matrix(self._device_bank_buttons, partial(DeviceBankButtonElement, modifiers=[self._shift_button])) self._shifted_matrix = ButtonMatrixElement(rows=recursive_map(self._with_shift, self._matrix_rows_raw)) self._shifted_scene_buttons = ButtonMatrixElement(rows=[[ self._with_shift(button) for button in self._scene_launch_buttons_raw ]]) def _create_session(self): self._session = SessionComponent(SESSION_WIDTH, SESSION_HEIGHT, auto_name=True, enable_skinning=True, is_enabled=False, layer=Layer(track_bank_left_button=self._left_button, track_bank_right_button=self._right_button, scene_bank_up_button=self._up_button, scene_bank_down_button=self._down_button, stop_all_clips_button=self._stop_all_button, stop_track_clip_buttons=self._track_stop_buttons, scene_launch_buttons=self._scene_launch_buttons, clip_launch_buttons=self._session_matrix, slot_launch_button=self._selected_slot_launch_button, selected_scene_launch_button=self._selected_scene_launch_button)) self._session_zoom = SessionZoomingComponent(self._session, name='Session_Overview', enable_skinning=True, is_enabled=False, layer=Layer(button_matrix=self._shifted_matrix, nav_up_button=self._with_shift(self._up_button), nav_down_button=self._with_shift(self._down_button), nav_left_button=self._with_shift(self._left_button), nav_right_button=self._with_shift(self._right_button), scene_bank_buttons=self._shifted_scene_buttons)) def _create_mixer(self): self._mixer = MixerComponent(MIXER_SIZE, auto_name=True, is_enabled=False, invert_mute_feedback=True, layer=Layer(volume_controls=self._volume_controls, arm_buttons=self._arm_buttons, solo_buttons=self._solo_buttons, mute_buttons=self._mute_buttons, track_select_buttons=self._select_buttons, shift_button=self._shift_button, crossfader_control=self._crossfader_control, prehear_volume_control=self._prehear_control)) self._mixer.master_strip().layer = Layer(volume_control=self._master_volume_control, select_button=self._master_select_button) def _create_device(self): self._device = DeviceComponent(name='Device_Component', is_enabled=False, layer=Layer(bank_buttons=self._device_bank_buttons, on_off_button=self._device_on_off_button), use_fake_banks=True) ChannelTranslationSelector(8, name='Control_Translations') self._device.set_parameter_controls(tuple(self._device_param_controls_raw)) def _create_detail_view_control(self): self._detail_view_toggler = DetailViewCntrlComponent(name='Detail_View_Control', is_enabled=False, layer=Layer(device_clip_toggle_button=self._device_clip_toggle_button, detail_toggle_button=self._detail_toggle_button, device_nav_left_button=self._detail_left_button, device_nav_right_button=self._detail_right_button)) def _create_transport(self): self._transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=self._play_button, stop_button=self._stop_button, record_button=self._record_button, nudge_up_button=self._nudge_up_button, nudge_down_button=self._nudge_down_button, tap_tempo_button=self._tap_tempo_button, quant_toggle_button=self._rec_quantization_button, overdub_button=self._overdub_button, metronome_button=self._metronome_button)) self._bank_button_translator = ChannelTranslationSelector(name='Bank_Button_Translations', is_enabled=False) def _create_global_control(self): def set_pan_controls(): for index, control in enumerate(self._global_param_controls): self._mixer.channel_strip(index).set_pan_control(control) self._mixer.channel_strip(index).set_send_controls((None, None, None)) control.set_channel(0) def set_send_controls(send_index): for index, control in enumerate(self._global_param_controls): self._mixer.channel_strip(index).set_pan_control(None) send_controls = [None] * 3 send_controls[send_index] = control self._mixer.channel_strip(index).set_send_controls(send_controls) control.set_channel(send_index + 1) encoder_modes = ModesComponent(name='Track_Control_Modes', is_enabled=False) encoder_modes.add_mode('pan', [set_pan_controls]) encoder_modes.add_mode('send_a', [partial(set_send_controls, 0)]) encoder_modes.add_mode('send_b', [partial(set_send_controls, 1)]) encoder_modes.add_mode('send_c', [partial(set_send_controls, 2)]) encoder_modes.selected_mode = 'pan' encoder_modes.layer = Layer(pan_button=self._global_bank_buttons[0], send_a_button=self._global_bank_buttons[1], send_b_button=self._global_bank_buttons[2], send_c_button=self._global_bank_buttons[3]) self._translation_selector = ChannelTranslationSelector(name='Global_Translations') def _create_fallback_control_owner(self): self.register_disconnectable(SimpleLayerOwner(layer=Layer(_matrix=self._session_matrix, priority=FALLBACK_CONTROL_OWNER_PRIORITY))) def get_matrix_button(self, column, row): return self._matrix_rows_raw[row][column] def _product_model_id_byte(self): return 115
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 AumPC20(APC): """ Monomodular script for Akai's APC20 Controller """ def __init__(self, c_instance, *a, **k): self._shift_modes = None super(AumPC20, self).__init__(c_instance, *a, **k) def disconnect(self): self._shift_modes = None super(AumPC20, self).disconnect() def _activate_combination_mode(self, track_offset, support_devices): super(AumPC20, self)._activate_combination_mode(track_offset, support_devices) if support_devices: self._shift_modes.invert_assignment() def _setup_session_control(self): is_momentary = True self._shift_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81, 'Shift_Button', self) self._session = APCSessionComponent(8, 5) self._session.name = 'Session_Control' self._matrix = ButtonMatrixElement() self._matrix.name = 'Button_Matrix' scene_launch_buttons = [ AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82), 'Scene_' + str(index) + '_Launch_Button', self) for index in range(5) ] self._scene_launch_buttons = scene_launch_buttons track_stop_buttons = [ AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52, 'Track_' + str(index) + '_Stop_Button', self) for index in range(8) ] self._track_stop_buttons = track_stop_buttons for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_' + str( index) + '_Launch_Button' for index in range(len(track_stop_buttons)): track_stop_buttons[index].name = 'Track_' + str( index) + '_Stop_Button' self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session.set_stop_track_clip_value(2) for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = AumPCMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53), '_Clip_' + str(scene_index) + '_Button', self) button.name = str(track_index) + '_Clip_' + str( scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(5) clip_slot.set_started_value(1) clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) self._matrix.add_row(tuple(button_row)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = ShiftableZoomingComponent( self._session, tuple(track_stop_buttons)) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(self._matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._solo_buttons = [] for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) solo_button = AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49, str(track) + '_Solo_Button', self) self._solo_buttons.append(solo_button) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) prehear_control = EncoderElement( MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) master_volume_control.name = 'Master_Volume_Control' prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_prehear_volume_control(prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) def _setup_custom_components(self): is_momentary = True master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) master_select_button.name = 'Master_Select_Button' self._master_select_button = master_select_button select_buttons = [] arm_buttons = [] sliders = [] for track in range(8): select_buttons.append( AumPCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51, str(track) + '_Select_Button', self)) arm_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) sliders.append( MonoEncoderElement(MIDI_CC_TYPE, track, 7, Live.MidiMap.MapMode.absolute, 'Slider_' + str(track), track, self)) select_buttons[-1].name = str(track) + '_Select_Button' arm_buttons[-1].name = str(track) + '_Arm_Button' #sliders[-1].name = str(track) + '_Volume_Control' self._select_buttons = select_buttons transport = TransportComponent() transport.name = 'Transport' slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) slider_modes.name = 'Slider_Modes' self._shift_modes = AumPC20ShiftableSelectorComponent( tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message, self) self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button) self._device = DeviceComponent() def _product_model_id_byte(self): return 123 def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_monomod(self): self._host = AumPC20MonomodComponent(self) self._host.name = 'Monomod_Host' self._host._navbox_selected = 16 self._host._navbox_unselected = 1 self.hosts = [self._host] self._monomod = ButtonMatrixElement() self._monomod.name = 'Monomod' for row in range(5): button_row = [] for column in range(8): button_row.append(self._matrix.get_button(column, row)) self._monomod.add_row(tuple(button_row)) self._monomod.add_row(tuple(self._track_stop_buttons)) self._monomod.add_row(tuple(self._select_buttons)) self._monomod.add_row(tuple(self._solo_buttons)) self._monomod_mode = MonomodModeComponent(self._monomod_mode_update, self) self._monomod_mode.name = "Monomod_Mode_Component" #self._shift_button.add_value_listener(self._shift_value) def _shift_value(self, value): if value > 0: self._mixer.master_strip().set_select_button(None) self._monomod_mode.set_mode_toggle(self._master_select_button) else: self._mixer.master_strip().set_select_button( self._master_select_button) self._monomod_mode.set_mode_toggle(None) def _monomod_mode_update(self): self.log_message('mode update: ' + str(self._monomod_mode._mode_index)) if (self._monomod_mode._mode_index == 0) or (self._host._active_client == None): self.flash_status = 0 self._host.set_enabled(False) self._host._set_button_matrix(None) #self._host._set_nav_buttons(None) self._host._set_lock_button(None) self._host._set_alt_button(None) self._host._set_shift_button(None) self._host._set_nav_buttons(None) self._scene_launch_buttons[2].set_on_off_values(127, 0) self._scene_launch_buttons[3].set_on_off_values(127, 0) self._monomod.reset() self._shift_modes.set_enabled(True) #self._session.set_track_bank_buttons(self._right_button, self._left_button) #self._session.set_scene_bank_buttons(self._down_button, self._up_button) for track in range(8): self._mixer.channel_strip(track).set_select_button( self._select_buttons[track]) self._mixer.channel_strip(track).set_solo_button( self._solo_buttons[track]) #self._transport.set_nudge_buttons(self._nudge_up_button, self._nudge_down_button) self._session.set_enabled(True) self._session_zoom._is_zoomed_out = False self._session_zoom.set_enabled(True) self.request_rebuild_midi_map() self._master_select_button.turn_off() elif (self._monomod_mode._mode_index == 1): if self._shift_modes._note_mode_active is True: self._shift_modes._mode_callback(ABLETON_MODE) self._shift_modes._note_mode_active = False self._session_zoom.set_ignore_buttons(False) self._shift_modes._transport.update() self._shift_modes._on_note_mode_changed() #self._transport.set_nudge_buttons(None, None) self._shift_modes.set_enabled(False) for track in range(8): self._mixer.channel_strip(track).set_select_button(None) self._mixer.channel_strip(track).set_solo_button(None) for scene in range(5): self._scene_launch_buttons[scene].turn_off() self._session.set_enabled(False) self._session_zoom.set_enabled(False) #self._session.set_track_bank_buttons(None, None) #self._session.set_scene_bank_buttons(None, None) self.flash_status = 1 self._monomod.reset() self._host._set_button_matrix(self._monomod) #self._host._set_nav_buttons([self._up_button, self._down_button, self._left_button, self._right_button]) self._host._set_shift_button(self._shift_button) self._host._set_lock_button(self._scene_launch_buttons[0]) self._host._set_alt_button(self._scene_launch_buttons[1]) self._host._set_nav_buttons( [self._scene_launch_buttons[2], self._scene_launch_buttons[3]]) self._host.set_enabled(True) self.request_rebuild_midi_map() self._master_select_button.turn_on() #self.log_message('mod mode') """m4l bridge""" def generate_strip_string(self, display_string): #self.log_message(display_string) NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center( (NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return ret def notification_to_bridge(self, name, value, sender): if isinstance(sender, MonoEncoderElement): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched += 1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip() is True: clip_names.append(clip_slot._clip_slot) ##.clip.name) return clip_slot._clip_slot ##self.log_message(str(clip_slot._clip_slot.clip.name)) return clip_names def update_display(self): super(AumPC20, self).update_display() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if self.flash_status: for control in self.controls: if isinstance(control, MonoButtonElement): control.flash(self._timer) def set_appointed_device(self, *a, **k): pass
def _setup_session_control(self): self.session = CustomSessionComponent(self.box_width, self.box_height, self) # subclass from _Framework is_momentary = True # what exactly does this do in the _Framework? if up_button_note_number >= 0 and down_button_note_number >= 0: # opt in enable UP/DOWN nav up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, up_button_note_number) up_button.name = 'Bank_Select_Up_Button' # sure, why not down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, down_button_note_number) down_button.name = 'Bank_Select_Down_Button' #sure, why not self.session.set_scene_bank_buttons(down_button, up_button) if right_button_note_number >= 0 and left_button_note_number >= 0: # opt in enable LEFT/RIGHT nav right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, right_button_note_number) right_button.name = 'Bank_Select_Right_Button' #sure, why not left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, left_button_note_number) left_button.name = 'Bank_Select_Left_Button' #sure, why not self.session.set_track_bank_buttons(right_button, left_button) self.session.name = 'Session_Control' #sure, why not matrix = ButtonMatrixElement( ) # @todo subclass this via established new patterns matrix.name = 'Button_Matrix' #sure, why not # I loop a little different. The goal is readbility, flexibility, and the web app...incase you did not notice yet if len(scene_launch_notes) > 0 and len( scene_launch_notes ) == self.box_height: # logic check have launch notes and scene = box height for index in range(self.box_height): self.session.scene(index).set_launch_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, scene_launch_notes[index])) else: self.log_message( "..::|| Scene launch not in use or error on case of use. Modern.DJ ||::.." ) if len(stop_track_buttons) > 0 and len( stop_track_buttons ) == self.box_width: #logic check have track stop assignments and track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, stop_track_buttons[index]) for index in range(len(stop_track_buttons)) ] for index in range(len(track_stop_buttons)): track_stop_buttons[index].name = 'Track_' + str( index) + '_Stop_Button' # sure, why not self.session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) else: self.log_message( "..::|| Stop notes not in use or error found Modern.DJ ||::..") # Check for stop all clips option if stop_all_clips >= 0: self.session.set_stop_all_clips_button( ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, stop_all_clips)) # creating the matrix of buttons from the launch_button_list (tuple) launch_button_list_len = len( launch_button_list ) # var used multiple times. This is a performance modification if ( self.box_height * self.box_width ) == launch_button_list_len: # check box size against number of button vars sent launch_ctr = launch_button_list_len - 1 # decrement for zero offset in list/tuple launch_button_list.reverse( ) #reverse list from human readable for decrement use (performance tweak) ## check for use of RGB if use_velocity_for_RGB != 1: # if not enabled use these defaults self.log_message( "..::|| RGB not in effect assigning defaults ||::..") self.clip_loaded_stopped = 1 self.clip_currently_playing = 127 self.clip_triggered_to_play = 64 else: # yes RGB in effect...assign per the parameters script self.clip_loaded_stopped = clip_loaded_stopped self.clip_currently_playing = clip_currently_playing self.clip_triggered_to_play = clip_triggered_to_play for scene_index in range( self.box_height): # loop on the notes matrix scene = self.session.scene( scene_index) # part of the martix built, think rows scene.name = 'Scene_' + str(scene_index) # sure, why not button_row = [] # create recepticle # loop across the tracks for track_index in range(self.box_width): button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, launch_button_list[launch_ctr] ) # button instance for _Framework launch_ctr = launch_ctr - 1 # decrement is faster than increment button.name = str(track_index) + '_Clip_' + str( scene_index) + '_Button' # sure, why not button_row.append(button) # add to our growing list clip_slot = scene.clip_slot( track_index ) # clips slot and buttons are not the same thing, this aligns these ideas in the red box clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) # sure, why not # assign the button and and status in th refrech update clip_slot.set_stopped_value( self.clip_loaded_stopped ) # this number is sent back to the machine allowing diff colors for stopped clip_slot.set_started_value( self.clip_currently_playing ) # this number is sent back to the machine allowing diff colors for started/is-playing clip_slot.set_triggered_to_play_value( self.clip_triggered_to_play ) # this number is sent back to the machine allowing diff colors for cued, will play next clip_slot.set_launch_button( button) # part of the slit+button = go time paradigm matrix.add_row( tuple(button_row) ) # close out the matrix build. @todo - possible subclass here? else: # log message self.log_message( "..::|| Number of notes defined does not match box height and width Modern.DJ ||::.." ) ''' live 9 only self.set_highlighting_session_component(self.session) # new for live9 -- this is for the box. via aumhaa/bitnomad ''' return None
class APC40(APC, OptimizedControlSurface): """ Script for Akai's APC40 Controller """ def __init__(self, *a, **k): super(APC40, self).__init__(*a, **k) self._color_skin = make_biled_skin() self._default_skin = make_default_skin() with self.component_guard(): self._create_controls() self._create_session() self._create_mixer() self._create_device() self._create_detail_view_control() self._create_transport() self._create_global_control() self._create_fallback_control_owner() self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) self.set_device_component(self._device) for component in self.components: component.set_enabled(False) self._device_selection_follows_track_selection = True def _with_shift(self, button): return ComboElement(button, modifiers=[self._shift_button]) def _create_controls(self): make_on_off_button = partial(make_button, skin=self._default_skin) make_color_button = partial(make_button, skin=self._color_skin) self._shift_button = make_button(0, 98, resource_type=PrioritizedResource, name='Shift_Button') self._right_button = make_button(0, 96, name='Bank_Select_Right_Button') self._left_button = make_button(0, 97, name='Bank_Select_Left_Button') self._up_button = make_button(0, 94, name='Bank_Select_Up_Button') self._down_button = make_button(0, 95, name='Bank_Select_Down_Button') self._session_matrix = ButtonMatrixElement(name='Button_Matrix') self._scene_launch_buttons_raw = [ make_color_button(0, index + 82, name='Scene_%d_Launch_Button' % index) for index in xrange(SESSION_HEIGHT) ] self._track_stop_buttons = [ make_color_button(index, 52, name='Track_%d_Stop_Button' % index) for index in xrange(SESSION_WIDTH) ] self._stop_all_button = make_color_button(0, 81, name='Stop_All_Clips_Button') self._matrix_rows_raw = [[ make_color_button(track_index, scene_index + 53, name='%d_Clip_%d_Button' % (track_index, scene_index)) for track_index in xrange(SESSION_WIDTH) ] for scene_index in xrange(SESSION_HEIGHT)] for row in self._matrix_rows_raw: self._session_matrix.add_row(row) self._selected_slot_launch_button = make_pedal_button( 67, name='Selected_Slot_Launch_Button') self._selected_scene_launch_button = make_pedal_button( 64, name='Selected_Scene_Launch_Button') self._volume_controls = [] self._arm_buttons = [] self._solo_buttons = [] self._mute_buttons = [] self._select_buttons = [] for index in xrange(MIXER_SIZE): self._volume_controls.append( make_slider(index, 7, name='%d_Volume_Control' % index)) self._arm_buttons.append( make_on_off_button(index, 48, name='%d_Arm_Button' % index)) self._solo_buttons.append( make_on_off_button(index, 49, name='%d_Solo_Button' % index)) self._mute_buttons.append( make_on_off_button(index, 50, name='%d_Mute_Button' % index)) self._select_buttons.append( make_on_off_button(index, 51, name='%d_Select_Button' % index)) self._crossfader_control = make_slider(0, 15, name='Crossfader') self._master_volume_control = make_slider(0, 14, name='Master_Volume_Control') self._master_select_button = make_on_off_button( 0, 80, name='Master_Select_Button') self._prehear_control = make_encoder(0, 47, name='Prehear_Volume_Control') self._device_bank_buttons = [] self._device_param_controls_raw = [] bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Metronome_Button') for index in range(8): self._device_bank_buttons.append( make_on_off_button(0, 58 + index, name=bank_button_labels[index])) encoder_name = 'Device_Control_%d' % index ringed_encoder = make_ring_encoder(16 + index, 24 + index, name=encoder_name) self._device_param_controls_raw.append(ringed_encoder) self._play_button = make_button(0, 91, name='Play_Button') self._stop_button = make_button(0, 92, name='Stop_Button') self._record_button = make_button(0, 93, name='Record_Button') self._nudge_up_button = make_button(0, 100, name='Nudge_Up_Button') self._nudge_down_button = make_button(0, 101, name='Nudge_Down_Button') self._tap_tempo_button = make_button(0, 99, name='Tap_Tempo_Button') self._global_bank_buttons = [] self._global_param_controls = [] for index in range(8): encoder_name = 'Track_Control_%d' % index ringed_encoder = make_ring_encoder(48 + index, 56 + index, name=encoder_name) self._global_param_controls.append(ringed_encoder) self._global_bank_buttons = [ make_on_off_button(0, 87 + index, name=name) for index, name in enumerate(('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button')) ] self._device_clip_toggle_button = self._device_bank_buttons[0] self._device_on_off_button = self._device_bank_buttons[1] self._detail_left_button = self._device_bank_buttons[2] self._detail_right_button = self._device_bank_buttons[3] self._detail_toggle_button = self._device_bank_buttons[4] self._rec_quantization_button = self._device_bank_buttons[5] self._overdub_button = self._device_bank_buttons[6] self._metronome_button = self._device_bank_buttons[7] def wrap_matrix(control_list, wrapper=nop): return ButtonMatrixElement(rows=[map(wrapper, control_list)]) self._scene_launch_buttons = wrap_matrix( self._scene_launch_buttons_raw) self._track_stop_buttons = wrap_matrix(self._track_stop_buttons) self._volume_controls = wrap_matrix(self._volume_controls) self._arm_buttons = wrap_matrix(self._arm_buttons) self._solo_buttons = wrap_matrix(self._solo_buttons) self._mute_buttons = wrap_matrix(self._mute_buttons) self._select_buttons = wrap_matrix(self._select_buttons) self._device_param_controls = wrap_matrix( self._device_param_controls_raw) self._device_bank_buttons = wrap_matrix( self._device_bank_buttons, partial(DeviceBankButtonElement, modifiers=[self._shift_button])) self._shifted_matrix = ButtonMatrixElement( rows=recursive_map(self._with_shift, self._matrix_rows_raw)) self._shifted_scene_buttons = ButtonMatrixElement(rows=[[ self._with_shift(button) for button in self._scene_launch_buttons_raw ]]) def _create_session(self): self._session = SessionComponent( SESSION_WIDTH, SESSION_HEIGHT, auto_name=True, enable_skinning=True, is_enabled=False, layer=Layer(track_bank_left_button=self._left_button, track_bank_right_button=self._right_button, scene_bank_up_button=self._up_button, scene_bank_down_button=self._down_button, stop_all_clips_button=self._stop_all_button, stop_track_clip_buttons=self._track_stop_buttons, scene_launch_buttons=self._scene_launch_buttons, clip_launch_buttons=self._session_matrix, slot_launch_button=self._selected_slot_launch_button, selected_scene_launch_button=self. _selected_scene_launch_button)) self._session_zoom = SessionZoomingComponent( self._session, name='Session_Overview', enable_skinning=True, is_enabled=False, layer=Layer(button_matrix=self._shifted_matrix, nav_up_button=self._with_shift(self._up_button), nav_down_button=self._with_shift(self._down_button), nav_left_button=self._with_shift(self._left_button), nav_right_button=self._with_shift(self._right_button), scene_bank_buttons=self._shifted_scene_buttons)) def _create_mixer(self): self._mixer = MixerComponent( MIXER_SIZE, auto_name=True, is_enabled=False, invert_mute_feedback=True, layer=Layer(volume_controls=self._volume_controls, arm_buttons=self._arm_buttons, solo_buttons=self._solo_buttons, mute_buttons=self._mute_buttons, track_select_buttons=self._select_buttons, shift_button=self._shift_button, crossfader_control=self._crossfader_control, prehear_volume_control=self._prehear_control)) self._mixer.master_strip().layer = Layer( volume_control=self._master_volume_control, select_button=self._master_select_button) def _create_device(self): self._device = DeviceComponent( name='Device_Component', is_enabled=False, layer=Layer(bank_buttons=self._device_bank_buttons, on_off_button=self._device_on_off_button), use_fake_banks=True) ChannelTranslationSelector(8, name='Control_Translations') self._device.set_parameter_controls( tuple(self._device_param_controls_raw)) def _create_detail_view_control(self): self._detail_view_toggler = DetailViewCntrlComponent( name='Detail_View_Control', is_enabled=False, layer=Layer( device_clip_toggle_button=self._device_clip_toggle_button, detail_toggle_button=self._detail_toggle_button, device_nav_left_button=self._detail_left_button, device_nav_right_button=self._detail_right_button)) def _create_transport(self): self._transport = TransportComponent( name='Transport', is_enabled=False, layer=Layer(play_button=self._play_button, stop_button=self._stop_button, record_button=self._record_button, nudge_up_button=self._nudge_up_button, nudge_down_button=self._nudge_down_button, tap_tempo_button=self._tap_tempo_button, quant_toggle_button=self._rec_quantization_button, overdub_button=self._overdub_button, metronome_button=self._metronome_button)) self._bank_button_translator = ChannelTranslationSelector( name='Bank_Button_Translations', is_enabled=False) def _create_global_control(self): def set_pan_controls(): for index, control in enumerate(self._global_param_controls): self._mixer.channel_strip(index).set_pan_control(control) self._mixer.channel_strip(index).set_send_controls( (None, None, None)) control.set_channel(0) def set_send_controls(send_index): for index, control in enumerate(self._global_param_controls): self._mixer.channel_strip(index).set_pan_control(None) send_controls = [None] * 3 send_controls[send_index] = control self._mixer.channel_strip(index).set_send_controls( send_controls) control.set_channel(send_index + 1) encoder_modes = ModesComponent(name='Track_Control_Modes', is_enabled=False) encoder_modes.add_mode('pan', [set_pan_controls]) encoder_modes.add_mode('send_a', [partial(set_send_controls, 0)]) encoder_modes.add_mode('send_b', [partial(set_send_controls, 1)]) encoder_modes.add_mode('send_c', [partial(set_send_controls, 2)]) encoder_modes.selected_mode = 'pan' encoder_modes.layer = Layer(pan_button=self._global_bank_buttons[0], send_a_button=self._global_bank_buttons[1], send_b_button=self._global_bank_buttons[2], send_c_button=self._global_bank_buttons[3]) self._translation_selector = ChannelTranslationSelector( name='Global_Translations') def _create_fallback_control_owner(self): self.register_disconnectable( SimpleLayerOwner( layer=Layer(_matrix=self._session_matrix, priority=FALLBACK_CONTROL_OWNER_PRIORITY))) def get_matrix_button(self, column, row): return self._matrix_rows_raw[row][column] def _product_model_id_byte(self): return 115
class Tweaker(ControlSurface): __module__ = __name__ __doc__ = " MonOhmod companion 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) with self.component_guard(): self._update_linked_device_selection = None self._tweaker_version = '0.2' self.log_message("--------------= Tweaker Mixer " + str(self._tweaker_version) + " log opened =--------------") self._update_linked_device_selection = None self._setup_mixer_control() self._setup_session_control() """script initialization methods""" def _setup_controls(self): is_momentary = True self._grid = [None for index in range(8)] for column in range(8): self._grid[column] = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, column + (row * 8), 'Grid_' + str(column) + '_' + str(row), self) for row in range(4)] self._button = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_BUTTONS[index], 'Button_' + str(index), self) for index in range(len(TWEAKER_BUTTONS))] self._nav = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_NAVS[index], 'Nav_' + str(index), self) for index in range(len(TWEAKER_NAVS))] self._encoder_buttons = [FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, TWEAKER_ENCODER_BUTTONS[index], 'Encoder_Button_' + str(index), self) for index in range(len(TWEAKER_ENCODER_BUTTONS))] self._dial = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_DIALS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_DIALS))] self._fader = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_FADERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_FADERS))] self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute) self._encoder = [EncoderElement(MIDI_CC_TYPE, CHANNEL, TWEAKER_ENCODERS[index], Live.MidiMap.MapMode.absolute) for index in range(len(TWEAKER_ENCODERS))] self._pad = [FlashingButtonElement(not is_momentary, MIDI_CC_TYPE, CHANNEL, TWEAKER_PADS[index], 'Pad_' + str(index), self) for index in range(len(TWEAKER_PADS))] self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' for row in range(4): button_row = [] for column in range(7): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_mixer_control(self): is_momentary = True self._num_tracks = (2) #A mixer is one-dimensional; self._mixer = MixerComponent(2, 0, False, True) self._mixer.name = 'Mixer' self._mixer.tracks_to_use = self._mixer_tracks_to_use(self._mixer) self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) def _setup_session_control(self): is_momentary = True num_tracks = 2 num_scenes = 3 self._session = SessionComponent(num_tracks, num_scenes) self._session.name = "Session" self._session.set_offsets(0, 0) self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) """general functionality""" def allow_updates(self, allow_updates): for component in self.components: component.set_allow_update(int(allow_updates!=0)) def disconnect(self): """clean things up on disconnect""" if self._session._is_linked(): self._session._unlink() self.log_message("--------------= Tweaker Mixer " + str(self._tweaker_version) + " log closed =--------------") #Create entry in log file ControlSurface.disconnect(self) return None def connect_script_instances(self, instanciated_scripts): link = False for s in instanciated_scripts: if '_tweaker_version' in dir(s): if s._tweaker_version == self._tweaker_version: link = True if not s is self: s._linked_session = self._session #break if link is True: if not self._session._is_linked(): #self._session.set_offsets(0, 0) self._session._link() def _mixer_tracks_to_use(self, mixer): def tracks_to_use(): return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) return tracks_to_use # a
class OhmModes(ControlSurface): __module__ = __name__ __doc__ = ' OhmModes controller script ' def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._version_check = 'b994' self._host_name = 'Ohm' self._color_type = 'OhmRGB' self._hosts = [] self.hosts = [] self._client = [ None for index in range(6) ] self._active_client = None self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< OhmModes ' + str(self._version_check) + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>') self._rgb = 0 self._timer = 0 self._touched = 0 self.flash_status = 1 self._backlight = 127 self._backlight_type = 'static' self._ohm = 127 self._ohm_type = 'static' self._pad_translations = PAD_TRANSLATION self._device_selection_follows_track_selection = FOLLOW self._keys_octave = 5 self._keys_scale = 0 self._tempo_buttons = None self._setup_monobridge() self._setup_controls() self._setup_transport_control() self._setup_mixer_control() self._setup_session_control() self._setup_device_control() self._setup_crossfader() self._setup_ohmmod() self._setup_switchboard() self._setup_modes() self._assign_page_constants() self._last_device = None self.song().view.add_selected_track_listener(self._update_selected_device) self.show_message('OhmModes Control Surface Loaded') self._send_midi(tuple(switchxfader)) if FORCE_TYPE is True: self._rgb = FORCE_COLOR_TYPE else: self.schedule_message(10, self.query_ohm, None) self.log_message(str(self._highlighting_session_component)) def query_ohm(self): self._send_midi(tuple(check_model)) def update_display(self): ControlSurface.update_display(self) self._timer = (self._timer + 1) % 256 self.flash() self.strobe() def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def get_device_bank(self): return self._device._bank_index def _setup_controls(self): is_momentary = True self._fader = [ None for index in range(8) ] self._dial = [ None for index in range(16) ] self._button = [ None for index in range(8) ] self._menu = [ None for index in range(6) ] for index in range(8): self._fader[index] = MonoEncoderElement2(MIDI_CC_TYPE, CHANNEL, OHM_FADERS[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self) for index in range(8): self._button[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_' + str(index), self) for index in range(16): self._dial[index] = CodecEncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_DIALS[index], Live.MidiMap.MapMode.absolute, 'Encoder_' + str(index), index, self) self._knobs = [] for index in range(12): self._knobs.append(self._dial[index]) for index in range(6): self._menu[index] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_MENU[index], 'Menu_' + str(index), self) self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute) self._crossfader.name = 'Crossfader' self._livid = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self) self._shift_l = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Page_Button_Left', self) self._shift_r = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Page_Button_Right', self) self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' self._grid = [ None for index in range(8) ] self._monomod = ButtonMatrixElement() self._monomod.name = 'Monomod' for column in range(8): self._grid[column] = [ None for index in range(8) ] for row in range(8): self._grid[column][row] = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, column * 8 + row, 'Grid_' + str(column) + '_' + str(row), self) for row in range(5): button_row = [] for column in range(7): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) for row in range(8): button_row = [] for column in range(8): button_row.append(self._grid[column][row]) self._monomod.add_row(tuple(button_row)) self._mod_matrix = ButtonMatrixElement() self._mod_matrix.name = 'Matrix' self._dial_matrix = EncoderMatrixElement(self) self._dial_matrix.name = 'Dial_Matrix' self._dial_button_matrix = ButtonMatrixElement() self._dial_button_matrix.name = 'Dial_Button_Matrix' for row in range(4): button_row = [] for column in range(4): button_row.append(self._grid[column + 4][row]) self._mod_matrix.add_row(tuple(button_row)) for row in range(3): dial_row = [] for column in range(4): dial_row.append(self._dial[row * 4 + column]) self._dial_matrix.add_row(tuple(dial_row)) for row in range(3): dial_button_row = [] for column in range(4): dial_button_row.append(self._grid[column][row]) self._dial_button_matrix.add_row(tuple(dial_button_row)) self._key = [ self._grid[KEYS[index][1]][KEYS[index][0]] for index in range(32) ] self._encoder = [ self._dial[index] for index in range(12) ] self._key_matrix = ButtonMatrixElement() button_row = [] for column in range(16): button_row.append(self._key[16 + column]) self._key_matrix.add_row(tuple(button_row)) def _setup_ohmmod(self): self._host = MonomodComponent(self) self._host.name = 'Monomod_Host' self.hosts = [self._host] self._hosts = [self._host] for index in range(6): self._client[index] = MonoClient(self, index) self._client[index].name = 'Client_' + str(index) self._client[index]._device_component.set_parameter_controls(tuple([ self._dial[num] for num in range(12) ])) self._client[index]._control_defs = {'dials': self._dial_matrix, 'buttons': self._dial_button_matrix, 'grid': self._mod_matrix, 'keys': self._key, 'knobs': [ self._dial[num + 12] for num in range(4) ]} self._host._active_client = self._client[0] self._host._active_client._is_active = True self._host.connect_to_clients(self) def _setup_switchboard(self): self._switchboard = SwitchboardElement(self, self._client) self._switchboard.name = 'Switchboard' def _setup_modes(self): self._shift_mode = ShiftModeComponent(self) self._shift_mode.name = 'Shift_Mode' self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r, self._livid) self._scale_mode = ScaleModeComponent(self) self._scale_mode.name = 'Scale_Mode' self._octave_mode = OctaveModeComponent(self) self._octave_mode.name = 'Octave_Mode' self._modNum = ModNumModeComponent(self, self.modNum_update) self._modNum.name = 'Mod_Number' self._modNum.set_mode = self._modNum_set_mode(self._modNum) self._modNum.set_mode_buttons([ self._menu[index] for index in range(6) ]) def _modNum_set_mode(self, modNum): def set_mode(mode): if modNum._is_enabled == True: assert isinstance(mode, int) assert (mode in range(modNum.number_of_modes())) if (modNum._mode_index != mode): modNum._mode_index = mode modNum.update() return set_mode def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_mixer_control(self): global mixer is_momentary = True self._num_tracks = 7 mixer = SpecialMixerComponent(7, 0, True, False) mixer.name = 'Mixer' self._mixer = mixer for index in range(7): mixer.channel_strip(index).set_volume_control(self._fader[index]) for index in range(7): mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) mixer.track_eq(index).name = 'Mixer_EQ_' + str(index) mixer.channel_strip(index)._invert_mute_feedback = True self.song().view.selected_track = mixer.channel_strip(0)._track def _setup_session_control(self): global session is_momentary = True num_tracks = 7 num_scenes = 5 session = SessionComponent(num_tracks, num_scenes) session.name = 'Session' self._session = session session.set_offsets(0, 0) self._scene = [ None for index in range(6) ] for row in range(num_scenes): self._scene[row] = session.scene(row) self._scene[row].name = 'Scene_' + str(row) for column in range(num_tracks): clip_slot = self._scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_' + str(row) session.set_mixer(self._mixer) session.set_show_highlight(True) self._session_zoom = SessionZoomingComponent(session) self._session_zoom.name = 'Session_Overview' self.set_highlighting_session_component(self._session) def _assign_session_colors(self): self.log_message('assign session colors') num_tracks = 7 num_scenes = 5 self._session.set_stop_track_clip_value(STOP_CLIP_COLOR[self._rgb]) for row in range(num_scenes): for column in range(num_tracks): self._scene[row].clip_slot(column).set_triggered_to_play_value(CLIP_TRIGD_TO_PLAY_COLOR[self._rgb]) self._scene[row].clip_slot(column).set_triggered_to_record_value(CLIP_TRIGD_TO_RECORD_COLOR[self._rgb]) self._scene[row].clip_slot(column).set_stopped_value(CLIP_STOPPED_COLOR[self._rgb]) self._scene[row].clip_slot(column).set_started_value(CLIP_STARTED_COLOR[self._rgb]) self._scene[row].clip_slot(column).set_recording_value(CLIP_RECORDING_COLOR[self._rgb]) self._session_zoom.set_stopped_value(ZOOM_STOPPED_COLOR[self._rgb]) self._session_zoom.set_playing_value(ZOOM_PLAYING_COLOR[self._rgb]) self._session_zoom.set_selected_value(ZOOM_SELECTED_COLOR[self._rgb]) for row in range(8): for column in range(8): self._grid[column][row].set_force_next_value() self._session.on_scene_list_changed() self._shift_mode.update() def _setup_device_control(self): self._device = DeviceComponent() self._device.name = 'Device_Component' self.set_device_component(self._device) self._device_navigator = DetailViewControllerComponent() self._device_navigator.name = 'Device_Navigator' self._device_selection_follows_track_selection = FOLLOW def device_follows_track(self, val): self._device_selection_follows_track_selection = val == 1 return self def _setup_crossfader(self): self._mixer.set_crossfader_control(self._crossfader) def disconnect(self): """clean things up on disconnect""" self.song().view.remove_selected_track_listener(self._update_selected_device) self.log_message(time.strftime('%d.%m.%Y %H:%M:%S', time.localtime()) + '--------------= OhmModes log closed =--------------') ControlSurface.disconnect(self) def _get_num_tracks(self): return self.num_tracks def flash(self): for row in range(8): if self._button[row]._flash_state > 0: self._button[row].flash(self._timer) for column in range(8): button = self._grid[column][row] if button._flash_state > 0: button.flash(self._timer) def strobe(self): if self._backlight_type != 'static': if self._backlight_type is 'pulse': self._backlight = int(math.fabs(self._timer * 16 % 64 - 32) + 32) if self._backlight_type is 'up': self._backlight = int(self._timer * 8 % 64 + 16) if self._backlight_type is 'down': self._backlight = int(math.fabs(int(self._timer * 8 % 64 - 64)) + 16) self._send_midi(tuple([176, 27, int(self._backlight)])) if self._ohm_type != 'static': if self._ohm_type is 'pulse': self._ohm = int(math.fabs(self._timer * 16 % 64 - 32) + 32) if self._ohm_type is 'up': self._ohm = int(self._timer * 8 % 64 + 16) if self._ohm_type is 'down': self._ohm = int(math.fabs(int(self._timer * 8 % 64 - 64)) + 16) self._send_midi(tuple([176, 63, int(self._ohm)])) self._send_midi(tuple([176, 31, int(self._ohm)])) def deassign_matrix(self): with self.component_guard(): self._host._set_knobs(None) self._host._set_button_matrix(None) self._host.set_enabled(False) self._modNum.set_enabled(False) self.assign_alternate_mappings(0) self._scale_mode.set_mode_buttons(None) self._scale_mode.set_enabled(False) self._octave_mode.set_mode_buttons(None) self._octave_mode.set_enabled(False) self._session_zoom.set_enabled(False) self._session_zoom.set_nav_buttons(None, None, None, None) self._session.set_track_bank_buttons(None, None) self._session.set_scene_bank_buttons(None, None) self._transport.set_enabled(False) for column in range(4): self._mixer.track_eq(column)._gain_controls = None self._mixer.track_eq(column).set_enabled(False) for column in range(7): self._mixer.channel_strip(column).set_crossfade_toggle(None) self._mixer.channel_strip(column).set_mute_button(None) self._mixer.channel_strip(column).set_solo_button(None) self._mixer.channel_strip(column).set_arm_button(None) self._mixer.channel_strip(column).set_send_controls(None) self._mixer.channel_strip(column).set_pan_control(None) self._mixer.track_eq(column).set_enabled(False) for row in range(5): self._scene[row].clip_slot(column).set_launch_button(None) """for column in range(8): self._button[column]._on_value = SELECT_COLOR[self._rgb] for row in range(8): self._grid[column][row].set_enabled(True) self._grid[column][row].release_parameter() self._grid[column][row].use_default_message() self._grid[column][row].set_on_off_values(127, 0) self._grid[column][row].send_value(0, True)""" for column in range(8): self._button[column]._on_value = SELECT_COLOR[self._rgb] for row in range(8): #self._grid[column][row].set_channel(0) self._grid[column][row].release_parameter() self._grid[column][row].use_default_message() self._grid[column][row].set_enabled(True) self._grid[column][row].send_value(0, True) self._grid[column][row]._on_value = 127 self._grid[column][row]._off_value = 0 self._grid[column][row].force_next_send() for index in range(6): self._menu[index]._on_value = 127 self._menu[index]._off_value = 0 for index in range(16): self._dial[index].use_default_message() self._dial[index].release_parameter() self._device.set_parameter_controls(None) self._device.set_enabled(False) self._device_navigator.set_enabled(False) self._mixer.update() self._matrix.reset() self.request_rebuild_midi_map() def _assign_page_constants(self): with self.component_guard(): self._session_zoom.set_zoom_button(self._grid[7][7]) self._session_zoom.set_button_matrix(self._matrix) for column in range(7): self._mixer.channel_strip(column).set_select_button(self._button[column]) self._mixer.channel_strip(column).set_volume_control(self._fader[column]) self._mixer.master_strip().set_volume_control(self._fader[7]) self._mixer.master_strip().set_select_button(self._button[7]) self._mixer.set_prehear_volume_control(self._dial[15]) self._transport.set_play_button(self._menu[0]) self._menu[0].send_value(PLAY_COLOR[self._rgb], True) self._menu[0]._on_value = PLAY_COLOR[self._rgb] self._transport.set_stop_button(self._menu[1]) self._menu[1]._off_value = STOP_COLOR[self._rgb] self._menu[1]._on_value = STOP_COLOR[self._rgb] self._menu[1].send_value(STOP_COLOR[self._rgb], True) self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[4]) def assign_page_0(self): with self.component_guard(): self._backlight_type = 'static' self._session_zoom.set_enabled(True) for column in range(7): self._grid[column][5]._on_value = MUTE_COLOR[self._rgb] self._mixer.channel_strip(column).set_mute_button(self._grid[column][5]) self._grid[column][6]._on_value = SOLO_COLOR[self._rgb] self._mixer.channel_strip(column).set_solo_button(self._grid[column][6]) self._grid[column][7]._on_value = ARM_COLOR[self._rgb] self._mixer.channel_strip(column).set_arm_button(self._grid[column][7]) self._mixer.channel_strip(column).set_pan_control(self._dial[column + 8]) for row in range(5): self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row]) for column in range(4): self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column], self._dial[column + 4]])) for index in range(5): self._grid[7][index]._off_value = SCENE_LAUNCH_COLOR[self._rgb] self._scene[index].set_launch_button(self._grid[7][index]) self._grid[7][index].set_force_next_value() self._grid[7][index].turn_off() for index in range(4): self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb] self._session.set_track_bank_buttons(self._menu[4], self._menu[3]) self._session.set_scene_bank_buttons(self._menu[5], self._menu[2]) self._menu[0]._on_value = PLAY_COLOR[self._rgb] self._menu[1]._off_value = STOP_COLOR[self._rgb] self._menu[1]._on_value = STOP_COLOR[self._rgb] self._transport.set_enabled(True) #self._mixer.update_all() self.request_rebuild_midi_map() #self.log_message('assign_page_0') def assign_page_1(self): with self.component_guard(): self._backlight_type = 'pulse' self._session_zoom.set_enabled(False) for column in range(4): for row in range(4): self._grid[column][row].send_value(DRUM_COLOR[self._rgb], True) self._grid[column + 4][row].send_value(BASS_COLOR[self._rgb], True) self._grid[column][row].set_enabled(False) self._grid[column][row]._msg_channel = PAGE1_DRUM_CHANNEL self._grid[column][row].set_identifier(PAGE1_DRUM_MAP[column][row]) self._grid[column + 4][row].set_enabled(False) self._grid[column + 4][row]._msg_channel = PAGE1_BASS_CHANNEL self._grid[column + 4][row].set_identifier(PAGE1_BASS_MAP[column][row]) scale_mode_buttons = [] for column in range(8): for row in range(3): self._grid[column][row + 4].set_enabled(False) self._grid[column][row + 4].send_value(KEYS_COLOR[self._rgb], True) self._grid[column][row + 4]._msg_channel = PAGE1_KEYS_CHANNEL self._grid[column][row + 4].set_identifier(int(PAGE1_KEYS_MAP[column][row]) + int(PAGE1_MODES_MAP[self._scale_mode._mode_index][column]) + int(self._octave_mode._mode_index * 12)) for row in range(1): scale_mode_buttons.append(self._grid[column][7]) self._scale_mode.set_mode_buttons(tuple(scale_mode_buttons)) self._scale_mode.set_enabled(True) self._octave_mode.set_mode_buttons(tuple([self._menu[5], self._menu[2]])) self._octave_mode.set_enabled(True) for column in range(7): self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column + 8]])) self._mixer.channel_strip(column).set_arm_button(self._button[column]) self._device.set_enabled(True) device_param_controls = [] for index in range(8): device_param_controls.append(self._dial[index]) self._device.set_parameter_controls(tuple(device_param_controls)) self._menu[0]._on_value = PLAY_COLOR[self._rgb] for index in range(4): self._menu[2 + index]._on_value = DEVICE_NAV_COLOR[self._rgb] self._device_navigator.set_enabled(True) self._menu[0]._on_value = PLAY_COLOR[self._rgb] self._menu[1]._off_value = STOP_COLOR[self._rgb] self._menu[1]._on_value = STOP_COLOR[self._rgb] self._transport.set_enabled(True) self.request_rebuild_midi_map() def assign_page_2(self): with self.component_guard(): self._backlight_type = 'up' self._session_zoom.set_enabled(True) for column in range(7): self._grid[column][5]._on_value = MUTE_COLOR[self._rgb] self._mixer.channel_strip(column).set_mute_button(self._grid[column][5]) self._grid[column][6]._on_value = CROSSFADE_ASSIGN_COLOR[self._rgb] self._mixer.channel_strip(column).set_crossfade_toggle(self._grid[column][6]) self._grid[column][7]._msg_channel = 2 self._grid[column][7].set_identifier(column) self._grid[column][7].reset() self._grid[column][7].set_enabled(False) self._grid[column][7].send_value(4, True) for row in range(5): self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row]) for row in range(5): self._grid[7][row]._off_value = SCENE_LAUNCH_COLOR[self._rgb] self._scene[row].set_launch_button(self._grid[7][row]) self._grid[7][row].set_force_next_value() self._grid[7][row].turn_off() for column in range(4): self._mixer.track_eq(column).set_gain_controls(tuple([self._dial[column + 8], self._dial[column + 4], self._dial[column]])) self._mixer.track_eq(column).set_enabled(True) for column in range(3): self._mixer.channel_strip(column + 4).set_pan_control(self._dial[column + 12]) for index in range(4): self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb] self._session.set_track_bank_buttons(self._menu[4], self._menu[3]) self._session.set_scene_bank_buttons(self._menu[5], self._menu[2]) self._set_tempo_buttons([self._grid[7][5], self._grid[7][6]]) self._menu[0]._on_value = PLAY_COLOR[self._rgb] self._menu[1]._off_value = STOP_COLOR[self._rgb] self._menu[1]._on_value = STOP_COLOR[self._rgb] self._transport.set_enabled(True) #self._mixer.update() self.request_rebuild_midi_map() def assign_mod(self): with self.component_guard(): self.deassign_matrix() self._host.set_enabled(True) self._modNum.set_enabled(True) self._host._set_dial_matrix(self._dial_matrix, self._dial_button_matrix) self._host._set_button_matrix(self._mod_matrix) self._host._set_key_buttons(tuple(self._key)) if not self._host._active_client.is_connected(): self.assign_alternate_mappings(self._modNum._mode_index + 1) def modNum_update(self): if self._modNum._is_enabled == True: self.assign_alternate_mappings(0) self._host._select_client(int(self._modNum._mode_index)) self._host.display_active_client() if not self._host._active_client.is_connected(): self.assign_alternate_mappings(self._modNum._mode_index + 1) for button in self._modNum._modes_buttons: if self._modNum._mode_index == self._modNum._modes_buttons.index(button): button.send_value(1) else: button.send_value(self._client[self._modNum._modes_buttons.index(button)]._mod_color) def assign_alternate_mappings(self, chan): for column in range(8): for row in range(8): self._grid[column][row].set_channel(chan) for knob in self._encoder: knob.set_channel(chan) knob.set_enabled(chan is 0) self.request_rebuild_midi_map() def display_mod_colors(self): pass def _update_selected_device(self): if self._device_selection_follows_track_selection is True: track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self.set_appointed_device(device_to_select) self.request_rebuild_midi_map() def handle_sysex(self, midi_bytes): if len(midi_bytes) > 10: if midi_bytes[:11] == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 7]): self.log_message(str('>>>color detected')) self._rgb = 0 elif midi_bytes[:11] == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 2]): self.log_message(str('>>>mono detected')) self._rgb = 1 self._assign_session_colors() def to_encoder(self, num, val): rv = int(val * 127) self._device._parameter_controls[num].receive_value(rv) p = self._device._parameter_controls[num]._parameter_to_map_to newval = val * (p.max - p.min) + p.min p.value = newval def set_local_ring_control(self, val = 1): self._local_ring_control = val != 0 def set_absolute_mode(self, val = 1): self._absolute_mode = val != 0 def send_ring_leds(self): """if self._host._is_enabled == True: leds = [240, 0, 1, 97, 8, 31] for index in range(12): wheel = self._encoder[index] bytes = wheel._get_ring() leds.append(bytes[0]) leds.append(int(bytes[1]) + int(bytes[2])) leds.append(247) self._send_midi(tuple(leds))""" pass def _set_tempo_buttons(self, buttons): if self._tempo_buttons != None: self._tempo_buttons[0].remove_value_listener(self._tempo_value) self._tempo_buttons[1].remove_value_listener(self._tempo_value) self._tempo_buttons = buttons if buttons != None: for button in buttons: assert isinstance(button, FlashingButtonElement) self._tempo_buttons[0].set_on_off_values(4, 0) self._tempo_buttons[0].add_value_listener(self._tempo_value, True) self._tempo_buttons[1].set_on_off_values(4, 0) self._tempo_buttons[1].add_value_listener(self._tempo_value, True) self._tempo_buttons[0].turn_on() self._tempo_buttons[1].turn_on() def _tempo_value(self, value, sender): if value > 0 and self._tempo_buttons.index(sender) == 0: self.song().tempo = round(min(self.song().tempo + 1, 999)) elif value > 0 and self._tempo_buttons.index(sender) == 1: self.song().tempo = round(max(self.song().tempo - 1, 20)) def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 12 if not display_string: return ' ' * NUM_CHARS_PER_DISPLAY_STRIP if len(display_string.strip()) > NUM_CHARS_PER_DISPLAY_STRIP - 1 and display_string.endswith('dB') and display_string.find('.') != -1: display_string = display_string[:-2] if len(display_string) > NUM_CHARS_PER_DISPLAY_STRIP - 1: for um in [' ', 'i', 'o', 'u', 'e', 'a']: while len(display_string) > NUM_CHARS_PER_DISPLAY_STRIP - 1 and display_string.rfind(um, 1) != -1: um_pos = display_string.rfind(um, 1) display_string = display_string[:um_pos] + display_string[um_pos + 1:] else: display_string = display_string.center(NUM_CHARS_PER_DISPLAY_STRIP - 1) ret = u'' for i in range(NUM_CHARS_PER_DISPLAY_STRIP - 1): if ord(display_string[i]) > 127 or ord(display_string[i]) < 0: ret += ' ' else: ret += display_string[i] ret += ' ' return ret def notification_to_bridge(self, name, value, sender): if isinstance(sender, tuple([MonoEncoderElement2, CodecEncoderElement])): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched += 1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip() is True: clip_names.append(clip_slot._clip_slot) return clip_slot._clip_slot return clip_names def shift_update(self): pass
class Lemaur256(ControlSurface): __module__ = __name__ __doc__ = " Lemaur256 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("--------------= Lemaur256 log opened =--------------") self._suggested_input_port = 'None' self._suggested_output_port = 'None' self.set_suppress_rebuild_requests(True) self._monomod_version = 'b994' self._host_name = 'AumPad' self._color_type = 'AumPad' self.connected = 0 self.hosts = [] self._osc_registry = {} self._bright = True self._rgb = 0 self._timer = 0 self.flash_status = 1 self._setup_monobridge() self._setup_controls() self._setup_monomod() self._setup_touchosc() self._host2._set_shift_button(self._bank_button[0]) self._host2._set_alt_button(self._bank_button[1]) self._host2._set_button_matrix(self._monomod256) self._host2._set_key_buttons(self._key_button) self._host2.set_enabled(True) self.set_suppress_rebuild_requests(False) self.reset() self.refresh_state() self.show_message('Aum256 Control Surface Loaded') """script initialization methods""" def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_controls(self): is_momentary = True self._monomod256 = ButtonMatrixElement() self._monomod256.name = 'Monomod256' self._square = [None for index in range(16)] for column in range(16): self._square[column] = [None for index in range(16)] for row in range(16): self._square[column][row] = OSCFlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, int(column/8) + 1, row + ((column%8) * 16), '256Grid_' + str(column) + '_' + str(row), '/Grid_'+str(column)+'_'+str(row), '/Grid/set '+str(column)+' '+str(row), None, self) for row in range(16): button_row = [] for column in range(16): button_row.append(self._square[column][row]) self._monomod256.add_row(tuple(button_row)) #self._bank_buttons = ButtonMatrixElement() self._key_buttons = ButtonMatrixElement() self._bank_button = [None for index in range(2)] for index in range(2): self._bank_button[index] = OSCFlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, index, '256Grid_Bank_' + str(index), '/Shift_'+str(index), '/Shift/set '+str(index), None, self) #button_row = [] #for index in range(2): # button_row.append(self._bank_button[index]) #self._bank_buttons.add_row(tuple(button_row)) button_row = [] self._key_button = [None for index in range(8)] for index in range(8): self._key_button[index] = OSCFlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, index+8, '256Grid_Key_' + str(index), '/Keys_'+str(index), '/Keys/set '+str(index), None, self) for index in range(8): button_row.append(self._key_button[index]) self._key_buttons.add_row(tuple(button_row)) def _setup_monomod(self): self._host2 = SpecialMonomodComponent(self) self._host2.name = '256_Monomod_Host' self.hosts = [self._host2] def _setup_touchosc(self): self._osc_registry = {} self._osc_registry['/ping'] = self._monobridge.ping self._osc_registry['/1'] = self._monobridge.page1 for control in self.controls: if hasattr(control, 'osc'): self._osc_registry[control.osc] = control.set_value #if hasattr(control, 'osc_alt'): # self._osc_registry[control.osc_alt] = control.set_value """called on timer""" def update_display(self): ControlSurface.update_display(self) self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if(self.flash_status > 0): for control in self.controls: if isinstance(control, OSCFlashingButtonElement): control.flash(self._timer) """m4l bridge""" def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 9 if (not display_string): #return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) return ('`_') if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return '`' + ret.replace(' ', '_') def notification_to_bridge(self, name, value, sender): if(isinstance(sender, MonoEncoderElement2)): #self.log_message(str(name) + str(value) + str(sender.num)) self._monobridge._send('lcd_name', sender.name, self.generate_strip_string(str(name))) self._monobridge._send('lcd_value', sender.name, self.generate_strip_string(str(value))) def clip_name(self, sender, name): self._monobridge._send_osc(sender.osc_name, self.generate_strip_string(str(name))) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip(): clip_names.append(clip_slot._clip_slot)##.clip.name) return clip_slot._clip_slot ##self.log_message(str(clip_slot._clip_slot.clip.name)) return clip_names """midi functionality""" def max_to_midi(self, message): #takes a 'tosymbol' list from Max, such as "240 126 0 6 1 247" msg_str = str(message) #gets rid of the quotation marks which 'tosymbol' has added midi_msg = tuple(int(s) for s in msg_str.split()) #converts to a tuple self._send_midi(midi_msg) #sends to controller def max_from_midi(self, message): #takes a 'tosymbol' list from Max, such as "240 126 0 6 1 247" msg_str = str(message) #gets rid of the quotation marks which 'tosymbol' has added midi_msg = tuple(int(s) for s in msg_str.split()) #converts to a tuple self.receive_external_midi(midi_msg) #sends to controller def to_encoder(self, num, val): rv=int(val*127) self._device._parameter_controls[num].receive_value(rv) p = self._device._parameter_controls[num]._parameter_to_map_to newval = (val * (p.max - p.min)) + p.min p.value = newval def receive_external_midi(self, midi_bytes): #self.log_message('receive_external_midi' + str(midi_bytes)) assert (midi_bytes != None) assert isinstance(midi_bytes, tuple) self.set_suppress_rebuild_requests(True) if (len(midi_bytes) is 3): msg_type = (midi_bytes[0] & 240) forwarding_key = [midi_bytes[0]] self.log_message(str(self._forwarding_registry)) if (msg_type is not MIDI_PB_TYPE): forwarding_key.append(midi_bytes[1]) recipient = self._forwarding_registry[tuple(forwarding_key)] self.log_message('receive_midi recipient ' + str(recipient)) if (recipient != None): recipient.receive_value(midi_bytes[2]) else: self.handle_sysex(midi_bytes) self.set_suppress_rebuild_requests(False) """general functionality""" def disconnect(self): """clean things up on disconnect""" #self._disconnect_notifier.set_mode(0) self.log_message("--------------= Lemaur256 log closed =--------------") #Create entry in log file ControlSurface.disconnect(self) return None def allow_updates(self, allow_updates): for component in self.components: component.set_allow_update(int(allow_updates!=0)) def _set_brightness(self, value): #self._bright = (value != 0) #for control in self.controls: # if isinstance(control, OSCFlashingButtonElement): # self._monobridge._send_osc(control.osc_alt, int(self._bright), True) pass def reset(self): for control in self.controls: control.reset()
class MonoWing(ControlSurface): def __init__(self, *a, **k): super(MonoWing, self).__init__(*a, **k) self._monomod_version = 'b995' self._codec_version = 'b996' self._cntrlr_version = 'b996' self._cntrlr = None self._host_name = 'MonoWing' self._color_type = 'OhmRGB' self.hosts = [] self._timer = 0 self.flash_status = 0 self._touched = 0 self._last_main_mode = 'looper' with self.component_guard(): self._setup_monobridge() self._setup_controls() self._setup_looper() self._setup_launcher() self._setup_device_control() self._setup_modes() self.schedule_message(1, self._open_log) #self._loop_selector.set_enabled(True) """script initialization methods""" def _open_log(self): self.log_message("<<<<<<<<<<<<<<<<<<<<= " + str(self._host_name) + " " + str(self._monomod_version) + " log opened =>>>>>>>>>>>>>>>>>>>") self.show_message(str(self._host_name) + ' Control Surface Loaded') def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_controls(self): self._pedal = [None for index in range(12)] for index in range(9): self._pedal[index] = DoublePressElement(MonoButtonElement(True, MIDI_NOTE_TYPE, 0, PEDAL_DEFS[index], 'Pedal_'+str(index), self)) #is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self self._pedal[index].name = 'Pedal_'+str(index) self._pedal[index]._report = False self._pedal[9] = LoopPedalExpressionElement(self, MIDI_CC_TYPE, 0, 3, Live.MidiMap.MapMode.absolute) self._pedal[9].name = 'Pedal_'+str(9) self._pedal[9]._report = False self._pedal[10] = LoopPedalExpressionElement(self, MIDI_CC_TYPE, 0, 1, Live.MidiMap.MapMode.absolute) self._pedal[10].name = 'Pedal_'+str(10) self._pedal[10]._report = False self._pedal[11] = LoopPedalExpressionElement(self, MIDI_CC_TYPE, 0, 2, Live.MidiMap.MapMode.absolute) self._pedal[11].name = 'Pedal_'+str(11) self._pedal[11]._report = False self._leds = [self._pedal[6], self._pedal[5], self._pedal[4], self._pedal[3]] self._side_buttons = [MonoButtonElement(True, MIDI_NOTE_TYPE, 0, SIDE_DEFS[index], 'Side_Button_'+str(index), self) for index in range(4)] self._select_buttons = ButtonMatrixElement() self._select_buttons.name = 'SelectMatrix' self._select_buttons.add_row([self._pedal[6], self._pedal[5], self._pedal[4], self._pedal[3]]) self._doublepress_select_buttons = ButtonMatrixElement() self._doublepress_select_buttons.name = 'DoublepressSelectMatrix' self._doublepress_select_buttons.add_row([self._pedal[6].double_press, self._pedal[5].double_press, self._pedal[4].double_press, self._pedal[3].double_press]) self._record_button = self._pedal[1] self._mute_button = self._pedal[2] self._overdub_button = self._pedal[0] self._clear_button = self._pedal[7] self._reverse_button = self._pedal[8] self._record_button.turn_off() self._mute_button.turn_off() self._overdub_button.turn_off() self._clear_button.turn_off() self._reverse_button.turn_off() def _setup_looper(self): self._looper = MonolooperComponent(self._leds, self) self._looper.layer = Layer(select_buttons = self._select_buttons, doublepress_select_buttons = self._doublepress_select_buttons, overdub_button = self._pedal[2], record_button = self._pedal[1], mute_button = self._pedal[0], clear_button = self._pedal[7], reverse_button = self._pedal[8], expression_pedal = self._pedal[9],) def _setup_launcher(self): self._launcher = LauncherComponent(self._leds, self) self._launcher.set_enabled(False) self._launcher.layer = Layer(select_buttons = self._select_buttons, doublepress_select_buttons = self._doublepress_select_buttons, fire1_button = self._pedal[2], fire2_button = self._pedal[1], fire3_button = self._pedal[0], fire4_button = self._pedal[8], expression_pedal = self._pedal[9]) def _setup_device_control(self): self._device_control = DeviceControlComponent(self._leds, self) self._device_control.set_enabled(False) self._device_control.layer = Layer(select_buttons = self._select_buttons, doublepress_select_buttons = self._doublepress_select_buttons, toggle1_button = self._pedal[2], toggle2_button = self._pedal[1], toggle3_button = self._pedal[0], toggle4_button = self._pedal[8], expression_pedal = self._pedal[9], expression2 = self._pedal[10], expression3 = self._pedal[11]) def _setup_modes(self): self._button_modes = ModesComponent(name='Button_Modes') self._button_modes.add_mode('launcher', self._launcher) self._button_modes.add_mode('looper', self._looper) self._button_modes.add_mode('device', self._device_control) self._button_modes.selected_mode = 'looper' self._button_modes.layer = Layer(looper_button = self._side_buttons[0], launcher_button = self._side_buttons[1], device_button = self._side_buttons[2]) self._button_modes.set_enabled(True) def receive_led(self, button, value): #self.log_message('receive led: ' + str(index) + ' ' + str(value)) pass def toggle_mode(self): self._button_modes.selected_mode = 'launcher' if self._button_modes.selected_mode is 'looper' else 'looper' self._last_main_mode = self._button_modes.selected_mode #self.log_message('toggle mode to: ' + str(self._button_modes.selected_mode)) def toggle_device_control(self, x): self._button_modes.selected_mode = 'device' if not self._button_modes.selected_mode is 'device' else self._last_main_mode if self._button_modes.selected_mode is 'device': self._device_control.set_bank(x) """called on timer""" def update_display(self): super(MonoWing, self).update_display() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if(self.flash_status > 0): for control in self.controls: if isinstance(control, MonoButtonElement): control.flash(self._timer)
class MidiFighterTwister(ControlSurface): __module__ = __name__ __doc__ = "MidiFighterTwister class" def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.__c_instance = c_instance self.show_message('Script initiated') self.init() def init(self): # initialize listeners, caches and colors self.flush_all() self.mf_disable_bank_buttons() self.mf_init_page_config() self.mf_init_light_pages() # Start listeners to call dispatcher self.song().view.add_detail_clip_listener( self.dispatch_detail_clip_listener) self.song().add_current_song_time_listener( self.dispatch_current_song_time_listener) self.song().view.add_selected_track_listener( self.dispatch_selected_track_listener) self.device_listener_wrapper() # Initialize the sequencer buttons self.sequencer_init_buttons() self.sequencer_init_rotaries() self.init_clip_page() self.init_pad_page() self.init_device_params() def flush_all(self): for poti in range(64): for channel in range(4): self._send_midi((175 + channel, poti, 0)) def mf_init_page_config(self): # Initialize configuration parameters # Sequencer configuration self.sequencer_page_default_color = 1 self.sequencer_current_page_color_index = self.sequencer_page_default_color self.sequencer_base_default_note = 36 self.sequencer_current_selected_note = self.sequencer_base_default_note self.sequencer_clip_position_16th = None # Midi Channels self.rotary_midi_channel = 175 + 1 self.ring_midi_channel = 175 + 1 self.switch_midi_channel = 175 + 2 self.light_midi_channel = 175 + 2 # Pages cc map self.clip_page_cc = range(0, 16) self.sequencer_page_cc = range(16, 32) self.note_page_cc = range(32, 48) self.control_page_cc = range(48, 64) # Pages init color self.clip_page_colors = [1] * 16 self.sequencer_page_colors = [self.sequencer_page_default_color] * 16 self.note_page_colors = range(1, 127, 16) * 2 #self.note_page_colors = [0] * 16 self.control_page_colors = [1] * 16 # Status cache for sequencer self.switch_encoder_status_cache = [False] * 64 # List to store ButtonElements in self.switch_encoder_buttons = [False] * 64 # Status cache for rotaries self.rotary_encoder_potis = [False] * 64 def mf_init_light_pages(self): sequencer_page_map = zip(self.sequencer_page_cc, self.sequencer_page_colors) for light_encoder_cc, light_color_cc in sequencer_page_map: self._mf_set_light(light_encoder_cc, light_color_cc, False) note_page_map = zip(self.note_page_cc, self.note_page_colors) for light_encoder_cc, light_color_cc in note_page_map: self._mf_set_light(light_encoder_cc, light_color_cc, False) def _mf_set_light(self, light_encoder_cc, light_color_cc, status): # Sets color on midi channel 2 (177) end updates status cache # for sequencer to remember statuses self._send_midi((self.light_midi_channel, light_encoder_cc, light_color_cc)) self.switch_encoder_status_cache[light_encoder_cc] = status def mf_disable_bank_buttons(self): # Workaround for not sending values to track when pressing bank buttons self.padm0 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 0) self.padm1 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 1) self.padm2 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 2) self.padm3 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 3) self.padm0.add_value_listener(self.bank_buttons_dummy, identify_sender=True) self.padm1.add_value_listener(self.bank_buttons_dummy, identify_sender=True) self.padm2.add_value_listener(self.bank_buttons_dummy, identify_sender=True) self.padm3.add_value_listener(self.bank_buttons_dummy, identify_sender=True) def bank_buttons_dummy(self): pass def dispatch_detail_clip_listener(self): self.current_clip = self.song().view.highlighted_clip_slot.clip self.init_sequencer() try: if self.current_clip.is_midi_clip and not self.current_clip.notes_has_listener: # Update leds when notes are added or removed self.current_clip.add_notes_listener( self._sequencer_update_notes_to_light) self.init_sequencer() else: self.sequencer_reset_colors() except AttributeError: pass def dispatch_current_song_time_listener(self): self.sequencer_light_follows_beat() def dispatch_selected_track_listener(self): self.device_auto_select() self.device_listener_wrapper() def device_listener_wrapper(self): selected_track = self.song().view.selected_track if not selected_track.devices_has_listener(self.device_auto_select): self.song().view.selected_track.add_devices_listener( self.device_auto_select) # Sequencer def init_sequencer(self): self.sequencer_current_selected_note = self.sequencer_base_default_note self.sequencer_current_page_color_index = self.sequencer_page_default_color self._sequencer_update_notes_to_light() def sequencer_init_buttons(self): for switch_encoder_cc in self.sequencer_page_cc: self.switch_encoder_buttons[switch_encoder_cc] = ButtonElement( IS_MOMENTARY, MIDI_CC_TYPE, 1, switch_encoder_cc) self.switch_encoder_buttons[switch_encoder_cc].add_value_listener( self.sequencer_button_press, identify_sender=True) self.padl14 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 14) self.padr17 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 17) self.padl16 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 16) self.padr19 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 19) self.padl14.add_value_listener(self.sequencer_side_button_press, identify_sender=True) self.padr17.add_value_listener(self.sequencer_side_button_press, identify_sender=True) self.padl16.add_value_listener(self.sequencer_side_button_press, identify_sender=True) self.padr19.add_value_listener(self.sequencer_side_button_press, identify_sender=True) def sequencer_init_rotaries(self): for rotary_encoder_cc in self.sequencer_page_cc: self.rotary_encoder_potis[rotary_encoder_cc] = EncoderElement( MIDI_CC_TYPE, 0, rotary_encoder_cc, Live.MidiMap.MapMode.absolute) self.rotary_encoder_potis[rotary_encoder_cc].add_value_listener(self.sequencer_rotary_change, identify_sender=True) def sequencer_rotary_change(self, value, sender): try: self.current_clip except AttributeError: return False if self.current_clip.is_midi_clip: cc_value = sender._msg_identifier if value > 0: if not self.switch_encoder_status_cache[cc_value]: self._send_midi((self.light_midi_channel, cc_value, self.sequencer_current_light_on_color)) self._send_midi(( self.ring_midi_channel, cc_value, 100)) self.switch_encoder_status_cache[cc_value] = True self.current_clip.set_notes(((self.sequencer_current_selected_note, cc_value % 16 * 0.25, 0.25, value, False),)) elif value == 0: self._send_midi((self.light_midi_channel, cc_value, self.sequencer_current_page_color)) self.current_clip.remove_notes( cc_value % 16 * 0.25, self.sequencer_current_selected_note, 0.25, 1) self.switch_encoder_status_cache[cc_value] = False def sequencer_button_press(self, value, sender): try: self.current_clip except AttributeError: return False if self.current_clip.is_midi_clip: cc_value = sender._msg_identifier if value > 0: if not self.switch_encoder_status_cache[cc_value]: self._send_midi((self.light_midi_channel, cc_value, self.sequencer_current_light_on_color)) self.current_clip.set_notes((( self.sequencer_current_selected_note, cc_value % 16 * 0.25, 0.25, 100, False),)) self.switch_encoder_status_cache[cc_value] = True self._send_midi((self.ring_midi_channel, cc_value, 100)) else: self._send_midi((self.light_midi_channel, cc_value, self.sequencer_current_page_color)) self._send_midi((self.ring_midi_channel, cc_value, 0)) self.current_clip.remove_notes( cc_value % 16 * 0.25, self.sequencer_current_selected_note, 0.25, 1) self.switch_encoder_status_cache[cc_value] = False def sequencer_side_button_press(self, value, sender): try: cc_value = sender._msg_identifier if value > 0: # Note/clolor up/down if cc_value == 14 and self.sequencer_current_selected_note > 0: self.sequencer_current_selected_note = self.sequencer_current_selected_note - 1 self.sequencer_current_page_color_index = self.sequencer_current_page_color_index - 16 self._sequencer_update_notes_to_light() self.sequencer_clip_position_16th = None self.show_message("Selected Midi Note: "+str(self.sequencer_current_selected_note)) if cc_value == 17 and self.sequencer_current_selected_note < 127: self.sequencer_current_selected_note = self.sequencer_current_selected_note + 1 self.sequencer_current_page_color_index = self.sequencer_current_page_color_index + 16 self._sequencer_update_notes_to_light() self.sequencer_clip_position_16th = None self.show_message("Selected Midi Note: "+str(self.sequencer_current_selected_note)) # New/duplicate clip if cc_value == 16 and self.sequencer_current_selected_note > 0: self.duplicate_clip() if cc_value == 19 and self.sequencer_current_selected_note > 0: self.session_record() except AttributeError: pass def sequencer_light_follows_beat(self): try: if self.current_clip.is_midi_clip: if self.sequencer_clip_position_16th == None: self.sequencer_clip_position_16th = int(self.current_clip.playing_position / 0.25) if self.switch_encoder_status_cache[self.sequencer_page_cc[self.sequencer_clip_position_16th]]: self._send_midi((177, self.sequencer_page_cc[self.sequencer_clip_position_16th], self.sequencer_current_light_on_color)) else: self._send_midi((177, self.sequencer_page_cc[self.sequencer_clip_position_16th], self.sequencer_current_page_color)) elif self.sequencer_clip_position_16th != int(self.current_clip.playing_position/0.25): if self.switch_encoder_status_cache[self.sequencer_page_cc[self.sequencer_clip_position_16th]]: self._send_midi((177, self.sequencer_page_cc[self.sequencer_clip_position_16th], self.sequencer_current_light_on_color)) else: self._send_midi((177, self.sequencer_page_cc[self.sequencer_clip_position_16th], self.sequencer_current_page_color)) self.sequencer_clip_position_16th = int(self.current_clip.playing_position/0.25) self._send_midi((177, self.sequencer_page_cc[self.sequencer_clip_position_16th], self.sequencer_current_light_beat_color)) except IndexError: pass @property def sequencer_current_light_on_color(self): # light on color to be relative to page color return self.sequencer_current_page_color + 32 % 128 @property def sequencer_current_light_beat_color(self): # light on color to be relative to page color return self.sequencer_current_page_color + 64 % 128 @property def sequencer_current_page_color(self): return self.sequencer_current_page_color_index % 128 def _sequencer_get_midi_notes(self, note): # self.current_clip.get_notes(start, self.sequencer_current_selected_note, # selection_length, hight) try: return self.current_clip.get_notes(0, note, 4, 1) except AttributeError: return [] def _sequencer_update_notes_to_light(self): self.sequencer_reset_colors() notes_for_current_selected_note = self._sequencer_get_midi_notes( self.sequencer_current_selected_note) for note in notes_for_current_selected_note: light_encoder_cc = int(note[1]*4+self.sequencer_page_cc[0]) self._send_midi((self.ring_midi_channel, light_encoder_cc, note[3])) self._mf_set_light(light_encoder_cc, self.sequencer_current_light_on_color, True) def sequencer_reset_colors(self): for light_encoder_cc in self.sequencer_page_cc: self._mf_set_light(light_encoder_cc, self.sequencer_current_page_color, False) self._send_midi((self.ring_midi_channel, light_encoder_cc, 0)) def duplicate_clip(self): self.log_message("duplicate clip") #if self._clip_slot and self._clip_slot.has_clip: # slot_name = self._clip_slot.clip.name # track = self._clip_slot.canonical_parent current_track = self.song().view.selected_track current_clip_slot = self.song().view.highlighted_clip_slot self.song().duplicate_scene(list(current_track.clip_slots).index(current_clip_slot)) #new_clip = current_track.duplicate_clip_slot( # list(current_track.clip_slots).index(current_clip_slot)+1) #self.log_message(new_clip) #selected_track = self.song().view.selected_track #selected_track.duplicate_clip_slot(selected_track) def session_record(self): self.log_message("session record") #self.song().trigger_session_record() # Clip page setion def init_clip_page(self): num_tracks = 4 num_scenes = 3 self.flash_status = 1 self.Mixer = MixerComponent(4, 3) # Volencoder self.volencoders = [None for index in range(num_tracks)] for index in range(num_tracks): self.volencoders[index] = EncoderElement( MIDI_CC_TYPE, 0, index, Live.MidiMap.MapMode.absolute) self.Mixer.channel_strip(index).set_volume_control( self.volencoders[index]) # Sendencoder for index in range(num_tracks): encoder_cc_send_1 = index + num_tracks encoder_cc_send_2 = index + num_tracks * 2 send1 = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_send_1, Live.MidiMap.MapMode.absolute) send2 = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_send_2, Live.MidiMap.MapMode.absolute) self.Mixer.channel_strip(index).set_send_controls((send1, send2)) # Panencoder for index in range(num_tracks): encoder_cc_pan = index + num_tracks * 3 pan = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_pan, Live.MidiMap.MapMode.absolute) self.Mixer.channel_strip(index).set_pan_control(pan) # Arm-/selectbuttons for index in range(num_tracks): armbutton = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, index + 12) self.Mixer.channel_strip(index).set_arm_button(armbutton) self.Mixer.channel_strip(index).set_select_button(armbutton) # Navigation buttons self.padl11 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 11) self.padr8 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 8) self.padl10 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 10) self.padr13 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 13) self.grid = [None for index in range(num_tracks * 3)] for index in range(num_tracks * 3): self.grid[index] = ButtonElement( IS_MOMENTARY, MIDI_CC_TYPE, 1, index) self.matrix = ButtonMatrixElement() for row in range(num_scenes): button_row = [] for column in range(num_tracks): button_row.append(self.grid[column+(row*4)]) self.log_message(str(column+(row*4))) self.matrix.add_row(tuple(button_row)) self.Session = SessionComponent(num_tracks, num_scenes) self.Session.name = "Session" self.Session.set_offsets(0, 0) self.Session.set_mixer(self.Mixer) self.Session._do_show_highlight() self.set_highlighting_session_component(self.Session) self.Session.set_track_bank_buttons(self.padl11, self.padr8) self.Session.set_scene_bank_buttons(self.padr13, self.padl10) self.scene = [None for index in range(num_scenes)] for row in range(num_scenes): self.scene[row] = self.Session.scene(row) self.scene[row].name = 'Scene_'+str(row) for column in range(num_tracks): clip_slot = self.scene[row].clip_slot(column) clip_slot.name = str(column)+'_Clip_Slot'+str(row) self.scene[row].clip_slot(column).set_triggered_to_play_value(35) self.scene[row].clip_slot(column).set_stopped_value(68) self.scene[row].clip_slot(column).set_started_value(45) self.scene[row].clip_slot(column).set_triggered_to_record_value(100) self.scene[row].clip_slot(column).set_recording_value(80) for column in range(num_tracks): for row in range(num_scenes): self.scene[row].clip_slot(column).set_launch_button(self.grid[column+(row*4)]) for index in range(num_tracks*num_scenes): self.grid[index].clear_send_cache() def update_display(self): # Called every 100 ms ControlSurface.update_display(self) self.refresh_state() self.Session.set_enabled(True) self.Session.update() # Sequencer hack try: for light_encoder_cc in self.sequencer_page_cc: self._send_midi((self.ring_midi_channel, light_encoder_cc, 0)) notes_for_current_selected_note = self._sequencer_get_midi_notes( self.sequencer_current_selected_note) for note in notes_for_current_selected_note: light_encoder_cc = int(note[1]*4+self.sequencer_page_cc[0]) self._send_midi((self.ring_midi_channel, light_encoder_cc, note[3])) except AttributeError: pass # Pad Section def init_pad_page(self): self.pad_device_params() PAD_TRANSLATION = ( (0, 0, 32, 1), (1, 0, 33, 1), (2, 0, 34, 1), (3, 0, 35, 1), (0, 1, 36, 1), (1, 1, 37, 1), (2, 1, 38, 1), (3, 1, 39, 1), (0, 2, 40, 1), (1, 2, 41, 1), (2, 2, 42, 1), (3, 2, 43, 1), (0, 3, 44, 1), (1, 3, 45, 1), (2, 3, 46, 1), (3, 3, 47, 1)) self.set_pad_translations(PAD_TRANSLATION) self._device_selection_follows_track_selection = True def pad_device_params(self): device_param_controls = [] for param in self.note_page_cc[:8]: self.rotary_encoder_potis[param] = EncoderElement( MIDI_CC_TYPE, 0, param, Live.MidiMap.MapMode.absolute) self.rotary_encoder_potis[param].release_parameter() self.rotary_encoder_potis[param].send_value(0, True) self.rotary_encoder_potis[param].clear_send_cache() device_param_controls.append(self.rotary_encoder_potis[param]) device = DeviceComponent() device.name = 'Device_Component pad' device.set_parameter_controls(tuple(device_param_controls)) self.set_device_component(device) #def scrolling(self): # self.application().view.scroll_view(ndir, 'Detail/DeviceChain', True) # Live.Song.Song.View.selected_track #Live.Song.Song.View.select_device()[0] # Device parameter section def init_device_params(self): device_param_controls = [] device_bank_buttons = [] for param in self.control_page_cc[:8]: self.rotary_encoder_potis[param] = EncoderElement( MIDI_CC_TYPE, 0, param, Live.MidiMap.MapMode.absolute) self.switch_encoder_buttons[param] = ButtonElement( IS_MOMENTARY, MIDI_CC_TYPE, 1, param) self.rotary_encoder_potis[param].release_parameter() self.rotary_encoder_potis[param].send_value(0, True) self.rotary_encoder_potis[param].clear_send_cache() device_param_controls.append(self.rotary_encoder_potis[param]) device_bank_buttons.append(self.switch_encoder_buttons[param]) device = DeviceComponent() device.name = 'Device_Component' device.set_parameter_controls(tuple(device_param_controls)) device.set_bank_buttons(tuple(device_bank_buttons)) device.set_on_off_button(ButtonElement( IS_MOMENTARY, MIDI_CC_TYPE, 1, 56)) self.set_device_component(device) def device_auto_select(self): # Iterates through devices within a track and assigns the first # DrumPad device to activate the individual drum's device. # Use first device in case none is a DrumPad device. selected_track = self.song().view.selected_track devices = selected_track.devices for device in devices: if device.can_have_drum_pads: self.current_drum_device = device pad_device = self.current_drum_device.view.selected_chain.devices[0] self.song().view.select_device(pad_device) if not self.current_drum_device.view.selected_drum_pad_has_listener( self.device_update_current_note): self.current_drum_device.view.add_selected_drum_pad_listener( self.device_update_current_note) break else: self.song().view.select_device(devices[0]) def device_update_current_note(self): current_note = self.current_drum_device.view.selected_drum_pad.note self.sequencer_current_selected_note = current_note # Update light of active pad #self._send_midi((self.light_midi_channel, light_encoder_cc, 63)) try: self.current_clip = self.song().view.highlighted_clip_slot.clip self.current_clip.is_midi_clip self._sequencer_update_notes_to_light() except AttributeError: pass
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._monomod_version = 'b995' self._host_name = 'LaunchMod' self._color_type = 'Launchpad' self.hosts = [] self._timer = 0 self._suppress_send_midi = True self._suppress_session_highlight = True self._suppress_highlight = False is_momentary = True self._suggested_input_port = 'Launchpad' self._suggested_output_port = 'Launchpad' self._control_is_with_automap = False self._user_byte_write_button = ButtonElement( is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = 'User_Byte_Button' self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener( self._user_byte_value) self._wrote_user_byte = False self._challenge = Live.Application.get_random_int( 0, 400000000) & 2139062143 matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' for row in range(8): button_row = [ ConfigurableButtonElement( is_momentary, MIDI_NOTE_TYPE, 0, ((row * 16) + column), str(column) + '_Clip_' + str(row) + '_Button', self) for column in range(8) ] matrix.add_row(tuple(button_row)) self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False) self._config_button.add_value_listener(self._config_value) top_button_names = [ 'Bank_Select_Up_Button', 'Bank_Select_Down_Button', 'Bank_Select_Left_Button', 'Bank_Select_Right_Button', 'Session_Button', 'User1_Button', 'User2_Button', 'Mixer_Button' ] side_button_names = [ 'Vol_Button', 'Pan_Button', 'SndA_Button', 'SndB_Button', 'Stop_Button', 'Trk_On_Button', 'Solo_Button', 'Arm_Button' ] top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, (104 + index), top_button_names[index], self) for index in range(8) ] side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index], side_button_names[index], self) for index in range(8) ] self._setup_monobridge() self._setup_monomod() self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self) self._selector.name = 'Main_Modes' for control in self.controls: if isinstance(control, MonoButtonElement): control.add_value_listener(self._button_value) self.set_highlighting_session_component( self._selector.session_component()) self._suppress_session_highlight = False self.log_message( "--------------= " + str(self._monomod_version) + " log opened =--------------") #Create entry in log file
def _setup_session_control(self): is_momentary = True num_tracks = 4 num_scenes = 4 global session #We want to instantiate the global session as a SessionComponent object (it was a global "None" type up until now...) session = MaschineSessionComponent(num_tracks, num_scenes) #(num_tracks, num_scenes) session.set_offsets(0, 0) #(track_offset, scene_offset) Sets the initial offset of the red box from top left matrix = ButtonMatrixElement() self._register_timer_callback(session.flash_clip_slots) """set up the session buttons""" left_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 91) right_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 93) session.set_track_bank_buttons(right_button, left_button) # Stop buttons track_stop_buttons = [ ButtonElement(is_momentary, MIDI_CC_TYPE, 4, (55 + index)) for index in range(num_tracks) ] session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 81) down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, 92) session.set_scene_bank_buttons(down_button, up_button) # (up_button, down_button) This is to move the "red box" up or down (increment track up or down, not screen up or down, so they are inversed) session.set_mixer(mixer) #Bind the mixer to the session so that they move together selected_scene = self.song().view.selected_scene #this is from the Live API all_scenes = self.song().scenes index = list(all_scenes).index(selected_scene) session.set_offsets(0, index) #(track_offset, scene_offset) scene_launch_buttons = [] for scene_index in range(4): scene = session.scene(scene_index) launch_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, (124 + scene_index)) scene.set_launch_button(launch_button) scene_launch_buttons.append(launch_button) clip_launch_notes = [ [24, 25, 26, 27], [20, 21, 22, 23], [16, 17, 18, 19], [12, 13, 14, 15], ] for scene_index in range(num_scenes): button_row = [] for track_index in range(num_tracks): clip_slot = session.scene(scene_index).clip_slot(track_index) clip_slot.set_triggered_to_record_value(127) clip_slot.set_recording_value(127) clip_slot.set_started_value(127) clip_slot.set_stopped_value(127) button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 2, clip_launch_notes[scene_index][track_index]) clip_slot.set_launch_button(button) button_row.append(button) matrix.add_row(tuple(button_row)) session_zoom = SessionZoomingComponent(session) session_zoom.set_zoom_button(self.shift_button) session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button) session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) session_zoom.set_button_matrix(matrix) session_zoom.set_stopped_value(0) session_zoom.set_selected_value(127)
def init(self): #skip init if already done. if self._init_done: return self._init_done = True # second part of the __init__ after model has been identified using its challenge response if self._mk3_rgb or self._lpx: from .SkinMK2 import make_skin self._skin = make_skin() self._side_notes = (89, 79, 69, 59, 49, 39, 29, 19) self._drum_notes = (20, 30, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126) elif self._mk2_rgb: from .SkinMK2 import make_skin self._skin = make_skin() self._side_notes = (89, 79, 69, 59, 49, 39, 29, 19) #self._drum_notes = (20, 30, 31, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126) self._drum_notes = (20, 30, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126) else: from .SkinMK1 import make_skin # @Reimport self._skin = make_skin() self._side_notes = (8, 24, 40, 56, 72, 88, 104, 120) self._drum_notes = (41, 42, 43, 44, 45, 46, 47, 57, 58, 59, 60, 61, 62, 63, 73, 74, 75, 76, 77, 78, 79, 89, 90, 91, 92, 93, 94, 95, 105, 106, 107) with self.component_guard(): is_momentary = True self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False) self._config_button.add_value_listener(self._config_value) self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = 'User_Byte_Button' self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' for row in range(8): button_row = [] for column in range(8): if self._mk2_rgb or self._mk3_rgb or self._lpx: # for mk2 buttons are assigned "top to bottom" midi_note = (81 - (10 * row)) + column else: midi_note = row * 16 + column button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, midi_note, skin = self._skin, control_surface = self) button.name = str(column) + '_Clip_' + str(row) + '_Button' button_row.append(button) matrix.add_row(tuple(button_row)) if self._mk3_rgb or self._lpx : top_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 91 + index, skin = self._skin) for index in range(8)] side_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, self._side_notes[index], skin = self._skin) for index in range(8)] else: top_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, skin = self._skin) for index in range(8)] side_buttons = [ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, self._side_notes[index], skin = self._skin) for index in range(8)] top_buttons[0].name = 'Bank_Select_Up_Button' top_buttons[1].name = 'Bank_Select_Down_Button' top_buttons[2].name = 'Bank_Select_Left_Button' top_buttons[3].name = 'Bank_Select_Right_Button' top_buttons[4].name = 'Session_Button' top_buttons[5].name = 'User1_Button' top_buttons[6].name = 'User2_Button' top_buttons[7].name = 'Mixer_Button' side_buttons[0].name = 'Vol_Button' side_buttons[1].name = 'Pan_Button' side_buttons[2].name = 'SndA_Button' side_buttons[3].name = 'SndB_Button' side_buttons[4].name = 'Stop_Button' side_buttons[5].name = 'Trk_On_Button' side_buttons[6].name = 'Solo_Button' side_buttons[7].name = 'Arm_Button' self._osd = M4LInterface() self._osd.name = "OSD" self._init_note_repeat() self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self._osd, self, self._note_repeat) self._selector.name = 'Main_Modes' self._do_combine() for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.add_value_listener(self._button_value) self._suppress_session_highlight = False self.set_highlighting_session_component(self._selector.session_component()) # due to our 2 stage init, we need to rebuild midi map self.request_rebuild_midi_map() # and request update self._selector.update() if self._lpx: self.log_message("LaunchPad95 (LPX) Loaded !") elif self._mk3_rgb: self.log_message("LaunchPad95 (mk3) Loaded !") elif self._mk2_rgb: self.log_message("LaunchPad95 (mk2) Loaded !") else: self.log_message("LaunchPad95 (classic) Loaded !")
class AumPC20(APC): __doc__ = " Script for Akai's APC20 Controller " def __init__(self, c_instance): self._shift_modes = None APC.__init__(self, c_instance) return None def disconnect(self): self._shift_modes = None APC.disconnect(self) return None def _activate_combination_mode(self, track_offset, support_devices): APC._activate_combination_mode(self, track_offset, support_devices) if support_devices: self._shift_modes.invert_assignment() def _setup_session_control(self): is_momentary = True self._shift_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81, self) self._session = APCSessionComponent(8, 5) self._session.name = 'Session_Control' self._matrix = ButtonMatrixElement() self._matrix.name = 'Button_Matrix' scene_launch_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82), self) for index in range(5) ] self._scene_launch_buttons = scene_launch_buttons track_stop_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52, self) for index in range(8) ] self._track_stop_buttons = track_stop_buttons for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_'+ str(index) + '_Launch_Button' for index in range(len(track_stop_buttons)): track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button' self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session.set_stop_track_clip_value(2) for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53), self) button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(5) clip_slot.set_started_value(1) clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) self._matrix.add_row(tuple(button_row)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = ShiftableZoomingComponent(self._session, tuple(track_stop_buttons)) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(self._matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._solo_buttons = [] for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, self) self._solo_buttons.append(solo_button) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) master_volume_control.name = 'Master_Volume_Control' prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_prehear_volume_control(prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) def _setup_custom_components(self): is_momentary = True master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) self._master_select_button = master_select_button master_select_button.name = 'Master_Select_Button' select_buttons = [] self._select_buttons = [] arm_buttons = [] sliders = [] for track in range(8): select_buttons.append(FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51, self)) self._select_buttons.append(select_buttons[track]) arm_buttons.append(ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) if track is 7: self._user3 = arm_buttons[track] sliders.append(MonoEncoderElement2(MIDI_CC_TYPE, track, 7, Live.MidiMap.MapMode.absolute, 'Slider_' + str(track), track, self)) #sliders.append(MonoEncoderElement2(MIDI_CC_TYPE, track, 7)) select_buttons[-1].name = str(track) + '_Select_Button' arm_buttons[-1].name = str(track) + '_Arm_Button' #sliders[-1].name = str(track) + '_Volume_Control' transport = TransportComponent() transport.name = 'Transport' slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) slider_modes.name = 'Slider_Modes' self._shift_modes = ShiftableSelectorComponent(tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message, self) self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button) def _product_model_id_byte(self): return 123 def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_monomod(self): self._host = MonomodComponent(self) self._host.name = 'Monomod_Host' self._host._set_nav_buttons = self._mod_set_nav_buttons(self._host) self._host._update_nav_buttons = self._mod_update_nav_buttons(self._host) self._host._set_nav_buttons = self._mod_set_nav_buttons(self._host) self.hosts = [self._host] self._monomod = ButtonMatrixElement() self._monomod.name = 'Monomod' for row in range(5): button_row = [] for column in range(8): button_row.append(self._matrix.get_button(column, row)) self._monomod.add_row(tuple(button_row)) self._monomod.add_row(tuple(self._track_stop_buttons)) self._monomod.add_row(tuple(self._select_buttons)) self._monomod.add_row(tuple(self._solo_buttons)) self._monomod_mode = MonomodModeComponent(self._monomod_mode_update, self) self._monomod_mode.name = "Monomod_Mode_Component" def _monomod_mode_update(self): if(self._monomod_mode._mode_index == 0) or (self._host._active_client == None): self.flash_status = 0 self._host.set_enabled(False) self._host._set_button_matrix(None) #self._host._set_nav_buttons(None) self._host._set_lock_button(None) self._host._set_alt_button(None) self._host._set_shift_button(None) self._host._set_nav_buttons(None) self._scene_launch_buttons[2].set_on_off_values(127, 0) self._scene_launch_buttons[3].set_on_off_values(127, 0) self._monomod.reset() self._shift_modes.set_enabled(True) #self._session.set_track_bank_buttons(self._right_button, self._left_button) #self._session.set_scene_bank_buttons(self._down_button, self._up_button) for track in range(8): self._mixer.channel_strip(track).set_select_button(self._select_buttons[track]) self._mixer.channel_strip(track).set_solo_button(self._solo_buttons[track]) #self._transport.set_nudge_buttons(self._nudge_up_button, self._nudge_down_button) self._session.set_enabled(True) self._session_zoom._is_zoomed_out = False self._session_zoom.set_enabled(True) self.request_rebuild_midi_map() self._master_select_button.turn_off() elif(self._monomod_mode._mode_index == 1): if self._shift_modes._note_mode_active is True: self._shift_modes._mode_callback(ABLETON_MODE) self._shift_modes._note_mode_active = False self._session_zoom.set_ignore_buttons(False) self._shift_modes._transport.update() self._shift_modes._on_note_mode_changed() #self._transport.set_nudge_buttons(None, None) self._shift_modes.set_enabled(False) for track in range(8): self._mixer.channel_strip(track).set_select_button(None) self._mixer.channel_strip(track).set_solo_button(None) for scene in range(5): self._scene_launch_buttons[scene].turn_off() self._session.set_enabled(False) self._session_zoom.set_enabled(False) #self._session.set_track_bank_buttons(None, None) #self._session.set_scene_bank_buttons(None, None) self.flash_status = 1 self._monomod.reset() self._host._set_button_matrix(self._monomod) #self._host._set_nav_buttons([self._up_button, self._down_button, self._left_button, self._right_button]) self._host._set_shift_button(self._shift_button) self._host._set_lock_button(self._scene_launch_buttons[0]) self._host._set_alt_button(self._scene_launch_buttons[1]) self._host._set_nav_buttons([self._scene_launch_buttons[2], self._scene_launch_buttons[3]]) self._host.set_enabled(True) self.request_rebuild_midi_map() self._master_select_button.turn_on() """m4l bridge""" def generate_strip_string(self, display_string): #self.log_message(display_string) NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return ret def notification_to_bridge(self, name, value, sender): if isinstance(sender, MonoEncoderElement2): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched +=1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip() is True: clip_names.append(clip_slot._clip_slot)##.clip.name) return clip_slot._clip_slot ##self.log_message(str(clip_slot._clip_slot.clip.name)) return clip_names def update_display(self): """ Live -> Script Aka on_timer. Called every 100 ms and should be used to update display relevant parts of the controller """ for message in self._scheduled_messages: message['Delay'] -= 1 if (message['Delay'] == 0): if (message['Parameter'] != None): message['Message'](message['Parameter']) else: message['Message']() del self._scheduled_messages[self._scheduled_messages.index(message)] for callback in self._timer_callbacks: callback() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if(self.flash_status > 0): for row in range(8): for column in range(8): button = self._monomod.get_button(column, row) if(button._flash_state > 0): button.flash(self._timer) ### Mod Overrides #### def _mod_set_nav_buttons(self, mod): def _set_nav_buttons(buttons): if mod._nav_buttons != None: mod._nav_buttons[0].remove_value_listener(mod._nav_up_value) mod._nav_buttons[1].remove_value_listener(mod._nav_down_value) mod._nav_buttons = buttons if buttons != None: assert len(buttons) == 2 for button in buttons: assert isinstance(button, FlashingButtonElement) mod._nav_buttons[0].set_on_off_values(8, 2) mod._nav_buttons[0].add_value_listener(mod._nav_up_value) mod._nav_buttons[1].set_on_off_values(8, 2) mod._nav_buttons[1].add_value_listener(mod._nav_down_value) return _set_nav_buttons def _mod_update_nav_buttons(self, mod): def _update_nav_buttons(): if mod._nav_buttons != None: if(mod._y > 0): mod._nav_buttons[0].turn_on() else: mod._nav_buttons[0].turn_off() if(mod._y < 8): mod._nav_buttons[1].turn_on() else: mod._nav_buttons[1].turn_off() return _update_nav_buttons
class AumPC20(APC20): def __init__(self, c_instance, *a, **k): self._monomod_version = 'b996' self._host_name = 'AumPC' self._color_type = 'APC' self._timer = 0 self._touched = 0 self.flash_status = False super(AumPC20, self).__init__(c_instance, *a, **k) with self.component_guard(): self._setup_mod() def disconnect(self): super(AumPC20, self).disconnect() rebuild_sys() def _create_controls(self): make_color_button = partial(make_button, skin=self._skin) self._shift_button = make_button(0, 81, name='Shift_Button', num=0, cs=self) self._matrix = ButtonMatrixElement(name='Button_Matrix') self._scene_launch_buttons_raw = [ make_color_button(0, index + 82, name='Scene_%d_Launch_Button' % index, num=index, cs=self) for index in xrange(SESSION_HEIGHT) ] self._track_stop_buttons = [ make_color_button(index, 52, name='Track_%d_Stop_Button' % index, num=index, cs=self) for index in xrange(SESSION_WIDTH) ] self._matrix_rows_raw = [] for scene_index in xrange(SESSION_HEIGHT): row = [ make_color_button( track_index, scene_index + 53, name='%d_Clip_%d_Button' % (track_index, scene_index), num=index, cs=self) for track_index in xrange(SESSION_WIDTH) ] self._matrix_rows_raw.append(row) self._matrix.add_row(row) self._selected_scene_launch_button = make_pedal_button( 64, name='Selected_Scene_Launch_Button') self._scene_launch_buttons = ButtonMatrixElement( rows=[self._scene_launch_buttons_raw]) self._solo_buttons = [ make_button(track_index, 49, name='%d_Solo_Button' % track_index, num=track_index, cs=self) for track_index in xrange(MIXER_SIZE) ] self._mute_buttons = [ make_button(track_index, 50, name='%d_Mute_Button' % track_index, num=track_index, cs=self) for track_index in xrange(MIXER_SIZE) ] self._master_volume_control = make_slider(0, 14, name='Master_Volume_Control', num=0, script=self) self._prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, MapMode.relative_two_compliment, name='Prehear_Volume_Control', num=0, script=self) self._master_select_button = make_button(0, 80, name='Master_Select_Button', num=index, cs=self) self._select_buttons = [ make_button(track_index, 51, name='%d_Select_Button' % track_index, num=track_index, cs=self) for track_index in xrange(8) ] self._arm_buttons = [ make_button(track_index, 48, name='%d_Arm_Button' % track_index, num=track_index, cs=self) for track_index in xrange(8) ] self._sliders = [ make_slider(track_index, 7, name='%d_Volume_Control' % track_index, num=track_index, script=self) for track_index in xrange(8) ] self._monomod = ButtonMatrixElement(name='Monomod') for row in self._matrix_rows_raw: self._monomod.add_row(row) self._monomod.add_row(self._track_stop_buttons) self._monomod.add_row(self._select_buttons) self._monomod.add_row(self._mute_buttons) self._setup_monobridge( ) #had to put this here b/c the original author foolishly placed assignment methods inside of creation methods...argh. def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_mod(self): self.monomodular = get_monomodular(self) self.monomodular.name = 'monomodular_switcher' self.modhandler = APCModHandler(self) self.modhandler.name = 'ModHandler' self.modhandler.layer = Layer( priority=5, grid=self._monomod, nav_up_button=self._scene_launch_buttons_raw[2], nav_down_button=self._scene_launch_buttons_raw[3], lock_button=self._scene_launch_buttons_raw[4], shiftlock_button=self._scene_launch_buttons_raw[0], alt_button=self._scene_launch_buttons_raw[1], shift_button=self._shift_button) self.modhandler.set_enabled(False) self._monomod_mode = MonomodModeComponent(self._monomod_mode_update, self) self._monomod_mode.name = "Monomod_Mode_Component" self._monomod_mode.layer = Layer( priority=5, mode_toggle=self._master_select_button) self._on_shift_value.subject = self._shift_button self._on_master_value.subject = self._master_select_button @subject_slot('value') def _on_shift_value(self, value): self._monomod_mode.set_enabled(value > 0) @subject_slot('value') def _on_master_value(self, value): if not self._shift_button.is_pressed( ) and not self.modhandler.is_enabled(): self.schedule_message(1, self._shift_modes.update) def _monomod_mode_update(self): #self.log_message('mode update: ' + str(self._monomod_mode._mode_index)) if (self._monomod_mode._mode_index == 0): self.flash_status = False self.modhandler.set_enabled(False) self._slider_modes.set_enabled(True) self._shift_modes.set_enabled(True) self._scene_launch_buttons[2].set_on_off_values(127, 0) self._scene_launch_buttons[3].set_on_off_values(127, 0) self._monomod.reset() self._shift_modes.set_enabled(True) for track in range(8): self._mixer.channel_strip(track).set_mute_button( self._mute_buttons[track]) self._session.set_enabled(True) self._session_zoom._is_zoomed_out = False self._session_zoom.set_enabled(True) self._transport.set_enabled(True) self.request_rebuild_midi_map() self.schedule_message(1, self._shift_modes.update) elif (self._monomod_mode._mode_index == 1): self._slider_modes.set_enabled(False) if self._shift_modes._note_mode_active is True: self._shift_modes._mode_callback(ABLETON_MODE) self._shift_modes._note_mode_active = False self._session_zoom.set_ignore_buttons(False) self._shift_modes._transport.update() self._shift_modes._on_note_mode_changed() self._shift_modes.set_enabled(False) self._session.set_clip_launch_buttons(None) for track in range(8): self._mixer.channel_strip(track).set_select_button(None) self._mixer.channel_strip(track).set_mute_button(None) self._session.set_track_bank_buttons(None, None) self._session.set_scene_bank_buttons(None, None) for scene in range(5): self._scene_launch_buttons[scene].turn_off() self._transport.set_enabled(False) self._session.set_enabled(False) self._session_zoom.set_enabled(False) self.flash_status = True self._monomod.reset() self.modhandler.set_enabled(True) self._master_select_button.send_value(self._monomod_mode._mode_index) """m4l bridge""" def generate_strip_string(self, display_string): #self.log_message(display_string) NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center( (NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return ret def notification_to_bridge(self, name, value, sender): if isinstance(sender, (MonoRingedEncoderElement, MonoEncoderElement)): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched += 1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip() is True: clip_names.append(clip_slot._clip_slot) ##.clip.name) return clip_slot._clip_slot ##self.log_message(str(clip_slot._clip_slot.clip.name)) return clip_names def update_display(self): super(AumPC20, self).update_display() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if self.flash_status: for control, _ in self._monomod.iterbuttons(): if isinstance(control, MonoButtonElement): control.flash(self._timer)
class LemurPad(MonOhm): __module__ = __name__ __doc__ = " Lemur version of the MonOhm companion controller script " def __init__(self, *a, **k): self._timer_callbacks = [] #Used for _monobridge, which uses L8 method for registering timer callbacks. deprecated, needs to be replaced by new L9 Task class. self._osc_registry = {} self._display_button_names = DISPLAY_BUTTON_NAMES super(LemurPad, self).__init__(*a, **k) self._host_name = "LemurPad" self._color_type = 'AumPad' self.connected = 0 with self.component_guard(): self._setup_touchosc() self._assign_host2() self._assign_session_colors() def query_ohm(self): pass """script initialization methods""" def _setup_monobridge(self): self._monobridge = OSCMonoBridgeElement(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(8): self._fader[index] = OSCMonoEncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_FADERS[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, '/Fader_'+str(index)+'/x', '/Strip'+str(index+8)+'/set', '/Strip'+str(index)+'/set', self) for index in range(8): self._button[index] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_'+str(index), '/Select_'+str(index)+'/value', '/Select/set '+str(index), '/Select/text '+str(index), self) for index in range(16): self._dial[index] = OSCMonoEncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_DIALS[index], Live.MidiMap.MapMode.absolute, 'Dial_' + str(index), index + 8, '/Dial_'+str(index)+'/x', '/Dial'+str(index)+'val/set', '/Dial'+str(index)+'name/set', self) for index in range(6): self._menu[index] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_MENU[index], 'Menu_' + str(index), '/Function_'+str(index)+'/value', '/Function/set '+str(index), '/Function/text '+str(index), self) self._crossfader = OSCMonoEncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute, "Crossfader", 24, '/XFader/x', '/XFader/none', None, self) self._livid = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', '/Livid/x', '/Livid/x', None, self) self._shift_l = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Shift_Button_Left', '/ShiftL/x', '/ShiftL/x', None, self) self._shift_r = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Shift_Button_Right', '/ShiftR/x', '/ShiftR/x', None, 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] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, (column * 8) + row, 'Grid_' + str(column) + '_' + str(row), '/ClipGrid_'+str(column)+'_'+str(row)+'/value', '/ClipGrid/set '+str(column)+' '+str(row), '/ClipGrid/text '+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._monomod256 = ButtonMatrixElement() self._monomod256.name = 'Monomod256' self._square = [None for index in range(16)] for column in range(16): self._square[column] = [None for index in range(16)] for row in range(16): self._square[column][row] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, int(column/8) + 1, row + ((column%8) * 16), '256Grid_' + str(column) + '_' + str(row), '/Grid_'+str(column)+'_'+str(row)+'/value', '/Grid/set '+str(column)+' '+str(row), None, self) #self._square[column][row] = FlashingButtonElement(is_momentary, 0, 15, -1, '256Grid_' + str(column) + '_' + str(row), '/1/p_grid/'+str(column)+'/'+str(row), '/1/c_grid/'+str(column)+'/'+str(row), self) for row in range(16): button_row = [] for column in range(16): button_row.append(self._square[column][row]) self._monomod256.add_row(tuple(button_row)) self._bank_buttons = ButtonMatrixElement() self._key_buttons = ButtonMatrixElement() self._bank_button = [None for index in range(2)] for index in range(2): self._bank_button[index] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, index, '256Grid_Bank_' + str(index), '/Shift_'+str(index)+'/value', '/Shift/set '+str(index), None, self) button_row = [] for index in range(2): button_row.append(self._bank_button[index]) self._bank_buttons.add_row(tuple(button_row)) button_row = [] self._key_button = [None for index in range(8)] for index in range(8): self._key_button[index] = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, 15, index+8, '256Grid_Key_' + str(index), '/Keys_'+str(index)+'/value', '/Keys/set '+str(index), None, self) for index in range(8): button_row.append(self._key_button[index]) self._key_buttons.add_row(tuple(button_row)) self._pedal = [None for index in range(8)] if self._use_pedal is True: for index in range(8): self._pedal[index] = EncoderElement(MIDI_CC_TYPE, 0, 25+index, Live.MidiMap.MapMode.absolute) self._pedal[index].name = 'Pedal_'+str(index) self._pedal[index]._report = False def _setup_session_control(self): is_momentary = True num_tracks = 4 num_scenes = 5 self._session = NameServerSessionComponent(num_tracks, num_scenes, self) self._session.name = "Left_Session" self._session.set_offsets(0, 0) self._session.set_stop_clip_value(self._color_defs['STOP_CLIP']) self._scene = [None for index in range(5)] for row in range(num_scenes): self._scene[row] = self._session.scene(row) self._scene[row].name = 'L_Scene_' + str(row) for column in range(num_tracks): clip_slot = self._scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_L_' + str(row) clip_slot.set_triggered_to_play_value(self._color_defs['CLIP_TRG_PLAY']) clip_slot.set_triggered_to_record_value(self._color_defs['CLIP_TRG_REC']) clip_slot.set_stopped_value(self._color_defs['CLIP_STOP']) clip_slot.set_started_value(self._color_defs['CLIP_STARTED']) clip_slot.set_recording_value(self._color_defs['CLIP_RECORDING']) self._session.set_mixer(self._mixer) self._session_zoom = SessionZoomingComponent(self._session) self._session_zoom.name = 'L_Session_Overview' self._session_zoom.set_stopped_value(self._color_defs['ZOOM_STOPPED']) self._session_zoom.set_playing_value(self._color_defs['ZOOM_PLAYING']) self._session_zoom.set_selected_value(self._color_defs['ZOOM_SELECTED']) self._session_zoom._zoom_button = (self._dummy_button) self._session_zoom.set_enabled(True) self._session2 = SessionComponent(num_tracks, num_scenes) self._session2.name = 'Right_Session' self._session2.set_offsets(4, 0) self._session2.set_stop_clip_value(self._color_defs['STOP_CLIP']) self._scene2 = [None for index in range(5)] for row in range(num_scenes): self._scene2[row] = self._session2.scene(row) self._scene2[row].name = 'R_Scene_' + str(row) for column in range(num_tracks): clip_slot = self._scene2[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_R_' + str(row) clip_slot.set_triggered_to_play_value(self._color_defs['CLIP_TRG_PLAY']) clip_slot.set_triggered_to_record_value(self._color_defs['CLIP_TRG_REC']) clip_slot.set_stopped_value(self._color_defs['CLIP_STOP']) clip_slot.set_started_value(self._color_defs['CLIP_STARTED']) clip_slot.set_recording_value(self._color_defs['CLIP_RECORDING']) self._session2.set_mixer(self._mixer2) self._session2.add_offset_listener(self._on_session_offset_changes) self._session_zoom2 = SessionZoomingComponent(self._session2) self._session_zoom2.name = 'R_Session_Overview' self._session_zoom2.set_stopped_value(self._color_defs['ZOOM_STOPPED']) self._session_zoom2.set_playing_value(self._color_defs['ZOOM_PLAYING']) self._session_zoom2.set_selected_value(self._color_defs['ZOOM_SELECTED']) self._session_zoom.set_enabled(True) self._session_zoom2._zoom_button = (self._dummy_button2) self._session_main = SessionComponent(8, num_scenes) self._session_main.name = 'Main_Session' self._session_main.set_stop_clip_value(self._color_defs['STOP_CLIP']) self._scene_main = [None for index in range(5)] for row in range(num_scenes): self._scene_main[row] = self._session_main.scene(row) self._scene_main[row].name = 'M_Scene_' + str(row) for column in range(8): clip_slot = self._scene_main[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_M_' + str(row) clip_slot.set_triggered_to_play_value(self._color_defs['CLIP_TRG_PLAY']) clip_slot.set_triggered_to_record_value(self._color_defs['CLIP_TRG_REC']) clip_slot.set_stopped_value(self._color_defs['CLIP_STOP']) clip_slot.set_started_value(self._color_defs['CLIP_STARTED']) clip_slot.set_recording_value(self._color_defs['CLIP_RECORDING']) self._session_main.set_mixer(self._mixer) self._session_zoom_main = SessionZoomingComponent(self._session_main) self._session_zoom_main.name = 'M_Session_Overview' self._session_zoom_main.set_stopped_value(self._color_defs['ZOOM_STOPPED']) self._session_zoom_main.set_playing_value(self._color_defs['ZOOM_PLAYING']) self._session_zoom_main.set_selected_value(self._color_defs['ZOOM_SELECTED']) self._session_zoom_main.set_enabled(True) self._session_zoom_main._zoom_button = (self._dummy_button3) self._sessions = [self._session, self._session2, self._session_main] self._zooms = [self._session_zoom, self._session_zoom2, self._session_zoom_main] def _setup_monomod(self): self._host = MonomodComponent(self) self._host.name = 'Monomod_Host' self._host2 = SpecialMonomodComponent(self) self._host2.name = '256_Monomod_Host' self.hosts = [self._host, self._host2] def _assign_host2(self): self._host2._set_shift_button(self._bank_button[0]) self._host2._set_alt_button(self._bank_button[1]) self._host2._set_button_matrix(self._monomod256) self._host2._set_key_buttons(self._key_button) self._host2.set_enabled(True) def _setup_touchosc(self): self._osc_registry = {} #self._osc_registry['/ping'] = self._monobridge.ping #self._osc_registry['/1'] = self._monobridge.page1 #self._osc_registry['/2'] = self._monobridge.page2 for control in self.controls: if hasattr(control, 'osc'): self._osc_registry[control.osc] = control.set_value #if hasattr(control, 'osc_alt'): # self._osc_registry[control.osc_alt] = control.set_value #self.log_message('create dict key: ' + str(control.osc) + str(control.name)) """shift/zoom methods""" def deassign_matrix(self): super(LemurPad, self).deassign_matrix() self.clear_grid_names() """menu button management methods""" def deassign_menu(self): super(LemurPad, self).deassign_menu() for index in range(6): self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(' ')) def assign_device_nav_to_menu(self): super(LemurPad, self).assign_device_nav_to_menu() for index in range(6): self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(DEVICE_NAV_NAMES[index]))) def assign_transport_to_menu(self): super(LemurPad, self).assign_transport_to_menu() for index in range(6): self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(TRANSPORT_NAMES[index]))) def assign_session_nav_to_menu(self): super(LemurPad, self).assign_session_nav_to_menu() for index in range(6): self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(SESSION_NAV_NAMES[index]))) def assign_session_main_nav_to_menu(self): super(LemurPad, self).assign_session_main_nav_to_menu() for index in range(6): self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(SESSION_NAV_NAMES[index]))) def assign_monomod_shift_to_menu(self): super(LemurPad, self).assign_monomod_shift_to_menu() for index in range(6): self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(MONOMOD_SHIFT_NAMES[index]))) def assign_monomod_to_menu(self): super(LemurPad, self).assign_monomod_shift_to_menu() for index in range(6): self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(MONOMOD_NAMES[index]))) def assign_session_bank_to_menu(self): super(LemurPad, self).assign_session_bank_to_menu() for index in range(6): self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(SESSION_BANK_NAMES[index]))) def assign_session2_bank_to_menu(self): super(LemurPad, self).assign_session2_bank_to_menu() for index in range(6): self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(SESSION_BANK2_NAMES[index]))) def assign_session_main_nav_to_menu(self): super(LemurPad, self).assign_session_main_nav_to_menu() for index in range(6): self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(str(SESSION_MAIN_BANK_NAMES[index]))) """m4l bridge""" def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 9 if (not display_string): return ('`_') if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return '`' + ret.replace(' ', '_') def notification_to_bridge(self, name, value, sender): if(isinstance(sender, MonoEncoderElement2)): #self.log_message(str(name) + str(value) + str(sender.num)) self._monobridge._send('lcd_name', sender.name, self.generate_strip_string(str(name))) self._monobridge._send('lcd_value', sender.name, self.generate_strip_string(str(value))) def clip_name(self, sender, name): #self.log_message('clip name ' + str(sender.osc_name) + ' ' + str(self.generate_strip_string(str(name)))) self._monobridge._send_osc(sender.osc_name, self.generate_strip_string(str(name))) """def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip(): clip_names.append(clip_slot._clip_slot)##.clip.name) #return clip_slot._clip_slot #self.log_message('clip name' + str(clip_slot._clip_slot.clip.name)) return clip_names""" """called on timer""" def update_display(self): super(LemurPad, self).update_display() for callback in self._timer_callbacks: callback() def flash(self): if(self.flash_status > 0): for control in self.controls: if isinstance(control, MonoButtonElement): control.flash(self._timer) def strobe(self): pass """general functionality""" def disconnect(self): super(MonOhm, self).disconnect() def clear_grid_names(self): #self.log_message('clear grid names' + str(self)) for column in range(8): for row in range(8): self._monobridge._send_osc(self._grid[column][row].osc_name, '`_') def _register_timer_callback(self, callback): """ Registers a callback that is triggerd on every call of update_display """ assert (callback != None) assert (dir(callback).count('im_func') is 1) assert (self._timer_callbacks.count(callback) == 0) self._timer_callbacks.append(callback) return None def _unregister_timer_callback(self, callback): """ Unregisters a timer callback """ assert (callback != None) assert (dir(callback).count('im_func') is 1) assert (self._timer_callbacks.count(callback) == 1) self._timer_callbacks.remove(callback) return None def _set_brightness(self, value): #self._bright = (value != 0) #for control in self.controls: # if isinstance(control, OSCMonoButtonElement): # self._monobridge._send_osc(control.osc_alt, int(self._bright), True) pass def reset(self): #self._monobridge._send_osc('/reset') for control in self.controls: control.reset() def assign_lower_grid_names(self, mode): if self._display_button_names is True: for column in range(8): for row in range(3): self._monobridge._send_osc(self._grid[column][row+5].osc_name, self.generate_strip_string(str(GRID_NAMES[mode][row][column]))) def reset_and_refresh_state(self, *a, **k): self.schedule_message(1, self.reset) self.schedule_message(2, self.refresh_state)
class MatrixModesComponent(ModeSelectorComponent): ' SelectorComponent that assigns matrix to different functions ' __module__ = __name__ def __init__(self, matrix, session, zooming, stop_buttons, parent): assert isinstance(matrix, ButtonMatrixElement) ModeSelectorComponent.__init__(self) self._controls = None self._session = session self._session_zoom = zooming self._matrix = matrix self._track_stop_buttons = stop_buttons self._stop_button_matrix = ButtonMatrixElement( ) #new dummy matrix for stop buttons, to allow note mode/user mode switching button_row = [] for track_index in range(8): button = self._track_stop_buttons[track_index] button_row.append(button) self._stop_button_matrix.add_row(tuple(button_row)) self._nav_left_button = None self._nav_right_button = None self._mode_index = 0 self._last_mode = 0 self._parent = parent self._parent.set_pad_translations( PAD_TRANSLATIONS) #comment out to remove Drum Rack mapping self._vu = None self._shift_button = self._parent._shift_button self._shift_button.add_value_listener(self._shift_value) def disconnect(self): for button in self._modes_buttons: button.remove_value_listener(self._mode_value) self._controls = None self._session = None self._session_zoom = None self._matrix = None self._track_stop_buttons = None self._stop_button_matrix = None self._shift_button.remove_value_listener(self._shift_value) ModeSelectorComponent.disconnect(self) def set_mode( self, mode): #override ModeSelectorComponent set_mode, to avoid flickers assert isinstance(mode, int) assert (mode in range(self.number_of_modes())) if (self._mode_index != mode): self._last_mode = 0 # self._mode_index # keep track of previous mode, to allow refresh after Note Mode only self._mode_index = mode self._set_modes() def set_mode_buttons(self, buttons): assert isinstance(buttons, (tuple, type(None))) for button in self._modes_buttons: button.remove_value_listener(self._mode_value) self._modes_buttons = [] if (buttons != None): for button in buttons: assert isinstance(button, ButtonElement) identify_sender = True button.add_value_listener(self._mode_value, identify_sender) self._modes_buttons.append(button) for index in range(len(self._modes_buttons)): if (index == self._mode_index): self._modes_buttons[index].turn_on() else: self._modes_buttons[index].turn_off() def _mode_value(self, value, sender): assert (len(self._modes_buttons) > 0) assert isinstance(value, int) assert isinstance(sender, ButtonElement) assert (self._modes_buttons.count(sender) == 1) if self.is_enabled(): if ((value is not 0) or (not sender.is_momentary())): self.set_mode(self._modes_buttons.index(sender)) def number_of_modes(self): return 8 def update(self): pass def get_mode_index_value(self): return self._mode_index def _set_modes(self): if self.is_enabled(): if self._vu != None: self._vu.disconnect() self._session.set_allow_update(False) self._session_zoom.set_allow_update(False) assert (self._mode_index in range(self.number_of_modes())) for index in range(len(self._modes_buttons)): if (index == self._mode_index): self._modes_buttons[index].turn_on() else: self._modes_buttons[index].turn_off() self._session.set_stop_track_clip_buttons( tuple(self._track_stop_buttons)) for track_index in range(8): button = self._track_stop_buttons[track_index] button.use_default_message() button.set_enabled(True) button.set_force_next_value() button.send_value(0) self._session_zoom.set_enabled(True) self._session.set_enabled(True) self._session.set_show_highlight(True) self._session_zoom.set_zoom_button(self._parent._shift_button) for scene_index in range(5): scene = self._session.scene(scene_index) for track_index in range(8): button = self._matrix.get_button(track_index, scene_index) button.use_default_message() clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(button) button.set_enabled(True) if (self._mode_index == 0): #Clip Launch self._session_zoom._on_zoom_value(1) #zoom out elif (self._mode_index == 1): #Session Overview self._session_zoom.set_zoom_button(None) self._session_zoom.set_enabled(True) self._session_zoom._is_zoomed_out = True self._session_zoom._scene_bank_index = int( ((self._session_zoom._session.scene_offset() / self._session_zoom._session.height()) / self._session_zoom._buttons.height())) self._session.set_enabled(False) self._session_zoom.update() elif (self._mode_index == 2): self._set_note_mode(PATTERN_1, CHANNEL_1, NOTEMAP_1, USE_STOP_ROW_1, IS_NOTE_MODE_1) elif (self._mode_index == 3): self._set_note_mode(PATTERN_2, CHANNEL_2, NOTEMAP_2, USE_STOP_ROW_2, IS_NOTE_MODE_2) elif (self._mode_index == 4): self._set_note_mode(PATTERN_3, CHANNEL_3, NOTEMAP_3, USE_STOP_ROW_3, IS_NOTE_MODE_3) elif (self._mode_index == 5): self._set_note_mode(PATTERN_4, CHANNEL_4, NOTEMAP_4, USE_STOP_ROW_4, IS_NOTE_MODE_4) elif (self._mode_index == 6): self._set_note_mode(PATTERN_5, CHANNEL_5, NOTEMAP_5, USE_STOP_ROW_5, IS_NOTE_MODE_5) elif (self._mode_index == 7): self._set_note_mode(PATTERN_6, CHANNEL_6, NOTEMAP_6, True, False) # VU Meters self._session.set_enabled(False) self._session_zoom._on_zoom_value(1) #zoom out self._session_zoom.set_enabled(True) self._session_zoom._is_zoomed_out = False self._session_zoom.set_zoom_button(self._parent._shift_button) self._session_zoom.update() self._update_vu_meters() else: pass self._session.set_allow_update(True) self._session_zoom.set_allow_update(True) #self._rebuild_callback() def _set_note_mode(self, pattern, channel, notemap, use_stop_row=False, is_note_mode=True): self._session_zoom.set_zoom_button(None) self._session_zoom.set_enabled(False) for scene_index in range(5): scene = self._session.scene(scene_index) for track_index in range(8): clip_slot = scene.clip_slot(track_index) button = self._matrix.get_button(track_index, scene_index) clip_slot.set_launch_button(None) button.set_channel( channel) #remap all Note Mode notes to new channel button.set_identifier(notemap[scene_index][track_index]) button.set_on_off_values(pattern[scene_index][track_index], 0) button.set_force_next_value() button.turn_on() if is_note_mode == True: button.set_enabled(False) if use_stop_row == True: self._session.set_stop_track_clip_buttons(None) for track_index in range(8): button = self._stop_button_matrix.get_button(track_index, 0) button.set_channel( channel) #remap all Note Mode notes to new channel button.set_identifier(notemap[5][track_index]) button.set_force_next_value() button.send_value(pattern[5][track_index]) if is_note_mode == True: button.set_enabled(False) else: for track_index in range(8): button = self._stop_button_matrix.get_button(track_index, 0) button.send_value(0, True) self._session.set_enabled(True) self._session.set_show_highlight(True) def _on_track_offset_changed(self): if (self.is_enabled() and self._mode_index == 7): self._update_vu_meters() def _shift_value(self, value): if (self.is_enabled() and self._mode_index == 7 and self._vu != None): if value != 0: self._vu.disconnect() self._vu.disable() else: self._update_vu_meters() self._vu.enable() def _update_vu_meters(self): if self._vu == None: self._vu = VUMeters(self._parent) else: self._vu.disconnect() self._vu.observe(int(self._session_zoom._session.track_offset()))
def _setup_session_control(self): Live.Base.log("LOG: AAAMatrix _setup_session_control") is_momentary = True # Set Highlight Grid Size session = CustomSessionComponent(num_tracks, num_scenes) # Set Session Name session.name = 'AAAMatrix Session' # Set Highlight Grid Size session.set_offsets(offset_tracks, offset_scenes) # SESSION NAVIGATION BUTTONS right_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, right_button_CC) left_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, left_button_CC) right_button.name = 'Bank_Select_Right_Button' left_button.name = 'Bank_Select_Left_Button' session.set_track_bank_buttons(right_button, left_button) up_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, up_button_CC) down_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, down_button_CC) up_button.name = 'Bank_Select_Up_Button' down_button.name = 'Bank_Select_Down_Button' session.set_scene_bank_buttons(down_button, up_button) #SCENE NAVIGATION BUTTONS prev_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, left_select_CC) next_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, right_select_CC) next_button.name = 'Next_Select_Button' prev_button.name = 'Prev_Select__Button' session.set_select_buttons(next_button, prev_button) #STOP ALL CLIP BUTTON stop_all_button = ButtonElement(is_momentary, MIDI_CC_TYPE, CHANNEL, stop_all_clips_CC) stop_all_button.name = 'Stop_All_Button' session.set_stop_all_clips_button(stop_all_button) #SCENE LAUCH BUTTONS scene_launch_buttons = [ ButtonElement(True, MIDI_CC_TYPE, CHANNEL, scene_launch_column_CCs[index]) for index in xrange(num_scenes) ] scene_launch_buttons = ButtonMatrixElement(name='Scene_Launch_Buttons', rows=[scene_launch_buttons]) session.set_scene_launch_buttons(scene_launch_buttons) #CLIP STOP BUTTONS scene_stop_buttons = [ ButtonElement(True, MIDI_CC_TYPE, CHANNEL, clip_stop_row_CCs[index]) for index in xrange(num_tracks) ] scene_stop_buttons = ButtonMatrixElement(name='Scene_Stop_Buttons', rows=[scene_stop_buttons]) session.set_stop_track_clip_buttons(scene_stop_buttons) #CLIP LAUCH BUTTONS matrix = ButtonMatrixElement(name='Button_Matrix') for scene_index in xrange(num_scenes): row = [ ButtonElement(True, MIDI_CC_TYPE, CHANNEL, clip_CCs[scene_index][track_index]) for track_index in xrange(num_tracks) ] matrix.add_row(row) session.set_clip_launch_buttons(matrix) self.set_highlighting_session_component(session)
class APC_64_40_9(APC): """ Script for Akai's APC40 Controller """ def __init__(self, c_instance): self._c_instance = c_instance self._shift_modes = None self._encoder_modes = None self._slider_modes = None self._sequencer = None APC.__init__(self, c_instance) self._device_selection_follows_track_selection = True def disconnect(self): self._shift_modes = None self._encoder_modes = None self._slider_modes = None self._sequencer = None APC.disconnect(self) def _setup_session_control(self): is_momentary = True self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98) self._right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96) self._left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97) self._up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94) self._down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95) self._right_button.name = 'Bank_Select_Right_button' self._left_button.name = 'Bank_Select_Left_button' self._up_button.name = 'Bank_Select_Up_button' self._down_button.name = 'Bank_Select_Down_button' self._session = PedaledSessionComponent(8, 5) self._session.name = 'Session_Control' self._session.set_track_bank_buttons(self._right_button, self._left_button) self._session.set_scene_bank_buttons(self._down_button, self._up_button) self._matrix = ButtonMatrixElement() self._matrix.name = 'Button_Matrix' self._scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, index + 82) for index in range(5) ] self._track_stop_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ] for index in range(len(self._scene_launch_buttons)): self._scene_launch_buttons[index].name = 'Scene_' + str( index) + '_Launch_Button' for index in range(len(self._track_stop_buttons)): self._track_stop_buttons[index].name = 'Track_' + str( index) + '_Stop_Button' self._stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) self._stop_all_button.name = 'Stop_All_Clips_Button' self._session.set_stop_all_clips_button(self._stop_all_button) self._session.set_stop_track_clip_buttons( tuple(self._track_stop_buttons)) self._session.set_stop_clip_value(0) self._session.set_stop_clip_triggered_value(2) for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(self._scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53)) button.name = str(track_index) + '_Clip_' + str( scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(5) clip_slot.set_started_value(1) clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) self._matrix.add_row(tuple(button_row)) self._session.set_slot_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = ShiftableZoomingComponent( self._session, tuple(self._track_stop_buttons)) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(self._matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_nav_buttons(self._up_button, self._down_button, self._left_button, self._right_button) self._session_zoom.set_scene_bank_buttons( tuple(self._scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(self, 8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) master_select_button.name = 'Master_Select_Button' self._mixer.master_strip().set_select_button(master_select_button) self._mixer.selected_strip().name = 'Selected_Channel_Strip' select_buttons = [] arm_buttons = [] solo_buttons = [] mute_buttons = [] sliders = [] for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) solo_buttons.append(solo_button) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) mute_buttons.append(mute_button) solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) select_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) select_buttons[-1].name = str(track) + '_Select_Button' arm_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) arm_buttons[-1].name = str(track) + '_Arm_Button' sliders.append(SliderElement(MIDI_CC_TYPE, track, 7)) sliders[-1].name = str(track) + '_Volume_Control' self._crossfader = SliderElement(MIDI_CC_TYPE, 0, 15) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) self._prehear_control = EncoderElement( MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) self._crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' self._prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_shift_button(self._shift_button) self._mixer.set_crossfader_control(self._crossfader) self._mixer.set_prehear_volume_control(self._prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) self._slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) self._slider_modes.name = 'Slider_Modes' matrix_modes = MatrixModesComponent(self._matrix, self._session, self._session_zoom, tuple(self._track_stop_buttons), self) matrix_modes.name = 'Matrix_Modes' self._sequencer = StepSequencerComponent( self, self._session, self._matrix, tuple(self._track_stop_buttons)) self._sequencer.set_bank_buttons(tuple(select_buttons)) self._sequencer.set_nav_buttons(self._up_button, self._down_button, self._left_button, self._right_button) self._sequencer.set_button_matrix(self._matrix) self._sequencer.set_follow_button(master_select_button) self._sequencer.set_velocity_buttons(tuple(arm_buttons)) self._sequencer.set_shift_button(self._shift_button) self._sequencer.set_lane_mute_buttons(tuple( self._scene_launch_buttons)) self._sequencer.set_loop_start_buttons(tuple(mute_buttons)) self._sequencer.set_loop_length_buttons(tuple(solo_buttons)) self._shift_modes = ShiftableSelectorComponent( self, tuple(select_buttons), master_select_button, tuple(self._track_stop_buttons), self._stop_all_button, tuple(mute_buttons), tuple(solo_buttons), tuple(arm_buttons), tuple(self._scene_launch_buttons), self._matrix, self._session, self._session_zoom, self._mixer, self._slider_modes, matrix_modes, self._sequencer) self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button) def _setup_custom_components(self): self._setup_device_and_transport_control() self._setup_global_control() def _setup_device_and_transport_control(self): is_momentary = True device_bank_buttons = [] device_param_controls = [] bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Metronome_Button') for index in range(8): device_bank_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 58 + index)) device_bank_buttons[-1].name = bank_button_labels[index] ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 24 + index) ringed_encoder = RingedEncoderElement( MIDI_CC_TYPE, 0, 16 + index, Live.MidiMap.MapMode.absolute) ringed_encoder.set_ring_mode_button(ring_mode_button) ringed_encoder.set_feedback_delay(-1) ringed_encoder.name = 'Device_Control_' + str(index) ring_mode_button.name = ringed_encoder.name + '_Ring_Mode_Button' device_param_controls.append(ringed_encoder) self._device = ShiftableDeviceComponent() self._device.name = 'Device_Component' self._device.set_bank_buttons(tuple(device_bank_buttons)) self._device.set_shift_button(self._shift_button) self._device.set_parameter_controls(tuple(device_param_controls)) self._device.set_on_off_button(device_bank_buttons[1]) self.set_device_component(self._device) detail_view_toggler = DetailViewCntrlComponent() detail_view_toggler.name = 'Detail_View_Control' detail_view_toggler.set_shift_button(self._shift_button) detail_view_toggler.set_device_clip_toggle_button( device_bank_buttons[0]) detail_view_toggler.set_detail_toggle_button(device_bank_buttons[4]) detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3]) transport = ShiftableTransportComponent() transport.name = 'Transport' play_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 91) stop_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 92) record_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 93) nudge_up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 100) nudge_down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 101) tap_tempo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99) play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' record_button.name = 'Record_Button' nudge_up_button.name = 'Nudge_Up_button' nudge_down_button.name = 'Nudge_Down_button' tap_tempo_button.name = 'Tap_Tempo_Button' transport.set_shift_button(self._shift_button) transport.set_play_button(play_button) transport.set_stop_button(stop_button) transport.set_record_button(record_button) transport.set_nudge_buttons(nudge_up_button, nudge_down_button) transport.set_undo_button(nudge_down_button) transport.set_redo_button(nudge_up_button) transport.set_tap_tempo_button(tap_tempo_button) self._device.set_lock_button(tap_tempo_button) transport.set_quant_toggle_button(device_bank_buttons[5]) transport.set_overdub_button(device_bank_buttons[6]) transport.set_metronome_button(device_bank_buttons[7]) transport.set_tempo_encoder(self._prehear_control) bank_button_translator = ShiftTranslatorComponent() bank_button_translator.set_controls_to_translate( tuple(device_bank_buttons)) bank_button_translator.set_shift_button(self._shift_button) def _setup_global_control(self): is_momentary = True self._global_bank_buttons = [] self._global_param_controls = [] for index in range(8): ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 56 + index) ringed_encoder = RingedEncoderElement( MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute) ringed_encoder.name = 'Track_Control_' + str(index) ringed_encoder.set_feedback_delay(-1) ring_button.name = ringed_encoder.name + '_Ring_Mode_Button' ringed_encoder.set_ring_mode_button(ring_button) self._global_param_controls.append(ringed_encoder) self._global_bank_buttons = [] global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button') for index in range(4): self._global_bank_buttons.append( ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 87 + index)) self._global_bank_buttons[-1].name = global_bank_labels[index] self._encoder_modes = EncModeSelectorComponent(self._mixer) self._encoder_modes.name = 'Track_Control_Modes' self._encoder_modes.set_controls(tuple(self._global_param_controls)) self._encoder_device_modes = EncoderDeviceComponent( self._mixer, self._device, self) self._encoder_device_modes.name = 'Alt_Device_Control_Modes' self._encoder_eq_modes = EncoderEQComponent(self._mixer, self) self._encoder_eq_modes.name = 'EQ_Control_Modes' global_translation_selector = ChannelTranslationSelector() global_translation_selector.name = 'Global_Translations' global_translation_selector.set_controls_to_translate( tuple(self._global_param_controls)) global_translation_selector.set_mode_buttons( tuple(self._global_bank_buttons)) encoder_user_modes = EncoderUserModesComponent( self, self._encoder_modes, tuple(self._global_param_controls), tuple(self._global_bank_buttons), self._mixer, self._device, self._encoder_device_modes, self._encoder_eq_modes) encoder_user_modes.name = 'Encoder_User_Modes' self._encoder_shift_modes = ShiftableEncoderSelectorComponent( self, tuple(self._global_bank_buttons), encoder_user_modes, self._encoder_modes, self._encoder_eq_modes, self._encoder_device_modes) self._encoder_shift_modes.name = 'Encoder_Shift_Modes' self._encoder_shift_modes.set_mode_toggle(self._shift_button) def _on_selected_track_changed(self): ControlSurface._on_selected_track_changed(self) track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) return None def _product_model_id_byte(self): return 115
class AumPC40(APC40): def __init__(self, c_instance, *a, **k): super(AumPC40, self).__init__(c_instance, *a, **k) self._monomod_version = 'b996' self._host_name = 'AumPC' self._color_type = 'APC' self._timer = 0 self._touched = 0 self.flash_status = False with self.component_guard(): self._setup_monobridge() self._setup_mod() self._device_component._current_bank_details = self._make_current_bank_details(self._device_component) def disconnect(self): super(AumPC40, self).disconnect() rebuild_sys() def _create_controls(self): make_on_off_button = partial(make_button, skin=self._default_skin) make_color_button = partial(make_button, skin=self._color_skin) self._shift_button = make_button(0, 98, resource_type=PrioritizedResource, name='Shift_Button') self._right_button = make_button(0, 96, name='Bank_Select_Right_Button') self._left_button = make_button(0, 97, name='Bank_Select_Left_Button') self._up_button = make_button(0, 94, name='Bank_Select_Up_Button') self._down_button = make_button(0, 95, name='Bank_Select_Down_Button') self._session_matrix = ButtonMatrixElement(name='Button_Matrix') self._scene_launch_buttons = [ make_color_button(0, index + 82, name='Scene_%d_Launch_Button' % index, cs = self) for index in xrange(SESSION_HEIGHT) ] self._track_stop_buttons = [ make_color_button(index, 52, name='Track_%d_Stop_Button' % index, cs = self) for index in xrange(SESSION_WIDTH) ] self._stop_all_button = make_color_button(0, 81, name='Stop_All_Clips_Button', cs = self) self._matrix_rows_raw = [ [ make_color_button(track_index, scene_index + 53, name='%d_Clip_%d_Button' % (track_index, scene_index), cs = self) for track_index in xrange(SESSION_WIDTH) ] for scene_index in xrange(SESSION_HEIGHT) ] for row in self._matrix_rows_raw: self._session_matrix.add_row(row) self._selected_slot_launch_button = make_pedal_button(67, name='Selected_Slot_Launch_Button') self._selected_scene_launch_button = make_pedal_button(64, name='Selected_Scene_Launch_Button') self._volume_controls = [] self._arm_buttons = [] self._original_solo_buttons = [] self._original_mute_buttons = [] self._select_buttons = [] for index in xrange(MIXER_SIZE): self._volume_controls.append(make_slider(index, 7, name='%d_Volume_Control' % index, num=index, script = self)) self._arm_buttons.append(make_on_off_button(index, 48, name='%d_Arm_Button' % index, cs = self)) self._original_solo_buttons.append(make_on_off_button(index, 49, name='%d_Solo_Button' % index, cs = self)) self._original_mute_buttons.append(make_on_off_button(index, 50, name='%d_Mute_Button' % index, cs = self)) self._select_buttons.append(make_on_off_button(index, 51, name='%d_Select_Button' % index, cs = self)) self._crossfader_control = make_slider(0, 15, name='Crossfader', script = self) self._master_volume_control = make_slider(0, 14, name='Master_Volume_Control', script = self) self._master_select_button = make_on_off_button(0, 80, name='Master_Select_Button', cs = self) self._prehear_control = make_encoder(0, 47, name='Prehear_Volume_Control', script = self) self._device_bank_buttons = [] self._device_param_controls_raw = [] bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Metronome_Button') for index in range(8): self._device_bank_buttons.append(make_on_off_button(0, 58 + index, name=bank_button_labels[index])) encoder_name = 'Device_Control_%d' % index ringed_encoder = make_ring_encoder(16 + index, 24 + index, name=encoder_name, num = index + 8, script = self) self._device_param_controls_raw.append(ringed_encoder) self._play_button = make_button(0, 91, name='Play_Button') self._stop_button = make_button(0, 92, name='Stop_Button') self._record_button = make_button(0, 93, name='Record_Button') self._nudge_up_button = make_button(0, 100, name='Nudge_Up_Button') self._nudge_down_button = make_button(0, 101, name='Nudge_Down_Button') self._tap_tempo_button = make_button(0, 99, name='Tap_Tempo_Button') self._global_bank_buttons = [] self._global_param_controls = [] for index in range(8): encoder_name = 'Track_Control_%d' % index ringed_encoder = make_ring_encoder(48 + index, 56 + index, name=encoder_name, num = index, script = self) self._global_param_controls.append(ringed_encoder) self._global_bank_buttons = [ make_on_off_button(0, 87 + index, name=name) for index, name in enumerate(('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button')) ] self._device_clip_toggle_button = self._device_bank_buttons[0] self._device_on_off_button = self._device_bank_buttons[1] self._detail_left_button = self._device_bank_buttons[2] self._detail_right_button = self._device_bank_buttons[3] self._detail_toggle_button = self._device_bank_buttons[4] self._rec_quantization_button = self._device_bank_buttons[5] self._overdub_button = self._device_bank_buttons[6] self._metronome_button = self._device_bank_buttons[7] self._monomod = ButtonMatrixElement(name = 'Monomod') for row in self._matrix_rows_raw: self._monomod.add_row(row) self._monomod.add_row(self._track_stop_buttons) self._monomod.add_row(self._select_buttons) self._monomod.add_row(self._original_mute_buttons) #self._doublepress_detail_button = DoublePressElement(self._detail_toggle_button) def wrap_matrix(control_list, wrapper = nop): return ButtonMatrixElement(rows=[map(wrapper, control_list)]) self._scene_launch_buttons = wrap_matrix(self._scene_launch_buttons) self._track_stop_buttons = wrap_matrix(self._track_stop_buttons) self._volume_controls = wrap_matrix(self._volume_controls) self._arm_buttons = wrap_matrix(self._arm_buttons) self._original_solo_buttons = wrap_matrix(self._original_solo_buttons) self._original_mute_buttons = wrap_matrix(self._original_mute_buttons) self._select_buttons = wrap_matrix(self._select_buttons) self._device_param_controls = wrap_matrix(self._device_param_controls_raw) self._device_bank_buttons = wrap_matrix(self._device_bank_buttons, partial(DeviceBankButtonElement, modifiers=[self._shift_button])) self._solo_buttons = self._original_solo_buttons self._mute_buttons = self._original_mute_buttons def _create_detail_view_control(self): self._detail_view_toggler = DetailViewCntrlComponent(name='Detail_View_Control', is_enabled=False, layer=Layer(device_clip_toggle_button=self._device_clip_toggle_button, device_nav_left_button=self._detail_left_button, device_nav_right_button=self._detail_right_button)) #detail_toggle_button=self._detail_toggle_button def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_mod(self): self.monomodular = get_monomodular(self) self.monomodular.name = 'monomodular_switcher' self.modhandler = APCModHandler(self) self.modhandler.name = 'ModHandler' self.modhandler.layer = Layer(priority = 5, grid = self._monomod, nav_up_button = self._up_button, nav_down_button = self._down_button, nav_left_button = self._left_button, nav_right_button = self._right_button, shiftlock_button = self._nudge_up_button, alt_button = self._nudge_down_button, shift_button = self._shift_button) self.modhandler.set_device_component(self._device_component) self.modhandler.set_enabled(False) self._monomod_mode = MonomodModeComponent(self._monomod_mode_update, self) self._monomod_mode.name = "Monomod_Mode_Component" self._monomod_mode.layer = Layer(priority = 5, mode_toggle = self._detail_toggle_button) self._on_shift_value.subject = self._shift_button @subject_slot('value') def _on_shift_value(self, value): #self._monomod_mode.set_enabled(value>0) self._monomod_mode.set_enabled(value is 0) #self.modhandler.is_enabled() and self.modhanlder._shift_value(value) if value: self.modhandler.set_lock_button(self._detail_toggle_button) else: self.modhandler.set_lock_button(None) def _monomod_mode_update(self): #self.log_message('mode update: ' + str(self._monomod_mode._mode_index)) if(self._monomod_mode._mode_index == 0): self.flash_status = False self.modhandler.set_enabled(False) self._monomod.reset() self._on_selected_track_changed() elif(self._monomod_mode._mode_index == 1): self.flash_status = True self._monomod.reset() self.modhandler.set_enabled(True) self._detail_toggle_button.send_value(self._monomod_mode._mode_index) """m4l bridge""" def generate_strip_string(self, display_string): #self.log_message(display_string) NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return ret def notification_to_bridge(self, name, value, sender): if isinstance(sender, (MonoRingedEncoderElement, MonoEncoderElement)): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched +=1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip() is True: clip_names.append(clip_slot._clip_slot)##.clip.name) return clip_slot._clip_slot ##self.log_message(str(clip_slot._clip_slot.clip.name)) return clip_names def update_display(self): super(AumPC40, self).update_display() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if self.flash_status: for control, _ in self._monomod.iterbuttons(): if isinstance(control, MonoButtonElement): control.flash(self._timer) def _make_current_bank_details(self, device_component): def _current_bank_details(): if not self.modhandler.active_mod() is None: if self.modhandler.active_mod() and self.modhandler.active_mod()._param_component._device_parent != None: bank_name = self.modhandler.active_mod()._param_component._bank_name bank = [param._parameter for param in self.modhandler.active_mod()._param_component._params] if self.modhandler._alt_value.subject and self.modhandler._alt_value.subject.is_pressed(): bank = bank[8:] #self.log_message('current mod bank details: ' + str(bank_name) + ' ' + str(bank)) return (bank_name, bank) else: return DeviceComponent._current_bank_details(device_component) else: return DeviceComponent._current_bank_details(device_component) return _current_bank_details
class Serato(ControlSurface): def __init__(self, c_instance): publish_in_cs_list = True ControlSurface.__init__(self, c_instance, not publish_in_cs_list) self._device_selection_follows_track_selection = True with self.component_guard(): self._matrix = None self._session = None self._mixer = None self._device = None self._scene_launch_buttons = None self._track_arm_buttons = None self._track_solo_buttons = None self._track_mute_buttons = None self._track_stop_buttons = None self._track_select_buttons = None self._device_on_off_button = None self._shift_button = None self._serato_interface = PySCAClipControl() self._serato_interface.PySCA_InitializeClipControl() self._setup_session_control() self._setup_mixer_control() self._setup_device_control() self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) return def disconnect(self): ControlSurface.disconnect(self) self._serato_interface.PySCA_DeinitializeClipControl() self._serato_interface = None return def connect_script_instances(self, instanciated_scripts): """ Called by the Application as soon as all scripts are initialized. You can connect yourself to other running scripts here, as we do it connect the extension modules (MackieControlXTs). """ for control_surface in self._control_surfaces(): control_surface_session = control_surface.highlighting_session_component( ) if control_surface_session: self._session.sync_to(control_surface_session) self._on_track_list_changed() break def build_midi_map(self, midi_map_handle): pass def update_display(self): ControlSurface.update_display(self) while self._serato_interface.PySCA_HasIncomingEvent(): new_event = self._serato_interface.PySCA_GetIncomingEvent() if not self._handle_session_event(new_event): if not self._handle_mixer_event(new_event): if not self._handle_device_event(new_event): print 'Unhandled Event: ' + str(new_event) def _setup_session_control(self): is_momentary = True self._session = SpecialSessionComponent(NUM_TRACKS, NUM_SCENES) self._session.set_serato_interface(self._serato_interface) self._matrix = ButtonMatrixElement() self._scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_SCENES) ] self._track_stop_buttons = [ ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0) for index in range(NUM_TRACKS) ] stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) self._session.set_stop_all_clips_button(stop_all_button) self._session.set_stop_track_clip_buttons( tuple(self._track_stop_buttons)) for scene_index in range(NUM_SCENES): scene = self._session.scene(scene_index) button_row = [] scene.set_launch_button(self._scene_launch_buttons[scene_index]) scene.set_index(scene_index) scene.set_serato_interface(self._serato_interface) for track_index in range(NUM_TRACKS): button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(button) clip_slot.set_serato_interface(self._serato_interface) self._matrix.add_row(tuple(button_row)) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(NUM_TRACKS) self._mixer.set_serato_interface(self._serato_interface) self._mixer.master_strip().set_serato_interface(self._serato_interface) self._track_arm_buttons = [] self._track_solo_buttons = [] self._track_mute_buttons = [] self._track_select_buttons = [] self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 0) for track in range(NUM_TRACKS): strip = self._mixer.channel_strip(track) strip.set_serato_interface(self._serato_interface) self._track_arm_buttons.append( ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_solo_buttons.append( ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_mute_buttons.append( ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) self._track_select_buttons.append( ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0)) strip.set_arm_button(self._track_arm_buttons[-1]) strip.set_solo_button(self._track_solo_buttons[-1]) strip.set_mute_button(self._track_mute_buttons[-1]) strip.set_select_button(self._track_select_buttons[-1]) strip.set_shift_button(self._shift_button) def _setup_device_control(self): is_momentary = True self._device_on_off_button = ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 0) self._device = SpecialDeviceComponent() self._device.set_serato_interface(self._serato_interface) self._device.set_parameter_controls( tuple([ SliderElement(MIDI_CC_TYPE, 0, 0) for index in range(NUM_PARAMS) ])) self._device.set_on_off_button(self._device_on_off_button) self.set_device_component(self._device) def _handle_session_event(self, event): result = False if event.type in CLIP_EVENTS: value = 127 * int(event.type == libInterprocessCommsAPIPython. kAbletonClipControlEventClipPlayedDown) track_index = event.key1 - 1 scene_index = event.key2 - 1 if track_index in range(NUM_TRACKS) and scene_index in range( NUM_SCENES): self._matrix.get_button(track_index, scene_index).receive_value(value) result = True elif event.type in SCENE_EVENTS: value = 127 * int(event.type == libInterprocessCommsAPIPython. kAbletonClipControlEventScenePlayedDown) scene_index = event.key1 - 1 if scene_index in range(NUM_SCENES): self._scene_launch_buttons[scene_index].receive_value(value) result = True elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixSizeChanged: new_width = event.key1 new_height = event.key2 self._session.set_size(new_width, new_height) result = True elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlMatrixOffsetChanged: x_increment = event.key1 y_increment = event.key2 self._session.move_by(x_increment, y_increment) result = True return result def _handle_mixer_event(self, event): result = True track_index = event.key1 - 1 value = event.key2 if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackMasterGainChange: self._mixer.master_strip().set_track_volume(fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackStopped: self.song().stop_all_clips() elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventMasterTrackSelect: self.song().view.selected_track = self.song().master_track else: result = track_index in range( NUM_TRACKS) and self._handle_strip_event(event) return result def _handle_strip_event(self, event): result = True track_index = event.key1 - 1 value = event.key2 if value == 0: self._shift_button.receive_value(127) if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSolo: self._track_solo_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackRecord: self._track_arm_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackActive: self._track_mute_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackStopped: self._track_stop_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSelect: self._track_select_buttons[track_index].receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackGainChange: self._mixer.channel_strip(track_index).set_track_volume( fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendAChange: self._mixer.channel_strip(track_index).set_send( 0, fixed_value(value)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventTrackSendBChange: self._mixer.channel_strip(track_index).set_send( 1, fixed_value(value)) else: result = False self._shift_button.receive_value(0) return result def _handle_device_event(self, event): result = True if event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceValueChanged: self._device.set_parameter_value(event.key1 - 1, fixed_value(event.key2)) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceActivate: self._device_on_off_button.receive_value(127) elif event.type == libInterprocessCommsAPIPython.kAbletonClipControlEventDeviceFocusMove: self._move_device_focus(event.key1) else: result = False return result def _move_device_focus(self, increment): if not self.application().view.is_view_visible( 'Detail') or not self.application().view.is_view_visible( 'Detail/DeviceChain'): self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: modifier_pressed = True direction = Live.Application.Application.View.NavDirection.left if increment > 0: direction = Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed)
class Codec(ControlSurface): __module__ = __name__ __doc__ = " MonoCode controller script " def __init__(self, c_instance, *a, **k): super(Codec, self).__init__(c_instance, *a, **k) self._monomod_version = 'b995' self._version_check = 'b995' self._host_name = 'Codec' self._color_type = 'Monochrome' self._link_mixer = LINK_MIXER self._hosts = [] self._linked_script = None self._local_ring_control = True self._last_device = None self._device_list = [None, None, None, None] self._device_select_buttons = None self._last_device_component = None self._timer = 0 self._touched = 0 self._locked = False self.flash_status = 1 self._shift_button = None self._shift_pressed = 0 self._shift_pressed_timer = 0 self._shift_thresh = SHIFT_THRESH self._use_device_selector = USE_DEVICE_SELECTOR self._device_selection_follows_track_selection = FOLLOW with self.component_guard(): #self.local_ring_control(True) #self.set_absolute_mode(True) self._setup_controls() self._setup_monobridge() self._setup_device_controls() self._setup_special_device_control() self._device.append( self._special_device ) #necessary for device browsing to work with special device self._setup_device_chooser() self._setup_mixer_controls() self._setup_monomod() self._setup_modes() self._setup_device_selector() self._setup_send_reset() self._setup_default_buttons() self.set_local_ring_control(1) self.song().view.add_selected_track_listener( self._update_selected_device) self._initialize_code() #self._shift_mode.set_mode(0) #self._monomod_mode.set_mode(0) self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Codec ' + str(self._monomod_version) + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>') self.show_message('Codec Control Surface Loaded') self.request_rebuild_midi_map() """script initialization methods""" def _initialize_code(self): self._send_midi(factoryreset) self._send_midi(btn_channels) self._send_midi(enc_channels) def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_controls(self): is_momentary = True self._livid = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self) self._dial = [None for index in range(8)] for column in range(8): self._dial[column] = [None for index in range(4)] for row in range(4): self._dial[column][row] = CodecEncoderElement( MIDI_CC_TYPE, CHANNEL, CODE_DIALS[row][column], Live.MidiMap.MapMode.absolute, 'Dial_' + str(column) + '_' + str(row), (column + (row * 8)), self) #CODE_DIALS[row][column] self._button = [None for index in range(8)] for column in range(8): self._button[column] = [None for index in range(4)] for row in range(4): self._button[column][row] = CodecMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_BUTTONS[row][column], 'Button_' + str(column) + '_' + str(row), self) self._column_button = [None for index in range(8)] for index in range(8): self._column_button[index] = CodecMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_COLUMN_BUTTONS[index], 'Column_Button_' + str(index), self) self._row_button = [None for index in range(4)] for index in range(4): self._row_button[index] = CodecMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_ROW_BUTTONS[index], 'Row_Button_' + str(index), self) self._dial_matrix = EncoderMatrixElement(self) self._dial_matrix.name = 'Encoder_Matrix' for row in range(4): dial_row = tuple([self._dial[column][row] for column in range(8)]) self._dial_matrix.add_row(dial_row) self._button_matrix = ButtonMatrixElement() self._button_matrix.name = 'Button_Matrix' for row in range(4): button_row = [self._button[column][row] for column in range(8)] button_row.append(self._row_button[row]) self._button_matrix.add_row(tuple(button_row)) self._button_matrix.add_row(tuple(self._column_button + [self._livid])) def _setup_modes(self): self._monomod_mode = MonomodModeComponent(self._mod_mode_update, self) self._monomod_mode.name = 'Monomod_Mode' self.set_shift_button(self._livid) self._shift_mode = ShiftModeComponent(self._shift_update, self) self._shift_mode.name = 'Shift_Mode' self._shift_mode.set_mode_buttons( tuple([ self._row_button[0], self._row_button[1], self._row_button[2], self._row_button[3] ])) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_monomod(self): self._host = CodecMonomodComponent(self) self._host.name = 'Monomod_Host' self._host._set_dial_matrix(self._dial_matrix, self._button_matrix) self.hosts = [self._host] encs = [] for row in range(4): for col in range(8): encs.append(self._dial[col][row]) self._host._set_parameter_controls(encs) def _setup_mixer_controls(self): is_momentary = True self._num_tracks = (8) self._session = SessionComponent(self._num_tracks, 0) self._session.name = 'Session' self._mixer = MixerComponent(self._num_tracks, 0, False, False) self._mixer.name = 'Mixer' self._mixer._next_track_value = self._mixer_next_track_value( self._mixer) self._mixer._prev_track_value = self._mixer_prev_track_value( self._mixer) self._mixer.set_track_offset( 0) #Sets start point for mixer strip (offset from left) #for index in range(8): #use the bottom row of encoders for volume, so add 24 to offset the index # self._mixer.channel_strip(index).set_volume_control(self._dial[index+24]) for index in range(8): self._mixer.channel_strip( index).name = 'Mixer_ChannelStrip_' + str(index) self._mixer.channel_strip(index)._invert_mute_feedback = True self._mixer.channel_strip( index)._mute_value = self._channelstrip_mute_value( self._mixer.channel_strip(index)) self._mixer.channel_strip( index)._solo_value = self._channelstrip_solo_value( self._mixer.channel_strip(index)) #mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index])) self.song().view.selected_track = self._mixer.channel_strip( 0 )._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error self._session.set_mixer(self._mixer) def _setup_device_controls(self): self._device = [None for index in range(4)] for index in range(4): self._device[index] = CodecDeviceComponent(self) self._device[index].name = 'CodecDevice_Component_' + str(index) device_param_controls = [] for control in range(8): device_param_controls.append(self._dial[control][index]) self._device[index].set_on_off_button(self._button[1][index]) self._device[index].set_lock_button(self._button[2][index]) self._device[index].set_bank_nav_buttons(self._button[4][index], self._button[5][index]) self._device[index].set_nav_buttons(self._button[6][index], self._button[7][index]) self._device[index].set_parameter_controls( tuple(device_param_controls)) self.set_device_component(self._device[0]) self._last_device_component = self._device[0] def _setup_special_device_control(self): self._special_device = SpecialCodecDeviceComponent(self) self._special_device.name = 'SpecialCodecDeviceComponent' self._special_device.set_on_off_button(self._button[1][0]) self._special_device.set_lock_button(self._button[2][0]) self._special_device.set_bank_nav_buttons(self._button[4][0], self._button[5][0]) self._special_device.set_nav_buttons(self._button[6][0], self._button[7][0]) device_param_controls = [] for row in range(4): for column in range(8): device_param_controls.append(self._dial[column][row]) self._special_device.set_parameter_controls( tuple(device_param_controls)) def _setup_device_chooser(self): self._selected_device = self._device[0] self._last_selected_device = self._device[0] self._device_select_buttons = [ self._button[0][index] for index in range(4) ] for button in self._device_select_buttons: button.add_value_listener(self._device_select_value, True) def _setup_device_selector(self): self._device_selector = CodecDeviceSelectorComponent( self, 'c', self._device + [self._special_device]) self._device_selector.name = 'Device_Selector' self._device_selector.set_mode_buttons(self._column_button) #self._device_selector.set_mode_toggle(self._livid) def _setup_send_reset(self): self._send_reset = CodecResetSendsComponent(self) self._send_reset.set_buttons(self._button) def _setup_default_buttons(self): self._value_default = ParameterDefaultComponent(self) buttons = [] dials = [] for column in self._button: for button in column: buttons.append(button) for column in self._dial: for dial in column: dials.append(dial) self._value_default.set_buttons(buttons) self._value_default.set_dials(dials) """multiple device support""" def _device_select_value(self, value, sender): #self.log_message('device_select_value ' + str(value) + ' ' + str(self._device_select_buttons.index(sender))) if not self._shift_pressed: if sender.is_momentary or value > 0: if self._shift_mode._mode_index == 2: self.set_device_component(self._device[ self._device_select_buttons.index(sender)]) self._last_device_component = self._device_component if self._device_component != None and isinstance( self._device_component._device, Live.Device.Device): if self._device_component.find_track( self._device_component._device) == self.song( ).view.selected_track: self._device_component.display_device() """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: self._send_midi(SLOWENCODER) if (self._shift_pressed_timer + self._shift_thresh) > self._timer: #if(self._host.is_enabled() != True) self.log_message('mod mode: ' + str(abs(self._monomod_mode._mode_index - 1))) self._monomod_mode.set_mode( max(0, min(1, abs(self._monomod_mode._mode_index - 1)))) #else: # self._monomod_mode.set_mode(0) self._shift_pressed_timer = self._timer % 256 else: self._send_midi(NORMALENCODER) def _mod_mode_update(self): if (self._monomod_mode._mode_index == 0): self._host._set_shift_button(None) self._host.set_enabled(False) self._dial_matrix.reset() self._shift_mode.set_enabled(True) self._shift_update() self.request_rebuild_midi_map() self._livid.turn_off() elif (self._monomod_mode._mode_index == 1): self._shift_mode.set_enabled(False) self._deassign_all() self._dial_matrix.reset() self._button_matrix.reset() self._livid.turn_on() if not self._host._active_client == None: self._host.set_enabled(True) self._host._set_shift_button(self._livid) else: self._assign_alternate_mappings(1) self.request_rebuild_midi_map() """Mode Functions""" def _shift_update(self): if (self._shift_mode.is_enabled()): with self.component_guard(): self.allow_updates(False) #if(not self._in_build_midi_map): # self.set_suppress_rebuild_requests(True) self._deassign_all() if (self._shift_mode._mode_index is 0): self._assign_volume() elif (self._shift_mode._mode_index is 1): self._assign_sends() elif (self._shift_mode._mode_index is 2): self._assign_devices() elif (self._shift_mode._mode_index is 3): self._assign_special_device() for index in range(self._shift_mode.number_of_modes()): if index == self._shift_mode._mode_index: self._shift_mode._modes_buttons[index].turn_on() else: self._shift_mode._modes_buttons[index].turn_off() self.allow_updates(True) #self.set_suppress_rebuild_requests(False) self.request_rebuild_midi_map() def _deassign_all(self): self._assign_alternate_mappings(0) self._device_selector.set_enabled(False) for index in range(8): self._mixer.channel_strip(index).set_volume_control(None) self._mixer.channel_strip(index).set_pan_control(None) self._mixer.channel_strip(index).set_send_controls( tuple([None, None, None, None])) for index in range(4): self._device[index].set_enabled(False) self._device[index]._parameter_controls = None #self._device_navigator[index].set_enabled(False) self._special_device.set_enabled(False) self._special_device._parameter_controls = None self._device_selector.set_enabled(False) self._deassign_buttons() for control in self.controls: control.reset() self.request_rebuild_midi_map() def _deassign_buttons(self): for index in range(8): self._mixer.channel_strip(index).set_select_button(None) self._mixer.channel_strip(index).set_solo_button(None) self._mixer.channel_strip(index).set_mute_button(None) self._mixer.set_select_buttons(None, None) self._send_reset.set_enabled(False) def _assign_volume(self): for index in range(8): self._mixer.channel_strip(index).set_volume_control( self._dial[index][3]) self._mixer.channel_strip(index).set_pan_control( self._dial[index][2]) self._mixer.channel_strip(index).set_send_controls( tuple([self._dial[index][0], self._dial[index][1]])) self._mixer.channel_strip(index).set_select_button( self._column_button[index]) self._mixer.channel_strip(index).set_solo_button( self._button[index][2]) self._mixer.channel_strip(index).set_mute_button( self._button[index][3]) self._mixer.set_select_buttons(self._button[7][0], self._button[6][0]) def _assign_sends(self): for index in range(8): self._mixer.channel_strip(index).set_send_controls( tuple([ self._dial[index][0], self._dial[index][1], self._dial[index][2], self._dial[index][3] ])) self._mixer.channel_strip(index).set_select_button( self._column_button[index]) self._send_reset.set_enabled(True) def _assign_devices(self): self.set_device_component(self._last_device_component) self._device_select_value( 1, self._device_select_buttons[self._device.index( self._device_component)]) for index in range(4): device_param_controls = [] for control in range(8): device_param_controls.append(self._dial[control][index]) self._device[index].set_parameter_controls( tuple(device_param_controls)) self._device[index].set_enabled(True) self._device_selector.set_enabled(self._use_device_selector) if not self._use_device_selector: for index in range(8): self._mixer.channel_strip(index).set_select_button( self._column_button[index]) def _assign_special_device(self): self.set_device_component(self._special_device) device_param_controls = [] for row in range(4): for column in range(8): device_param_controls.append(self._dial[column][row]) self._special_device.set_parameter_controls( tuple(device_param_controls)) self._special_device.set_enabled(True) self._device_selector.set_enabled(self._use_device_selector) if not self._use_device_selector: for index in range(8): self._mixer.channel_strip(index).set_select_button( self._column_button[index]) def _assign_alternate_mappings(self, chan): for column in self._dial: for control in column: control.set_channel(chan) control.set_enabled(chan is 0) for column in self._button: for control in column: control.set_channel(chan) control.set_enabled(chan is 0) for control in self._column_button: control.set_channel(chan) control.set_enabled(chan is 0) for control in self._row_button: control.set_channel(chan) control.set_enabled(chan is 0) """general functionality""" def disconnect(self): """clean things up on disconnect""" if not self._shift_button is None: if self._shift_button.value_has_listener(self._shift_value): self._shift_button.remove_value_listener(self._shift_value) for button in self._device_select_buttons: if button.value_has_listener(self._device_select_value): button.remove_value_listener(self._device_select_value) if self._session._is_linked(): self._session._unlink() self.song().view.remove_selected_track_listener( self._update_selected_device) """for cs in self._control_surfaces(): for host in self._hosts: self.log_message('installed: ' + str(cs) + ' vs. ' + str(host)) if str(type(cs)) == str(type(host)): self.log_message('disconnecting: ' + str(type(cs))) cs.disconnect(cs)""" #self._host._set_parameter_controls(None) self._hosts = [] if self._linked_script != None: self._linked_script._update_linked_device_selection = None self._linked_script = None #self._disconnect_notifier.set_mode(0) self.log_message( '<<<<<<<<<<<<<<<<<<<<<<<<< Codec log closed >>>>>>>>>>>>>>>>>>>>>>>>>' ) ControlSurface.disconnect(self) return None def connect_script_instances(self, instanciated_scripts): found = False for s in instanciated_scripts: if '_codec_version' in dir(s): if s._codec_version == self._version_check: if s._host_name == ('MonOhm'): self.log_message('found codec version ' + str(s._codec_version) + ' in script ' + str(s._host_name)) found = True self._linked_script = s self._linked_script._update_linked_device_selection = self._update_linked_device_selection if not self._session._is_linked( ) and self._link_mixer is True: self._session.set_offsets(LINK_OFFSET[0], LINK_OFFSET[1]) self._session._link() else: self.log_message('version mismatch: Monomod version ' + str(self._version_check) + ' vs. Host version ' + str(s._codec_version)) if found == False: for s in instanciated_scripts: if '_codec_version' in dir(s): if s._codec_version == self._version_check: if s._host_name == 'BlockMod': self.log_message('found codec version ' + str(s._codec_version) + ' in script ' + str(s._host_name)) self._linked_script = s self._linked_script._update_linked_device_selection = self._update_linked_device_selection if not self._session._is_linked( ) and self._link_mixer is True: self._session.set_offsets(LINK_OFFSET[0], LINK_OFFSET[1]) self._session._link() else: self.log_message('version mismatch: Monomod version ' + str(self._version_check) + ' vs. Host version ' + str(s._codec_version)) #self.log_message('hosts: ' + str(self._hosts))""" def update_display(self): ControlSurface.update_display( self ) #since we are overriding this from the inherited method, we need to call the original routine as well self._timer = (self._timer + 1) % 256 if (self._timer == 0): self._shift_pressed_timer = -12 if (self._local_ring_control is False): self.send_ring_leds() self.flash() def handle_sysex(self, midi_bytes): #self._send_midi(tuple([240, 00, 01, 97, 04, 15, 01, 247])) #response = [long(0),long(0)] #self.log_message(response) pass def flash(self): if (self.flash_status > 0): for control in self.controls: if isinstance(control, MonoButtonElement): control.flash(self._timer) def send_ring_leds(self): leds = [240, 0, 1, 97, 4, 31] for column in range(8): for row in range(4): wheel = self._dial[column][row] bytes = wheel._get_ring() leds.append(bytes[0]) leds.append(int(bytes[1]) + int(bytes[2])) #if(row == 1 and column == 0): # self.log_message(str(leds) + ' ' + str(bytes[0]) + ' ' + str(bytes[1]) + ' ' + str(bytes[2])) leds.append(247) self._send_midi(tuple(leds)) def set_absolute_mode(self, val=1): self._absolute_mode = (val != 0) if self._absolute_mode is True: self._send_midi( tuple([240, 0, 1, 97, 4, 17, 0, 0, 0, 0, 0, 0, 0, 0, 247])) else: self._send_midi( tuple([ 240, 0, 1, 97, 4, 17, 127, 127, 127, 127, 127, 127, 127, 127, 247 ])) def set_local_ring_control(self, val=1): self._local_ring_control = (val != 0) if (self._local_ring_control is True): #self._send_midi(tuple([240, 0, 1, 97, 4, 32, 0, 247])) self._send_midi(tuple([240, 0, 1, 97, 4, 8, 72, 247])) else: #self._send_midi(tuple([240, 0, 1, 97, 4, 32, 1, 247])) self._send_midi(tuple([240, 0, 1, 97, 4, 8, 64, 247])) def device_follows_track(self, val): self._device_selection_follows_track_selection = (val == 1) return self """m4l bridge""" def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center( (NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return ret def notification_to_bridge(self, name, value, sender): if (isinstance(sender, CodecEncoderElement)): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if not self._host.is_enabled(): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched += 1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip() is True: clip_names.append(clip_slot._clip_slot) ##.clip.name) return clip_slot._clip_slot ##self.log_message(str(clip_slot._clip_slot.clip.name)) return clip_names """overrides""" def allow_updates(self, allow_updates): for component in self.components: component.set_allow_update(int(allow_updates != 0)) def set_device_component(self, device_component): if self._device_component != None: self._device_component._lock_callback = None assert (device_component != None) assert isinstance(device_component, DeviceComponent) self._device_component = device_component self._device_component._lock_callback = self._toggle_lock #old: self._device_component.set_lock_callback(self._toggle_lock) if self._device_select_buttons != None: for button in self._device_select_buttons: button.send_value( self._device_select_buttons.index(button) == self._device.index(self._device_component)) self._update_device_selection() return None def _update_selected_device(self): if self._device_selection_follows_track_selection is True: self._update_device_selection() return None def _update_linked_device_selection(self, device): #self.log_message('codec received ' + str(device.name)) if self._device_component != None and device != None: if not self._device_component.is_locked(): self._device_component.set_device(device) def _get_num_tracks(self): return self.num_tracks def _update_device_selection(self): #self.log_message('_update_device_selection') if self._device_component != None: if not self._device_component.is_locked(): track = self.song().view.selected_track device_to_select = track.view.selected_device if ((device_to_select == None) and (len(track.devices) > 0)): device_to_select = track.devices[0] if (device_to_select != None): self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) def _channelstrip_mute_value(self, channelstrip): def _mute_value(value): if not self._shift_pressed: self.log_message('shift not pressed') ChannelStripComponent._mute_value(channelstrip, value) return _mute_value def _channelstrip_solo_value(self, channelstrip): def _solo_value(value): if not self._shift_pressed: ChannelStripComponent._solo_value(channelstrip, value) return _solo_value def _mixer_next_track_value(self, mixer): def _next_track_value(value): if not self._shift_pressed: MixerComponent._next_track_value(mixer, value) return _next_track_value def _mixer_prev_track_value(self, mixer): def _prev_track_value(value): if not self._shift_pressed: MixerComponent._prev_track_value(mixer, value) return _prev_track_value
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self.set_suppress_rebuild_requests(True) self._suppress_send_midi = True self._suppress_session_highlight = True is_momentary = True self._suggested_input_port = 'Launchpad' self._suggested_output_port = 'Launchpad' self._control_is_with_automap = False self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = 'User_Byte_Button' self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self._wrote_user_byte = False self._challenge = Live.Application.get_random_int( 0, 400000000) & 2139062143 matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' for row in range(8): button_row = [] for column in range(8): button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, row * 16 + column) button.name = str(column) + '_Clip_' + str(row) + '_Button' button_row.append(button) matrix.add_row(tuple(button_row)) self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0) self._config_button.add_value_listener(self._config_value) top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index) for index in range(8) ] side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index]) for index in range(8) ] top_buttons[0].name = 'Bank_Select_Up_Button' top_buttons[1].name = 'Bank_Select_Down_Button' top_buttons[2].name = 'Bank_Select_Left_Button' top_buttons[3].name = 'Bank_Select_Right_Button' top_buttons[4].name = 'Session_Button' top_buttons[5].name = 'User1_Button' top_buttons[6].name = 'User2_Button' top_buttons[7].name = 'Mixer_Button' side_buttons[0].name = 'Vol_Button' side_buttons[1].name = 'Pan_Button' side_buttons[2].name = 'SndA_Button' side_buttons[3].name = 'SndB_Button' side_buttons[4].name = 'Stop_Button' side_buttons[5].name = 'Trk_On_Button' side_buttons[6].name = 'Solo_Button' side_buttons[7].name = 'Arm_Button' self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self) self._selector.name = 'Main_Modes' self._do_combine() for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.add_value_listener(self._button_value) self._suppress_session_highlight = False self.set_suppress_rebuild_requests(False) self.log_message("LaunchPad85 Loaded !")
class APC20(APC): """ Script for Akai's APC20 Controller """ def __init__(self, *a, **k): super(APC20, self).__init__(*a, **k) self._skin = make_biled_skin() with self.component_guard(): self._create_controls() self._create_session() self._create_mixer() self._create_transport() self._create_background() self._create_global_control() self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) for component in self.components: component.set_enabled(False) def _activate_combination_mode(self, track_offset, support_devices): super(APC20, self)._activate_combination_mode(track_offset, support_devices) if support_devices: self._shift_modes.invert_assignment() def _create_controls(self): make_color_button = partial(make_button, skin=self._skin) self._shift_button = make_button(0, 81, name='Shift_Button') self._matrix = ButtonMatrixElement(name='Button_Matrix') self._scene_launch_buttons = [ make_color_button(0, index + 82, name='Scene_%d_Launch_Button' % index) for index in xrange(SESSION_HEIGHT) ] self._track_stop_buttons = [ make_color_button(index, 52, name='Track_%d_Stop_Button' % index) for index in xrange(SESSION_WIDTH) ] for scene_index in xrange(SESSION_HEIGHT): row = [ make_color_button(track_index, scene_index + 53, name='%d_Clip_%d_Button' % (track_index, scene_index)) for track_index in xrange(SESSION_WIDTH) ] self._matrix.add_row(row) self._selected_scene_launch_button = make_pedal_button(64, name='Selected_Scene_Launch_Button') self._scene_launch_buttons = ButtonMatrixElement(name='Scene_Launch_Buttons', rows=[self._scene_launch_buttons]) self._solo_buttons = [ make_button(track_index, 49, name='%d_Solo_Button' % track_index) for track_index in xrange(MIXER_SIZE) ] self._mute_buttons = [ make_button(track_index, 50, name='%d_Mute_Button' % track_index) for track_index in xrange(MIXER_SIZE) ] self._master_volume_control = make_slider(0, 14, name='Master_Volume_Control') self._prehear_control = EncoderElement(MIDI_CC_TYPE, 0, 47, MapMode.relative_two_compliment, name='Prehear_Volume_Control') self._master_select_button = make_button(0, 80, name='Master_Select_Button') self._select_buttons = [ make_button(track_index, 51, name='%d_Select_Button' % track_index) for track_index in xrange(8) ] self._arm_buttons = [ make_button(track_index, 48, name='%d_Arm_Button' % track_index) for track_index in xrange(8) ] self._sliders = [ make_slider(track_index, 7, name='%d_Volume_Control' % track_index) for track_index in xrange(8) ] self._note_matrix = ButtonMatrixElement(name='Note_Button_Matrix') self._note_buttons = [ [ make_button(9, note + i, name='Note_%d_Button' % (note + i)) for i in xrange(4) ] for note in xrange(36, 75, 4) ] for row in self._note_buttons: for button in row: button.send_depends_on_forwarding = False self._note_matrix.add_row(row) def _create_session(self): self._session = SessionComponent(SESSION_WIDTH, SESSION_HEIGHT, name='Session_Control', auto_name=True, enable_skinning=True) self._session.set_clip_launch_buttons(self._matrix) self._session.set_stop_track_clip_buttons(tuple(self._track_stop_buttons)) self._session.set_scene_launch_buttons(self._scene_launch_buttons) for scene_index in xrange(SESSION_HEIGHT): scene = self._session.scene(scene_index) for track_index in xrange(SESSION_WIDTH): clip_slot = scene.clip_slot(track_index) clip_slot.name = '%d_Clip_Slot_%d' % (track_index, scene_index) self._session.selected_scene().set_launch_button(self._selected_scene_launch_button) self._session_zoom = ShiftableZoomingComponent(self._session, tuple(self._track_stop_buttons), name='Session_Overview', enable_skinning=True) self._session_zoom.set_button_matrix(self._matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_scene_bank_buttons(self._scene_launch_buttons) def _create_mixer(self): self._mixer = MixerComponent(MIXER_SIZE, name='Mixer') self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.selected_strip().name = 'Selected_Channel_Strip' buttons = izip(self._solo_buttons, self._mute_buttons) for track_index, (solo_button, mute_button) in enumerate(buttons): strip = self._mixer.channel_strip(track_index) strip.name = 'Channel_Strip_%d' % track_index strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) self._mixer.set_prehear_volume_control(self._prehear_control) self._mixer.master_strip().set_volume_control(self._master_volume_control) def _create_transport(self): self._transport = TransportComponent(name='Transport') def _create_background(self): self._background = BackgroundComponent(name='Background') def _create_global_control(self): self._slider_modes = SliderModesComponent(self._mixer, tuple(self._sliders), name='Slider_Modes') self._shift_modes = ShiftableSelectorComponent(tuple(self._select_buttons), self._master_select_button, tuple(self._arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, self._transport, self._slider_modes, self._send_introduction_message, self._note_matrix, self._background, name='Shift_Modes') self._shift_modes.set_mode_toggle(self._shift_button) def _product_model_id_byte(self): return 123
class APC20(APC): """ Script for Akai's APC20 Controller """ def __init__(self, c_instance): self._shift_modes = None APC.__init__(self, c_instance) def disconnect(self): self._shift_modes = None APC.disconnect(self) def _activate_combination_mode(self, track_offset, support_devices): APC._activate_combination_mode(self, track_offset, support_devices) if support_devices: self._shift_modes.invert_assignment() def _setup_session_control(self): is_momentary = True self._shift_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) self._session = APCSessionComponent(8, 5) self._session.name = 'Session_Control' self._matrix = ButtonMatrixElement() self._matrix.name = 'Button_Matrix' scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, index + 82) for index in range(5) ] track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(8) ] for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_' + str( index) + '_Launch_Button' for index in range(len(track_stop_buttons)): track_stop_buttons[index].name = 'Track_' + str( index) + '_Stop_Button' self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session.set_stop_track_clip_value(2) for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, scene_index + 53) button.name = str(track_index) + '_Clip_' + str( scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(5) clip_slot.set_started_value(1) clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) self._matrix.add_row(tuple(button_row)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = ShiftableZoomingComponent( self._session, tuple(track_stop_buttons)) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(self._matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5) def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.selected_strip().name = 'Selected_Channel_Strip' for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) solo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50) solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) prehear_control = EncoderElement( MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) master_volume_control.name = 'Master_Volume_Control' prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_prehear_volume_control(prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) def _setup_custom_components(self): is_momentary = True master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) master_select_button.name = 'Master_Select_Button' select_buttons = [] arm_buttons = [] sliders = [] for track in range(8): select_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51)) arm_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48)) sliders.append(SliderElement(MIDI_CC_TYPE, track, 7)) select_buttons[-1].name = str(track) + '_Select_Button' arm_buttons[-1].name = str(track) + '_Arm_Button' sliders[-1].name = str(track) + '_Volume_Control' transport = TransportComponent() transport.name = 'Transport' slider_modes = SliderModesComponent(self._mixer, tuple(sliders)) slider_modes.name = 'Slider_Modes' self._shift_modes = ShiftableSelectorComponent( tuple(select_buttons), master_select_button, tuple(arm_buttons), self._matrix, self._session, self._session_zoom, self._mixer, transport, slider_modes, self._send_introduction_message) self._shift_modes.name = 'Shift_Modes' self._shift_modes.set_mode_toggle(self._shift_button) def _product_model_id_byte(self): return 123
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self._suggested_input_port = "Launchpad" self._suggested_output_port = "Launchpad" # Launchpad configuration self._send_midi(LAUNCHPAD_RESET) self._send_midi(LAUNCHPAD_ENABLE_BLINKING) # make buttons top_buttons = [make_button(MIDI_CC_TYPE, 104 + i) for i in range(8)] side_buttons = [make_button(MIDI_NOTE_TYPE, 8 + 16 * i) for i in range(8)] matrix = ButtonMatrixElement() for row in range(8): button_row = [make_button(MIDI_NOTE_TYPE, 16 * row + col) for col in range(8)] matrix.add_row(tuple(button_row)) # mixer and session components self._mixer = MixerComponent(8) self._session = SessionComponent(8, SCENES_AMOUNT) self._session.set_mixer(self._mixer) self.set_highlighting_session_component(self._session) # navigation for button in top_buttons[:4]: button.set_on_off_values(GREEN_FULL, GREEN_THIRD) self._session.set_scene_bank_buttons(top_buttons[1], top_buttons[0]) self._session.set_track_bank_buttons(top_buttons[3], top_buttons[2]) # clip launch for scene_index in range(SCENES_AMOUNT): scene = self._session.scene(scene_index) scene.set_launch_button(side_buttons[scene_index]) scene.set_triggered_value(GREEN_BLINK) scene.set_scene_value(GREEN_THIRD) scene.set_no_scene_value(LED_OFF) for track_index in range(8): clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(matrix.get_button(track_index, scene_index)) clip_slot.set_triggered_to_play_value(GREEN_BLINK) clip_slot.set_triggered_to_record_value(RED_BLINK) clip_slot.set_started_value(GREEN_FULL) clip_slot.set_stopped_value(AMBER_THIRD) clip_slot.set_recording_value(RED_FULL) # track stop self._session.set_stop_track_clip_buttons([matrix.get_button(i, ROW_STOP) for i in range(8)]) self._session.set_stop_clip_value(RED_THIRD) self._session.set_stop_clip_triggered_value(RED_BLINK) button_stop_all = side_buttons[ROW_STOP] button_stop_all.set_on_off_values(RED_FULL, RED_THIRD) self._session.set_stop_all_clips_button(button_stop_all) # track select self._mixer.set_track_select_buttons([matrix.get_button(i, ROW_SELECT) for i in range(8)]) self._mixer.set_track_select_values(AMBER_FULL, AMBER_THIRD, LED_OFF) button_select_master = side_buttons[ROW_SELECT] button_select_master.set_on_off_values(AMBER_FULL, AMBER_THIRD) self._mixer.set_master_select_button(button_select_master) # delete clip button self._delete_button = top_buttons[INDEX_DELETE_BUTTON] self._delete_button.set_on_off_values(RED_BLINK, RED_THIRD) self._delete_button.add_value_listener(self._delete_value_listener) self._del_pressed = False self._delete_button.turn_off() # quantization toggle self._quantization_toggle = QuantizationToggle( top_buttons[INDEX_QUANTIZATION_BUTTON], self.song(), GREEN_THIRD, RED_THIRD ) # browser view toggle self._browser_view_toggle = ViewToggle( side_buttons[INDEX_BROWSER_VIEW_BUTTON], ABLETON_VIEW_BROWSER, GREEN_THIRD, RED_THIRD ) # detail view toggle self._device_view_toggle = DetailViewToggle( side_buttons[INDEX_DETAIL_VIEW_BUTTON], GREEN_THIRD, RED_THIRD, LED_OFF )
class LemurPad(MonOhm): __module__ = __name__ __doc__ = " Lemur version of the MonOhm companion controller script " def __init__(self, *a, **k): self._timer_callbacks = [ ] #Used for _monobridge, which uses L8 method for registering timer callbacks. deprecated, needs to be replaced by new L9 Task class. self._osc_registry = {} self._display_button_names = DISPLAY_BUTTON_NAMES super(LemurPad, self).__init__(*a, **k) self._host_name = "LemurPad" self._color_type = 'AumPad' self.connected = 0 with self.component_guard(): self._setup_touchosc() self._assign_host2() self._assign_session_colors() def query_ohm(self): pass """script initialization methods""" def _setup_monobridge(self): self._monobridge = OSCMonoBridgeElement(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(8): self._fader[index] = OSCMonoEncoderElement( MIDI_CC_TYPE, CHANNEL, OHM_FADERS[index], Live.MidiMap.MapMode.absolute, 'Fader_' + str(index), index, self, osc='/Fader_' + str(index) + '/x', osc_parameter='/Strip' + str(index + 8) + '/set', osc_name='/Strip' + str(index) + '/set') for index in range(8): self._button[index] = OSCMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_BUTTONS[index], 'Button_' + str(index), self, osc='/Select_' + str(index) + '/value', osc_alt='/Select/set ' + str(index), osc_name='/Select/text ' + str(index)) for index in range(16): self._dial[index] = OSCMonoEncoderElement( MIDI_CC_TYPE, CHANNEL, OHM_DIALS[index], Live.MidiMap.MapMode.absolute, 'Dial_' + str(index), index + 8, self, osc='/Dial_' + str(index) + '/x', osc_parameter='/Dial' + str(index) + 'val/set', osc_name='/Dial' + str(index) + 'name/set') for index in range(6): self._menu[index] = OSCMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_MENU[index], 'Menu_' + str(index), self, osc='/Function_' + str(index) + '/value', osc_alt='/Function/set ' + str(index), osc_name='/Function/text ' + str(index)) self._crossfader = OSCMonoEncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute, "Crossfader", 24, self, osc='/XFader/x', osc_parameter='/XFader/none', osc_name=None) self._livid = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self, osc='/Livid/x', osc_alt='/Livid/x', osc_name=None) self._shift_l = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Shift_Button_Left', self, osc='/ShiftL/x', osc_alt='/ShiftL/x', osc_name=None) self._shift_r = OSCMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Shift_Button_Right', self, osc='/ShiftR/x', osc_alt='/ShiftR/x', osc_name=None) 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] = OSCMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, CHANNEL, (column * 8) + row, 'Grid_' + str(column) + '_' + str(row), self, osc='/ClipGrid_' + str(column) + '_' + str(row) + '/value', osc_alt='/ClipGrid/set ' + str(column) + ' ' + str(row), osc_name='/ClipGrid/text ' + str(column) + ' ' + str(row)) 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._monomod256 = ButtonMatrixElement() self._monomod256.name = 'Monomod256' self._square = [None for index in range(16)] for column in range(16): self._square[column] = [None for index in range(16)] for row in range(16): self._square[column][row] = OSCMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, int(column / 8) + 1, row + ((column % 8) * 16), '256Grid_' + str(column) + '_' + str(row), self, osc='/Grid_' + str(column) + '_' + str(row) + '/value', osc_alt='/Grid/set ' + str(column) + ' ' + str(row), osc_name=None) #self._square[column][row] = FlashingButtonElement(is_momentary, 0, 15, -1, '256Grid_' + str(column) + '_' + str(row), '/1/p_grid/'+str(column)+'/'+str(row), '/1/c_grid/'+str(column)+'/'+str(row), self) for row in range(16): button_row = [] for column in range(16): button_row.append(self._square[column][row]) self._monomod256.add_row(tuple(button_row)) self._bank_buttons = ButtonMatrixElement() self._key_buttons = ButtonMatrixElement() self._bank_button = [None for index in range(2)] for index in range(2): self._bank_button[index] = OSCMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, 15, index, '256Grid_Bank_' + str(index), self, osc='/Shift_' + str(index) + '/value', osc_alt='/Shift/set ' + str(index), osc_name=None) button_row = [] for index in range(2): button_row.append(self._bank_button[index]) self._bank_buttons.add_row(tuple(button_row)) button_row = [] self._key_button = [None for index in range(8)] for index in range(8): self._key_button[index] = OSCMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, 15, index + 8, '256Grid_Key_' + str(index), self, osc='/Keys_' + str(index) + '/value', osc_alt='/Keys/set ' + str(index), osc_name=None) for index in range(8): button_row.append(self._key_button[index]) self._key_buttons.add_row(tuple(button_row)) def _setup_session_control(self): is_momentary = True num_tracks = 4 num_scenes = 5 self._session = NameServerSessionComponent(num_tracks, num_scenes, self) self._session.name = "Left_Session" self._session.set_offsets(0, 0) self._session.set_stop_clip_value(self._color_defs['STOP_CLIP']) self._scene = [None for index in range(5)] for row in range(num_scenes): self._scene[row] = self._session.scene(row) self._scene[row].name = 'L_Scene_' + str(row) for column in range(num_tracks): clip_slot = self._scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_L_' + str(row) clip_slot.set_triggered_to_play_value( self._color_defs['CLIP_TRG_PLAY']) clip_slot.set_triggered_to_record_value( self._color_defs['CLIP_TRG_REC']) clip_slot.set_stopped_value(self._color_defs['CLIP_STOP']) clip_slot.set_started_value(self._color_defs['CLIP_STARTED']) clip_slot.set_recording_value( self._color_defs['CLIP_RECORDING']) self._session.set_mixer(self._mixer) self._session_zoom = SessionZoomingComponent(self._session) self._session_zoom.name = 'L_Session_Overview' self._session_zoom.set_stopped_value(self._color_defs['ZOOM_STOPPED']) self._session_zoom.set_playing_value(self._color_defs['ZOOM_PLAYING']) self._session_zoom.set_selected_value( self._color_defs['ZOOM_SELECTED']) self._session_zoom._zoom_button = (self._dummy_button) self._session_zoom.set_enabled(True) self._session2 = SessionComponent(num_tracks, num_scenes) self._session2.name = 'Right_Session' self._session2.set_offsets(4, 0) self._session2.set_stop_clip_value(self._color_defs['STOP_CLIP']) self._scene2 = [None for index in range(5)] for row in range(num_scenes): self._scene2[row] = self._session2.scene(row) self._scene2[row].name = 'R_Scene_' + str(row) for column in range(num_tracks): clip_slot = self._scene2[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_R_' + str(row) clip_slot.set_triggered_to_play_value( self._color_defs['CLIP_TRG_PLAY']) clip_slot.set_triggered_to_record_value( self._color_defs['CLIP_TRG_REC']) clip_slot.set_stopped_value(self._color_defs['CLIP_STOP']) clip_slot.set_started_value(self._color_defs['CLIP_STARTED']) clip_slot.set_recording_value( self._color_defs['CLIP_RECORDING']) self._session2.set_mixer(self._mixer2) self._session2.add_offset_listener(self._on_session_offset_changes) self._session_zoom2 = SessionZoomingComponent(self._session2) self._session_zoom2.name = 'R_Session_Overview' self._session_zoom2.set_stopped_value(self._color_defs['ZOOM_STOPPED']) self._session_zoom2.set_playing_value(self._color_defs['ZOOM_PLAYING']) self._session_zoom2.set_selected_value( self._color_defs['ZOOM_SELECTED']) self._session_zoom.set_enabled(True) self._session_zoom2._zoom_button = (self._dummy_button2) self._session_main = SessionComponent(8, num_scenes) self._session_main.name = 'Main_Session' self._session_main.set_stop_clip_value(self._color_defs['STOP_CLIP']) self._scene_main = [None for index in range(5)] for row in range(num_scenes): self._scene_main[row] = self._session_main.scene(row) self._scene_main[row].name = 'M_Scene_' + str(row) for column in range(8): clip_slot = self._scene_main[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_M_' + str(row) clip_slot.set_triggered_to_play_value( self._color_defs['CLIP_TRG_PLAY']) clip_slot.set_triggered_to_record_value( self._color_defs['CLIP_TRG_REC']) clip_slot.set_stopped_value(self._color_defs['CLIP_STOP']) clip_slot.set_started_value(self._color_defs['CLIP_STARTED']) clip_slot.set_recording_value( self._color_defs['CLIP_RECORDING']) self._session_main.set_mixer(self._mixer) self._session_zoom_main = SessionZoomingComponent(self._session_main) self._session_zoom_main.name = 'M_Session_Overview' self._session_zoom_main.set_stopped_value( self._color_defs['ZOOM_STOPPED']) self._session_zoom_main.set_playing_value( self._color_defs['ZOOM_PLAYING']) self._session_zoom_main.set_selected_value( self._color_defs['ZOOM_SELECTED']) self._session_zoom_main.set_enabled(True) self._session_zoom_main._zoom_button = (self._dummy_button3) self._sessions = [self._session, self._session2, self._session_main] self._zooms = [ self._session_zoom, self._session_zoom2, self._session_zoom_main ] def _setup_mod(self): self.monomodular = get_monomodular(self) self.monomodular.name = 'monomodular_switcher' self.modhandler = LemurOhmModHandler(self) self.modhandler.name = 'ModHandler' self.modhandler256 = LemurModHandler(self) self.modhandler256.name = 'ModHandler256' def _assign_host2(self): self.modhandler256.set_shift_button(self._bank_button[0]) self.modhandler256.set_alt_button(self._bank_button[1]) self.modhandler256.set_grid(self._monomod256) self.modhandler256.set_key_buttons(self._key_buttons) self.modhandler256.set_enabled(True) def _setup_touchosc(self): self._osc_registry = {} #self._osc_registry['/ping'] = self._monobridge.ping #self._osc_registry['/1'] = self._monobridge.page1 #self._osc_registry['/2'] = self._monobridge.page2 for control in self.controls: if hasattr(control, 'osc'): self._osc_registry[control.osc] = control.set_value #if hasattr(control, 'osc_alt'): # self._osc_registry[control.osc_alt] = control.set_value #self.log_message('create dict key: ' + str(control.osc) + str(control.name)) """shift/zoom methods""" def deassign_matrix(self): super(LemurPad, self).deassign_matrix() self.clear_grid_names() """menu button management methods""" def deassign_menu(self): super(LemurPad, self).deassign_menu() for index in range(6): self._monobridge._send_osc(self._menu[index].osc_name, self.generate_strip_string(' ')) def assign_device_nav_to_menu(self): super(LemurPad, self).assign_device_nav_to_menu() for index in range(6): self._monobridge._send_osc( self._menu[index].osc_name, self.generate_strip_string(str(DEVICE_NAV_NAMES[index]))) def assign_transport_to_menu(self): super(LemurPad, self).assign_transport_to_menu() for index in range(6): self._monobridge._send_osc( self._menu[index].osc_name, self.generate_strip_string(str(TRANSPORT_NAMES[index]))) def assign_session_nav_to_menu(self): super(LemurPad, self).assign_session_nav_to_menu() for index in range(6): self._monobridge._send_osc( self._menu[index].osc_name, self.generate_strip_string(str(SESSION_NAV_NAMES[index]))) def assign_session_main_nav_to_menu(self): super(LemurPad, self).assign_session_main_nav_to_menu() for index in range(6): self._monobridge._send_osc( self._menu[index].osc_name, self.generate_strip_string(str(SESSION_NAV_NAMES[index]))) def assign_monomod_shift_to_menu(self): super(LemurPad, self).assign_monomod_shift_to_menu() for index in range(6): self._monobridge._send_osc( self._menu[index].osc_name, self.generate_strip_string(str(MONOMOD_SHIFT_NAMES[index]))) def assign_monomod_to_menu(self): super(LemurPad, self).assign_monomod_shift_to_menu() for index in range(6): self._monobridge._send_osc( self._menu[index].osc_name, self.generate_strip_string(str(MONOMOD_NAMES[index]))) def assign_session_bank_to_menu(self): super(LemurPad, self).assign_session_bank_to_menu() for index in range(6): self._monobridge._send_osc( self._menu[index].osc_name, self.generate_strip_string(str(SESSION_BANK_NAMES[index]))) def assign_session2_bank_to_menu(self): super(LemurPad, self).assign_session2_bank_to_menu() for index in range(6): self._monobridge._send_osc( self._menu[index].osc_name, self.generate_strip_string(str(SESSION_BANK2_NAMES[index]))) def assign_session_main_nav_to_menu(self): super(LemurPad, self).assign_session_main_nav_to_menu() for index in range(6): self._monobridge._send_osc( self._menu[index].osc_name, self.generate_strip_string(str( SESSION_MAIN_BANK_NAMES[index]))) """m4l bridge""" def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 9 if (not display_string): return ('`_') if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center( (NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return '`' + ret.replace(' ', '_') def notification_to_bridge(self, name, value, sender): if (isinstance(sender, MonoEncoderElement2)): #self.log_message(str(name) + str(value) + str(sender.num)) self._monobridge._send('lcd_name', sender.name, self.generate_strip_string(str(name))) self._monobridge._send('lcd_value', sender.name, self.generate_strip_string(str(value))) def clip_name(self, sender, name): #self.log_message('clip name ' + str(sender.osc_name) + ' ' + str(self.generate_strip_string(str(name)))) self._monobridge._send_osc(sender.osc_name, self.generate_strip_string(str(name))) """def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip(): clip_names.append(clip_slot._clip_slot)##.clip.name) #return clip_slot._clip_slot #self.log_message('clip name' + str(clip_slot._clip_slot.clip.name)) return clip_names""" """called on timer""" def update_display(self): super(LemurPad, self).update_display() for callback in self._timer_callbacks: callback() def strobe(self): pass """general functionality""" def disconnect(self): super(MonOhm, self).disconnect() def clear_grid_names(self): #self.log_message('clear grid names' + str(self)) for column in range(8): for row in range(8): self._monobridge._send_osc(self._grid[column][row].osc_name, '`_') def _register_timer_callback(self, callback): """ Registers a callback that is triggerd on every call of update_display """ assert (callback != None) assert (dir(callback).count('im_func') is 1) assert (self._timer_callbacks.count(callback) == 0) self._timer_callbacks.append(callback) return None def _unregister_timer_callback(self, callback): """ Unregisters a timer callback """ assert (callback != None) assert (dir(callback).count('im_func') is 1) assert (self._timer_callbacks.count(callback) == 1) self._timer_callbacks.remove(callback) return None def _set_brightness(self, value): #self._bright = (value != 0) #for control in self.controls: # if isinstance(control, OSCMonoButtonElement): # self._monobridge._send_osc(control.osc_alt, int(self._bright), True) pass def reset(self): #self._monobridge._send_osc('/reset') for control in self.controls: control.reset() def assign_lower_grid_names(self, mode): if self._display_button_names is True: for column in range(8): for row in range(3): self._monobridge._send_osc( self._grid[column][row + 5].osc_name, self.generate_strip_string( str(GRID_NAMES[mode][row][column]))) def reset_and_refresh_state(self, *a, **k): self.schedule_message(1, self.reset) self.schedule_message(2, self.refresh_state)
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
class MidiFighterTwister(ControlSurface): __module__ = __name__ __doc__ = "MidiFighterTwister class" def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.__c_instance = c_instance self.show_message('Script initiated') self.init() def init(self): # initialize listeners, caches and colors self.flush_all() self.mf_disable_bank_buttons() self.mf_init_page_config() self.mf_init_light_pages() # Start listeners to call dispatcher self.song().view.add_detail_clip_listener( self.dispatch_detail_clip_listener) self.song().add_current_song_time_listener( self.dispatch_current_song_time_listener) self.song().view.add_selected_track_listener( self.dispatch_selected_track_listener) self.device_listener_wrapper() # Initialize the sequencer buttons self.sequencer_init_buttons() self.sequencer_init_rotaries() self.init_clip_page() self.init_pad_page() self.init_device_params() def flush_all(self): for poti in range(64): for channel in range(4): self._send_midi((175 + channel, poti, 0)) def mf_init_page_config(self): # Initialize configuration parameters # Sequencer configuration self.sequencer_page_default_color = 1 self.sequencer_current_page_color_index = self.sequencer_page_default_color self.sequencer_base_default_note = 36 self.sequencer_current_selected_note = self.sequencer_base_default_note self.sequencer_clip_position_16th = None # Midi Channels self.rotary_midi_channel = 175 + 1 self.ring_midi_channel = 175 + 1 self.switch_midi_channel = 175 + 2 self.light_midi_channel = 175 + 2 # Pages cc map self.clip_page_cc = range(0, 16) self.sequencer_page_cc = range(16, 32) self.note_page_cc = range(32, 48) self.control_page_cc = range(48, 64) # Pages init color self.clip_page_colors = [1] * 16 self.sequencer_page_colors = [self.sequencer_page_default_color] * 16 self.note_page_colors = range(1, 127, 16) * 2 #self.note_page_colors = [0] * 16 self.control_page_colors = [1] * 16 # Status cache for sequencer self.switch_encoder_status_cache = [False] * 64 # List to store ButtonElements in self.switch_encoder_buttons = [False] * 64 # Status cache for rotaries self.rotary_encoder_potis = [False] * 64 def mf_init_light_pages(self): sequencer_page_map = zip(self.sequencer_page_cc, self.sequencer_page_colors) for light_encoder_cc, light_color_cc in sequencer_page_map: self._mf_set_light(light_encoder_cc, light_color_cc, False) note_page_map = zip(self.note_page_cc, self.note_page_colors) for light_encoder_cc, light_color_cc in note_page_map: self._mf_set_light(light_encoder_cc, light_color_cc, False) def _mf_set_light(self, light_encoder_cc, light_color_cc, status): # Sets color on midi channel 2 (177) end updates status cache # for sequencer to remember statuses self._send_midi( (self.light_midi_channel, light_encoder_cc, light_color_cc)) self.switch_encoder_status_cache[light_encoder_cc] = status def mf_disable_bank_buttons(self): # Workaround for not sending values to track when pressing bank buttons self.padm0 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 0) self.padm1 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 1) self.padm2 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 2) self.padm3 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 4, 3) self.padm0.add_value_listener(self.bank_buttons_dummy, identify_sender=True) self.padm1.add_value_listener(self.bank_buttons_dummy, identify_sender=True) self.padm2.add_value_listener(self.bank_buttons_dummy, identify_sender=True) self.padm3.add_value_listener(self.bank_buttons_dummy, identify_sender=True) def bank_buttons_dummy(self): pass def dispatch_detail_clip_listener(self): self.current_clip = self.song().view.highlighted_clip_slot.clip self.init_sequencer() try: if self.current_clip.is_midi_clip and not self.current_clip.notes_has_listener: # Update leds when notes are added or removed self.current_clip.add_notes_listener( self._sequencer_update_notes_to_light) self.init_sequencer() else: self.sequencer_reset_colors() except AttributeError: pass def dispatch_current_song_time_listener(self): self.sequencer_light_follows_beat() def dispatch_selected_track_listener(self): self.device_auto_select() self.device_listener_wrapper() def device_listener_wrapper(self): selected_track = self.song().view.selected_track if not selected_track.devices_has_listener(self.device_auto_select): self.song().view.selected_track.add_devices_listener( self.device_auto_select) # Sequencer def init_sequencer(self): self.sequencer_current_selected_note = self.sequencer_base_default_note self.sequencer_current_page_color_index = self.sequencer_page_default_color self._sequencer_update_notes_to_light() def sequencer_init_buttons(self): for switch_encoder_cc in self.sequencer_page_cc: self.switch_encoder_buttons[switch_encoder_cc] = ButtonElement( IS_MOMENTARY, MIDI_CC_TYPE, 1, switch_encoder_cc) self.switch_encoder_buttons[switch_encoder_cc].add_value_listener( self.sequencer_button_press, identify_sender=True) self.padl14 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 14) self.padr17 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 17) self.padl16 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 16) self.padr19 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 19) self.padl14.add_value_listener(self.sequencer_side_button_press, identify_sender=True) self.padr17.add_value_listener(self.sequencer_side_button_press, identify_sender=True) self.padl16.add_value_listener(self.sequencer_side_button_press, identify_sender=True) self.padr19.add_value_listener(self.sequencer_side_button_press, identify_sender=True) def sequencer_init_rotaries(self): for rotary_encoder_cc in self.sequencer_page_cc: self.rotary_encoder_potis[rotary_encoder_cc] = EncoderElement( MIDI_CC_TYPE, 0, rotary_encoder_cc, Live.MidiMap.MapMode.absolute) self.rotary_encoder_potis[rotary_encoder_cc].add_value_listener( self.sequencer_rotary_change, identify_sender=True) def sequencer_rotary_change(self, value, sender): try: self.current_clip except AttributeError: return False if self.current_clip.is_midi_clip: cc_value = sender._msg_identifier if value > 0: if not self.switch_encoder_status_cache[cc_value]: self._send_midi((self.light_midi_channel, cc_value, self.sequencer_current_light_on_color)) self._send_midi((self.ring_midi_channel, cc_value, 100)) self.switch_encoder_status_cache[cc_value] = True self.current_clip.set_notes( ((self.sequencer_current_selected_note, cc_value % 16 * 0.25, 0.25, value, False), )) elif value == 0: self._send_midi((self.light_midi_channel, cc_value, self.sequencer_current_page_color)) self.current_clip.remove_notes( cc_value % 16 * 0.25, self.sequencer_current_selected_note, 0.25, 1) self.switch_encoder_status_cache[cc_value] = False def sequencer_button_press(self, value, sender): try: self.current_clip except AttributeError: return False if self.current_clip.is_midi_clip: cc_value = sender._msg_identifier if value > 0: if not self.switch_encoder_status_cache[cc_value]: self._send_midi((self.light_midi_channel, cc_value, self.sequencer_current_light_on_color)) self.current_clip.set_notes( ((self.sequencer_current_selected_note, cc_value % 16 * 0.25, 0.25, 100, False), )) self.switch_encoder_status_cache[cc_value] = True self._send_midi((self.ring_midi_channel, cc_value, 100)) else: self._send_midi((self.light_midi_channel, cc_value, self.sequencer_current_page_color)) self._send_midi((self.ring_midi_channel, cc_value, 0)) self.current_clip.remove_notes( cc_value % 16 * 0.25, self.sequencer_current_selected_note, 0.25, 1) self.switch_encoder_status_cache[cc_value] = False def sequencer_side_button_press(self, value, sender): try: cc_value = sender._msg_identifier if value > 0: # Note/clolor up/down if cc_value == 14 and self.sequencer_current_selected_note > 0: self.sequencer_current_selected_note = self.sequencer_current_selected_note - 1 self.sequencer_current_page_color_index = self.sequencer_current_page_color_index - 16 self._sequencer_update_notes_to_light() self.sequencer_clip_position_16th = None self.show_message( "Selected Midi Note: " + str(self.sequencer_current_selected_note)) if cc_value == 17 and self.sequencer_current_selected_note < 127: self.sequencer_current_selected_note = self.sequencer_current_selected_note + 1 self.sequencer_current_page_color_index = self.sequencer_current_page_color_index + 16 self._sequencer_update_notes_to_light() self.sequencer_clip_position_16th = None self.show_message( "Selected Midi Note: " + str(self.sequencer_current_selected_note)) # New/duplicate clip if cc_value == 16 and self.sequencer_current_selected_note > 0: self.duplicate_clip() if cc_value == 19 and self.sequencer_current_selected_note > 0: self.session_record() except AttributeError: pass def sequencer_light_follows_beat(self): try: if self.current_clip.is_midi_clip: if self.sequencer_clip_position_16th == None: self.sequencer_clip_position_16th = int( self.current_clip.playing_position / 0.25) if self.switch_encoder_status_cache[self.sequencer_page_cc[ self.sequencer_clip_position_16th]]: self._send_midi( (177, self.sequencer_page_cc[ self.sequencer_clip_position_16th], self.sequencer_current_light_on_color)) else: self._send_midi((177, self.sequencer_page_cc[ self.sequencer_clip_position_16th], self.sequencer_current_page_color)) elif self.sequencer_clip_position_16th != int( self.current_clip.playing_position / 0.25): if self.switch_encoder_status_cache[self.sequencer_page_cc[ self.sequencer_clip_position_16th]]: self._send_midi( (177, self.sequencer_page_cc[ self.sequencer_clip_position_16th], self.sequencer_current_light_on_color)) else: self._send_midi((177, self.sequencer_page_cc[ self.sequencer_clip_position_16th], self.sequencer_current_page_color)) self.sequencer_clip_position_16th = int( self.current_clip.playing_position / 0.25) self._send_midi((177, self.sequencer_page_cc[ self.sequencer_clip_position_16th], self.sequencer_current_light_beat_color)) except IndexError: pass @property def sequencer_current_light_on_color(self): # light on color to be relative to page color return self.sequencer_current_page_color + 32 % 128 @property def sequencer_current_light_beat_color(self): # light on color to be relative to page color return self.sequencer_current_page_color + 64 % 128 @property def sequencer_current_page_color(self): return self.sequencer_current_page_color_index % 128 def _sequencer_get_midi_notes(self, note): # self.current_clip.get_notes(start, self.sequencer_current_selected_note, # selection_length, hight) try: return self.current_clip.get_notes(0, note, 4, 1) except AttributeError: return [] def _sequencer_update_notes_to_light(self): self.sequencer_reset_colors() notes_for_current_selected_note = self._sequencer_get_midi_notes( self.sequencer_current_selected_note) for note in notes_for_current_selected_note: light_encoder_cc = int(note[1] * 4 + self.sequencer_page_cc[0]) self._send_midi( (self.ring_midi_channel, light_encoder_cc, note[3])) self._mf_set_light(light_encoder_cc, self.sequencer_current_light_on_color, True) def sequencer_reset_colors(self): for light_encoder_cc in self.sequencer_page_cc: self._mf_set_light(light_encoder_cc, self.sequencer_current_page_color, False) self._send_midi((self.ring_midi_channel, light_encoder_cc, 0)) def duplicate_clip(self): self.log_message("duplicate clip") #if self._clip_slot and self._clip_slot.has_clip: # slot_name = self._clip_slot.clip.name # track = self._clip_slot.canonical_parent current_track = self.song().view.selected_track current_clip_slot = self.song().view.highlighted_clip_slot self.song().duplicate_scene( list(current_track.clip_slots).index(current_clip_slot)) #new_clip = current_track.duplicate_clip_slot( # list(current_track.clip_slots).index(current_clip_slot)+1) #self.log_message(new_clip) #selected_track = self.song().view.selected_track #selected_track.duplicate_clip_slot(selected_track) def session_record(self): self.log_message("session record") #self.song().trigger_session_record() # Clip page setion def init_clip_page(self): num_tracks = 4 num_scenes = 3 self.flash_status = 1 self.Mixer = MixerComponent(4, 3) # Volencoder self.volencoders = [None for index in range(num_tracks)] for index in range(num_tracks): self.volencoders[index] = EncoderElement( MIDI_CC_TYPE, 0, index, Live.MidiMap.MapMode.absolute) self.Mixer.channel_strip(index).set_volume_control( self.volencoders[index]) # Sendencoder for index in range(num_tracks): encoder_cc_send_1 = index + num_tracks encoder_cc_send_2 = index + num_tracks * 2 send1 = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_send_1, Live.MidiMap.MapMode.absolute) send2 = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_send_2, Live.MidiMap.MapMode.absolute) self.Mixer.channel_strip(index).set_send_controls((send1, send2)) # Panencoder for index in range(num_tracks): encoder_cc_pan = index + num_tracks * 3 pan = EncoderElement(MIDI_CC_TYPE, 0, encoder_cc_pan, Live.MidiMap.MapMode.absolute) self.Mixer.channel_strip(index).set_pan_control(pan) # Arm-/selectbuttons for index in range(num_tracks): armbutton = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, index + 12) self.Mixer.channel_strip(index).set_arm_button(armbutton) self.Mixer.channel_strip(index).set_select_button(armbutton) # Navigation buttons self.padl11 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 11) self.padr8 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 8) self.padl10 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 10) self.padr13 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 3, 13) self.grid = [None for index in range(num_tracks * 3)] for index in range(num_tracks * 3): self.grid[index] = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, index) self.matrix = ButtonMatrixElement() for row in range(num_scenes): button_row = [] for column in range(num_tracks): button_row.append(self.grid[column + (row * 4)]) self.log_message(str(column + (row * 4))) self.matrix.add_row(tuple(button_row)) self.Session = SessionComponent(num_tracks, num_scenes) self.Session.name = "Session" self.Session.set_offsets(0, 0) self.Session.set_mixer(self.Mixer) self.Session._do_show_highlight() self.set_highlighting_session_component(self.Session) self.Session.set_track_bank_buttons(self.padl11, self.padr8) self.Session.set_scene_bank_buttons(self.padr13, self.padl10) self.scene = [None for index in range(num_scenes)] for row in range(num_scenes): self.scene[row] = self.Session.scene(row) self.scene[row].name = 'Scene_' + str(row) for column in range(num_tracks): clip_slot = self.scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot' + str(row) self.scene[row].clip_slot(column).set_triggered_to_play_value( 35) self.scene[row].clip_slot(column).set_stopped_value(68) self.scene[row].clip_slot(column).set_started_value(45) self.scene[row].clip_slot( column).set_triggered_to_record_value(100) self.scene[row].clip_slot(column).set_recording_value(80) for column in range(num_tracks): for row in range(num_scenes): self.scene[row].clip_slot(column).set_launch_button( self.grid[column + (row * 4)]) for index in range(num_tracks * num_scenes): self.grid[index].clear_send_cache() def update_display(self): # Called every 100 ms ControlSurface.update_display(self) self.refresh_state() self.Session.set_enabled(True) self.Session.update() # Sequencer hack try: for light_encoder_cc in self.sequencer_page_cc: self._send_midi((self.ring_midi_channel, light_encoder_cc, 0)) notes_for_current_selected_note = self._sequencer_get_midi_notes( self.sequencer_current_selected_note) for note in notes_for_current_selected_note: light_encoder_cc = int(note[1] * 4 + self.sequencer_page_cc[0]) self._send_midi( (self.ring_midi_channel, light_encoder_cc, note[3])) except AttributeError: pass # Pad Section def init_pad_page(self): self.pad_device_params() PAD_TRANSLATION = ((0, 0, 32, 1), (1, 0, 33, 1), (2, 0, 34, 1), (3, 0, 35, 1), (0, 1, 36, 1), (1, 1, 37, 1), (2, 1, 38, 1), (3, 1, 39, 1), (0, 2, 40, 1), (1, 2, 41, 1), (2, 2, 42, 1), (3, 2, 43, 1), (0, 3, 44, 1), (1, 3, 45, 1), (2, 3, 46, 1), (3, 3, 47, 1)) self.set_pad_translations(PAD_TRANSLATION) self._device_selection_follows_track_selection = True def pad_device_params(self): device_param_controls = [] for param in self.note_page_cc[:8]: self.rotary_encoder_potis[param] = EncoderElement( MIDI_CC_TYPE, 0, param, Live.MidiMap.MapMode.absolute) self.rotary_encoder_potis[param].release_parameter() self.rotary_encoder_potis[param].send_value(0, True) self.rotary_encoder_potis[param].clear_send_cache() device_param_controls.append(self.rotary_encoder_potis[param]) device = DeviceComponent() device.name = 'Device_Component pad' device.set_parameter_controls(tuple(device_param_controls)) self.set_device_component(device) #def scrolling(self): # self.application().view.scroll_view(ndir, 'Detail/DeviceChain', True) # Live.Song.Song.View.selected_track #Live.Song.Song.View.select_device()[0] # Device parameter section def init_device_params(self): device_param_controls = [] device_bank_buttons = [] for param in self.control_page_cc[:8]: self.rotary_encoder_potis[param] = EncoderElement( MIDI_CC_TYPE, 0, param, Live.MidiMap.MapMode.absolute) self.switch_encoder_buttons[param] = ButtonElement( IS_MOMENTARY, MIDI_CC_TYPE, 1, param) self.rotary_encoder_potis[param].release_parameter() self.rotary_encoder_potis[param].send_value(0, True) self.rotary_encoder_potis[param].clear_send_cache() device_param_controls.append(self.rotary_encoder_potis[param]) device_bank_buttons.append(self.switch_encoder_buttons[param]) device = DeviceComponent() device.name = 'Device_Component' device.set_parameter_controls(tuple(device_param_controls)) device.set_bank_buttons(tuple(device_bank_buttons)) device.set_on_off_button( ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 56)) self.set_device_component(device) def device_auto_select(self): # Iterates through devices within a track and assigns the first # DrumPad device to activate the individual drum's device. # Use first device in case none is a DrumPad device. selected_track = self.song().view.selected_track devices = selected_track.devices for device in devices: if device.can_have_drum_pads: self.current_drum_device = device pad_device = self.current_drum_device.view.selected_chain.devices[ 0] self.song().view.select_device(pad_device) if not self.current_drum_device.view.selected_drum_pad_has_listener( self.device_update_current_note): self.current_drum_device.view.add_selected_drum_pad_listener( self.device_update_current_note) break else: self.song().view.select_device(devices[0]) def device_update_current_note(self): current_note = self.current_drum_device.view.selected_drum_pad.note self.sequencer_current_selected_note = current_note # Update light of active pad #self._send_midi((self.light_midi_channel, light_encoder_cc, 63)) try: self.current_clip = self.song().view.highlighted_clip_slot.clip self.current_clip.is_midi_clip self._sequencer_update_notes_to_light() except AttributeError: pass
def _setup_session_control(self): is_momentary = True right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 43) left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 42) up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 44) down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 45) right_button.name = 'Bank_Select_Right_Button' left_button.name = 'Bank_Select_Left_Button' up_button.name = 'Bank_Select_Up_Button' down_button.name = 'Bank_Select_Down_Button' global session session = SessionComponent(4, 4) session.name = 'Session_Control' session.set_track_bank_buttons(right_button, left_button) session.set_scene_bank_buttons(down_button, up_button) self._session = session matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' scene_launch_notes = [33,34,35,36] scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, scene_launch_notes[index]) for index in range(4) ] #track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(4) ] for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_'+ str(index) + '_Launch_Button' #for index in range(len(track_stop_buttons)): # track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button' #stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) #stop_all_button.name = 'Stop_All_Clips_Button' #self._session.set_stop_all_clips_button(stop_all_button) #self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) #self._session.set_stop_clip_value(2) button_notes = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32] for scene_index in range(4): scene = session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) #scene.set_triggered_value(2) for track_index in range(4): button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, (track_index * 4) + scene_index + 1) button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index) #clip_slot.set_triggered_to_play_value(2) #clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(0) clip_slot.set_started_value(64) #clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) matrix.add_row(tuple(button_row)) #self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)) session.selected_scene().name = 'Selected_Scene' #session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) #session_zoom = SessionZoomingComponent(session) #session_zoom.name = 'Session_Overview' #session_zoom.set_button_matrix(matrix) #session_zoom.set_zoom_button(self._shift_button) #session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button) #session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) #session_zoom.set_stopped_value(0) #session_zoom.set_selected_value(127) self.set_highlighting_session_component(session) session.set_mixer(mixer) return None #return session
class AumPC40(APC): __doc__ = " Script for Akai's APC40 Controller " def __init__(self, c_instance): APC.__init__(self, c_instance) self._device_selection_follows_track_selection = True def _setup_session_control(self): is_momentary = True self._shift_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98, self) right_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96, self) self._right_button = right_button left_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97, self) self._left_button = left_button up_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94, self) self._up_button = up_button down_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95, self) self._down_button = down_button right_button.name = 'Bank_Select_Right_Button' left_button.name = 'Bank_Select_Left_Button' up_button.name = 'Bank_Select_Up_Button' down_button.name = 'Bank_Select_Down_Button' self._session = PedaledSessionComponent(8, 5) self._session.name = 'Session_Control' self._session.set_track_bank_buttons(right_button, left_button) self._session.set_scene_bank_buttons(down_button, up_button) matrix = ButtonMatrixElement() self._matrix = matrix # added a matrix.name = 'Button_Matrix' scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82)) for index in range(5) ] track_stop_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52, self) for index in range(8) ] self._track_stop_buttons = track_stop_buttons # added a for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_' + str( index) + '_Launch_Button' for index in range(len(track_stop_buttons)): track_stop_buttons[index].name = 'Track_' + str( index) + '_Stop_Button' stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) stop_all_button.name = 'Stop_All_Clips_Button' self._session.set_stop_all_clips_button(stop_all_button) self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session.set_stop_track_clip_value(2) for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53), self) button.name = str(track_index) + '_Clip_' + str( scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(5) clip_slot.set_started_value(1) clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) matrix.add_row(tuple(button_row)) self._session.set_slot_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = SessionZoomingComponent(self._session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button) self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5) return None def _setup_mixer_control(self): is_momentary = True self._mixer = SpecialMixerComponent(8) self._mixer.name = 'Mixer' self._mixer.master_strip().name = 'Master_Channel_Strip' self._mixer.selected_strip().name = 'Selected_Channel_Strip' self._solo_buttons = [] # added a self._select_buttons = [] # added a for track in range(8): strip = self._mixer.channel_strip(track) strip.name = 'Channel_Strip_' + str(track) volume_control = MonoEncoderElement2(MIDI_CC_TYPE, track, 7, Live.MidiMap.MapMode.absolute, 'Slider_' + str(track), track, self) arm_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 48) solo_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 50, self) self._solo_buttons.append(solo_button) # added a mute_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 49) select_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track, 51, self) self._select_buttons.append(select_button) # added a #volume_control.name = str(track) + '_Volume_Control' arm_button.name = str(track) + '_Arm_Button' solo_button.name = str(track) + '_Solo_Button' mute_button.name = str(track) + '_Mute_Button' select_button.name = str(track) + '_Select_Button' strip.set_volume_control(volume_control) strip.set_arm_button(arm_button) strip.set_solo_button(solo_button) strip.set_mute_button(mute_button) strip.set_select_button(select_button) strip.set_shift_button(self._shift_button) strip.set_invert_mute_feedback(True) crossfader = SliderElement(MIDI_CC_TYPE, 0, 15) master_volume_control = SliderElement(MIDI_CC_TYPE, 0, 14) master_select_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 80) self._master_select_button = master_select_button prehear_control = EncoderElement( MIDI_CC_TYPE, 0, 47, Live.MidiMap.MapMode.relative_two_compliment) crossfader.name = 'Crossfader' master_volume_control.name = 'Master_Volume_Control' master_select_button.name = 'Master_Select_Button' prehear_control.name = 'Prehear_Volume_Control' self._mixer.set_crossfader_control(crossfader) self._mixer.set_prehear_volume_control(prehear_control) self._mixer.master_strip().set_volume_control(master_volume_control) self._mixer.master_strip().set_select_button(master_select_button) def _setup_custom_components(self): self._setup_device_and_transport_control() self._setup_global_control() def _setup_device_and_transport_control(self): is_momentary = True device_bank_buttons = [] device_param_controls = [] bank_button_labels = ('Clip_Track_Button', 'Device_On_Off_Button', 'Previous_Device_Button', 'Next_Device_Button', 'Detail_View_Button', 'Rec_Quantization_Button', 'Midi_Overdub_Button', 'Metronome_Button') for index in range(8): device_bank_buttons.append( ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 58 + index)) device_bank_buttons[-1].name = bank_button_labels[index] ring_mode_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 24 + index) ringed_encoder = MonoRingedEncoderElement( MIDI_CC_TYPE, 0, 16 + index, Live.MidiMap.MapMode.absolute, index, self) 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(self) 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 = DetailViewCntrlComponent() detail_view_toggler.name = 'Detail_View_Control' detail_view_toggler.set_shift_button(self._shift_button) detail_view_toggler.set_device_clip_toggle_button( device_bank_buttons[0]) detail_view_toggler.set_detail_toggle_button(device_bank_buttons[4]) detail_view_toggler.set_device_nav_buttons(device_bank_buttons[2], device_bank_buttons[3]) transport = ShiftableTransportComponent() transport.name = 'Transport' self._transport = transport play_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 91) stop_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 92) record_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 93) nudge_up_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 100, self) self._nudge_up_button = nudge_up_button nudge_down_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 101, self) self._nudge_down_button = nudge_down_button tap_tempo_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99) play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' record_button.name = 'Record_Button' nudge_up_button.name = 'Nudge_Up_Button' nudge_down_button.name = 'Nudge_Down_Button' tap_tempo_button.name = 'Tap_Tempo_Button' transport.set_shift_button(self._shift_button) transport.set_play_button(play_button) transport.set_stop_button(stop_button) transport.set_record_button(record_button) transport.set_nudge_buttons(nudge_up_button, nudge_down_button) transport.set_tap_tempo_button(tap_tempo_button) transport.set_quant_toggle_button(device_bank_buttons[5]) transport.set_overdub_button(device_bank_buttons[6]) transport.set_metronome_button(device_bank_buttons[7]) bank_button_translator = ShiftTranslatorComponent() bank_button_translator.set_controls_to_translate( tuple(device_bank_buttons)) bank_button_translator.set_shift_button(self._shift_button) def _setup_global_control(self): is_momentary = True global_bank_buttons = [] global_param_controls = [] for index in range(8): ring_button = ButtonElement(not is_momentary, MIDI_CC_TYPE, 0, 56 + index) ringed_encoder = MonoRingedEncoderElement( MIDI_CC_TYPE, 0, 48 + index, Live.MidiMap.MapMode.absolute, index + 8, self) ringed_encoder.name = 'Track_Control_' + str(index) ring_button.name = ringed_encoder.name + '_Ring_Mode_Button' ringed_encoder.set_ring_mode_button(ring_button) global_param_controls.append(ringed_encoder) global_bank_buttons = [] global_bank_labels = ('Pan_Button', 'Send_A_Button', 'Send_B_Button', 'Send_C_Button') for index in range(4): global_bank_buttons.append( ButtonElement(not is_momentary, MIDI_NOTE_TYPE, 0, 87 + index)) global_bank_buttons[-1].name = global_bank_labels[index] encoder_modes = EncModeSelectorComponent(self._mixer) encoder_modes.name = 'Track_Control_Modes' encoder_modes.set_modes_buttons(global_bank_buttons) encoder_modes.set_controls(tuple(global_param_controls)) global_translation_selector = ChannelTranslationSelector() global_translation_selector.name = 'Global_Translations' global_translation_selector.set_controls_to_translate( tuple(global_param_controls)) global_translation_selector.set_mode_buttons( tuple(global_bank_buttons)) def _product_model_id_byte(self): return 115 def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_monomod(self): self._host = MonomodComponent(self) self._host.name = 'Monomod_Host' self.hosts = [self._host] self._monomod = ButtonMatrixElement() self._monomod.name = 'Monomod' for row in range(5): button_row = [] for column in range(8): button_row.append(self._matrix.get_button(column, row)) self._monomod.add_row(tuple(button_row)) self._monomod.add_row(tuple(self._track_stop_buttons)) self._monomod.add_row(tuple(self._select_buttons)) self._monomod.add_row(tuple(self._solo_buttons)) self._monomod_mode = MonomodModeComponent(self._monomod_mode_update, self) self._monomod_mode.name = "Monomod_Mode_Component" def _monomod_mode_update(self): if (self._monomod_mode._mode_index == 0) or (self._host._active_client == None): self.flash_status = 0 self._host.set_enabled(False) self._host._set_button_matrix(None) self._host._set_nav_buttons(None) self._host._set_lock_button(None) self._host._set_alt_button(None) self._host._set_shift_button(None) self._monomod.reset() self._session.set_track_bank_buttons(self._right_button, self._left_button) self._session.set_scene_bank_buttons(self._down_button, self._up_button) for track in range(8): self._mixer.channel_strip(track).set_select_button( self._select_buttons[track]) self._mixer.channel_strip(track).set_solo_button( self._solo_buttons[track]) self._transport.set_nudge_buttons(self._nudge_up_button, self._nudge_down_button) self._session.set_enabled(True) self._session_zoom._is_zoomed_out = False self._session_zoom.set_enabled(True) self.request_rebuild_midi_map() self._master_select_button.turn_off() elif (self._monomod_mode._mode_index == 1): self._transport.set_nudge_buttons(None, None) for track in range(8): self._mixer.channel_strip(track).set_select_button(None) self._mixer.channel_strip(track).set_solo_button(None) self._session.set_enabled(False) self._session_zoom.set_enabled(False) self._session.set_track_bank_buttons(None, None) self._session.set_scene_bank_buttons(None, None) self.flash_status = 1 self._monomod.reset() self._host._set_button_matrix(self._monomod) self._host._set_nav_buttons([ self._up_button, self._down_button, self._left_button, self._right_button ]) self._host._set_shift_button(self._shift_button) self._host._set_lock_button(self._nudge_up_button) self._host._set_alt_button(self._nudge_down_button) self._host.set_enabled(True) self.request_rebuild_midi_map() self._master_select_button.turn_on() """m4l bridge""" def generate_strip_string(self, display_string): #self.log_message(display_string) NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center( (NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return ret def notification_to_bridge(self, name, value, sender): if isinstance(sender, (MonoRingedEncoderElement, MonoEncoderElement2)): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched += 1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip() is True: clip_names.append(clip_slot._clip_slot) ##.clip.name) return clip_slot._clip_slot ##self.log_message(str(clip_slot._clip_slot.clip.name)) return clip_names def update_display(self): """ Live -> Script Aka on_timer. Called every 100 ms and should be used to update display relevant parts of the controller """ for message in self._scheduled_messages: message['Delay'] -= 1 if (message['Delay'] == 0): if (message['Parameter'] != None): message['Message'](message['Parameter']) else: message['Message']() del self._scheduled_messages[ self._scheduled_messages.index(message)] for callback in self._timer_callbacks: callback() self._timer = (self._timer + 1) % 256 self.flash() def flash(self): if (self.flash_status > 0): for row in range(8): for column in range(8): button = self._monomod.get_button(column, row) if (button._flash_state > 0): button.flash(self._timer)
def _setup_session_control(self): self.session = CustomSessionComponent(self.box_width, self.box_height, self) # subclass from _Framework is_momentary = True # what exactly does this do in the _Framework? if up_button_note_number >= 0 and down_button_note_number >= 0: # opt in enable UP/DOWN nav up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, up_button_note_number) up_button.name = 'Bank_Select_Up_Button' # sure, why not down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, down_button_note_number) down_button.name = 'Bank_Select_Down_Button' #sure, why not self.session.set_scene_bank_buttons(down_button, up_button) if right_button_note_number >= 0 and left_button_note_number >= 0: # opt in enable LEFT/RIGHT nav right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, right_button_note_number) right_button.name = 'Bank_Select_Right_Button' #sure, why not left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, left_button_note_number) left_button.name = 'Bank_Select_Left_Button' #sure, why not self.session.set_track_bank_buttons(right_button, left_button) self.session.name = 'Session_Control' #sure, why not matrix = ButtonMatrixElement() # @todo subclass this via established new patterns matrix.name = 'Button_Matrix' #sure, why not # I loop a little different. The goal is readbility, flexibility, and the web app...incase you did not notice yet if len(scene_launch_notes) > 0 and len(scene_launch_notes) == self.box_height: # logic check have launch notes and scene = box height for index in range(self.box_height): self.session.scene(index).set_launch_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, scene_launch_notes[index])) else : self.log_message("..::|| Scene launch not in use or error on case of use. Modern.DJ ||::..") if len(stop_track_buttons) >0 and len(stop_track_buttons) == self.box_width: #logic check have track stop assignments and track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, stop_track_buttons[index]) for index in range(len(stop_track_buttons))] for index in range(len(track_stop_buttons)): track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button' # sure, why not self.session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) else : self.log_message("..::|| Stop notes not in use or error found Modern.DJ ||::..") # Check for stop all clips option if stop_all_clips >=0 : self.session.set_stop_all_clips_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, stop_all_clips)) # creating the matrix of buttons from the launch_button_list (tuple) launch_button_list_len = len(launch_button_list) # var used multiple times. This is a performance modification if (self.box_height*self.box_width) == launch_button_list_len : # check box size against number of button vars sent launch_ctr = launch_button_list_len -1 # decrement for zero offset in list/tuple launch_button_list.reverse() #reverse list from human readable for decrement use (performance tweak) ## check for use of RGB if use_velocity_for_RGB != 1: # if not enabled use these defaults self.log_message("..::|| RGB not in effect assigning defaults ||::..") self.clip_loaded_stopped = 1 self.clip_currently_playing = 127 self.clip_triggered_to_play = 64 else: # yes RGB in effect...assign per the parameters script self.clip_loaded_stopped = clip_loaded_stopped self.clip_currently_playing = clip_currently_playing self.clip_triggered_to_play = clip_triggered_to_play for scene_index in range(self.box_height): # loop on the notes matrix scene = self.session.scene(scene_index) # part of the martix built, think rows scene.name = 'Scene_' + str(scene_index) # sure, why not button_row = [] # create recepticle # loop across the tracks for track_index in range(self.box_width): button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, midi_channel, launch_button_list[launch_ctr]) # button instance for _Framework launch_ctr = launch_ctr -1# decrement is faster than increment button.name = str(track_index) + '_Clip_' + str(scene_index) + '_Button' # sure, why not button_row.append(button) # add to our growing list clip_slot = scene.clip_slot(track_index) # clips slot and buttons are not the same thing, this aligns these ideas in the red box clip_slot.name = str(track_index) + '_Clip_Slot_' + str(scene_index) # sure, why not # assign the button and and status in th refrech update clip_slot.set_stopped_value(self.clip_loaded_stopped ) # this number is sent back to the machine allowing diff colors for stopped clip_slot.set_started_value(self.clip_currently_playing) # this number is sent back to the machine allowing diff colors for started/is-playing clip_slot.set_triggered_to_play_value(self.clip_triggered_to_play) # this number is sent back to the machine allowing diff colors for cued, will play next clip_slot.set_launch_button(button) # part of the slit+button = go time paradigm matrix.add_row(tuple(button_row)) # close out the matrix build. @todo - possible subclass here? else : # log message self.log_message("..::|| Number of notes defined does not match box height and width Modern.DJ ||::..") ''' live 9 only self.set_highlighting_session_component(self.session) # new for live9 -- this is for the box. via aumhaa/bitnomad ''' return None
def _setup_session_control(self): is_momentary = True self._shift_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 98, self) right_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 96, self) self._right_button = right_button left_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 97, self) self._left_button = left_button up_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 94, self) self._up_button = up_button down_button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 95, self) self._down_button = down_button right_button.name = 'Bank_Select_Right_Button' left_button.name = 'Bank_Select_Left_Button' up_button.name = 'Bank_Select_Up_Button' down_button.name = 'Bank_Select_Down_Button' self._session = PedaledSessionComponent(8, 5) self._session.name = 'Session_Control' self._session.set_track_bank_buttons(right_button, left_button) self._session.set_scene_bank_buttons(down_button, up_button) matrix = ButtonMatrixElement() self._matrix = matrix # added a matrix.name = 'Button_Matrix' scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, (index + 82)) for index in range(5) ] track_stop_buttons = [ FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52, self) for index in range(8) ] self._track_stop_buttons = track_stop_buttons # added a for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_' + str( index) + '_Launch_Button' for index in range(len(track_stop_buttons)): track_stop_buttons[index].name = 'Track_' + str( index) + '_Stop_Button' stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) stop_all_button.name = 'Stop_All_Clips_Button' self._session.set_stop_all_clips_button(stop_all_button) self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session.set_stop_track_clip_value(2) for scene_index in range(5): scene = self._session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) scene.set_triggered_value(2) for track_index in range(8): button = FlashingButtonElement(is_momentary, MIDI_NOTE_TYPE, track_index, (scene_index + 53), self) button.name = str(track_index) + '_Clip_' + str( scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) clip_slot.set_triggered_to_play_value(2) clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(5) clip_slot.set_started_value(1) clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) matrix.add_row(tuple(button_row)) self._session.set_slot_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)) self._session.selected_scene().name = 'Selected_Scene' self._session.selected_scene().set_launch_button( ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) self._session_zoom = SessionZoomingComponent(self._session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_button_matrix(matrix) self._session_zoom.set_zoom_button(self._shift_button) self._session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button) self._session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) self._session_zoom.set_stopped_value(3) self._session_zoom.set_selected_value(5) return None
def __init__(self, c_instance): live = Live.Application.get_application() self._live_major_version = live.get_major_version() self._live_minor_version = live.get_minor_version() self._live_bugfix_version = live.get_bugfix_version() self._mk2 = Settings.DEVICE == 'Launchpad mk2' if self._mk2: self._skin = Skin('Launchpad mk2') self._side_notes = (89, 79, 69, 59, 49, 39, 29, 19) self._drum_notes = (20, 30, 31, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126) else: self._skin = Skin('Launchpad') self._side_notes = (8, 24, 40, 56, 72, 88, 104, 120) self._drum_notes = (41, 42, 43, 44, 45, 46, 47, 57, 58, 59, 60, 61, 62, 63, 73, 74, 75, 76, 77, 78, 79, 89, 90, 91, 92, 93, 94, 95, 105, 106, 107) ControlSurface.__init__(self, c_instance) with self.component_guard(): self._suppress_send_midi = True self._suppress_session_highlight = True is_momentary = True if self._mk2: self._suggested_input_port = 'Launchpad' self._suggested_output_port = 'Launchpad' else: self._suggested_input_port = 'Launchpad MK2' self._suggested_output_port = 'Launchpad MK2' self._control_is_with_automap = False self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = 'User_Byte_Button' self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self._wrote_user_byte = False self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143 matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' for row in range(8): button_row = [] for column in range(8): if self._mk2: # for mk2 buttons are assigned "top to bottom" midi_note = (81 - (10 * row)) + column else: midi_note = row * 16 + column button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, midi_note, self._skin.off) button.name = str(column) + '_Clip_' + str(row) + '_Button' button_row.append(button) matrix.add_row(tuple(button_row)) self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False) self._config_button.add_value_listener(self._config_value) top_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, self._skin.off) for index in range(8)] side_buttons = [ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, self._side_notes[index], self._skin.off) for index in range(8)] top_buttons[0].name = 'Bank_Select_Up_Button' top_buttons[1].name = 'Bank_Select_Down_Button' top_buttons[2].name = 'Bank_Select_Left_Button' top_buttons[3].name = 'Bank_Select_Right_Button' top_buttons[4].name = 'Session_Button' top_buttons[5].name = 'User1_Button' top_buttons[6].name = 'User2_Button' top_buttons[7].name = 'Mixer_Button' side_buttons[0].name = 'Vol_Button' side_buttons[1].name = 'Pan_Button' side_buttons[2].name = 'SndA_Button' side_buttons[3].name = 'SndB_Button' side_buttons[4].name = 'Stop_Button' side_buttons[5].name = 'Trk_On_Button' side_buttons[6].name = 'Solo_Button' side_buttons[7].name = 'Arm_Button' self._osd = M4LInterface() self._osd.name = "OSD" self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self._osd, self, self._skin) self._selector.name = 'Main_Modes' self._do_combine() for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.add_value_listener(self._button_value) self.set_highlighting_session_component(self._selector.session_component()) self._suppress_session_highlight = False self.log_message("LaunchPad95 Loaded !")
class OhmModesHH(ControlSurface): __module__ = __name__ __doc__ = " OhmModes controller script, custom script for Herbie Hancock by amounra " def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= OhmModesHH2 log opened =--------------") # Writes message into Live's main log file. This is a ControlSurface method. #self.set_suppress_rebuild_requests(True) # Turn off rebuild MIDI map until after we're done setting up self.revision = 'HH' self.flash_status = 1 self._backlight = 127 self._backlight_type = 'static' self._ohm = 127 self._ohm_type = 'static' self._pad_translations = PAD_TRANSLATION self._rgb = 1 self._keys_octave = 5 self._keys_scale = 0 self._tempo_buttons = None self._scene_indexes = [[[0,0], [8, 0], [16, 0], [24, 0], [32, 0], [40, 0]], [[0,0], [8, 0], [16, 0], [24, 0], [32, 0], [40, 0]], [[0,0], [8, 0], [16, 0], [24, 0], [32, 0], [40, 0]], [[0,0], [8, 0], [16, 0], [24, 0], [32, 0], [40, 0]], [[0,0], [8, 0], [16, 0], [24, 0], [32, 0], [40, 0]]] self._scene_bank = 0 self._bank_is_on = False self._setup_monobridge() self._setup_controls() self._setup_transport_control() # Run the transport setup part of the script self._setup_mixer_control() # Setup the mixer object self._setup_session_control() # Setup the session object self._setup_device_control() # Setup the device object self._setup_crossfader() self._setup_looper() #self._setup_scene_selector() #self._setup_modes() self._assign_page_constants() self.assign_page_0() self._setup_hilight_knobs() self._last_device = None self._timer = 0 #self.set_suppress_rebuild_requests(False) #Turn rebuild back on, now that we're done setting up self.song().view.add_selected_track_listener(self._update_selected_device) self._on_selected_scene_changed() self.show_message('OhmModes Control Surface Loaded') self._send_midi(tuple(switchxfader)) #self.schedule_message(10, self.query_ohm, None) #self.song().view.selected_scene = self.song().scenes[0] self._assign_session_colors() def query_ohm(self): #self.log_message('querying Ohm') self._send_midi(tuple(check_model)) def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def update_display(self): ControlSurface.update_display(self) self._timer = (self._timer + 1) % 256 self.flash() def get_device_bank(self): return self._device._bank_index def _setup_controls(self): is_momentary = True self._fader = [None for index in range(8)] self._dial = [None for index in range(16)] self._button = [None for index in range(8)] self._menu = [None for index in range(6)] for index in range(8): self._fader[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_FADERS[index], Live.MidiMap.MapMode.absolute) self._fader[index].name = 'Fader_' + str(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(16): self._dial[index] = EncoderElement(MIDI_CC_TYPE, CHANNEL, OHM_DIALS[index], Live.MidiMap.MapMode.absolute) self._dial[index].name = 'Dial_' + str(index) for index in range(6): self._menu[index] = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, OHM_MENU[index], 'Menu_' + str(index), self) self._crossfader = EncoderElement(MIDI_CC_TYPE, CHANNEL, CROSSFADER, Live.MidiMap.MapMode.absolute) self._crossfader.name = "Crossfader" self._livid = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self) self._shift_l = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_L, 'Page_Button_Left', self) self._shift_r = MonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, SHIFT_R, 'Page_Button_Right', self) self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' self._grid = [None for index in range(8)] 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(6): button_row = [] for column in range(7): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) def _setup_modes(self): self._shift_mode = ShiftModeComponent(self) self._shift_mode.name = 'Shift_Mode' #self._shift_mode.set_mode_toggle(self._shift_l, self._shift_r) #self._select_mode = ModeSelectorComponent(self) #self._select_mode.name = 'Select_Mode' #self._select_mode.set_mode_toggle(self._menu[5]) #self._select_mode.update = self.select_mode_update(self._select_mode) #self._menu[5].add_value_listener(self._select_mode) #self._scale_mode = ScaleModeComponent(self) #self._scale_mode.name = "Scale_Mode" #self._octave_mode = OctaveModeComponent(self) #self._octave_mode.name = "Octave_Mode" def select_mode_update(self, mode_selector): def update(): if mode_selector._mode_index>0: pass return update def _setup_looper(self): self._looper = [None for index in range(2)] for index in range(2): self._looper[index] = LooperListenerComponent(self, index + 1) self._looper[index].assign_buttons(self._button[index*4], self._button[(index*4)+1], self._button[(index*4)+2], self._button[(index*4)+3]) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_mixer_control(self): is_momentary = True self._num_tracks = (7) #A mixer is one-dimensional; global mixer mixer = SpecialMixerComponent(7, 0, True, False) mixer.name = 'Mixer' self._mixer = mixer mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(7): mixer.channel_strip(index).set_volume_control(self._fader[index]) for index in range(7): mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) mixer.track_eq(index).name = 'Mixer_EQ_' + str(index) mixer.channel_strip(index)._invert_mute_feedback = True self.song().view.selected_track = mixer.channel_strip(0)._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error def _setup_session_control(self): is_momentary = True num_tracks = 7 num_scenes = 7 ###changed from 5 for HH global session session = SessionComponent(num_tracks, num_scenes) session.name = "Session" session.set_offsets(0, 0) self._session = session self._scene = [None for index in range(num_scenes)] for row in range(num_scenes): self._scene[row] = session.scene(row) self._scene[row].name = 'Scene_' + str(row) for column in range(num_tracks): clip_slot = self._scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_' + str(row) session.set_mixer(mixer) self._session_zoom = SessionZoomingComponent(session) self._session_zoom.name = 'Session_Overview' #self._session_zoom.set_enabled(False) self.set_highlighting_session_component(self._session) def _assign_session_colors(self): num_tracks = 7 num_scenes = 7 self._session.set_stop_clip_value(STOP_CLIP_COLOR[self._rgb]) for row in range(num_scenes): for column in range(num_tracks): self._scene[row].clip_slot(column).set_triggered_to_play_value(CLIP_TRIGD_TO_PLAY_COLOR[self._rgb]) self._scene[row].clip_slot(column).set_triggered_to_record_value(CLIP_TRIGD_TO_RECORD_COLOR[self._rgb]) self._scene[row].clip_slot(column).set_stopped_value(CLIP_STOPPED_COLOR[self._rgb]) self._scene[row].clip_slot(column).set_started_value(CLIP_STARTED_COLOR[self._rgb]) self._scene[row].clip_slot(column).set_recording_value(CLIP_RECORDING_COLOR[self._rgb]) self._session_zoom.set_stopped_value(ZOOM_STOPPED_COLOR[self._rgb]) self._session_zoom.set_playing_value(ZOOM_PLAYING_COLOR[self._rgb]) self._session_zoom.set_selected_value(ZOOM_SELECTED_COLOR[self._rgb]) def _setup_device_control(self): self._device = DeviceComponent() self._device.name = 'Device_Component' self.set_device_component(self._device) self._device_navigator = DetailViewControllerComponent() self._device_navigator.name = 'Device_Navigator' self._device_selection_follows_track_selection = FOLLOW def device_follows_track(self, val): self._device_selection_follows_track_selection = (val == 1) return self def _setup_crossfader(self): self._mixer.set_crossfader_control(self._crossfader) def _setup_scene_selector(self): for index in range(5): self._menu[index].add_value_listener(self._select_new_scene, True) def set_bank(self, val): self._scene_bank = int(val) self._monobridge._send('bank', self._scene_bank) self._display_bank() def _select_mode(self, value): self.log_message('select mode update' + str(value)) self._bank_is_on = value!=0 if self._bank_is_on is True: self._display_bank() else: self._on_selected_scene_changed() def _select_new_scene(self, value, sender): if self._bank_is_on is False: if value > 0: new_scene = int(self._scene_indexes[self._scene_bank][self._menu.index(sender)][0]) new_track = int(self._scene_indexes[self._scene_bank][self._menu.index(sender)][1]) self.log_message('select new scene ' + str(new_scene) + ' and track ' + str(new_track)) all_scenes = self.song().scenes all_tracks = self.song().tracks if (new_scene < len(all_scenes)) and (new_track < len(all_tracks)): self.song().view.selected_scene = all_scenes[(new_scene)] self.song().view.selected_track = all_tracks[(new_track)] self._session.set_offsets(self._scene_indexes[self._scene_bank][self._menu.index(sender)][1], self._scene_indexes[self._scene_bank][self._menu.index(sender)][0]) else: if value > 0: self._scene_bank = int(self._menu.index(sender)) self._monobridge._send('bank', self._scene_bank) self._display_bank() def _display_bank(self): if(self._bank_is_on): for index in range(5): if index == self._scene_bank: self._menu[index].send_value(11) else: self._menu[index].send_value(0) def _on_selected_scene_changed(self): ControlSurface._on_selected_scene_changed(self) #self.log_message('scene offset: ' + str(self._session._scene_offset)) for index in range(6): if self._session._scene_offset == self._scene_indexes[self._scene_bank][index][0]: ## and self._session._scene_offset < self._scene_indexes[index + 1]: self._menu[index].turn_on() else: self._menu[index].turn_off() #if self._session._scene_offset >= self._scene_indexes[5]: # self._menu[5].turn_on #else: # self._menu[5].turn_off def _setup_hilight_knobs(self): self._dial[15].add_value_listener(self._knob_set_scene, True) self._dial[14].add_value_listener(self._knob_set_track, True) def _knob_set_scene(self, value, sender): all_scenes = self.song().scenes num_scenes = len(all_scenes) new_scene = float(value/127.0) * float(num_scenes - 1) self.song().view.selected_scene = all_scenes[int(new_scene)] self._session.set_offsets(self._session._track_offset, int(new_scene)) def _knob_set_track(self, value, sender): #self.log_message(str(value)) all_tracks = self.song().visible_tracks #self.song().tracks num_tracks = len(self.song().visible_tracks) new_track = float(value/127.0) * float(num_tracks - 1) #self.log_message(str(int(new_track))) #self.log_message(str(value) + str(float(value/127.0))) self.song().view.selected_track = all_tracks[int(new_track)] self._session.set_offsets(int(new_track), self._session._scene_offset) def disconnect(self): """clean things up on disconnect""" for index in range(5): if self._menu[index].value_has_listener(self._select_new_scene): self._menu[index].remove_value_listener(self._select_new_scene) if self._menu[5].value_has_listener(self._select_mode): self._menu[5].remove_value_listener(self._select_mode) if self._dial[15].value_has_listener(self._knob_set_scene): self._dial[15].remove_value_listener(self._knob_set_scene) if self._dial[15].value_has_listener(self._knob_set_scene): self._dial[15].remove_value_listener(self._knob_set_scene) self.song().view.remove_selected_track_listener(self._update_selected_device) ControlSurface.disconnect(self) self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= OhmModes log closed =--------------") #Create entry in log file return None def _get_num_tracks(self): return self.num_tracks def flash(self): #if(self.flash_status > 0): for index in range(6): if(self._menu[index]._flash_state>0): self._menu[index].flash(self._timer) for row in range(8): if(self._button[row]._flash_state > 0): self._button[row].flash(self._timer) for column in range(8): button = self._grid[column][row] if(button._flash_state > 0): button.flash(self._timer) def strobe(self): if(self._backlight_type != 'static'): if(self._backlight_type is 'pulse'): self._backlight = int(math.fabs(((self._timer * 16) % 64) -32) +32) if(self._backlight_type is 'up'): self._backlight = int(((self._timer * 8) % 64) + 16) if(self._backlight_type is 'down'): self._backlight = int(math.fabs(int(((self._timer * 8) % 64) - 64)) + 16) self._send_midi(tuple([176, 27, int(self._backlight)])) if(self._ohm_type != 'static'): if(self._ohm_type is 'pulse'): self._ohm = int(math.fabs(((self._timer * 16) % 64) -32) +32) if(self._ohm_type is 'up'): self._ohm = int(((self._timer * 8) % 64) + 16) if(self._ohm_type is 'down'): self._ohm = int(math.fabs(int(((self._timer * 8) % 64) - 64)) + 16) self._send_midi(tuple([176, 63, int(self._ohm)])) self._send_midi(tuple([176, 31, int(self._ohm)])) def deassign_matrix(self): #self._scale_mode.set_mode_buttons(None) #self._scale_mode.set_enabled(False) #self._octave_mode.set_mode_buttons(None) #self._octave_mode.set_enabled(False) #self._session_zoom.set_button_matrix(None) #if self._dial[15].has_value_listener(self._knob_set_scene): # self._dial[15].remove_value_listener(self._knob_set_scene) #if self._dial[14].has_value_listener(self._knob_set_track): # self._dial[14].remove_value_listener(self._knob_set_track) self._session_zoom.set_enabled(False) self._session_zoom.set_nav_buttons(None, None, None, None) self._session.set_track_bank_buttons(None, None) self._session.set_scene_bank_buttons(None, None) for column in range(7): self._mixer.channel_strip(column).set_crossfade_toggle(None) self._mixer.channel_strip(column).set_mute_button(None) self._mixer.channel_strip(column).set_solo_button(None) self._mixer.channel_strip(column).set_arm_button(None) self._mixer.channel_strip(column).set_send_controls(None) self._mixer.channel_strip(column).set_pan_control(None) self._mixer.track_eq(column).set_enabled(False) for row in range(7): self._scene[row].clip_slot(column).set_launch_button(None) for column in range(8): #self._button[column]._on_value = SELECT_COLOR[self._rgb] for row in range(8): self._grid[column][row].set_channel(0) self._grid[column][row].release_parameter() self._grid[column][row].use_default_message() self._grid[column][row].set_enabled(True) self._grid[column][row].send_value(0, True) self._grid[column][row]._on_value = 127 self._grid[column][row]._off_value = 0 #for index in range(8): # self._button[index].set_channel(0) # self._button[index].use_default_message() # self._button[index].set_enabled(True) # self._button[index].reset() #for index in range(6): # self._menu[index]._on_value = 127 # self._menu[index]._off_value = 0 # self._menu[index].reset() #for index in range(16): # self._dial[index].use_default_message() # self._dial[index].release_parameter() #self._dial[index].set_enabled(True) if(self._device._parameter_controls != None): for control in self._device._parameter_controls: control.release_parameter() self._device._parameter_controls = None self._device_navigator.set_enabled(False) self._mixer.update() self._matrix.reset() """HH Specific""" #self._mixer.master_strip().set_select_button(None) #for column in range(7): # self._mixer.channel_strip(column).set_select_button(None) self._session_zoom.set_zoom_button(None) self._transport.set_play_button(None) self._transport.set_stop_button(None) self._device_navigator.set_device_nav_buttons(None, None) #for index in range(2): # self._looper[index].find_looper() def _assign_page_constants(self): #self._session_zoom.set_zoom_button(self._button[7]) #commented out pn 070111 #self._session_zoom.set_zoom_button(self._grid[7][7]) #added pn 070111 #self._session_zoom.set_button_matrix(self._matrix) #self._session_zoom.set_enabled(True) #for column in range(7): #self._mixer.channel_strip(column).set_select_button(self._button[column]) # self._mixer.channel_strip(column).set_volume_control(self._fader[column]) #self._mixer.master_strip().set_volume_control(self._fader[7]) #for column in range(8): # self._button[column]._on_value = SELECT_COLOR[self._rgb] #self._mixer.master_strip().set_select_button(self._button[7]) #added pn 070111 #self._mixer.set_prehear_volume_control(self._dial[15]) #self._transport.set_play_button(self._menu[0]) #self._menu[0].send_value(PLAY_COLOR[self._rgb], True) #self._menu[0]._on_value = PLAY_COLOR[self._rgb] #self._transport.set_stop_button(self._menu[1]) #self._menu[1]._off_value = STOP_COLOR[self._rgb] #self._menu[1]._on_value = STOP_COLOR[self._rgb] #self._menu[1].send_value(STOP_COLOR[self._rgb], True) self._livid._on_value = TAP_COLOR[self._rgb] self._transport.set_tap_tempo_button(self._livid) #self._livid.send_value(TAP_COLOR, True) #self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[4]) for index in range(2): self._menu[index + 4]._on_value = SESSION_NAV[self._rgb] self._menu[index * 3]._on_value = SESSION_NAV[self._rgb] self._session.set_track_bank_buttons(self._menu[5], self._menu[4]) self._session.set_scene_bank_buttons(self._menu[3], self._menu[0]) def assign_page_0(self): self._backlight_type = 'static' #self._session_zoom.set_button_matrix(self._matrix) self._session_zoom.set_enabled(True) for column in range(7): #self._grid[column][5]._on_value = MUTE_COLOR[self._rgb] #self._mixer.channel_strip(column).set_mute_button(self._grid[column][5]) #self._grid[column][6]._on_value = SOLO_COLOR[self._rgb] #self._mixer.channel_strip(column).set_solo_button(self._grid[column][6]) #self._grid[column][7]._on_value = ARM_COLOR[self._rgb] #self._mixer.channel_strip(column).set_arm_button(self._grid[column][7]) #self._mixer.channel_strip(column).set_pan_control(self._dial[column + 8]) for row in range(7): self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row]) #for column in range(4): # self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column], self._dial[column + 4]])) track_stop_buttons = [] for index in range(7): self._grid[7][index]._off_value = SCENE_LAUNCH_COLOR[self._rgb] self._scene[index].set_launch_button(self._grid[7][index]) self._grid[index][7]._on_value = TRACK_STOP[self._rgb] self._grid[index][7]._off_value = TRACK_STOP[self._rgb] track_stop_buttons.append(self._grid[index][7]) self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._session.set_stop_all_clips_button(self._grid[7][7]) #for index in range(4): # self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb] #self._session.set_track_bank_buttons(self._menu[4], self._menu[3]) #self._session.set_scene_bank_buttons(self._menu[5], self._menu[2]) #for index in range(6): # self._menu[index]._on_value = HHMENU[index][1] # self._menu[index]._off_value = HHMENU[index][0] for index in range(8): self._button[index].set_channel(2) self._button[index].set_identifier(index) #self._button[index].reset() self._button[index].set_enabled(False) self.request_rebuild_midi_map() for index in range(7): self._grid[index][7].turn_on() for index in range(2): self._looper[index]._state_change() self._button[1 + (index * 4)].send_value(3) self._button[2 + (index * 4)].send_value(6) self._button[3 + (index * 4)].send_value(1) def assign_page_1(self): self._backlight_type = 'pulse' self._session_zoom.set_enabled(False) for column in range(4): for row in range(4): self._grid[column][row].set_channel(PAGE1_DRUM_CHANNEL) self._grid[column][row].set_identifier(PAGE1_DRUM_MAP[column][row]) self._grid[column][row].send_value(DRUM_COLOR[self._rgb], True) self._grid[column][row].set_enabled(False) self._grid[column + 4][row].set_channel(PAGE1_BASS_CHANNEL) self._grid[column + 4][row].set_identifier(PAGE1_BASS_MAP[column][row]) self._grid[column + 4][row].send_value(BASS_COLOR[self._rgb], True) self._grid[column + 4][row].set_enabled(False) scale_mode_buttons = [] for column in range(8): for row in range(3): self._grid[column][row + 4].set_enabled(False) self._grid[column][row + 4].set_channel(PAGE1_KEYS_CHANNEL) self._grid[column][row + 4].set_identifier(int(PAGE1_KEYS_MAP[column][row]) + int(PAGE1_MODES_MAP[self._scale_mode._mode_index][column]) + int(self._octave_mode._mode_index * 12)) self._grid[column][row + 4].send_value(KEYS_COLOR[self._rgb], True) for row in range(1): scale_mode_buttons.append(self._grid[column][7]) self._scale_mode.set_mode_buttons(tuple(scale_mode_buttons)) self._scale_mode.set_enabled(True) #self._octave_mode.set_mode_buttons(tuple([self._menu[5], self._menu[2]])) #self._octave_mode.set_enabled(True) for column in range(7): self._mixer.channel_strip(column).set_send_controls(tuple([self._dial[column + 8]])) #self._button[column].set_on_off_values(REC_ARM, 0) #self._mixer.channel_strip(column).set_arm_button(self._button[column]) self._device.set_enabled(True) device_param_controls = [] for index in range(8): device_param_controls.append(self._dial[index]) self._device.set_parameter_controls(tuple(device_param_controls)) #for index in range(4): # self._menu[2 + index]._on_value = (DEVICE_NAV_COLOR[self._rgb]) #self._device_navigator.set_enabled(True) """HH Specific from Constants""" #self._mixer.master_strip().set_select_button(self._button[7]) #for column in range(7): # self._button[column].set_on_off_values(REC_ARM, 0) #self._session_zoom.set_zoom_button(self._grid[7][7]) #self._transport.set_play_button(self._menu[0]) #self._menu[0].send_value(PLAY_COLOR[self._rgb], True) #self._menu[0]._on_value = PLAY_COLOR[self._rgb] #self._transport.set_stop_button(self._menu[1]) #self._menu[1]._off_value = STOP_COLOR[self._rgb] #self._menu[1]._on_value = STOP_COLOR[self._rgb] #self._menu[1].send_value(STOP_COLOR[self._rgb], True) #self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[4]) for index in range(8): self._button[index].set_channel(2) self._button[index].set_identifier(index) #self._button[index].reset() self._button[index].set_enabled(False) self.request_rebuild_midi_map() #for index in range(8): # self._grid[index][7].send(self. for index in range(2): self._looper[index]._state_change() self._button[1 + (index * 4)].send_value(3) self._button[2 + (index * 4)].send_value(6) self._button[3 + (index * 4)].send_value(1) def assign_page_2(self): self._backlight_type = 'up' #self._session_zoom.set_button_matrix(self._matrix) self._session_zoom.set_enabled(False) for column in range(7): self._grid[column][5]._on_value = MUTE_COLOR[self._rgb] self._mixer.channel_strip(column).set_mute_button(self._grid[column][5]) self._grid[column][6]._on_value = CROSSFADE_ASSIGN_COLOR[self._rgb] self._mixer.channel_strip(column).set_crossfade_toggle(self._grid[column][6]) self._grid[column][7].set_channel(2) self._grid[column][7].set_identifier(column) self._grid[column][7].reset() self._grid[column][7].set_enabled(False) self._grid[column][7].send_value(4, True) for row in range(5): self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row]) for row in range(5): self._grid[7][row]._off_value = SCENE_LAUNCH_COLOR[self._rgb] self._scene[row].set_launch_button(self._grid[7][row]) for column in range(4): self._mixer.track_eq(column).set_gain_controls(tuple([self._dial[column + 8], self._dial[column + 4], self._dial[column]])) self._mixer.track_eq(column).set_enabled(True) for column in range(3): self._mixer.channel_strip(column+4).set_pan_control(self._dial[column + 12]) #for index in range(4): # self._menu[2 + index]._on_value = NAV_BUTTON_COLOR[self._rgb] #self._session.set_track_bank_buttons(self._menu[4], self._menu[3]) #self._session.set_scene_bank_buttons(self._menu[5], self._menu[2]) self._set_tempo_buttons([self._grid[7][5], self._grid[7][6]]) """HH Specific from Constants""" #self._mixer.master_strip().set_select_button(self._button[7]) #for column in range(7): # self._mixer.channel_strip(column).set_select_button(self._button[column]) #for index in range(8): # self._button[index].set_on_off_values(SELECT_COLOR[self._rgb], 0) self._session_zoom.set_zoom_button(self._grid[7][7]) #self._transport.set_play_button(self._menu[0]) #self._menu[0].send_value(PLAY_COLOR[self._rgb], True) #self._menu[0]._on_value = PLAY_COLOR[self._rgb] #self._transport.set_stop_button(self._menu[1]) #self._menu[1]._off_value = STOP_COLOR[self._rgb] #self._menu[1]._on_value = STOP_COLOR[self._rgb] #self._menu[1].send_value(STOP_COLOR[self._rgb], True) #self._device_navigator.set_device_nav_buttons(self._menu[3], self._menu[4]) for index in range(8): self._button[index].set_channel(2) self._button[index].set_identifier(index) #self._button[index].reset() self._button[index].set_enabled(False) self.request_rebuild_midi_map() for index in range(2): self._looper[index]._state_change() self._button[1 + (index * 4)].send_value(3) self._button[2 + (index * 4)].send_value(6) self._button[3 + (index * 4)].send_value(1) def _update_selected_device(self): if self._device_selection_follows_track_selection is True: track = self.song().view.selected_track device_to_select = track.view.selected_device if device_to_select == None and len(track.devices) > 0: device_to_select = track.devices[0] if device_to_select != None: self.song().view.select_device(device_to_select) #self._device.set_device(device_to_select) self.set_appointed_device(device_to_select) #self._device_selector.set_enabled(True) self.request_rebuild_midi_map() return None def handle_sysex(self, midi_bytes): #self.log_message(str('>>sysexIN') + str(midi_bytes)) if len(midi_bytes) > 10: #self.log_message(str('>>sysex>10') + str(midi_bytes[:11])) if midi_bytes[:11] == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 7]): self.log_message(str('>>>color detected')) self._rgb = 1 elif midi_bytes[:11] == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 2]): self.log_message(str('>>>mono detected')) self._rgb = 0 self._assign_session_colors() #self._shift_mode.update() self.deassign_matrix() self._assign_page_constants() self.assign_page_0() #self._setup_hilight_knobs() for index in range(8): self._grid[7][index].send_value(SCENE_LAUNCH_COLOR[self._rgb]) for index in range(7): self._grid[index][7].turn_on() # def handle_sysex(self, midi_bytes): # #assert(isinstance (midi_bytes, tuple)) # ##self.log_message(str('sysex') + str(midi_bytes)) # if midi_bytes == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 7, 0, 15, 10, 0, 0, 247]): # self.log_message(str('color detected')) # self._rgb = 1 # elif midi_bytes == tuple([240, 126, 0, 6, 2, 0, 1, 97, 1, 0, 2, 0, 0, 1, 1, 0, 247]): # self.log_message(str('mono detected')) # self._rgb = 0 # self._assign_session_colors() def receive_midi(self, midi_bytes): """ Live -> Script MIDI messages are only received through this function, when explicitly forwarded in 'build_midi_map'. """ assert (midi_bytes != None) assert isinstance(midi_bytes, tuple) ##self.log_message('got message' + str(midi_bytes)) #self.set_suppress_rebuild_requests(True) with self.component_guard(): if (len(midi_bytes) is 3): msg_type = (midi_bytes[0] & 240) forwarding_key = [midi_bytes[0]] if (msg_type is not MIDI_PB_TYPE): forwarding_key.append(midi_bytes[1]) if (tuple(forwarding_key) in self._forwarding_registry.keys()): recipient = self._forwarding_registry[tuple(forwarding_key)] if (recipient != None): recipient.receive_value(midi_bytes[2]) else: self.log_message(('Got unknown message: ' + str(midi_bytes))) else: self.handle_sysex(midi_bytes) #self.set_suppress_rebuild_requests(False) def _set_tempo_buttons(self, buttons): if self._tempo_buttons != None: self._tempo_buttons[0].remove_value_listener(self._tempo_value) self._tempo_buttons[1].remove_value_listener(self._tempo_value) self._tempo_buttons = buttons if buttons != None: for button in buttons: assert isinstance(button, FlashingButtonElement) self._tempo_buttons[0].set_on_off_values(4, 0) self._tempo_buttons[0].add_value_listener(self._tempo_value, True) self._tempo_buttons[1].set_on_off_values(4, 0) self._tempo_buttons[1].add_value_listener(self._tempo_value, True) self._tempo_buttons[0].turn_on() self._tempo_buttons[1].turn_on() def _tempo_value(self, value, sender): if (value > 0) and (self._tempo_buttons.index(sender) == 0): self.song().tempo = round(min((self.song().tempo + 1), 999)) elif (value > 0) and (self._tempo_buttons.index(sender) == 1): self.song().tempo = round(max((self.song().tempo - 1), 20)) def set_scene_index_value(self, bank_index, scene, track): bank = int(bank_index)/5 index = int(bank_index)%5 self.log_message('set_scene_index_value' + str(bank) + str(index) + str(scene) + str(track)) #self.log_message( str(type(index)) + str(type(scene)) + str(type(track))) self._scene_indexes[bank][index][0] = scene self._scene_indexes[bank][index][1] = track #self._on_selected_scene_changed() def connect_script_instances(self, instanciated_scripts): #link = False #offsets = [0, 0] #new_channel = CHAN for s in instanciated_scripts: if isinstance(s, APC) or s is self: #link = True if not s._session._is_linked(): s._session._link() #self.log_message('found other linked instance') #offsets[0] += (int(self._link_offset[0]) * 8) #offsets[1] += (int(self._link_offset[1]) * 4) #new_channel += 1 #if link and not self._session._is_linked(): #self._session.set_offsets(offsets[0], offsets[1]) #self._session._link() #self._set_code_channels(new_channel) # #
class code(ControlSurface): __module__ = __name__ __doc__ = " Code controller script " def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= Code opened =--------------") # Writes message into Live's main log file. This is a ControlSurface method. self._send_midi(factoryreset) self._send_midi(btn_channels) self._send_midi(enc_channels) #self.set_suppress_rebuild_requests(True) # Turn off rebuild MIDI map until after we're done setting up self._setup_controls() self._setup_device_controls() self._setup_mixer_control() # Setup the mixer object self._setup_transport_control() self._setup_session_control() # Setup the session object - do this last self._setup_modes() #self.set_suppress_rebuild_requests(False) # Turn rebuild back on, once we're done setting up ##self.assign_page_2() def handle_sysex(self, midi_bytes): self._send_midi(tuple([240, 00, 01, 97, 04, 15, 01, 247])) #response = [long(0),long(0)] #self.log_message(str(response)) def _setup_controls(self): is_momentary = True self._dial = [None for index in range(DIALCOUNT)] self._trackbtns = [None for index in range(8)] self._modebtns = [None for index in range(5)] for index in range(DIALCOUNT): self._dial[index] = EncoderElement(MIDI_CC_TYPE, CH, matrix_nums[index], Live.MidiMap.MapMode.absolute) self._dial[index].name = 'Dial_' + str(index) self._dial[index].set_feedback_delay(-1) for index in range(8): self._trackbtns[index] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index]) self._trackbtns[index].name = 'Button_' + str(index) for index in range(5): self._modebtns[index] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, mode_select_notes[index]) self._modebtns[index].name = 'ModeButton_' + str(index) self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' self._grid = [None for index in range(COLS)] for column in range(COLS): self._grid[column] = [None for index in range(COLS)] for row in range(ROWS): nn = 1+(column * ROWS) + row self._grid[column][row] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, nn) #comment out if you don't want clip launch self._grid[column][row].name = 'Grid_' + str(column) + '_' + str(row) for row in range(ROWS): button_row = [] for column in range(COLS): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) """ not sure about this bit, but somehow I'll need to set up the modes here...!""" def _setup_modes(self): self._shift_mode = ShiftModeComponent(self, tuple(button for button in self._modebtns)) self._shift_mode.name = 'Mix_Mode' #mode 1 #self._shift_mode.set_mode_buttons(self._modebtns) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_mixer_control(self): is_momentary = True self._num_tracks = (COLS) global mixer mixer = MixerComponent(COLS, 0, True, True) mixer.name = 'Mixer' self._mixer = mixer mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(COLS): #use the bottom row of encoders for volume, so add 24 to offset the index mixer.channel_strip(index).set_volume_control(self._dial[index+24]) for index in range(COLS): mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) mixer.track_eq(index).name = 'Mixer_EQ_' + str(index) mixer.track_filter(index).name = 'Mixer_Filter_' + str(index) #added by a mixer.channel_strip(index)._invert_mute_feedback = True #mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index])) self.song().view.selected_track = mixer.channel_strip(0)._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error """ Technically, we aren't using the session control, but I'm going to set it up in case inter-script communication needs it""" def _setup_session_control(self): is_momentary = True num_tracks = COLS num_scenes = ROWS global session session = SessionComponent(num_tracks, num_scenes) session.name = "Session" session.set_offsets(0, 0) self._session = session self._session.set_stop_track_clip_value(0) self._scene = [None for index in range(ROWS)] for row in range(num_scenes): self._scene[row] = session.scene(row) self._scene[row].name = 'Scene_' + str(row) for column in range(num_tracks): clip_slot = self._scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_' + str(row) clip_slot.set_triggered_to_play_value(64) clip_slot.set_triggered_to_record_value(64) clip_slot.set_stopped_value(0) clip_slot.set_started_value(64) clip_slot.set_recording_value(64) #clip_slot.set_launch_button(self._grid[column][row]) #comment out if you don't want clip launch session.set_mixer(mixer) self._session_zoom = SessionZoomingComponent(session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_stopped_value(0) self._session_zoom.set_playing_value(64) self._session_zoom.set_selected_value(64) if STANDALONE is True: self.set_highlighting_session_component(self._session) self._session.set_track_bank_buttons(self._grid[5][3], self._grid[4][3]) #comment out when using with Griid self._session.set_scene_bank_buttons(self._grid[7][3], self._grid[6][3]) # comment out when using with Griid """this is where we take care of setting up the the multiple devices per page, we will need 4""" def _setup_device_controls(self): self._device = [None for index in range(4)] for index in range(ROWS): self._device[index] = DeviceComponent() self._device[index].name = 'Device_Component_' + str(index) #self.set_device_component(self._device) #this doesn't work anymore, because we have multiple devices for the controller....we'll have to get fancy here, but that's for later #self._device_navigator = DetailViewControllerComponent() #its unclear if we'll need this....how is device navigation (i.e. banking for device parameter banks) going to be handled by the script? #self._device_navigator.name = 'Device_Navigator' device_param_controls = [] for control in range(COLS): """this setups up 8 device parameters per row""" #dial_index = control + (index*COLS) """alternatively, this setus up device controls in 4 4x2 groups""" dial_index = device_encoders[control + (index*COLS)] device_param_controls.append(self._dial[dial_index]) self._device[index].set_parameter_controls(tuple(device_param_controls)) """this is where we deassign every control that will be changing function when we switch modes...best to just deassign them all, and reassign them on update""" def deassign_matrix(self): for index in range(DIALCOUNT): #this should totally work!!! I'm over appealing to Python's sadistic mannerisms right now.... self._dial[index].send_value(0, True) ##this is kind of a hack, and should be unnecessary; the bool at the end tells the send_value method to force the value out to the controller for index in range(COLS): self._mixer.track_eq(index).set_enabled(False) ##set_gain_controls(tuple([None for index in range(3)])) self._mixer.channel_strip(index).set_volume_control(None) self._mixer.track_filter(index).set_enabled(False) ##set_filter_controls(tuple([None, None])) self._mixer.channel_strip(index).set_pan_control(None) self._mixer.channel_strip(index).set_select_button(None) self._mixer.channel_strip(index).set_send_controls(tuple([None for index in range(4)])) for device in range(4): self._device[device].set_bank_nav_buttons(None, None) self._device[device].set_enabled(False) ##set_parameter_controls(tuple([None for index in range(8)])) for track in range(8): self._mixer.channel_strip(track).set_select_button(None) for scene in range(4): self._scene[scene].clip_slot(track).set_launch_button(None) #self.request_rebuild_midi_map() # I think this is causing problems updating the leds when in build? """EQ Hi/Mid/Low and volume""" def assign_page_0(self): """for each column""" is_momentary = True for index in range(COLS): self._mixer.track_eq(index).set_gain_controls((self._dial[index+16],self._dial[index+8],self._dial[index])) self._mixer.track_eq(index).set_enabled(True) self._mixer.channel_strip(index).set_volume_control(self._dial[index+24])#use the bottom row of encoders for volume, so add 24 to offset the index self._mixer.channel_strip(index).set_select_button(self._trackbtns[index]) self.assign_cliplaunch() self._mixer.update() """sends 1-4""" def assign_page_1(self): is_momentary = True for index in range(COLS): send_controllers = [self._dial[index],self._dial[index+8],self._dial[index+16],self._dial[index+24]] self._mixer.channel_strip(index).set_send_controls(tuple(send_controllers)) self._mixer.channel_strip(index).set_select_button(self._trackbtns[index]) self._mixer.update() """devices 1-8""" def assign_pages_2_3(self): ##these need to be here anyway, whether or not there is a device present to control for index in range(4): self._device[index].set_enabled(True) #device_param_controls = [] ###no need to reassign it, since we are turning it off and on #for control in range(COLS): ###in fact, I think we can assign all this stuff in the header except for things directly connected to the mixer module # device_param_controls.append(self._dial[control + (index*COLS)]) #self._device[index].set_parameter_controls(tuple(device_param_controls)) self._reassign_devices(self._shift_mode._mode_index) """ filter res,filter q, pan, volume""" def assign_page_4(self): is_momentary = True for index in range(COLS): self._mixer.track_filter(index).set_filter_controls(self._dial[index], self._dial[index + 8]) #set_filter_controls(self, freq, reso) self._mixer.track_filter(index).set_enabled(True) #self._mixer.track_eq(index).set_gain_controls((self._dial[index],self._dial[index+8],self._dial[index+16])) self._mixer.channel_strip(index).set_pan_control(self._dial[index+16]) self._mixer.channel_strip(index).set_volume_control(self._dial[index+24]) self._mixer.channel_strip(index).set_select_button(self._trackbtns[index]) self._mixer.update() def assign_cliplaunch(self): if STANDALONE is True: for column in range(COLS): for row in range(ROWS-1): self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row]) def _reassign_devices(self, mode_index): if self._shift_mode._mode_index in range(2, 4): ##both of these lines would be better handled by a property offset = (mode_index - 2) * 4 ## set up in an override module of the device_component....bleh track = self.song().view.selected_track for index in range(4): if index + offset < len(track.devices): #self.log_message('assigning device') self._device[index].set_device(track.devices[index + offset]) else: #self.log_message('assigning device to None') self._device[index].set_device(None) self._device[index].set_bank_nav_buttons(self._trackbtns[(index * 2)], self._trackbtns[(index * 2) + 1]) self._device[index].update() def disconnect(self): """clean things up on disconnect""" self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= Code log closed =--------------") #Create entry in log file ControlSurface.disconnect(self) return None
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
class MaschineMk2(ControlSurface): __module__ = __name__ __doc__ = 'Control Script for Maschine Mk2 and Maschine Mikro Mk2' def __init__(self, c_instance): ControlSurface.__init__(self, c_instance, False) with self.component_guard(): self._suppress_send_midi = True self.togglecolor = (10, 30, 50, 70, 90) self.toggleindex = 0 self._c_ref = c_instance self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143 self._c_inst = c_instance is_momentary = True self._active = True self._modifier_down = False self._return_mode = 0 self._returntopad = False self._mode = CLIP_MODE self.init_slot = 0 self.init_done = False self._midi_pause_count = 0 self.nav_index = 0 self._base_note = 0 self._octave = 0.55 self._scale_select_mode = MODE_PRESS_NONE self.send_slider_index = 0 self._pad_mode = PM_OFF self._note_display_mode = ND_KEYBOARD1 self._set_suppress_rebuild_requests(True) self._scenematrix = SceneMatrix(self) self._master_knob = Mk2KnobControl(self) self._device = self._set_up_device_control() self.show_message(str('')) self.request_rebuild_midi_map() self._set_global_buttons() self._set_mode_buttons() self._setup_transport() self._set_modecontrol() self._set_up_session() self._set_up_mixer() self._set_up_timer() self._set_up_machine_knobs() self.current_scale_index = 0 self.assign_transpose(SCALES[self.current_scale_index]) self.set_highlighting_session_component(self._session) self._navigate_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 127) self._navigate_button.add_value_listener(self._do_focus_navigate) self.display_update_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 86) self.display_update_button.add_value_listener(self._a_display_update) self._set_suppress_rebuild_requests(False) self.song().view.add_detail_clip_listener(self.clip_handle) self.song().add_visible_tracks_listener(self.clip_handle) self.song().add_scenes_listener(self.clip_handle) self.application().view.add_view_focus_changed_listener(self.focus_changed) self.log_message('########## LIVE 9 MASCHINE MK2 V 1.02 #############') self._suppress_send_midi = False def _set_up_mixer(self): is_momentary = True self._mixer = MixerComponent(8) self.send_sliders = [] for track in range(8): self.send_sliders.append(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, SEND_CC_OFF + track)) for track in range(8): strip = self._mixer.channel_strip(track) strip.set_arm_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, ARM_CC_OFF + track)) strip.set_solo_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SOLO_CC_OFF + track)) strip.set_mute_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, MUTE_CC_OFF + track)) strip.set_volume_control(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, LEVEL_CC_OFF + track)) strip.set_pan_control(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, PAN_CC_OFF + track)) strip.set_select_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SELECT_CC_OFF + track)) st = tuple([self.send_sliders[track]]) strip.set_send_controls(st) self.send_slider_toggle_button = StateButton(False, MIDI_CC_TYPE, 0, 90) self.send_slider_toggle_button.add_value_listener(self._do_toggle_send) self._session.set_mixer(self._mixer) def _set_global_buttons(self): is_momentary = True self._undo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 85) self._undo_button.add_value_listener(self._do_undo) self._redo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 87) self._redo_button.add_value_listener(self._do_redo) self._armsolomode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 89) self._armsolomode_button.add_value_listener(self._do_armsolo_mode) self._fire_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 9) self._fire_button.add_value_listener(self._do_fire_button) self.track_left_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 120) self.track_right_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 121) self.track_left_button.add_value_listener(self._a_trk_left) self.track_right_button.add_value_listener(self._a_trk_right) self.test_button = StateButton(True, MIDI_CC_TYPE, 5, 60) self.note_repeat_button = StateButton(True, MIDI_CC_TYPE, 5, 61) self.test_button.add_value_listener(self.do_test) self.note_repeat_button.add_value_listener(self.do_note_repeat) self.reset_test_button = StateButton(True, MIDI_CC_TYPE, 5, 62) self.reset_test_button.add_value_listener(self.do_reset) def _set_mode_buttons(self): self.xfade_assign_button = StateButton(True, MIDI_CC_TYPE, 0, 116) self._pad_select_button = StateButton(False, MIDI_CC_TYPE, 0, 117) self._pad_solo_button = StateButton(False, MIDI_CC_TYPE, 0, 118) self._mute_button = StateButton(False, MIDI_CC_TYPE, 0, 119) self._pad_scale_up = GatedColorButton(True, MIDI_CC_TYPE, 83, 0) self._pad_scale_down = GatedColorButton(True, MIDI_CC_TYPE, 94, 16) self._pad_select_button.add_value_listener(self._do_pad_select_multi) self._mute_button.add_value_listener(self._do_mute_button) self._pad_solo_button.add_value_listener(self._do_pad_solo_multi) self.xfade_assign_button.add_value_listener(self._do_xfade_assign) self._pad_scale_up.add_value_listener(self._do_pad_note_up) self._pad_scale_down.add_value_listener(self._do_pad_note_down) def set_appointed_device(self, device): with self.component_guard(): self._device_component.set_device(device) def _set_up_device_control(self): is_momentary = True device = MaschineDeviceComponent(self) device.set_device_changed_listener(self._handle_device_changed) device.set_device_parm_listener(self._hande_device_parm_changed) param_controls = [] for index in range(8): param_controls.append(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_CC_OFF + index)) device.set_parameter_controls(tuple(param_controls)) device.set_on_off_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF)) device.set_bank_nav_buttons(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 4), ButtonElement(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 5)) self._device_nav_button_left = StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 6) self._device_nav_button_right = StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF + 7) self._device_nav_button_left.add_value_listener(self._nav_value_left) self._device_nav_button_right.add_value_listener(self._nav_value_right) device.name = 'Device_Component' self.set_device_component(device) return device def _setup_transport(self): is_momentary = True transport = TransportComponent() playButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 108) stopButton = StateButton(not is_momentary, MIDI_CC_TYPE, 0, 110) recordButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 109) overdubButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 107) metrononmeButton = StateButton(is_momentary, MIDI_CC_TYPE, 0, 104) playButton.name = 'Play' stopButton.name = 'Stop' recordButton.name = 'Record' overdubButton.name = 'Overdub' metrononmeButton.name = 'Metronome' transport.set_play_button(playButton) transport.set_stop_button(stopButton) transport.set_record_button(recordButton) transport.set_overdub_button(overdubButton) transport.set_metronome_button(metrononmeButton) transport.set_nudge_buttons(StateButton(is_momentary, MIDI_CC_TYPE, 1, 51), StateButton(is_momentary, MIDI_CC_TYPE, 1, 50)) punchinbutton = ToggleButton(MIDI_CC_TYPE, 1, 52) punchoutbutton = ToggleButton(MIDI_CC_TYPE, 1, 53) punchinbutton.name = 'Punch In' punchoutbutton.name = 'Punch Out' transport.set_punch_buttons(punchinbutton, punchoutbutton) transport.set_loop_button(StateButton(is_momentary, MIDI_CC_TYPE, 1, 54)) self.transp_ff_button = ButtonElement(True, MIDI_CC_TYPE, 1, 59) self.transp_rw_button = ButtonElement(True, MIDI_CC_TYPE, 1, 58) transport.set_seek_buttons(self.transp_ff_button, self.transp_rw_button) self.xfadeKnob = SliderElement(MIDI_CC_TYPE, 1, 100) self.xfadeKnob.connect_to(self.song().master_track.mixer_device.crossfader) self.tap_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 88) self.tap_button.add_value_listener(self._do_tap_tempo) self.cue_add_delete_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 55) self.cue_prev_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 56) self.cue_next_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 57) self.cue_add_delete_button.add_value_listener(self._do_toggle_cue) self.cue_prev_button.add_value_listener(self._do_toggle_prev_cue) self.cue_next_button.add_value_listener(self._do_toggle_next_cue) def _set_up_machine_knobs(self): master_track = self.song().master_track self.master_volume = SliderElement(MIDI_CC_TYPE, 0, 40) self.prehear = SliderElement(MIDI_CC_TYPE, 0, 41) self.master_volume.connect_to(master_track.mixer_device.volume) self.prehear.connect_to(master_track.mixer_device.cue_volume) def _set_up_session(self): is_momentary = True self._session = MaschineSessionComponent() self._session.add_offset_listener(self.notify_track_scroll) nhue = COLOR_HUE_NAV self.nav_buttons = (GatedColorButton(True, MIDI_CC_TYPE, 92, nhue), GatedColorButton(True, MIDI_CC_TYPE, 81, nhue), GatedColorButton(True, MIDI_CC_TYPE, 93, nhue), GatedColorButton(True, MIDI_CC_TYPE, 91, nhue)) self._session.set_scene_bank_buttons(self.nav_buttons[0], self.nav_buttons[1]) self._session.set_track_bank_buttons(self.nav_buttons[2], self.nav_buttons[3]) self._session.set_stop_all_clips_button(StateButton(is_momentary, MIDI_CC_TYPE, 0, 111)) track_stop_buttons = [ StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, index + STOP_CC_OFF) for index in range(4) ] self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._init_matrix() self._set_up_buttons() self._session._link() self._session.set_advance(STEP4) def _set_up_buttons(self): self._bmatrix = ButtonMatrixElement() for scene_index in range(4): button_row = [] scene = self._session.scene(scene_index) for track_index in range(4): button = self._matrix[scene_index][track_index] clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(button) clip_slot.set_triggered_to_play_value(1) clip_slot.set_triggered_to_record_value(1) clip_slot.set_started_value(1) clip_slot.set_recording_value(1) clip_slot.set_stopped_value(1) self._bmatrix.add_row(tuple(button_row)) def _init_matrix(self): is_momentary = True self._button_sequence = [] self._matrix = [] for scene_index in range(4): button_row = [] for track_index in range(4): button = VarButtonElement(is_momentary, 0, scene_index, track_index, self) partner = TwinButton(is_momentary, 1, button) partner.add_value_listener(self.ox, True) button_row.append(button) self._matrix.append(tuple(button_row)) for scene_index in [3, 2, 1, 0]: for track_index in range(4): self._button_sequence.append(self._matrix[scene_index][track_index]) self._session.set_matrix(self._matrix) def set_pad_translations(self, pad_translations): ControlSurface.set_pad_translations(pad_translations) def refresh_state(self): ControlSurface.refresh_state(self) self._update_hardware() def ox(self, value, button): if not isinstance(button, TwinButton): raise AssertionError self._mode == PAD_MODE and button.fire(value) def _update_hardware(self): self._session.update() self._set_suppress_rebuild_requests(True) self._set_mode() self._master_knob.update() if self._scenematrix.soloexclusive: self._armsolomode_button.send_value(1, True) else: self._armsolomode_button.send_value(0, True) self._master_knob.start_up() self._pad_scale_up.activate() self._pad_scale_down.activate() self.current_scale_to_display() self.send_to_display(KEY_COLOR_MODES_STRINGS[self._note_display_mode], 1) for scene_index in range(4): scene = self._session.scene(scene_index) for track_index in range(4): button = self._matrix[scene_index][track_index] button.refresh() self._set_suppress_rebuild_requests(False) def get_color(self, value, track_index, scene_index): if not self._active: return if self._mode == SCENE_MODE or self._mode == CONTROL_MODE or self._pad_mode == PM_ON: element = self._scenematrix.get_element(scene_index, track_index) return element.get_color(value) elif self._mode == CLIP_MODE: scene = self._session.scene(scene_index) clip_slot = scene.clip_slot(track_index)._clip_slot cindex = 0 if value == 0: cindex = 1 if clip_slot != None: if clip_slot.has_clip: if clip_slot.clip.is_recording or clip_slot.clip.will_record_on_start: return PColor.CLIP_RECORD[cindex] if clip_slot.clip.is_playing: return PColor.CLIP_PLAY[cindex] elif clip_slot.clip.is_triggered: return PColor.CLIP_PLAY[cindex] else: return PColor.CLIP_STOPPED[cindex] elif clip_slot.will_record_on_start: return PColor.CLIP_RECORD[cindex] elif clip_slot.is_playing: return PColor.CLIP_GROUP_PLAY[cindex] elif clip_slot.controls_other_clips: return PColor.CLIP_GROUP_CONTROL[cindex] elif clip_slot.is_triggered: return PColor.CLIP_GROUP_TRIGGER[cindex] elif self._mode == PAD_MODE: button = self._matrix[scene_index][track_index] return self.get_color_by_note_mode(button.get_identifier(), value > 0) def step_key_color_mode(self): self._note_display_mode = (self._note_display_mode + 1) % len(KEY_COLOR_MODES_STRINGS) self.show_message('Pad Mode Key Color = ' + KEY_COLOR_MODES_STRINGS[self._note_display_mode]) self.send_to_display('Colors: ' + KEY_COLOR_MODES_STRINGS[self._note_display_mode], 1) if self._mode == PAD_MODE: for note_index in range(16): button = self._button_sequence[note_index] button.send_color_direct(self.get_color_by_note_mode(button.get_identifier(), False)) def get_color_by_note_mode(self, midi_note, on): if self._note_display_mode == ND_BASE_OTHER: interval = (midi_note + 12 - self._base_note) % 12 if on: return INTERVAL_COLOR_MAP[interval][0] else: return INTERVAL_COLOR_MAP[interval][1] elif on: return KEY_COLOR_MAP[midi_note % 12][0] else: return KEY_COLOR_MAP[midi_note % 12][1] def _send_midi(self, midi_bytes, **keys): self._c_ref.send_midi(midi_bytes) if self._midi_pause_count == 2: time.sleep(0.002) self._midi_pause_count = 0 else: self._midi_pause_count = self._midi_pause_count + 1 return True def clip_handle(self): if self._mode == SCENE_MODE or self._mode == CONTROL_MODE or self._modifier_down: self._scenematrix.update() def _a_display_update(self, value): if not self.display_update_button != None: raise AssertionError raise value in range(128) or AssertionError (value != 0 or not self.display_update_button.is_momentary()) and self._update_hardware() self.show_message('Maschine Display Updated') def _set_up_timer(self): self.blink_state = 1 def update_display(self): with self.component_guard(): with self._is_sending_scheduled_messages(): self._task_group.update(0.1) if self._mode == CLIP_MODE and not self._modifier_down: if self.blink_state == 0: self._session.notify(1, 0) elif self.blink_state == 1: self._session.notify(1, 1) elif self.blink_state == 3: self._session.notify(2, 0) elif self.blink_state == 4: self._session.notify(2, 1) elif self._mode == PAD_MODE: pass elif self.blink_state == 0: self._scenematrix.notify_scene_mode(1) elif self.blink_state == 2: self._scenematrix.notify_scene_mode(0) self.blink_state = (self.blink_state + 1) % 4 self.init_slot += 1 def _invoke_track_edit(self, mode): self._deassign_matrix() self._scenematrix.assign() self._scenematrix.set_mode(mode) self._pad_mode = PM_ON self.request_rebuild_midi_map() self._scenematrix.update() def _set_modecontrol(self): is_momentary = True self.scene_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 112) self.clip_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 113) self.pad_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 114) self.control_mode_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 115) self.xfade_assign_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 116) self.scene_mode_button.add_value_listener(self._a_mode_scene) self.clip_mode_button.add_value_listener(self._a_mode_clip) self.pad_mode_button.add_value_listener(self._a_mode_pad) self.control_mode_button.add_value_listener(self._a_mode_control) def _set_mode(self, mode = None): if mode == None: mode = self._mode if mode == SCENE_MODE: self.clip_mode_button.send_value(OFF_VALUE, True) self.pad_mode_button.send_value(OFF_VALUE, True) self.control_mode_button.send_value(OFF_VALUE, True) self.scene_mode_button.send_value(ON_VALUE, True) elif mode == CLIP_MODE: self.scene_mode_button.send_value(OFF_VALUE, True) self.pad_mode_button.send_value(OFF_VALUE, True) self.control_mode_button.send_value(OFF_VALUE, True) self.clip_mode_button.send_value(ON_VALUE, True) elif mode == PAD_MODE: self.scene_mode_button.send_value(OFF_VALUE, True) self.clip_mode_button.send_value(OFF_VALUE, True) self.control_mode_button.send_value(OFF_VALUE, True) self.pad_mode_button.send_value(ON_VALUE, True) elif mode == CONTROL_MODE: self.scene_mode_button.send_value(OFF_VALUE, True) self.clip_mode_button.send_value(OFF_VALUE, True) self.pad_mode_button.send_value(OFF_VALUE, True) self.control_mode_button.send_value(ON_VALUE, True) def _reset_matrix(self): for scene_index in range(4): scene = self._session.scene(scene_index) for track_index in range(4): button = self._matrix[scene_index][track_index] clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(button) def update_button_matrix(self): self._session.update() for scene_index in range(4): scene = self._session.scene(scene_index) for track_index in range(4): button = self._matrix[scene_index][track_index] clip_slot = scene.clip_slot(track_index) if clip_slot._clip_slot != None and clip_slot._clip_slot.clip != None: button.send_value(1, True) else: button.send_value(0, True) def _deassign_matrix(self): for scene_index in range(4): scene = self._session.scene(scene_index) for track_index in range(4): clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(None) def _from_pad_mode(self, matrix_mode): self._mode = SCENE_MODE self._register_buttons() self._scenematrix.assign() self._scenematrix.set_mode(matrix_mode) self._set_suppress_rebuild_requests(True) self.request_rebuild_midi_map() self._scenematrix.update() self._set_suppress_rebuild_requests(False) def _enter_pad_mode(self): self._set_mode(PAD_MODE) if self._mode == CLIP_MODE: self._deassign_matrix() elif self._mode == SCENE_MODE: self._scenematrix.deassign() elif self._mode == CONTROL_MODE: self._scenematrix.deassign() self._master_knob.exit_matrix_mode() self._mode = PAD_MODE self._set_suppress_rebuild_requests(True) for row in range(4): for column in range(4): button = self._matrix[row][column] button.send_value(0, True) button.set_to_notemode(True) self._forwarding_registry[MIDI_NOTE_ON_STATUS, button.get_identifier()] = button self._forwarding_registry[MIDI_NOTE_OFF_STATUS, button.get_identifier()] = button self._set_suppress_rebuild_requests(False) def _register_buttons(self, update = False): self._set_suppress_rebuild_requests(True) for row in range(4): for column in range(4): button = self._matrix[row][column] button.set_to_notemode(False) if update: button.send_value(127, True) fwkey = [MIDI_NOTE_ON_STATUS] fwkey.append(button.get_identifier()) self._forwarding_registry[tuple(fwkey)] = button self._forwarding_registry[MIDI_NOTE_OFF_STATUS, button.get_identifier()] = button self._set_suppress_rebuild_requests(False) def _back_to_clip_mode(self): self._pad_mode = PM_OFF self._scenematrix.set_mode(SCENE_MODE_NORMAL) self._scenematrix.deassign() self._set_up_clip_matrix() def _set_up_clip_matrix(self): for row in range(4): for column in range(4): button = self._matrix[row][column] button.set_to_notemode(False) self._set_suppress_rebuild_requests(True) self.request_rebuild_midi_map() self._reset_matrix() self.update_button_matrix() self._set_suppress_rebuild_requests(False) def _enter_scene_mode(self): self._set_mode(SCENE_MODE) if self._mode == CLIP_MODE: self._deassign_matrix() elif self._mode == CONTROL_MODE: self._master_knob.exit_matrix_mode() elif self._mode == PAD_MODE: self._register_buttons() self._mode = SCENE_MODE self._scenematrix.assign() self._scenematrix.set_mode(SCENE_MODE_NORMAL) self._return_mode = SCENE_MODE_NORMAL self.request_rebuild_midi_map() def _enter_clip_mode(self): self._set_suppress_rebuild_requests(True) self._set_mode(CLIP_MODE) if self._mode == SCENE_MODE: self._scenematrix.deassign() elif self._mode == CONTROL_MODE: self._master_knob.exit_matrix_mode() self._mode = CLIP_MODE self._set_up_clip_matrix() self.request_rebuild_midi_map() self._set_suppress_rebuild_requests(False) def _enter_control_mode(self): self._set_mode(CONTROL_MODE) if self._mode == CLIP_MODE: self._deassign_matrix() elif self._mode == PAD_MODE: self._mode = CONTROL_MODE self._register_buttons() self._mode = CONTROL_MODE self._set_suppress_rebuild_requests(True) self._scenematrix.set_mode(SCENE_MODE_CONTROL) self._return_mode = SCENE_MODE_CONTROL self._scenematrix.assign() self._master_knob.switch_to_matrix_mode() self._set_suppress_rebuild_requests(False) self.request_rebuild_midi_map() self._scenematrix.update() def _a_mode_scene(self, value): if not self.scene_mode_button != None: raise AssertionError raise value in range(128) or AssertionError value != 0 and self.show_message('SCENE MODE') self._enter_scene_mode() def _a_mode_clip(self, value): if not self.clip_mode_button != None: raise AssertionError raise value in range(128) or AssertionError value != 0 and self.show_message('CLIP MODE') self._enter_clip_mode() def _a_mode_pad(self, value): if not self.pad_mode_button != None: raise AssertionError raise value in range(128) or AssertionError value != 0 and self.show_message('PAD MODE') self._enter_pad_mode() def _a_mode_control(self, value): if not self.control_mode_button != None: raise AssertionError raise value in range(128) or AssertionError value != 0 and self.show_message('CONTROL MODE') self._enter_control_mode() def _do_pad_select_multi(self, value): if not value in range(128): raise AssertionError self._modifier_down = value != 0 if self._mode == PAD_MODE or self._returntopad: value != 0 and self._from_pad_mode(SCENE_MODE_SELECT) self._returntopad = True else: self._returntopad = False self._enter_pad_mode() elif self._mode == CLIP_MODE: if value != 0: self._invoke_track_edit(SCENE_MODE_SELECT) else: self._back_to_clip_mode() elif self._mode != PAD_MODE: if value == 0: self._scenematrix.set_mode(self._return_mode) else: if self._scenematrix.in_main_mode(): self._return_mode = self._scenematrix.mode self._scenematrix.set_mode(SCENE_MODE_SELECT) def _do_mute_button(self, value): if not self._mute_button != None: raise AssertionError if not value in range(128): raise AssertionError self._modifier_down = value != 0 (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_MUTE) self._returntopad = True else: self._returntopad = False self._enter_pad_mode() elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE: if value == 0: self._scenematrix.set_mode(self._return_mode) self._pad_mode = PM_OFF else: if self._scenematrix.in_main_mode(): self._return_mode = self._scenematrix.mode self._scenematrix.set_mode(SCENE_MODE_MUTE) self._pad_mode = PM_ON elif self._mode == CLIP_MODE: if value > 0: self._invoke_track_edit(SCENE_MODE_MUTE) else: self._back_to_clip_mode() self._pad_mode = PM_OFF def _do_pad_solo_multi(self, value): if not value in range(128): raise AssertionError self._modifier_down = value != 0 if self._mode == PAD_MODE or self._returntopad: value != 0 and self._from_pad_mode(SCENE_MODE_SOLO) self._returntopad = True else: self._returntopad = False self._enter_pad_mode() elif self._mode == CLIP_MODE: if value != 0: self._invoke_track_edit(SCENE_MODE_SOLO) else: self._back_to_clip_mode() elif self._mode != PAD_MODE: if value == 0: self._scenematrix.set_mode(self._return_mode) else: if self._scenematrix.in_main_mode(): self._return_mode = self._scenematrix.mode self._scenematrix.set_mode(SCENE_MODE_SOLO) def _do_xfade_assign(self, value): if not self.xfade_assign_button != None: raise AssertionError if not value in range(128): raise AssertionError (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_XFADE) self._returntopad = True else: self._returntopad = False self._enter_pad_mode() elif self._mode == CLIP_MODE: if value != 0: self._invoke_track_edit(SCENE_MODE_XFADE) else: self._back_to_clip_mode() elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE: if value == 0: self._scenematrix.set_mode(self._return_mode) else: if self._scenematrix.in_main_mode(): self._return_mode = self._scenematrix.mode self._scenematrix.set_mode(SCENE_MODE_XFADE) def _do_pad_note_up(self, value): if not self._pad_scale_up != None: raise AssertionError if not value in range(128): raise AssertionError self._pad_scale_up.send_value(value, True) self._modifier_down = value != 0 (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_ARM) self._returntopad = True else: self._returntopad = False self._enter_pad_mode() elif self._mode == CLIP_MODE: self.show_message('Arm tracks with pads') if value != 0: self._invoke_track_edit(SCENE_MODE_ARM) else: self._back_to_clip_mode() elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE: self.show_message('Arm tracks with pads') if value == 0: self._scenematrix.set_mode(self._return_mode) else: if self._scenematrix.in_main_mode(): self._return_mode = self._scenematrix.mode self._scenematrix.set_mode(SCENE_MODE_ARM) def _do_pad_note_down(self, value): if not self._pad_scale_down != None: raise AssertionError if not value in range(128): raise AssertionError self._pad_scale_down.send_value(value, True) self._modifier_down = value != 0 (self._mode == PAD_MODE or self._returntopad) and value != 0 and self._from_pad_mode(SCENE_MODE_STOP) self._returntopad = True else: self._returntopad = False self._enter_pad_mode() elif self._mode == CLIP_MODE: self.show_message('Stop tracks with pads') if value != 0: self._invoke_track_edit(SCENE_MODE_STOP) else: self._back_to_clip_mode() elif self._mode == SCENE_MODE or self._mode == CONTROL_MODE: self.show_message('Stop tracks with pads') if value == 0: self._scenematrix.set_mode(self._return_mode) else: if self._scenematrix.in_main_mode(): self._return_mode = self._scenematrix.mode self._scenematrix.set_mode(SCENE_MODE_STOP) def modify_track_offset(self, delta): self._scenematrix.mod_track_offset(delta) def modify_scene_offset(self, delta): self._scenematrix.mod_scene_offset(delta) def move_view_horizontal(self, delta): if delta == 1: self._session.bank_right() else: self._session.bank_left() if self._mode == CONTROL_MODE: self._scenematrix.update() def inc_octave(self, inc): scale = SCALES[self.current_scale_index] octave = scale.to_octave(self._octave) newoctave = octave + inc if newoctave < 0: newoctave = 0 elif newoctave > scale.octave_range: newoctave = scale.octave_range self._octave = scale.to_relative(newoctave, self._octave) scale = SCALES[self.current_scale_index] self.show_message(' OCTAVE ' + BASE_NOTE[self._base_note] + str(newoctave - 2) + ' to ' + scale.name) self.current_scale_to_display() def inc_base_note(self, inc): newbase = self._base_note + inc if newbase < 0: self._base_note = 0 elif newbase > 11: self._base_note = 11 else: self._base_note = newbase scale = SCALES[self.current_scale_index] self.show_message(' Base Note ' + BASE_NOTE[self._base_note] + ' to ' + scale.name) self.current_scale_to_display() def current_scale_to_display(self): scale = SCALES[self.current_scale_index] text = scale.name + ' ' + BASE_NOTE[self._base_note] + str(scale.to_octave(self._octave)) self.send_to_display(text) def inc_scale(self, inc): nr_of_scales = len(SCALES) newindex = self.current_scale_index + inc if newindex < 0: newindex = 0 elif newindex >= nr_of_scales: newindex = nr_of_scales - 1 else: self.current_scale_index += inc newscale = SCALES[self.current_scale_index] self.show_message(' PAD Scale ' + newscale.name + ' ' + BASE_NOTE[self._base_note] + str(newscale.to_octave(self._octave) - 2)) self.current_scale_to_display() def update_transpose(self): self.assign_transpose(SCALES[self.current_scale_index]) self._set_suppress_rebuild_requests(True) self.request_rebuild_midi_map() self._set_suppress_rebuild_requests(False) def set_scale(self, scale): raise isinstance(scale, PadScale) or AssertionError scale_len = len(scale.notevalues) octave = scale.to_octave(self._octave) def assign_transpose(self, scale): raise isinstance(scale, PadScale) or AssertionError scale_len = len(scale.notevalues) octave = scale.to_octave(self._octave) last_note_val = None for note_index in range(16): button = self._button_sequence[note_index] scale_index = note_index % scale_len octave_offset = note_index / scale_len note_value = scale.notevalues[scale_index] + self._base_note + octave * 12 + octave_offset * 12 if note_value < 128: last_note_val = note_value elif last_note_val != None: note_value = last_note_val button.set_send_note(note_value) if self._mode == PAD_MODE: button.send_color_direct(self.get_color_by_note_mode(note_value, False)) def do_reset(self, value): if value == 0: return for row in range(4): for column in range(4): button = self._matrix[row][column] data_byte1 = button._original_identifier button.send_midi((MIDI_CC_STATUS + 2, data_byte1, 0)) def do_test(self, value): color = self.togglecolor[self.toggleindex] self.toggleindex = (self.toggleindex + 1) % len(self.togglecolor) if value == 0: return for row in range(4): for column in range(4): button = self._matrix[row][column] self.schedule_message(1, self.dosend, (color, 127, 127, row, column)) def dosend(self, parm = None): button = self._matrix[parm[3]][parm[4]] data_byte1 = button._original_identifier button.send_midi((MIDI_CC_STATUS + 0, data_byte1, parm[0])) button.send_midi((MIDI_CC_STATUS + 1, data_byte1, parm[1])) button.send_midi((MIDI_CC_STATUS + 2, data_byte1, parm[2])) def do_note_repeat(self, value): nrvalue = 0 if value != 0: nrvalue = 1 self._c_ref.set_note_repeat_state(nrvalue) def _do_toggle_send(self, value): nr_of_tracks = len(self.song().return_tracks) if value == 0 or nr_of_tracks < 1: return prev = self.send_slider_index self.send_slider_index += 1 if self.send_slider_index >= nr_of_tracks: self.send_slider_index = 0 self.show_message(' Set Send ' + str(SENDS[self.send_slider_index])) if prev != self.send_slider_index: for track in range(8): strip = self._mixer.channel_strip(track) slider_list = [] for index in range(self.send_slider_index + 1): if index < self.send_slider_index - 1: slider_list.append(None) else: slider_list.append(self.send_sliders[track]) strip.set_send_controls(tuple(slider_list)) def _do_armsolo_mode(self, value): if not self._armsolomode_button != None: raise AssertionError raise value in range(128) or AssertionError value != 0 and self._scenematrix.set_armsolo_exclusive(self._armsolomode_button) def _do_fire_button(self, value): if not self._fire_button != None: raise AssertionError if not value in range(128): raise AssertionError clip_slot = (value != 0 or not self._mute_button.is_momentary()) and self.song().view.highlighted_clip_slot clip_slot and clip_slot.fire() def _do_undo(self, value): if not self._undo_button != None: raise AssertionError if not value in range(128): raise AssertionError (value != 0 or not self._undo_button.is_momentary()) and self.song().can_undo == 1 and self.song().undo() self.show_message(str('UNDO')) def _do_redo(self, value): if not self._redo_button != None: raise AssertionError if not value in range(128): raise AssertionError (value != 0 or not self._redo_button.is_momentary()) and self.song().can_redo == 1 and self.song().redo() self.show_message(str('REDO')) def _a_trk_left(self, value): if not value in range(128): raise AssertionError if value != 0: direction = self.application().view.is_view_visible('Session') and Live.Application.Application.View.NavDirection.left self.application().view.scroll_view(direction, 'Session', True) def _a_trk_right(self, value): if not value in range(128): raise AssertionError if value != 0: direction = self.application().view.is_view_visible('Session') and Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Session', True) def _nav_value_left(self, value): if not self._device_nav_button_left != None: raise AssertionError if not value in range(128): raise AssertionError modifier_pressed = True value > 0 and (not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain')) and self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: direction = Live.Application.Application.View.NavDirection.left self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed) def _nav_value_right(self, value): if not self._device_nav_button_right != None: raise AssertionError if not value in range(128): raise AssertionError modifier_pressed = value > 0 and True (not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain')) and self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: direction = Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed) def _do_tap_tempo(self, value): if not value in range(128): raise AssertionError value > 0 and self.song().tap_tempo() def _do_toggle_cue(self, value): if not value in range(128): raise AssertionError value > 0 and self.song().set_or_delete_cue() def _do_toggle_prev_cue(self, value): if not value in range(128): raise AssertionError value > 0 and self.song().jump_to_prev_cue() def _do_toggle_next_cue(self, value): if not value in range(128): raise AssertionError value > 0 and self.song().jump_to_next_cue() def focus_changed(self): pass def _handle_device_changed(self, device): pass def _hande_device_parm_changed(self): pass def _do_focus_navigate(self, value): if not self._navigate_button != None: raise AssertionError raise value in range(128) or AssertionError self.nav_index = value != 0 and (self.nav_index + 1) % len(VIEWS_ALL) self.application().view.focus_view(VIEWS_ALL[self.nav_index]) self.show_message('Focus on : ' + str(VIEWS_ALL[self.nav_index])) def scroll_focus(self, delta): if delta == 1: self.nav_index = (self.nav_index + 1) % len(VIEWS_ALL) elif self.nav_index == 0: self.nav_index = len(VIEWS_ALL) - 1 else: self.nav_index -= 1 self.show_message('Focus on : ' + str(VIEWS_ALL[self.nav_index])) self.application().view.focus_view(VIEWS_ALL[self.nav_index]) def scroll_device(self, delta): if not (delta == 1 or delta == -1): raise AssertionError direction = delta == 1 and Live.Application.Application.View.NavDirection.right else: direction = Live.Application.Application.View.NavDirection.left self.application().view.scroll_view(direction, 'Detail/DeviceChain', True) def scroll_scene(self, delta): if not self.track_left_button != None: raise AssertionError raise delta == 1 or delta == -1 or AssertionError direction = delta == 1 and Live.Application.Application.View.NavDirection.down else: direction = Live.Application.Application.View.NavDirection.up self.application().view.scroll_view(direction, 'Session', True) def index_in_strip(self, track): for ind in range(len(self._mixer._channel_strips)): strack = self._mixer._channel_strips[ind]._track if strack == track: return ind return -1 def notify_track_scroll(self): self._scenematrix.update_control_selection() if self._mode == CONTROL_MODE: self._scenematrix.eval_matrix() self._scenematrix.fire_values() def send_to_display(self, text, grid = 0): if USE_DISPLAY == False: return if len(text) > 28: text = text[:27] msgsysex = [240, 0, 0, 102, 23, 18, min(grid, 3) * 28] filled = text.ljust(28) for c in filled: msgsysex.append(ord(c)) msgsysex.append(247) self._send_midi(tuple(msgsysex)) def send_color(self, button, hue, sat, bright): raise isinstance(button, ButtonElement) or AssertionError raise hue in range(128) or AssertionError raise sat in range(128) or AssertionError raise bright in range(128) or AssertionError data_byte1 = button._original_identifier button.send_midi((MIDI_CC_STATUS + 2, data_byte1, bright)) button.send_midi((MIDI_CC_STATUS + 1, data_byte1, sat)) button.send_midi((MIDI_CC_STATUS + 0, data_byte1, hue)) def turn_off_matrix(self): for row in range(4): for column in range(4): button = self._matrix[row][column] self.send_color(button, 2, 0, 0) button.set_to_notemode(False) def remove_listener(self, control, callback): if control != None and control.value_has_listener(callback): control.remove_value_listener(callback) control.disconnect() def disconnect(self): self.turn_off_matrix() self.scene_mode_button.send_value(0, True) self.clip_mode_button.send_value(0, True) self.pad_mode_button.send_value(0, True) self.control_mode_button.send_value(0, True) time.sleep(0.2) self._active = False self._suppress_send_midi = True self.remove_listener(self.scene_mode_button, self._a_mode_scene) self.remove_listener(self.clip_mode_button, self._a_mode_clip) self.remove_listener(self.pad_mode_button, self._a_mode_pad) self.remove_listener(self.control_mode_button, self._a_mode_control) self.remove_listener(self._undo_button, self._do_undo) self.remove_listener(self._redo_button, self._do_redo) self.remove_listener(self._armsolomode_button, self._do_armsolo_mode) self.remove_listener(self.xfade_assign_button, self._do_xfade_assign) self.remove_listener(self._fire_button, self._do_fire_button) self._session.remove_offset_listener(self.notify_track_scroll) self._mixer.disconnect() ControlSurface.disconnect(self)
def _setup_session_control(self): is_momentary = True right_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 43) left_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 42) up_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 44) down_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, 45) right_button.name = 'Bank_Select_Right_Button' left_button.name = 'Bank_Select_Left_Button' up_button.name = 'Bank_Select_Up_Button' down_button.name = 'Bank_Select_Down_Button' global session session = SessionComponent(4, 4) session.name = 'Session_Control' session.set_track_bank_buttons(right_button, left_button) session.set_scene_bank_buttons(down_button, up_button) self._session = session matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' scene_launch_notes = [33, 34, 35, 36] scene_launch_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, scene_launch_notes[index]) for index in range(4) ] #track_stop_buttons = [ ButtonElement(is_momentary, MIDI_NOTE_TYPE, index, 52) for index in range(4) ] for index in range(len(scene_launch_buttons)): scene_launch_buttons[index].name = 'Scene_' + str( index) + '_Launch_Button' #for index in range(len(track_stop_buttons)): # track_stop_buttons[index].name = 'Track_' + str(index) + '_Stop_Button' #stop_all_button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 81) #stop_all_button.name = 'Stop_All_Clips_Button' #self._session.set_stop_all_clips_button(stop_all_button) #self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) #self._session.set_stop_clip_value(2) button_notes = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 ] for scene_index in range(4): scene = session.scene(scene_index) scene.name = 'Scene_' + str(scene_index) button_row = [] scene.set_launch_button(scene_launch_buttons[scene_index]) #scene.set_triggered_value(2) for track_index in range(4): button = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CHAN, (track_index * 4) + scene_index + 1) button.name = str(track_index) + '_Clip_' + str( scene_index) + '_Button' button_row.append(button) clip_slot = scene.clip_slot(track_index) clip_slot.name = str(track_index) + '_Clip_Slot_' + str( scene_index) #clip_slot.set_triggered_to_play_value(2) #clip_slot.set_triggered_to_record_value(4) clip_slot.set_stopped_value(0) clip_slot.set_started_value(64) #clip_slot.set_recording_value(3) clip_slot.set_launch_button(button) matrix.add_row(tuple(button_row)) #self._session.set_slot_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 67)) session.selected_scene().name = 'Selected_Scene' #session.selected_scene().set_launch_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 64)) #session_zoom = SessionZoomingComponent(session) #session_zoom.name = 'Session_Overview' #session_zoom.set_button_matrix(matrix) #session_zoom.set_zoom_button(self._shift_button) #session_zoom.set_nav_buttons(up_button, down_button, left_button, right_button) #session_zoom.set_scene_bank_buttons(tuple(scene_launch_buttons)) #session_zoom.set_stopped_value(0) #session_zoom.set_selected_value(127) self.set_highlighting_session_component(session) session.set_mixer(mixer) return None #return session
class Codec(ControlSurface): __module__ = __name__ __doc__ = " MonoCode controller script " def __init__(self, c_instance, *a, **k): super(Codec, self).__init__(c_instance, *a, **k) self._monomod_version = 'b995' self._version_check = 'b995' self._host_name = 'Codec' self._color_type = 'Monochrome' self._link_mixer = LINK_MIXER self._hosts = [] self._linked_script = None self._local_ring_control = True self._last_device = None self._device_list = [None, None, None, None] self._device_select_buttons = None self._last_device_component = None self._timer = 0 self._touched = 0 self._locked = False self.flash_status = 1 self._shift_button = None self._shift_pressed = 0 self._shift_pressed_timer = 0 self._shift_thresh = SHIFT_THRESH self._use_device_selector = USE_DEVICE_SELECTOR self._device_selection_follows_track_selection=FOLLOW with self.component_guard(): #self.local_ring_control(True) #self.set_absolute_mode(True) self._setup_controls() self._setup_monobridge() self._setup_device_controls() self._setup_special_device_control() self._device.append(self._special_device) #necessary for device browsing to work with special device self._setup_device_chooser() self._setup_mixer_controls() self._setup_monomod() self._setup_modes() self._setup_device_selector() self._setup_send_reset() self._setup_default_buttons() self.set_local_ring_control(1) self.song().view.add_selected_track_listener(self._update_selected_device) self._initialize_code() #self._shift_mode.set_mode(0) #self._monomod_mode.set_mode(0) self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Codec ' + str(self._monomod_version) + ' log opened >>>>>>>>>>>>>>>>>>>>>>>>>') self.show_message('Codec Control Surface Loaded') self.request_rebuild_midi_map() """script initialization methods""" def _initialize_code(self): self._send_midi(factoryreset) self._send_midi(btn_channels) self._send_midi(enc_channels) def _setup_monobridge(self): self._monobridge = MonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _setup_controls(self): is_momentary = True self._livid = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, LIVID, 'Livid_Button', self) self._dial = [None for index in range(8)] for column in range(8): self._dial[column] = [None for index in range(4)] for row in range(4): self._dial[column][row] = CodecEncoderElement(MIDI_CC_TYPE, CHANNEL, CODE_DIALS[row][column], Live.MidiMap.MapMode.absolute, 'Dial_' + str(column) + '_' + str(row), (column + (row*8)), self) #CODE_DIALS[row][column] self._button = [None for index in range(8)] for column in range(8): self._button[column] = [None for index in range(4)] for row in range(4): self._button[column][row] = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_BUTTONS[row][column], 'Button_' + str(column) + '_' + str(row), self) self._column_button = [None for index in range(8)] for index in range(8): self._column_button[index] = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_COLUMN_BUTTONS[index], 'Column_Button_' + str(index), self) self._row_button = [None for index in range(4)] for index in range(4): self._row_button[index] = CodecMonoButtonElement(is_momentary, MIDI_NOTE_TYPE, CHANNEL, CODE_ROW_BUTTONS[index], 'Row_Button_' + str(index), self) self._dial_matrix = EncoderMatrixElement(self) self._dial_matrix.name = 'Encoder_Matrix' for row in range(4): dial_row = tuple([self._dial[column][row] for column in range(8)]) self._dial_matrix.add_row(dial_row) self._button_matrix = ButtonMatrixElement() self._button_matrix.name = 'Button_Matrix' for row in range(4): button_row = [self._button[column][row] for column in range(8)] button_row.append(self._row_button[row]) self._button_matrix.add_row(tuple(button_row)) self._button_matrix.add_row(tuple(self._column_button + [self._livid])) def _setup_modes(self): self._monomod_mode = MonomodModeComponent(self._mod_mode_update, self) self._monomod_mode.name = 'Monomod_Mode' self.set_shift_button(self._livid) self._shift_mode = ShiftModeComponent(self._shift_update, self) self._shift_mode.name = 'Shift_Mode' self._shift_mode.set_mode_buttons(tuple([self._row_button[0], self._row_button[1], self._row_button[2], self._row_button[3]])) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_monomod(self): self._host = CodecMonomodComponent(self) self._host.name = 'Monomod_Host' self._host._set_dial_matrix(self._dial_matrix, self._button_matrix) self.hosts = [self._host] encs = [] for row in range(4): for col in range(8): encs.append(self._dial[col][row]) self._host._set_parameter_controls(encs) def _setup_mixer_controls(self): is_momentary = True self._num_tracks = (8) self._session = SessionComponent(self._num_tracks, 0) self._session.name = 'Session' self._mixer = MixerComponent(self._num_tracks, 0, False, False) self._mixer.name = 'Mixer' self._mixer._next_track_value = self._mixer_next_track_value(self._mixer) self._mixer._prev_track_value = self._mixer_prev_track_value(self._mixer) self._mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) #for index in range(8): #use the bottom row of encoders for volume, so add 24 to offset the index # self._mixer.channel_strip(index).set_volume_control(self._dial[index+24]) for index in range(8): self._mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) self._mixer.channel_strip(index)._invert_mute_feedback = True self._mixer.channel_strip(index)._mute_value = self._channelstrip_mute_value(self._mixer.channel_strip(index)) self._mixer.channel_strip(index)._solo_value = self._channelstrip_solo_value(self._mixer.channel_strip(index)) #mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index])) self.song().view.selected_track = self._mixer.channel_strip(0)._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error self._session.set_mixer(self._mixer) def _setup_device_controls(self): self._device = [None for index in range(4)] for index in range(4): self._device[index] = CodecDeviceComponent(self) self._device[index].name = 'CodecDevice_Component_' + str(index) device_param_controls = [] for control in range(8): device_param_controls.append(self._dial[control][index]) self._device[index].set_on_off_button(self._button[1][index]) self._device[index].set_lock_button(self._button[2][index]) self._device[index].set_bank_nav_buttons(self._button[4][index], self._button[5][index]) self._device[index].set_nav_buttons(self._button[6][index], self._button[7][index]) self._device[index].set_parameter_controls(tuple(device_param_controls)) self.set_device_component(self._device[0]) self._last_device_component = self._device[0] def _setup_special_device_control(self): self._special_device = SpecialCodecDeviceComponent(self) self._special_device.name = 'SpecialCodecDeviceComponent' self._special_device.set_on_off_button(self._button[1][0]) self._special_device.set_lock_button(self._button[2][0]) self._special_device.set_bank_nav_buttons(self._button[4][0], self._button[5][0]) self._special_device.set_nav_buttons(self._button[6][0], self._button[7][0]) device_param_controls = [] for row in range(4): for column in range(8): device_param_controls.append(self._dial[column][row]) self._special_device.set_parameter_controls(tuple(device_param_controls)) def _setup_device_chooser(self): self._selected_device = self._device[0] self._last_selected_device = self._device[0] self._device_select_buttons = [self._button[0][index] for index in range(4)] for button in self._device_select_buttons: button.add_value_listener(self._device_select_value, True) def _setup_device_selector(self): self._device_selector = CodecDeviceSelectorComponent(self, 'c', self._device + [self._special_device]) self._device_selector.name = 'Device_Selector' self._device_selector.set_mode_buttons(self._column_button) #self._device_selector.set_mode_toggle(self._livid) def _setup_send_reset(self): self._send_reset = CodecResetSendsComponent(self) self._send_reset.set_buttons(self._button) def _setup_default_buttons(self): self._value_default = ParameterDefaultComponent(self) buttons = [] dials = [] for column in self._button: for button in column: buttons.append(button) for column in self._dial: for dial in column: dials.append(dial) self._value_default.set_buttons(buttons) self._value_default.set_dials(dials) """multiple device support""" def _device_select_value(self, value, sender): #self.log_message('device_select_value ' + str(value) + ' ' + str(self._device_select_buttons.index(sender))) if not self._shift_pressed: if sender.is_momentary or value > 0: if self._shift_mode._mode_index == 2: self.set_device_component(self._device[self._device_select_buttons.index(sender)]) self._last_device_component = self._device_component if self._device_component != None and isinstance(self._device_component._device, Live.Device.Device): if self._device_component.find_track(self._device_component._device) == self.song().view.selected_track: self._device_component.display_device() """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: self._send_midi(SLOWENCODER) if (self._shift_pressed_timer + self._shift_thresh) > self._timer: #if(self._host.is_enabled() != True) self.log_message('mod mode: ' + str(abs(self._monomod_mode._mode_index - 1))) self._monomod_mode.set_mode(max(0, min(1, abs(self._monomod_mode._mode_index - 1)))) #else: # self._monomod_mode.set_mode(0) self._shift_pressed_timer = self._timer % 256 else: self._send_midi(NORMALENCODER) def _mod_mode_update(self): if(self._monomod_mode._mode_index == 0): self._host._set_shift_button(None) self._host.set_enabled(False) self._dial_matrix.reset() self._shift_mode.set_enabled(True) self._shift_update() self.request_rebuild_midi_map() self._livid.turn_off() elif(self._monomod_mode._mode_index == 1): self._shift_mode.set_enabled(False) self._deassign_all() self._dial_matrix.reset() self._button_matrix.reset() self._livid.turn_on() if not self._host._active_client == None: self._host.set_enabled(True) self._host._set_shift_button(self._livid) else: self._assign_alternate_mappings(1) self.request_rebuild_midi_map() """Mode Functions""" def _shift_update(self): if(self._shift_mode.is_enabled()): with self.component_guard(): self.allow_updates(False) #if(not self._in_build_midi_map): # self.set_suppress_rebuild_requests(True) self._deassign_all() if(self._shift_mode._mode_index is 0): self._assign_volume() elif(self._shift_mode._mode_index is 1): self._assign_sends() elif(self._shift_mode._mode_index is 2): self._assign_devices() elif(self._shift_mode._mode_index is 3): self._assign_special_device() for index in range(self._shift_mode.number_of_modes()): if index == self._shift_mode._mode_index: self._shift_mode._modes_buttons[index].turn_on() else: self._shift_mode._modes_buttons[index].turn_off() self.allow_updates(True) #self.set_suppress_rebuild_requests(False) self.request_rebuild_midi_map() def _deassign_all(self): self._assign_alternate_mappings(0) self._device_selector.set_enabled(False) for index in range(8): self._mixer.channel_strip(index).set_volume_control(None) self._mixer.channel_strip(index).set_pan_control(None) self._mixer.channel_strip(index).set_send_controls(tuple([None, None, None, None])) for index in range(4): self._device[index].set_enabled(False) self._device[index]._parameter_controls = None #self._device_navigator[index].set_enabled(False) self._special_device.set_enabled(False) self._special_device._parameter_controls = None self._device_selector.set_enabled(False) self._deassign_buttons() for control in self.controls: control.reset() self.request_rebuild_midi_map() def _deassign_buttons(self): for index in range(8): self._mixer.channel_strip(index).set_select_button(None) self._mixer.channel_strip(index).set_solo_button(None) self._mixer.channel_strip(index).set_mute_button(None) self._mixer.set_select_buttons(None, None) self._send_reset.set_enabled(False) def _assign_volume(self): for index in range(8): self._mixer.channel_strip(index).set_volume_control(self._dial[index][3]) self._mixer.channel_strip(index).set_pan_control(self._dial[index][2]) self._mixer.channel_strip(index).set_send_controls(tuple([self._dial[index][0], self._dial[index][1]])) self._mixer.channel_strip(index).set_select_button(self._column_button[index]) self._mixer.channel_strip(index).set_solo_button(self._button[index][2]) self._mixer.channel_strip(index).set_mute_button(self._button[index][3]) self._mixer.set_select_buttons(self._button[7][0], self._button[6][0]) def _assign_sends(self): for index in range(8): self._mixer.channel_strip(index).set_send_controls(tuple([self._dial[index][0], self._dial[index][1], self._dial[index][2], self._dial[index][3]])) self._mixer.channel_strip(index).set_select_button(self._column_button[index]) self._send_reset.set_enabled(True) def _assign_devices(self): self.set_device_component(self._last_device_component) self._device_select_value(1, self._device_select_buttons[self._device.index(self._device_component)]) for index in range(4): device_param_controls = [] for control in range(8): device_param_controls.append(self._dial[control][index]) self._device[index].set_parameter_controls(tuple(device_param_controls)) self._device[index].set_enabled(True) self._device_selector.set_enabled(self._use_device_selector) if not self._use_device_selector: for index in range(8): self._mixer.channel_strip(index).set_select_button(self._column_button[index]) def _assign_special_device(self): self.set_device_component(self._special_device) device_param_controls = [] for row in range(4): for column in range(8): device_param_controls.append(self._dial[column][row]) self._special_device.set_parameter_controls(tuple(device_param_controls)) self._special_device.set_enabled(True) self._device_selector.set_enabled(self._use_device_selector) if not self._use_device_selector: for index in range(8): self._mixer.channel_strip(index).set_select_button(self._column_button[index]) def _assign_alternate_mappings(self, chan): for column in self._dial: for control in column: control.set_channel(chan) control.set_enabled(chan is 0) for column in self._button: for control in column: control.set_channel(chan) control.set_enabled(chan is 0) for control in self._column_button: control.set_channel(chan) control.set_enabled(chan is 0) for control in self._row_button: control.set_channel(chan) control.set_enabled(chan is 0) """general functionality""" def disconnect(self): """clean things up on disconnect""" if not self._shift_button is None: if self._shift_button.value_has_listener(self._shift_value): self._shift_button.remove_value_listener(self._shift_value) for button in self._device_select_buttons: if button.value_has_listener(self._device_select_value): button.remove_value_listener(self._device_select_value) if self._session._is_linked(): self._session._unlink() self.song().view.remove_selected_track_listener(self._update_selected_device) """for cs in self._control_surfaces(): for host in self._hosts: self.log_message('installed: ' + str(cs) + ' vs. ' + str(host)) if str(type(cs)) == str(type(host)): self.log_message('disconnecting: ' + str(type(cs))) cs.disconnect(cs)""" #self._host._set_parameter_controls(None) self._hosts = [] if self._linked_script != None: self._linked_script._update_linked_device_selection = None self._linked_script = None #self._disconnect_notifier.set_mode(0) self.log_message('<<<<<<<<<<<<<<<<<<<<<<<<< Codec log closed >>>>>>>>>>>>>>>>>>>>>>>>>') ControlSurface.disconnect(self) return None def connect_script_instances(self, instanciated_scripts): found = False for s in instanciated_scripts: if '_codec_version' in dir(s): if s._codec_version == self._version_check: if s._host_name == ('MonOhm'): self.log_message('found codec version ' + str(s._codec_version) + ' in script ' + str(s._host_name)) found = True self._linked_script = s self._linked_script._update_linked_device_selection = self._update_linked_device_selection if not self._session._is_linked() and self._link_mixer is True: self._session.set_offsets(LINK_OFFSET[0], LINK_OFFSET[1]) self._session._link() else: self.log_message('version mismatch: Monomod version ' + str(self._version_check) + ' vs. Host version ' + str(s._codec_version)) if found == False: for s in instanciated_scripts: if '_codec_version' in dir(s): if s._codec_version == self._version_check: if s._host_name == 'BlockMod': self.log_message('found codec version ' + str(s._codec_version) + ' in script ' + str(s._host_name)) self._linked_script = s self._linked_script._update_linked_device_selection = self._update_linked_device_selection if not self._session._is_linked() and self._link_mixer is True: self._session.set_offsets(LINK_OFFSET[0], LINK_OFFSET[1]) self._session._link() else: self.log_message('version mismatch: Monomod version ' + str(self._version_check) + ' vs. Host version ' + str(s._codec_version)) #self.log_message('hosts: ' + str(self._hosts))""" def update_display(self): ControlSurface.update_display(self) #since we are overriding this from the inherited method, we need to call the original routine as well self._timer = (self._timer + 1) % 256 if(self._timer == 0): self._shift_pressed_timer = -12 if(self._local_ring_control is False): self.send_ring_leds() self.flash() def handle_sysex(self, midi_bytes): #self._send_midi(tuple([240, 00, 01, 97, 04, 15, 01, 247])) #response = [long(0),long(0)] #self.log_message(response) pass def flash(self): if(self.flash_status > 0): for control in self.controls: if isinstance(control, MonoButtonElement): control.flash(self._timer) def send_ring_leds(self): leds = [240, 0, 1, 97, 4, 31] for column in range(8): for row in range(4): wheel = self._dial[column][row] bytes = wheel._get_ring() leds.append(bytes[0]) leds.append(int(bytes[1]) + int(bytes[2])) #if(row == 1 and column == 0): # self.log_message(str(leds) + ' ' + str(bytes[0]) + ' ' + str(bytes[1]) + ' ' + str(bytes[2])) leds.append(247) self._send_midi(tuple(leds)) def set_absolute_mode(self, val = 1): self._absolute_mode = (val!=0) if self._absolute_mode is True: self._send_midi(tuple([240, 0, 1, 97, 4, 17, 0, 0, 0, 0, 0, 0, 0, 0, 247])) else: self._send_midi(tuple([240, 0, 1, 97, 4, 17, 127, 127, 127, 127, 127, 127, 127, 127, 247])) def set_local_ring_control(self, val = 1): self._local_ring_control = (val!=0) if(self._local_ring_control is True): #self._send_midi(tuple([240, 0, 1, 97, 4, 32, 0, 247])) self._send_midi(tuple([240, 0, 1, 97, 4, 8, 72, 247])) else: #self._send_midi(tuple([240, 0, 1, 97, 4, 32, 1, 247])) self._send_midi(tuple([240, 0, 1, 97, 4, 8, 64, 247])) def device_follows_track(self, val): self._device_selection_follows_track_selection = (val == 1) return self """m4l bridge""" def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 12 if (not display_string): return (' ' * NUM_CHARS_PER_DISPLAY_STRIP) if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center((NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return ret def notification_to_bridge(self, name, value, sender): if(isinstance(sender, CodecEncoderElement)): self._monobridge._send(sender.name, 'lcd_name', str(self.generate_strip_string(name))) self._monobridge._send(sender.name, 'lcd_value', str(self.generate_strip_string(value))) def touched(self): if not self._host.is_enabled(): if self._touched is 0: self._monobridge._send('touch', 'on') self.schedule_message(2, self.check_touch) self._touched +=1 def check_touch(self): if self._touched > 5: self._touched = 5 elif self._touched > 0: self._touched -= 1 if self._touched is 0: self._monobridge._send('touch', 'off') else: self.schedule_message(2, self.check_touch) def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip() is True: clip_names.append(clip_slot._clip_slot)##.clip.name) return clip_slot._clip_slot ##self.log_message(str(clip_slot._clip_slot.clip.name)) return clip_names """overrides""" def allow_updates(self, allow_updates): for component in self.components: component.set_allow_update(int(allow_updates!=0)) def set_device_component(self, device_component): if self._device_component != None: self._device_component._lock_callback = None assert (device_component != None) assert isinstance(device_component, DeviceComponent) self._device_component = device_component self._device_component._lock_callback = self._toggle_lock #old: self._device_component.set_lock_callback(self._toggle_lock) if self._device_select_buttons != None: for button in self._device_select_buttons: button.send_value(self._device_select_buttons.index(button) == self._device.index(self._device_component)) self._update_device_selection() return None def _update_selected_device(self): if self._device_selection_follows_track_selection is True: self._update_device_selection() return None def _update_linked_device_selection(self, device): #self.log_message('codec received ' + str(device.name)) if self._device_component != None and device != None: if not self._device_component.is_locked(): self._device_component.set_device(device) def _get_num_tracks(self): return self.num_tracks def _update_device_selection(self): #self.log_message('_update_device_selection') if self._device_component != None: if not self._device_component.is_locked(): track = self.song().view.selected_track device_to_select = track.view.selected_device if ((device_to_select == None) and (len(track.devices) > 0)): device_to_select = track.devices[0] if (device_to_select != None): self.song().view.select_device(device_to_select) self._device_component.set_device(device_to_select) def _channelstrip_mute_value(self, channelstrip): def _mute_value(value): if not self._shift_pressed: self.log_message('shift not pressed') ChannelStripComponent._mute_value(channelstrip, value) return _mute_value def _channelstrip_solo_value(self, channelstrip): def _solo_value(value): if not self._shift_pressed: ChannelStripComponent._solo_value(channelstrip, value) return _solo_value def _mixer_next_track_value(self, mixer): def _next_track_value(value): if not self._shift_pressed: MixerComponent._next_track_value(mixer, value) return _next_track_value def _mixer_prev_track_value(self, mixer): def _prev_track_value(value): if not self._shift_pressed: MixerComponent._prev_track_value(mixer, value) return _prev_track_value
class code(ControlSurface): __module__ = __name__ __doc__ = " Code controller script " def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= Code opened =--------------") # Writes message into Live's main log file. This is a ControlSurface method. self._send_midi(factoryreset) self._send_midi(btn_channels) self._send_midi(enc_channels) #self.set_suppress_rebuild_requests(True) # Turn off rebuild MIDI map until after we're done setting up self._setup_controls() self._setup_device_controls() self._setup_mixer_control() # Setup the mixer object self._setup_transport_control() self._setup_session_control() # Setup the session object - do this last self._setup_modes() self._setup_m4l_interface() #self.set_suppress_rebuild_requests(False) # Turn rebuild back on, once we're done setting up ##self.assign_page_2() def handle_sysex(self, midi_bytes): self._send_midi(tuple([240, 00, 01, 97, 04, 15, 01, 247])) #response = [long(0),long(0)] #self.log_message(str(response)) def _setup_m4l_interface(self): self._m4l_interface = M4LInterfaceComponent(controls=self.controls, component_guard=self.component_guard) 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 _setup_controls(self): is_momentary = True self._dial = [None for index in range(DIALCOUNT)] self._trackbtns = [None for index in range(8)] self._modebtns = [None for index in range(5)] for index in range(DIALCOUNT): self._dial[index] = EncoderElement(MIDI_CC_TYPE, CH, matrix_nums[index], Live.MidiMap.MapMode.absolute) self._dial[index].name = 'Dial_' + str(index) self._dial[index].set_feedback_delay(-1) for index in range(8): self._trackbtns[index] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index]) self._trackbtns[index].name = 'Button_' + str(index) for index in range(5): self._modebtns[index] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, mode_select_notes[index]) self._modebtns[index].name = 'ModeButton_' + str(index) self._matrix = ButtonMatrixElement() self._matrix.name = 'Matrix' self._grid = [None for index in range(COLS)] for column in range(COLS): self._grid[column] = [None for index in range(COLS)] for row in range(ROWS): nn = 1+(column * ROWS) + row self._grid[column][row] = ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, nn) #comment out if you don't want clip launch self._grid[column][row].name = 'Grid_' + str(column) + '_' + str(row) for row in range(ROWS): button_row = [] for column in range(COLS): button_row.append(self._grid[column][row]) self._matrix.add_row(tuple(button_row)) """ not sure about this bit, but somehow I'll need to set up the modes here...!""" def _setup_modes(self): self._shift_mode = ShiftModeComponent(self, tuple(button for button in self._modebtns)) self._shift_mode.name = 'Mix_Mode' #mode 1 #self._shift_mode.set_mode_buttons(self._modebtns) def _setup_transport_control(self): self._transport = TransportComponent() self._transport.name = 'Transport' def _setup_mixer_control(self): is_momentary = True self._num_tracks = (COLS) global mixer mixer = MixerComponent(COLS, 0, True, True) mixer.name = 'Mixer' self._mixer = mixer mixer.set_track_offset(0) #Sets start point for mixer strip (offset from left) for index in range(COLS): #use the bottom row of encoders for volume, so add 24 to offset the index mixer.channel_strip(index).set_volume_control(self._dial[index+24]) for index in range(COLS): mixer.channel_strip(index).name = 'Mixer_ChannelStrip_' + str(index) mixer.track_eq(index).name = 'Mixer_EQ_' + str(index) mixer.track_filter(index).name = 'Mixer_Filter_' + str(index) #added by a mixer.channel_strip(index)._invert_mute_feedback = True #mixer.channel_strip(index).set_select_button(ButtonElement(is_momentary, MIDI_NOTE_TYPE, CH, track_select_notes[index])) self.song().view.selected_track = mixer.channel_strip(0)._track #set the selected strip to the first track, so that we don't, for example, try to assign a button to arm the master track, which would cause an assertion error """ Technically, we aren't using the session control, but I'm going to set it up in case inter-script communication needs it""" def _setup_session_control(self): is_momentary = True num_tracks = COLS num_scenes = ROWS global session session = SessionComponent(num_tracks, num_scenes) session.name = "Session" session.set_offsets(0, 0) self._session = session self._session.set_stop_clip_value(0) self._scene = [None for index in range(ROWS)] for row in range(num_scenes): self._scene[row] = session.scene(row) self._scene[row].name = 'Scene_' + str(row) for column in range(num_tracks): clip_slot = self._scene[row].clip_slot(column) clip_slot.name = str(column) + '_Clip_Slot_' + str(row) clip_slot.set_triggered_to_play_value(64) clip_slot.set_triggered_to_record_value(64) clip_slot.set_stopped_value(0) clip_slot.set_started_value(64) clip_slot.set_recording_value(64) #clip_slot.set_launch_button(self._grid[column][row]) #comment out if you don't want clip launch session.set_mixer(mixer) self._session_zoom = SessionZoomingComponent(session) self._session_zoom.name = 'Session_Overview' self._session_zoom.set_stopped_value(0) self._session_zoom.set_playing_value(64) self._session_zoom.set_selected_value(64) if STANDALONE is True: self.set_highlighting_session_component(self._session) self._session.set_track_bank_buttons(self._grid[5][3], self._grid[4][3]) #comment out when using with Griid self._session.set_scene_bank_buttons(self._grid[7][3], self._grid[6][3]) # comment out when using with Griid """this is where we take care of setting up the the multiple devices per page, we will need 4""" def _setup_device_controls(self): self._device = [None for index in range(4)] for index in range(ROWS): self._device[index] = DeviceComponent() self._device[index].name = 'Device_Component_' + str(index) #self.set_device_component(self._device) #this doesn't work anymore, because we have multiple devices for the controller....we'll have to get fancy here, but that's for later #self._device_navigator = DetailViewControllerComponent() #its unclear if we'll need this....how is device navigation (i.e. banking for device parameter banks) going to be handled by the script? #self._device_navigator.name = 'Device_Navigator' device_param_controls = [] for control in range(COLS): """this setups up 8 device parameters per row""" #dial_index = control + (index*COLS) """alternatively, this setus up device controls in 4 4x2 groups""" dial_index = device_encoders[control + (index*COLS)] device_param_controls.append(self._dial[dial_index]) self._device[index].set_parameter_controls(tuple(device_param_controls)) """this is where we deassign every control that will be changing function when we switch modes...best to just deassign them all, and reassign them on update""" def deassign_matrix(self): for index in range(DIALCOUNT): #this should totally work!!! I'm over appealing to Python's sadistic mannerisms right now.... self._dial[index].send_value(0, True) ##this is kind of a hack, and should be unnecessary; the bool at the end tells the send_value method to force the value out to the controller for index in range(COLS): self._mixer.track_eq(index).set_enabled(False) ##set_gain_controls(tuple([None for index in range(3)])) self._mixer.channel_strip(index).set_volume_control(None) self._mixer.track_filter(index).set_enabled(False) ##set_filter_controls(tuple([None, None])) self._mixer.channel_strip(index).set_pan_control(None) self._mixer.channel_strip(index).set_select_button(None) self._mixer.channel_strip(index).set_send_controls(tuple([None for index in range(4)])) for device in range(4): self._device[device].set_bank_nav_buttons(None, None) self._device[device].set_enabled(False) ##set_parameter_controls(tuple([None for index in range(8)])) for track in range(8): self._mixer.channel_strip(track).set_select_button(None) for scene in range(4): self._scene[scene].clip_slot(track).set_launch_button(None) #self.request_rebuild_midi_map() # I think this is causing problems updating the leds when in build? """EQ Hi/Mid/Low and volume""" def assign_page_0(self): """for each column""" is_momentary = True for index in range(COLS): self._mixer.track_eq(index).set_gain_controls((self._dial[index+16],self._dial[index+8],self._dial[index])) self._mixer.track_eq(index).set_enabled(True) self._mixer.channel_strip(index).set_volume_control(self._dial[index+24])#use the bottom row of encoders for volume, so add 24 to offset the index self._mixer.channel_strip(index).set_select_button(self._trackbtns[index]) self.assign_cliplaunch() self._mixer.update() """sends 1-4""" def assign_page_1(self): is_momentary = True for index in range(COLS): send_controllers = [self._dial[index],self._dial[index+8],self._dial[index+16],self._dial[index+24]] self._mixer.channel_strip(index).set_send_controls(tuple(send_controllers)) self._mixer.channel_strip(index).set_select_button(self._trackbtns[index]) self._mixer.update() """devices 1-8""" def assign_pages_2_3(self): ##these need to be here anyway, whether or not there is a device present to control for index in range(4): self._device[index].set_enabled(True) #device_param_controls = [] ###no need to reassign it, since we are turning it off and on #for control in range(COLS): ###in fact, I think we can assign all this stuff in the header except for things directly connected to the mixer module # device_param_controls.append(self._dial[control + (index*COLS)]) #self._device[index].set_parameter_controls(tuple(device_param_controls)) self._reassign_devices(self._shift_mode._mode_index) """ filter res,filter q, pan, volume""" def assign_page_4(self): is_momentary = True for index in range(COLS): self._mixer.track_filter(index).set_filter_controls(self._dial[index], self._dial[index + 8]) #set_filter_controls(self, freq, reso) self._mixer.track_filter(index).set_enabled(True) #self._mixer.track_eq(index).set_gain_controls((self._dial[index],self._dial[index+8],self._dial[index+16])) self._mixer.channel_strip(index).set_pan_control(self._dial[index+16]) self._mixer.channel_strip(index).set_volume_control(self._dial[index+24]) self._mixer.channel_strip(index).set_select_button(self._trackbtns[index]) self._mixer.update() def assign_cliplaunch(self): if STANDALONE is True: for column in range(COLS): for row in range(ROWS-1): self._scene[row].clip_slot(column).set_launch_button(self._grid[column][row]) def _reassign_devices(self, mode_index): if self._shift_mode._mode_index in range(2, 4): ##both of these lines would be better handled by a property offset = (mode_index - 2) * 4 ## set up in an override module of the device_component....bleh track = self.song().view.selected_track for index in range(4): if index + offset < len(track.devices): #self.log_message('assigning device') self._device[index].set_device(track.devices[index + offset]) else: #self.log_message('assigning device to None') self._device[index].set_device(None) self._device[index].set_bank_nav_buttons(self._trackbtns[(index * 2)], self._trackbtns[(index * 2) + 1]) self._device[index].update() def disconnect(self): """clean things up on disconnect""" self.log_message(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime()) + "--------------= Code log closed =--------------") #Create entry in log file ControlSurface.disconnect(self) return None
def init(self): #skip init if already done. if self._init_done: return self._init_done = True # second part of the __init__ after model has been identified using its challenge response if self._mk2_rgb: from SkinMK2 import make_skin self._skin = make_skin() self._side_notes = (89, 79, 69, 59, 49, 39, 29, 19) #self._drum_notes = (20, 30, 31, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126) self._drum_notes = (20, 30, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126) else: from SkinMK1 import make_skin self._skin = make_skin() self._side_notes = (8, 24, 40, 56, 72, 88, 104, 120) self._drum_notes = (41, 42, 43, 44, 45, 46, 47, 57, 58, 59, 60, 61, 62, 63, 73, 74, 75, 76, 77, 78, 79, 89, 90, 91, 92, 93, 94, 95, 105, 106, 107) with self.component_guard(): is_momentary = True self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False) self._config_button.add_value_listener(self._config_value) self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = 'User_Byte_Button' self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) matrix = ButtonMatrixElement() matrix.name = 'Button_Matrix' for row in range(8): button_row = [] for column in range(8): if self._mk2_rgb: # for mk2 buttons are assigned "top to bottom" midi_note = (81 - (10 * row)) + column else: midi_note = row * 16 + column button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, midi_note, skin = self._skin, control_surface = self) button.name = str(column) + '_Clip_' + str(row) + '_Button' button_row.append(button) matrix.add_row(tuple(button_row)) top_buttons = [ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, 104 + index, skin = self._skin) for index in range(8)] side_buttons = [ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, self._side_notes[index], skin = self._skin) for index in range(8)] top_buttons[0].name = 'Bank_Select_Up_Button' top_buttons[1].name = 'Bank_Select_Down_Button' top_buttons[2].name = 'Bank_Select_Left_Button' top_buttons[3].name = 'Bank_Select_Right_Button' top_buttons[4].name = 'Session_Button' top_buttons[5].name = 'User1_Button' top_buttons[6].name = 'User2_Button' top_buttons[7].name = 'Mixer_Button' side_buttons[0].name = 'Vol_Button' side_buttons[1].name = 'Pan_Button' side_buttons[2].name = 'SndA_Button' side_buttons[3].name = 'SndB_Button' side_buttons[4].name = 'Stop_Button' side_buttons[5].name = 'Trk_On_Button' side_buttons[6].name = 'Solo_Button' side_buttons[7].name = 'Arm_Button' self._osd = M4LInterface() self._osd.name = "OSD" self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button, self._osd, self) self._selector.name = 'Main_Modes' self._do_combine() for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.add_value_listener(self._button_value) self.set_highlighting_session_component(self._selector.session_component()) self._suppress_session_highlight = False # due to our 2 stage init, we need to rebuild midi map self.request_rebuild_midi_map() # and request update self._selector.update() if self._mk2_rgb: self.log_message("LaunchPad95 (mk2) Loaded !") else: self.log_message("LaunchPad95 Loaded !")
class Lemur256(ControlSurface): __module__ = __name__ __doc__ = " Lemur Monomodular 256cell controller script " def __init__(self, *a, **k): self._timer_callbacks = [ ] #Used for _monobridge, which uses L8 method for registering timer callbacks. deprecated, needs to be replaced by new L9 Task class. super(Lemur256, self).__init__(*a, **k) self._host_name = "Lemur256" self._color_type = 'AumPad' self.connected = 0 self._suggested_input_port = 'None' self._suggested_output_port = 'None' self._monomod_version = 'b995' self.hosts = [] self._bright = True self._rgb = 0 self._timer = 0 self.flash_status = 1 self._osc_registry = {} with self.component_guard(): self._setup_monobridge() self._setup_controls() self._setup_monomod() self._setup_touchosc() self._assign_host2() self.reset() self.refresh_state() self.show_message(str(self._host_name) + ' Control Surface Loaded') self.log_message("<<<<<<<<<<<<<<<<<<<< " + str(self._host_name) + " " + str(self._monomod_version) + " log opened >>>>>>>>>>>>>>>>>>>>") def _setup_controls(self): is_momentary = True self._monomod256 = ButtonMatrixElement() self._monomod256.name = 'Monomod256' self._square = [None for index in range(16)] for column in range(16): self._square[column] = [None for index in range(16)] for row in range(16): self._square[column][row] = OSCMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, int(column / 8) + 1, row + ((column % 8) * 16), '256Grid_' + str(column) + '_' + str(row), '/Grid_' + str(column) + '_' + str(row), '/Grid/set ' + str(column) + ' ' + str(row), None, self) for row in range(16): button_row = [] for column in range(16): button_row.append(self._square[column][row]) self._monomod256.add_row(tuple(button_row)) self._key_buttons = ButtonMatrixElement() self._bank_button = [None for index in range(2)] for index in range(2): self._bank_button[index] = OSCMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, 15, index, '256Grid_Bank_' + str(index), '/Shift_' + str(index), '/Shift/set ' + str(index), None, self) button_row = [] self._key_button = [None for index in range(8)] for index in range(8): self._key_button[index] = OSCMonoButtonElement( is_momentary, MIDI_NOTE_TYPE, 15, index + 8, '256Grid_Key_' + str(index), '/Keys_' + str(index), '/Keys/set ' + str(index), None, self) for index in range(8): button_row.append(self._key_button[index]) self._key_buttons.add_row(tuple(button_row)) def _setup_monomod(self): self._host2 = SpecialMonomodComponent(self) self._host2.name = '256_Monomod_Host' self.hosts = [self._host2] """script initialization methods""" def _setup_monobridge(self): self._monobridge = OSCMonoBridgeElement(self) self._monobridge.name = 'MonoBridge' def _assign_host2(self): self._host2._set_shift_button(self._bank_button[0]) self._host2._set_alt_button(self._bank_button[1]) self._host2._set_button_matrix(self._monomod256) self._host2._set_key_buttons(self._key_button) self._host2.set_enabled(True) def _setup_touchosc(self): self._osc_registry = {} self._osc_registry['/ping'] = self._monobridge.ping self._osc_registry['/1'] = self._monobridge.page1 for control in self.controls: if hasattr(control, 'osc'): self._osc_registry[control.osc] = control.set_value #if hasattr(control, 'osc_alt'): # self._osc_registry[control.osc_alt] = control.set_value #self.log_message('create dict key: ' + str(control.osc) + str(control.name)) """m4l bridge""" def generate_strip_string(self, display_string): NUM_CHARS_PER_DISPLAY_STRIP = 9 if (not display_string): return ('`_') if ((len(display_string.strip()) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.endswith('dB') and (display_string.find('.') != -1))): display_string = display_string[:-2] if (len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)): for um in [' ', 'i', 'o', 'u', 'e', 'a']: while ((len(display_string) > (NUM_CHARS_PER_DISPLAY_STRIP - 1)) and (display_string.rfind(um, 1) != -1)): um_pos = display_string.rfind(um, 1) display_string = (display_string[:um_pos] + display_string[(um_pos + 1):]) else: display_string = display_string.center( (NUM_CHARS_PER_DISPLAY_STRIP - 1)) ret = u'' for i in range((NUM_CHARS_PER_DISPLAY_STRIP - 1)): if ((ord(display_string[i]) > 127) or (ord(display_string[i]) < 0)): ret += ' ' else: ret += display_string[i] ret += ' ' assert (len(ret) == NUM_CHARS_PER_DISPLAY_STRIP) return '`' + ret.replace(' ', '_') def notification_to_bridge(self, name, value, sender): if (isinstance(sender, MonoEncoderElement2)): #self.log_message(str(name) + str(value) + str(sender.num)) self._monobridge._send('lcd_name', sender.name, self.generate_strip_string(str(name))) self._monobridge._send('lcd_value', sender.name, self.generate_strip_string(str(value))) def clip_name(self, sender, name): #self.log_message('clip name ' + str(sender.osc_name) + ' ' + str(self.generate_strip_string(str(name)))) self._monobridge._send_osc(sender.osc_name, self.generate_strip_string(str(name))) """def get_clip_names(self): clip_names = [] for scene in self._session._scenes: for clip_slot in scene._clip_slots: if clip_slot.has_clip(): clip_names.append(clip_slot._clip_slot)##.clip.name) #return clip_slot._clip_slot #self.log_message('clip name' + str(clip_slot._clip_slot.clip.name)) return clip_names""" """called on timer""" def update_display(self): super(Lemur256, self).update_display() for callback in self._timer_callbacks: callback() def flash(self): if (self.flash_status > 0): for control in self.controls: if isinstance(control, MonoButtonElement): control.flash(self._timer) def strobe(self): pass """general functionality""" def disconnect(self): self.log_message("<<<<<<<<<<<<<<<<<<<< " + str(self._host_name) + " log closed >>>>>>>>>>>>>>>>>>>>") super(ControlSurface, self).disconnect() def clear_grid_names(self): #self.log_message('clear grid names' + str(self)) for column in range(8): for row in range(8): self._monobridge._send_osc(self._grid[column][row].osc_name, '`_') def _register_timer_callback(self, callback): """ Registers a callback that is triggerd on every call of update_display """ assert (callback != None) assert (dir(callback).count('im_func') is 1) assert (self._timer_callbacks.count(callback) == 0) self._timer_callbacks.append(callback) return None def _unregister_timer_callback(self, callback): """ Unregisters a timer callback """ assert (callback != None) assert (dir(callback).count('im_func') is 1) assert (self._timer_callbacks.count(callback) == 1) self._timer_callbacks.remove(callback) return None def _set_brightness(self, value): pass def reset(self): #self._monobridge._send_osc('/reset') for control in self.controls: control.reset() def assign_lower_grid_names(self, mode): if self._display_button_names is True: for column in range(8): for row in range(3): self._monobridge._send_osc( self._grid[column][row + 5].osc_name, self.generate_strip_string( str(GRID_NAMES[mode][row][column]))) def reset_and_refresh_state(self, *a, **k): self.schedule_message(1, self.reset) self.schedule_message(2, self.refresh_state)
def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) with self.component_guard(): #self.set_suppress_rebuild_requests(True) self._suppress_send_midi = True self._suppress_session_highlight = True is_momentary = True self._suggested_input_port = "Launchpad" self._suggested_output_port = "Launchpad" self._control_is_with_automap = False self._user_byte_write_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 16) self._user_byte_write_button.name = "User_Byte_Button" self._user_byte_write_button.send_value(1) self._user_byte_write_button.add_value_listener(self._user_byte_value) self._wrote_user_byte = False self._challenge = (Live.Application.get_random_int(0, 400000000) & 2139062143) matrix = ButtonMatrixElement() matrix.name = "Button_Matrix" """ TRACKFINDER TEST track_index = 0 for track in self.song().tracks: if track_index < 8: button_row = [] if track.is_foldable: for column in range(8): log("right one: " + str(track_index)) button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((track_index * 16) + column)) #@UndefinedVariable button.name = (((str(column) + "_Clip_") + str(track_index)) + "_Button") button_row.append(button) track_index = track_index + 1 else: for column in range(8): log("wrong one: " + str(track_index)) button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, 99, True) #@UndefinedVariable button.name = (str(column) + "_Clip_Button-DUMMY") button_row.append(button) matrix.add_row(tuple(button_row)) log("done")""" """ ORIGINAL CODE """ for row in range(8): button_row = [] for column in range(8): button = ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, ((row * 16) + column)) button.name = (((str(column) + "_Clip_") + str(row)) + "_Button") button_row.append(button) matrix.add_row(tuple(button_row)) self._config_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 0, optimized_send_midi=False) self._config_button.add_value_listener(self._config_value) top_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_CC_TYPE, 0, (104 + index)) for index in range(8) ] side_buttons = [ ConfigurableButtonElement(is_momentary, MIDI_NOTE_TYPE, 0, SIDE_NOTES[index]) for index in range(8) ] top_buttons[0].name = "Bank_Select_Up_Button" top_buttons[1].name = "Bank_Select_Down_Button" top_buttons[2].name = "Bank_Select_Left_Button" top_buttons[3].name = "Bank_Select_Right_Button" top_buttons[4].name = "Session_Button" top_buttons[5].name = "User1_Button" top_buttons[6].name = "User2_Button" top_buttons[7].name = "Mixer_Button" side_buttons[0].name = "Vol_Button" side_buttons[1].name = "Pan_Button" side_buttons[2].name = "SndA_Button" side_buttons[3].name = "SndB_Button" side_buttons[4].name = "Stop_Button" side_buttons[5].name = "Trk_On_Button" side_buttons[6].name = "Solo_Button" side_buttons[7].name = "Arm_Button" self._selector = MainSelectorComponent(matrix, tuple(top_buttons), tuple(side_buttons), self._config_button) self._selector.name = "Main_Modes" for control in self.controls: if isinstance(control, ConfigurableButtonElement): control.add_value_listener(self._button_value) self.set_highlighting_session_component(self._selector.session_component()) self._suppress_session_highlight = False
class Maschine(ControlSurface): __module__ = __name__ __doc__ = 'Basic Control Script for All Maschine Modell Mikro, Mikro Mk2, Mk1, Mk2, Studio' def __init__(self, c_instance): super(Maschine, self).__init__(c_instance) with self.component_guard(): register_sender(self) self._diplay_cache = ['', '', '', ''] self._suppress_send_midi = True is_momentary = True self._c_ref = c_instance self.display_task = DisplayTask() self._challenge = Live.Application.get_random_int(0, 400000000) & 2139062143 self._active = False self._midi_pause_count = 0 self.blink_state = 0 self.send_slider_index = 0 self.nav_index = 0 self.arm_selected_track = False self.undo_state = 0 self.redo_state = 0 self._set_suppress_rebuild_requests(True) self._modeselect = ModeSelector(self.is_monochrome()) self._device = self._set_up_device_control() self._set_up_session(self._modeselect) self._set_up_mixer() self._setup_transport() self._set_global_buttons() self._editsection = EditSection() self._editsection.connect_session(self._session) self._editsection.set_mode_selector(self._modeselect) self._session.set_mode(self._modeselect._clip_mode) self._audio_clip_editor = AudioClipEditComponent() self._note_repeater = NoteRepeatComponent(c_instance.note_repeat) self._midi_edit = MidiEditSection() self._init_settings() self._init_maschine() self.set_highlighting_session_component(self._session) self.set_pad_translations(PAD_TRANSLATIONS) self._on_selected_track_changed() self.set_up_function_buttons() self.show_message(str('')) self.request_rebuild_midi_map() self._set_suppress_rebuild_requests(False) self._active = True self._display_device_param = False self.set_feedback_channels(FEEDBACK_CHANNELS) self._final_init() self._suppress_send_midi = False self.apply_preferences() self.init_text_display() self._on_appointed_device_changed.subject = self.song() def _init_maschine(self): pass def _final_init(self): pass def create_pad_button(self, scene_index, track_index, color_source): pass def create_gated_button(self, identifier, hue): pass def apply_preferences(self): pref_dict = self._pref_dict if 'step_advance' in pref_dict: self._session.set_step_advance(pref_dict['step_advance']) if 'solo_exclusive' in pref_dict: self._modeselect.set_solo_exclusive(pref_dict['solo_exclusive']) else: self._modeselect.set_solo_exclusive(True) if 'arm_exclusive' in pref_dict: self._modeselect.set_arm_exclusive(pref_dict['arm_exclusive']) else: self._modeselect.set_arm_exclusive(True) if 'quantize_val' in pref_dict: self._editsection.quantize = pref_dict['quantize_val'] else: self._editsection.quantize = 5 if 'initial_cliplen' in pref_dict: self._editsection.initial_clip_len = pref_dict['initial_cliplen'] else: self._editsection.initial_clip_len = 4.0 if 'auto_arm_sel_track' in pref_dict: self.arm_selected_track = pref_dict['auto_arm_sel_track'] else: self.arm_selected_track = False if 'note_color_mode' in pref_dict: self._modeselect._pad_mode._note_display_mode = pref_dict['note_color_mode'] else: self._modeselect._pad_mode._note_display_mode = ND_KEYBOARD1 self._pref_dict['note_color_mode'] = self._modeselect._pad_mode._note_display_mode self.set_sel_arm_button.send_value(self.arm_selected_track and 127 or 0, True) self._note_repeater.recall_values(self._pref_dict) def store_preferences(self): self._pref_dict['step_advance'] = self._session.get_step_advance() self._pref_dict['solo_exclusive'] = self._modeselect.is_solo_exclusive() self._pref_dict['arm_exclusive'] = self._modeselect.is_arm_exclusive() self._pref_dict['quantize_val'] = self._editsection.quantize self._pref_dict['initial_cliplen'] = self._editsection.initial_clip_len self._pref_dict['auto_arm_sel_track'] = self.arm_selected_track self._pref_dict['note_color_mode'] = self._modeselect._pad_mode._note_display_mode self._note_repeater.store_values(self._pref_dict) def _init_settings(self): from pickle import loads, dumps from encodings import ascii nop(ascii) preferences = self._c_instance.preferences(self.preferences_name()) self._pref_dict = {} try: self._pref_dict = loads(str(preferences)) except Exception: pass pref_dict = self._pref_dict preferences.set_serializer(lambda : dumps(pref_dict)) def preferences_name(self): return 'Maschine' def _pre_serialize(self): from pickle import dumps from encodings import ascii nop(ascii) preferences = self._c_instance.preferences('Maschine') self.store_preferences() dump = dumps(self._pref_dict) preferences.set_serializer(lambda : dump) def toggle_nav_mode(self): self._session.switch_step_advance() self.show_message(' View Navigation in steps of ' + str(self._session.get_step_advance())) def _set_up_session(self, mode_selector): is_momentary = True self._session = MaschineSessionComponent() self._session.set_color_manager(mode_selector.get_color_manager()) self.nav_buttons = (self.create_gated_button(92, COLOR_HUE_NAV), self.create_gated_button(81, COLOR_HUE_NAV), self.create_gated_button(93, COLOR_HUE_NAV), self.create_gated_button(91, COLOR_HUE_NAV)) self._session.set_scene_bank_buttons(self.nav_buttons[0], self.nav_buttons[1]) self._session.set_track_bank_buttons(self.nav_buttons[2], self.nav_buttons[3]) track_stop_buttons = [ StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, index + STOP_CC_OFF) for index in range(4) ] self._session.set_stop_track_clip_buttons(tuple(track_stop_buttons)) self._matrix = [] self._bmatrix = ButtonMatrixElement() for scene_index in range(4): button_row = [] for track_index in range(4): button = self.create_pad_button(scene_index, track_index, mode_selector) button_row.append(button) self._matrix.append(tuple(button_row)) self._bmatrix.add_row(tuple(button_row)) self._session.set_matrix(self._matrix) for button, (track_index, scene_index) in self._bmatrix.iterbuttons(): if button: scene = self._session.scene(scene_index) clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(button) clip_slot.set_triggered_to_play_value(1) clip_slot.set_triggered_to_record_value(1) clip_slot.set_started_value(1) clip_slot.set_recording_value(1) clip_slot.set_stopped_value(1) self._session._link() def _set_up_mixer(self): is_momentary = True self._mixer = MaschineMixerComponent(8) self.send_sliders = [] for track in range(8): self.send_sliders.append(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, SEND_CC_OFF + track)) for track in range(8): strip = self._mixer.channel_strip(track) strip.set_arm_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, ARM_CC_OFF + track)) strip.set_solo_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SOLO_CC_OFF + track)) strip.set_mute_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, MUTE_CC_OFF + track)) strip.set_volume_control(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, LEVEL_CC_OFF + track)) strip.set_pan_control(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, PAN_CC_OFF + track)) strip.set_select_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, SELECT_CC_OFF + track)) st = tuple([self.send_sliders[track]]) strip.set_send_controls(st) self.send_slider_toggle_button = StateButton(False, MIDI_CC_TYPE, 0, 90) self._do_toggle_send.subject = self.send_slider_toggle_button self._session.set_mixer(self._mixer) def _set_global_buttons(self): is_momentary = True self._undo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 85) self._do_undo.subject = self._undo_button self._redo_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 87) self._do_redo.subject = self._redo_button self._stop_all_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 111) self._do_stop_all.subject = self._stop_all_button self._toggle_detail_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 121) self._action_toogle_detail_view.subject = self._toggle_detail_button self._fire_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 9) self._do_fire_button.subject = self._fire_button self._g_clear_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 106) self._hold_clear_action.subject = self._g_clear_button self._g_duplicate_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 107) self._hold_duplicate_action.subject = self._g_duplicate_button self.track_left_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 120) self.track_right_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 121) self.set_sel_arm_button = StateButton(is_momentary, MIDI_CC_TYPE, 2, 56) self._reenable_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 1, 120) self._do_auto_reenable.subject = self._reenable_button self._on_change_reenabled.subject = self.song() self._on_change_reenabled() self._a_trk_left.subject = self.track_left_button self._a_trk_right.subject = self.track_right_button self._a_sel_arm.subject = self.set_sel_arm_button def _set_up_device_control(self): is_momentary = True device = MaschineDeviceComponent() param_controls = [] for index in range(8): param_controls.append(SliderElement(MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_CC_OFF + index)) device.set_parameter_controls(tuple(param_controls)) self.device_control = param_controls device.set_on_off_button(StateButton(is_momentary, MIDI_CC_TYPE, BASIC_CHANNEL, DEVICE_BUTTON_CC_OFF)) device.set_bank_nav_buttons(StateButton(is_momentary, MIDI_CC_TYPE, 3, 104), ButtonElement(is_momentary, MIDI_CC_TYPE, 3, 105)) self._device_nav_button_left = StateButton(is_momentary, MIDI_CC_TYPE, 3, 106) self._device_nav_button_right = StateButton(is_momentary, MIDI_CC_TYPE, 3, 107) self._navigate_button = StateButton(is_momentary, MIDI_CC_TYPE, 0, 127) self._nav_value_left.subject = self._device_nav_button_left self._nav_value_right.subject = self._device_nav_button_right self._do_focus_navigate.subject = self._navigate_button self.set_device_component(device) return device 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 set_up_function_buttons(self): is_momentary = True self.keycolor_mod_button = StateButton(is_momentary, MIDI_CC_TYPE, 1, 73) self._do_key_color.subject = self.keycolor_mod_button self._update_button = ButtonElement(is_momentary, MIDI_CC_TYPE, 0, 86) self._do_update_display.subject = self._update_button @subject_slot('appointed_device') def _on_appointed_device_changed(self): self._modeselect._device_changed() def _update_hardware(self): self._session.update() self._modeselect.refresh() self.update_undo_redo(True) def refresh_state(self): ControlSurface.refresh_state(self) self._update_hardware() def _send_midi(self, midi_bytes, **keys): self._c_ref.send_midi(midi_bytes) return True def init_text_display(self): if USE_DISPLAY: self._modeselect._pad_mode.update_text_display() def _on_selected_track_changed(self): super(Maschine, self)._on_selected_track_changed() self.set_controlled_track(self.song().view.selected_track) self._on_devices_changed.subject = self.song().view.selected_track @subject_slot('devices') def _on_devices_changed(self): pass def update(self): self.set_feedback_channels(FEEDBACK_CHANNELS) super(Maschine, self).update() def is_monochrome(self): return False def _deassign_matrix(self): for scene_index in range(4): scene = self._session.scene(scene_index) for track_index in range(4): clip_slot = scene.clip_slot(track_index) clip_slot.set_launch_button(None) def update_display(self): with self.component_guard(): with self._is_sending_scheduled_messages(): self._task_group.update(0.1) self._modeselect.notify(self.blink_state) self.blink_state = (self.blink_state + 1) % 4 self.display_task.tick() self.update_undo_redo(False) def update_undo_redo(self, force = False): if force: self.undo_state = self.song().can_undo self.redo_state = self.song().can_redo if self.song().can_undo != self.undo_state: self.undo_state = self.song().can_undo self._undo_button.send_value(self.undo_state == 1 and 127 or 0) if self.song().can_redo != self.redo_state: self.redo_state = self.song().can_redo self._redo_button.send_value(self.redo_state == 1 and 127 or 0) def adjust_loop_start(self, delta): loopval = self.song().loop_start self.song().loop_start = min(self.song().song_length, max(0, loopval + delta)) def adjust_loop_length(self, delta): loopval = self.song().loop_length self.song().loop_length = min(self.song().song_length, max(abs(delta), loopval + delta)) def _do_armsolo_mode(self, value): pass @subject_slot('value') def _do_fire_button(self, value): raise self._fire_button != None or AssertionError raise value in range(128) or AssertionError if value != 0: if self.isShiftDown(): self.song().tap_tempo() else: clip_slot = self.song().view.highlighted_clip_slot if clip_slot: clip_slot.fire() @subject_slot('value') def _do_undo(self, value): if value != 0: if self.use_layered_buttons() and self.isShiftDown(): if self.song().can_redo == 1: self.song().redo() self.show_message(str('REDO')) elif self.song().can_undo == 1: self.song().undo() self.show_message(str('UNDO')) @subject_slot('value') def _do_redo(self, value): if value != 0: if self.song().can_redo == 1: self.song().redo() self.show_message(str('REDO')) @subject_slot('value') def _do_stop_all(self, value): if value != 0: if self.use_layered_buttons() and self.isShiftDown(): self.song().stop_all_clips(0) else: self.song().stop_all_clips(1) def isShiftDown(self): return self._editsection.isShiftdown() def modifiers(self): return self._editsection.modifiers() def use_layered_buttons(self): return False def _handle_base_note(self, diff): self._modeselect._pad_mode.inc_base_note(diff) def _handle_octave(self, diff): self._modeselect._pad_mode.inc_octave(diff) octave_val = self._modeselect._pad_mode def _handle_scale(self, diff): self._modeselect._pad_mode.inc_scale(diff) @subject_slot('value') def _do_update_display(self, value): if value != 0: self.refresh_state() @subject_slot('value') def _do_key_color(self, value): if not value in range(128): raise AssertionError value != 0 and self._modeselect._pad_mode.step_key_color_mode() @subject_slot('value') def _do_tap_tempo(self, value): if not value in range(128): raise AssertionError value != 0 and self.song().tap_tempo() @subject_slot('value') def _do_toggle_cue(self, value): if not value in range(128): raise AssertionError value != 0 and self.song().set_or_delete_cue() @subject_slot('value') def _do_toggle_prev_cue(self, value): if not value in range(128): raise AssertionError value != 0 and self.song().jump_to_prev_cue() @subject_slot('value') def _do_toggle_next_cue(self, value): if not value in range(128): raise AssertionError value != 0 and self.song().jump_to_next_cue() @subject_slot('value') def _do_toggle_send(self, value): if not value in range(128): raise AssertionError if self.isShiftDown(): value != 0 and self.refresh_state() self.show_message('Refresh Display') else: nr_of_tracks = len(self.song().return_tracks) if value == 0 or nr_of_tracks < 1: return prev = self.send_slider_index self.send_slider_index += 1 if self.send_slider_index >= nr_of_tracks: self.send_slider_index = 0 self.show_message(' Set Send ' + str(SENDS[self.send_slider_index])) self.timed_message(2, ' Set Send ' + str(SENDS[self.send_slider_index])) if prev != self.send_slider_index: for track in range(8): strip = self._mixer.channel_strip(track) slider_list = [] for index in range(self.send_slider_index + 1): if index < self.send_slider_index - 1: slider_list.append(None) else: slider_list.append(self.send_sliders[track]) strip.set_send_controls(tuple(slider_list)) @subject_slot('value') def _a_trk_left(self, value): if not value in range(128): raise AssertionError if value != 0: if self.application().view.is_view_visible('Session'): direction = Live.Application.Application.View.NavDirection.left self.application().view.scroll_view(direction, 'Session', True) track = self.song().view.selected_track self.timed_message(2, 'T:' + track.name, False) self.arm_selected_track and track.can_be_armed and arm_exclusive(self.song(), track) @subject_slot('value') def _a_trk_right(self, value): if not value in range(128): raise AssertionError if value != 0: if self.application().view.is_view_visible('Session'): direction = Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Session', True) track = self.song().view.selected_track self.timed_message(2, 'T:' + track.name, False) self.arm_selected_track and track.can_be_armed and arm_exclusive(self.song(), track) @subject_slot('value') def _a_sel_arm(self, value): if value != 0: if self.arm_selected_track: self.arm_selected_track = False self.set_sel_arm_button.send_value(0, True) else: self.arm_selected_track = True self.set_sel_arm_button.send_value(127, True) @subject_slot('value') def _nav_value_left(self, value): if not self._device_nav_button_left != None: raise AssertionError if not value in range(128): raise AssertionError modifier_pressed = True value != 0 and (not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain')) and self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: direction = Live.Application.Application.View.NavDirection.left self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed) @subject_slot('value') def _nav_value_right(self, value): if not self._device_nav_button_right != None: raise AssertionError if not value in range(128): raise AssertionError modifier_pressed = value != 0 and True (not self.application().view.is_view_visible('Detail') or not self.application().view.is_view_visible('Detail/DeviceChain')) and self.application().view.show_view('Detail') self.application().view.show_view('Detail/DeviceChain') else: direction = Live.Application.Application.View.NavDirection.right self.application().view.scroll_view(direction, 'Detail/DeviceChain', not modifier_pressed) @subject_slot('value') def _do_focus_navigate(self, value): if not self._navigate_button != None: raise AssertionError raise value in range(128) or AssertionError self.nav_index = value != 0 and (self.nav_index + 1) % len(VIEWS_ALL) self.application().view.focus_view(VIEWS_ALL[self.nav_index]) self.show_message('Focus on : ' + str(VIEWS_ALL[self.nav_index])) def focus_clip_detail(self): self.application().view.focus_view('Detail/Clip') @subject_slot('follow_song') def _song_follow_changed(self): view = self.song().view if view.follow_song: self.song_follow_button.send_value(1, True) else: self.song_follow_button.send_value(0, True) @subject_slot('value') def _do_song_follow(self, value): if value != 0: view = self.song().view if view.follow_song: view.follow_song = False self.song_follow_button.send_value(0, True) else: view.follow_song = True self.song_follow_button.send_value(1, True) @subject_slot('value') def _hold_duplicate_action(self, value): if value != 0: pass @subject_slot('value') def _hold_clear_action(self, value): if value != 0: self._mixer.enter_clear_mode() self._device_component.enter_clear_mode() else: self._mixer.exit_clear_mode() self._device_component.exit_clear_mode() @subject_slot('value') def _action_toogle_main_view(self, value): if value != 0: appv = self.application().view if appv.is_view_visible('Arranger'): appv.show_view('Session') else: appv.show_view('Arranger') @subject_slot('value') def _action_toogle_detail_view(self, value): if value != 0: appv = self.application().view if self.isShiftDown(): if appv.is_view_visible('Arranger'): appv.show_view('Session') else: appv.show_view('Arranger') elif appv.is_view_visible('Detail/Clip'): appv.show_view('Detail/DeviceChain') else: appv.show_view('Detail/Clip') @subject_slot('re_enable_automation_enabled') def _on_change_reenabled(self): if self.song().re_enable_automation_enabled: self._reenable_button.turn_on() else: self._reenable_button.turn_off() @subject_slot('value') def _do_auto_reenable(self, value): if value != 0: self.song().re_enable_automation() def to_color_edit_mode(self, active): pass def clear_display_all(self): self.send_to_display('', 0) self.send_to_display('', 1) self.send_to_display('', 2) self.send_to_display('', 3) def clear_display(self, grid): self.send_to_display('', grid) def timed_message(self, grid, text, hold = False): if USE_DISPLAY == False: self.show_message(text) else: self.display_task.set_func(self.clear_display, grid) self.send_to_display(text, grid) if hold: self.display_task.hold() self.display_task.start() def timed_message_release(self): self.display_task.release() def update_bank_display(self): if USE_DISPLAY: name, bank = self._device._current_bank_details() if self._display_device_param: prms = len(bank) d1 = '' for i in range(4): parm = bank[i] if parm: name = parm.name d1 += name[:6] + (i < 3 and '|' or '') else: d1 += ' ' + (i < 3 and '|' or '') self.send_to_display(d1, 2) d1 = '' for i in range(4): parm = bank[i + 4] if parm: name = parm.name d1 += name[:6] + (i < 3 and '|' or '') else: d1 += ' ' + (i < 3 and '|' or '') self.send_to_display(d1, 4) else: self.timed_message(2, 'Bank: ' + name) def display_parameters(self, paramlist): if USE_DISPLAY == False: return def send_to_display(self, text, grid = 0): if USE_DISPLAY == False: return if self._diplay_cache[grid] == text: return self._diplay_cache[grid] = text if len(text) > 28: text = text[:27] msgsysex = [240, 0, 0, 102, 23, 18, min(grid, 3) * 28] filled = text.ljust(28) for c in filled: msgsysex.append(ord(c)) msgsysex.append(247) self._send_midi(tuple(msgsysex)) def cleanup(self): pass def disconnect(self): self._pre_serialize() self.clear_display_all() for button, (track_index, scene_index) in self._bmatrix.iterbuttons(): if button: button.send_color_direct(PColor.OFF[0]) time.sleep(0.2) self._active = False self._suppress_send_midi = True super(Maschine, self).disconnect()