コード例 #1
0
class OP1(ControlSurface):
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self.c_instance = c_instance

        self.retries_count = 0
        self.device_connected = False

        self.clip_color_callbacks = {}
        self.slot_callbacks = {}

        self.text_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x03)
        self.text_end_sequence = (0xf7, )
        self.enable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x02, 0xf7)
        self.disable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x00,
                                 0xf7)

        self.id_sequence = (0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7)

        self.text_color_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x04)

        self.log('INITIALIZING')

        self.app = Live.Application.get_application()

        #maj = self.app.get_major_version()
        #min = self.app.get_minor_version()
        #bug = self.app.get_bugfix_version()
        #self.show_message(str(1) + "." + str(0) + "." + str(9))

        self.show_message("Version " + VERSION)

        # reseting text
        self.write_text(' ')

        # reset display clips
        self.reset_display_clips()

        # getting browser visible state
        self.session_browser_visible = self.app.view.is_view_visible("Browser")

        # getting browser visible state
        self.arrange_browser_visible = self.app.view.is_view_visible("Browser")

        # getting session view visible state
        self.session_visible = self.app.view.is_view_visible("Session")

        # getting arrange view visible state
        self.arrange_visible = self.app.view.is_view_visible("Arranger")

        # getting detail view visible state
        self.detail_visible = self.app.view.is_view_visible("Detail")

        # getting back to arranger state
        self.back_to_arranger_state = self.song().back_to_arranger

        # initializing channel strip to null
        self._channel_strip = None

        # initializing transport component
        self._transport = TransportComponent()

        # initializing mixer component
        self._mixer = MixerComponent(NUM_TRACKS, 2)

        # initializing session component
        self._session = SessionComponent(NUM_TRACKS, NUM_ROWS)
        self._session.add_offset_listener(self.session_offset_changed)

        # configuring operation mode selector buttons
        self._operation_mode_buttons = ButtonElement(
            True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_1_BUTTON), ButtonElement(
                True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_2_BUTTON), ButtonElement(
                    True, MIDI_CC_TYPE, CHANNEL,
                    OP1_MODE_3_BUTTON), ButtonElement(True, MIDI_CC_TYPE,
                                                      CHANNEL,
                                                      OP1_MODE_4_BUTTON),

        # initializing operation mode selector
        self._operation_mode_selector = OP1ModeSelectorComponent(
            self, self._transport, self._mixer, self._session)

        # setting operation mode selector buttons
        self._operation_mode_selector.set_mode_buttons(
            self._operation_mode_buttons)

        # adding value listener for operation mode index
        self._operation_mode_selector.add_mode_index_listener(
            self.mode_index_changed)

        # setting global transport assignments
        self._transport.set_record_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_REC_BUTTON))
        self._transport.set_play_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_PLAY_BUTTON))
        self._transport.set_stop_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_STOP_BUTTON))
        self._transport.set_metronome_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_METRONOME_BUTTON))
        self._transport.set_tap_tempo_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_HELP_BUTTON))
        self._transport.set_punch_buttons(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS1_BUTTON),
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS2_BUTTON))
        self._transport.set_loop_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS3_BUTTON))
        self._transport.set_overdub_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS4_BUTTON))

        # setting global session assignments
        self._session.set_scene_bank_buttons(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_COM),
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MICRO))

        # setting misc listeners
        self.browser_toggle_button = ButtonElement(False, MIDI_CC_TYPE,
                                                   CHANNEL, 15)
        self.browser_toggle_button.add_value_listener(
            self.browser_toggle_button_callback)

        self.mainview_toggle_button = ButtonElement(False, MIDI_CC_TYPE,
                                                    CHANNEL, 16)
        self.mainview_toggle_button.add_value_listener(
            self.mainview_toggle_button_callback)

        self.detailview_toggle_button = ButtonElement(False, MIDI_CC_TYPE,
                                                      CHANNEL, 17)
        self.detailview_toggle_button.add_value_listener(
            self.detailview_toggle_button_callback)

        self.clear_track_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL,
                                                25)
        self.clear_track_button.add_value_listener(
            self.clear_track_button_callback)

        self.back_to_arranger_button = ButtonElement(True, MIDI_CC_TYPE,
                                                     CHANNEL, 26)
        self.back_to_arranger_button.add_value_listener(
            self.back_to_arranger_button_callback)

        # adding value listener for selected track change
        self.song().view.add_selected_track_listener(
            self.selected_track_changed)

        # adding value listener for selected scene change
        self.song().view.add_selected_scene_listener(
            self.selected_scene_changed)

        # setting assignments for currently selected track
        self.selected_track_changed()

        # setting assignments for currently selected scene
        self.selected_scene_changed()

    def handle_sysex(self, midi_bytes):
        if ((midi_bytes[6] == 32) and (midi_bytes[7] == 118)):
            self.device_connected = True
            self.log("OP-1 CONNECTED. SENDING ABLETON LIVE MODE INIT SEQUENCE")
            self._send_midi(self.enable_sequence)

    def add_clip_slot_listeners(self):
        #self.log('ADDING CLIP SLOT LISTENERS')

        # creating an empty list for all clip slots
        clip_slots = []

        # getting a reference to all tracks
        tracks = self.song().tracks

        # appending all tracks clip slots to clip_slots
        for track in tracks:
            clip_slots.append(track.clip_slots)

        # iterating over all clip slots
        for t in range(len(clip_slots)):
            for c in range(len(clip_slots[t])):
                clip_slot = clip_slots[t][c]

                # adding has clip listener to clip slot
                self.add_slot_listener(clip_slot)

                # if clip slot has clip
                if clip_slot.has_clip:
                    # adding clip listeners
                    self.add_clip_listener(clip_slot.clip)

    def rem_clip_slot_listeners(self):
        #self.log('REMOVING CLIP SLOT LISTENERS')

        # iterate over all clip color change callbacks
        for c in self.clip_color_callbacks:
            # if clip still exists
            if c != None:
                # and it has a has clip listener
                if c.color_has_listener(self.clip_color_callbacks[c]) == 1:
                    # remove it
                    c.remove_color_listener(self.clip_color_callbacks[c])

        # iterate over all clip slot callbacks
        for cs in self.slot_callbacks:
            # if clip slot still exists
            if cs != None:
                # and it has a has clip listener
                if cs.has_clip_has_listener(self.slot_callbacks[cs]) == 1:
                    # remove it
                    cs.remove_has_clip_listener(self.slot_callbacks[cs])

    def add_slot_listener(self, cs):
        # setting has clip listener
        callback = lambda: self.has_clip_listener(cs)

        # if we don't have a clip slot has clip listener for this clip slot yet
        if not (self.slot_callbacks.has_key(cs)):
            # adding has clip callback to clip slot
            cs.add_has_clip_listener(callback)

            # saving callback for future release
            self.slot_callbacks[cs] = callback

    def add_clip_listener(self, clip):
        # setting callback for clip color change
        color_callback = lambda: self.update_display_clips()

        # if we don't have a clip color change callback for this clip yet
        if not (self.clip_color_callbacks.has_key(clip)):
            # adding clip color change callback
            clip.add_color_listener(color_callback)

            # saving callback for future release
            self.clip_color_callbacks[clip] = color_callback

    def has_clip_listener(self, cs):
        # clip slot has clip listener callback
        if cs.has_clip:
            # add clip listener
            self.add_clip_listener(cs.clip)
        else:
            # update display if clip slot was removed
            self.update_display_clips()

    def session_offset_changed(self):
        # if session component offset changes, update display
        self.update_display_clips()

    def selected_scene_changed(self):
        # if on clip mode update display
        if (self._operation_mode_selector.mode_index == OP1_MODE_CLIP):
            self.update_display_clip_mode()

    def mode_index_changed(self):
        # update display to current mode info
        if (self._operation_mode_selector.mode_index == OP1_MODE_PERFORM):
            self.update_display_perform_mode()
        elif (self._operation_mode_selector.mode_index == OP1_MODE_CLIP):
            self.update_display_clip_mode()
        elif (self._operation_mode_selector.mode_index == OP1_MODE_TRANSPORT):
            self.update_display_transport_mode()
        elif (self._operation_mode_selector.mode_index == OP1_MODE_MIXER):
            self.update_display_mixer_mode()

    def clear_track_button_callback(self, value):
        # if clear track button was called, reset track
        if (value == 127):
            for i in range(len(self.song().tracks)):
                self.song().tracks[i].arm = 0
                self.song().tracks[i].solo = 0
                self.song().tracks[i].mute = 0

            for i in range(len(self.song().return_tracks)):
                self.song().tracks[i].solo = 0
                self.song().tracks[i].mute = 0

    def clear_return_track_assignment(self, strip):
        # clear return track assingments
        strip.set_volume_control(None)
        strip.set_pan_control(None)
        strip.set_mute_button(None)
        strip.set_solo_button(None)

    def clear_track_assignment(self, strip):
        # clear track assignments
        strip.set_volume_control(None)
        strip.set_pan_control(None)
        strip.set_mute_button(None)
        strip.set_solo_button(None)
        strip.set_arm_button(None)

    def clear_tracks_assigments(self):
        # for all normal tracks, clear assignments
        for i in range(NUM_TRACKS):
            strip = self._mixer.channel_strip(i)
            if (strip != None):
                self.clear_track_assignment(strip)

        # for all return tracks, clear assignments
        for i in range(2):
            return_strip = self._mixer.return_strip(i)
            if (return_strip != None):
                self.clear_return_track_assignment(return_strip)

    def selected_track_changed(self):
        # if on mixer mode update display
        if (self._operation_mode_selector.mode_index == OP1_MODE_MIXER):
            self.update_display_mixer_mode()

        # clear track assignments
        self.clear_tracks_assigments()

        # getting selected strip
        self._channel_strip = self._mixer.selected_strip()

        # perform track assignments
        self._channel_strip.set_volume_control(
            EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_1,
                           Live.MidiMap.MapMode.relative_two_compliment))
        self._channel_strip.set_pan_control(
            EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_2,
                           Live.MidiMap.MapMode.relative_two_compliment))

        # setting a tuple of encoders to control sends
        send_controls = EncoderElement(
            MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_3,
            Live.MidiMap.MapMode.relative_two_compliment), EncoderElement(
                MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_4,
                Live.MidiMap.MapMode.relative_two_compliment),

        # setting send encoders
        self._channel_strip.set_send_controls(tuple(send_controls))

        # setting solo button
        self._channel_strip.set_solo_button(
            ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS6_BUTTON))

        # if track can be armed, set arm button
        if (self._channel_strip._track.can_be_armed):
            self._channel_strip.set_arm_button(
                ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS7_BUTTON))

        # if track is no master, set mute button
        if (self._channel_strip._track != self.song().master_track):
            self._channel_strip.set_mute_button(
                ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS5_BUTTON))

    def browser_toggle_button_callback(self, value):
        if (value == 127):
            if (self.session_visible):
                if (self.session_browser_visible == True):
                    self.session_browser_visible = False
                    self.app.view.hide_view("Browser")
                else:
                    self.session_browser_visible = True
                    self.app.view.show_view("Browser")

            if (self.arrange_visible):
                if (self.arrange_browser_visible == True):
                    self.arrange_browser_visible = False
                    self.app.view.hide_view("Browser")
                else:
                    self.arrange_browser_visible = True
                    self.app.view.show_view("Browser")

    def back_to_arranger_button_callback(self, value):
        if (value == 127):
            self.song().back_to_arranger = False

    def mainview_toggle_button_callback(self, value):
        if (value == 127):
            if (self.session_visible == True):
                self.session_visible = False
                self.arrange_visible = True
                self.app.view.show_view("Arranger")
                self.arrange_browser_visible = self.app.view.is_view_visible(
                    "Browser")
            else:
                self.session_visible = True
                self.arrange_visible = False
                self.app.view.show_view("Session")
                self.session_browser_visible = self.app.view.is_view_visible(
                    "Browser")

    def detailview_toggle_button_callback(self, value):
        if (value == 127):
            if (self.detail_visible == True):
                self.detail_visible = False
                self.app.view.hide_view("Detail")
            else:
                self.detail_visible = True
                self.app.view.show_view("Detail")

    def write_text(self, msg):
        text_list = []
        sequence = ()

        text_list.append(len(msg.strip()))

        for i in msg.strip():
            text_list.append(ord(i))

        sequence = self.text_start_sequence + tuple(
            text_list) + self.text_end_sequence

        self._send_midi(sequence)

    def suggest_input_port(self):
        return "OP-1 Midi Device"

    def suggest_output_port(self):
        return "OP-1 Midi Device"

    def update_display_perform_mode(self):
        self.write_text("perform\rmode")

    def reset_display_clips(self):
        count = 0
        colors = []
        length = []
        sequence = ()

        for i in range(NUM_TRACKS):
            count += 1

            colors.append(0x00)
            colors.append(0x00)
            colors.append(0x00)

        length.append(count)
        sequence = self.text_color_start_sequence + tuple(length) + tuple(
            colors) + self.text_end_sequence
        self._send_midi(sequence)

    def update_display_clips(self):
        #self.log("UPDATING DISPLAY CLIPS")
        count = 0
        colors = []
        length = []
        sequence = ()

        tracks_len = len(self.song().tracks) - self._session._track_offset

        if (tracks_len > NUM_TRACKS):
            tracks_len = NUM_TRACKS

        for i in range(tracks_len):
            count += 1

            clip_slot = self._session.scene(0).clip_slot(i)

            if (clip_slot != None):
                if (clip_slot.has_clip() != False):
                    clip_color = clip_slot._clip_slot.clip.color
                    colors.append(((clip_color >> 16) & 0x000000ff) >> 1)
                    colors.append(((clip_color >> 8) & 0x000000ff) >> 1)
                    colors.append((clip_color & 0x000000ff) >> 1)
                else:
                    colors.append(0x00)
                    colors.append(0x00)
                    colors.append(0x00)
            else:
                colors.append(0x00)
                colors.append(0x00)
                colors.append(0x00)

        length.append(count)
        sequence = self.text_color_start_sequence + tuple(length) + tuple(
            colors) + self.text_end_sequence
        self._send_midi(sequence)

    def update_display_clip_mode(self):
        self.write_text(
            "sel. scene\r" +
            str(self.song().view.selected_scene.name.lower().strip()))

    def update_display_transport_mode(self):
        song_time = str(self.song().get_current_beats_song_time())
        self.write_text("song pos.\r" + song_time[:len(song_time) - 4])

    def update_display_mixer_mode(self):
        self.write_text("sel. track\r" +
                        str(self.song().view.selected_track.name.lower()))

    def update_display(self):
        if not (self.device_connected):
            if (self.retries_count < 5):
                self.log("TRYING OP-1 CONNECTION")
                self.retries_count += 1
                self._send_midi(self.id_sequence)
                time.sleep(1)

        # if in transport mode, update display with song position
        if (self._operation_mode_selector.mode_index == OP1_MODE_TRANSPORT):
            self.update_display_transport_mode()

        # checking if app current view is session
        if (self.app.view.is_view_visible("Session")):
            # checking if session browser state is diferent from the internal
            if (self.session_browser_visible !=
                    self.app.view.is_view_visible("Browser")):
                self.session_browser_visible = self.app.view.is_view_visible(
                    "Browser")

        # checking if app current view is arrange
        if (self.app.view.is_view_visible("Arranger")):
            # checking if arrange browser state is diferent from the internal
            if (self.arrange_browser_visible !=
                    self.app.view.is_view_visible("Browser")):
                self.arrange_browser_visible = self.app.view.is_view_visible(
                    "Browser")

        # checking if app current view is detail
        if (self.app.view.is_view_visible("Detail")):
            # checking if detail state is diferent from the internal
            if (self.detail_visible !=
                    self.app.view.is_view_visible("Detail")):
                self.detail_visible = self.app.view.is_view_visible("Detail")

    def refresh_state(self):
        self.log("REFRESH STATE")
        self.retries_count = 0
        self.device_connected = False

    def build_midi_map(self, midi_map_handle):
        #self.log("BUILD MIDI MAP")

        assert (self._suppress_requests_counter == 0)
        self._in_build_midi_map = True
        self._midi_map_handle = midi_map_handle
        self._forwarding_registry = {}
        for control in self.controls:
            if isinstance(control, InputControlElement):
                control.install_connections()
        self._midi_map_handle = None
        self._in_build_midi_map = False
        if (self._pad_translations != None):
            self._c_instance.set_pad_translation(self._pad_translations)

        # remove clip listeners
        self.rem_clip_slot_listeners()

        # add clip listeners
        self.add_clip_slot_listeners()

        # update display
        self.update_display_clips()

    def log(self, msg):
        self.c_instance.log_message("[TE OP-1] " + msg)

    def disconnect(self):
        # removing clip slots listeners
        self.rem_clip_slot_listeners()

        # removing value listener for track changed
        self.song().view.remove_selected_track_listener(
            self.selected_track_changed)

        # removing value listener for scene changed
        self.song().view.remove_selected_scene_listener(
            self.selected_scene_changed)

        # removing value listener for operation mode index
        self._operation_mode_selector.remove_mode_index_listener(
            self.mode_index_changed)

        # removing global transport assignments
        self._transport.set_punch_buttons(None, None)
        self._transport.set_loop_button(None)
        self._transport.set_overdub_button(None)
        self._transport.set_record_button(None)
        self._transport.set_play_button(None)
        self._transport.set_stop_button(None)
        self._transport.set_metronome_button(None)
        self._transport.set_tap_tempo_button(None)

        # removing global session assignments
        self._session.set_scene_bank_buttons(None, None)

        # removing misc listeners
        self.browser_toggle_button.remove_value_listener(
            self.browser_toggle_button_callback)
        self.mainview_toggle_button.remove_value_listener(
            self.mainview_toggle_button_callback)
        self.detailview_toggle_button.remove_value_listener(
            self.detailview_toggle_button_callback)
        self.clear_track_button.remove_value_listener(
            self.clear_track_button_callback)
        self.back_to_arranger_button.remove_value_listener(
            self.back_to_arranger_button_callback)

        # sending special ableton mode disable sequence
        self._send_midi(self.disable_sequence)

        # disconnecting control surface
        ControlSurface.disconnect(self)

        self.log("DISCONNECTED")
コード例 #2
0
ファイル: LemurPad.py プロジェクト: Adamdma/monomodular
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)
コード例 #3
0
class joyMIDI(ControlSurface):
    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            self.setup_transport()
            self.setup_mixer()
            self.setup_session()

    def setup_transport(self):
        # elements
        self.play_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 93)
        self.stop_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 94)
        self.record_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 95)
        # transport
        self.transport = TransportComponent()
        self.transport.set_play_button(self.play_button)
        self.transport.set_stop_button(self.stop_button)
        self.transport.set_record_button(self.record_button)

    def setup_mixer(self):
        # elements
        self.mute_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                         92)  # tracks, return_tracks
        self.solo_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                         84)  # tracks, return_tracks
        self.arm_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 85)  # tracks
        self.senda_up_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                             96)  # tracks, return_tracks
        self.senda_down_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                               88)  # tracks, return_tracks
        self.sendb_up_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                             97)  # tracks, return_tracks
        self.sendb_down_button = ButtonElement(True, MIDI_NOTE_TYPE, 0,
                                               89)  # tracks, return_tracks
        self.pan_up_button = ButtonElement(
            True, MIDI_NOTE_TYPE, 0, 98)  # tracks, return_tracks, master_track
        self.pan_down_button = ButtonElement(
            True, MIDI_NOTE_TYPE, 0, 90)  # tracks, return_tracks, master_track
        self.volume_up_button = ButtonElement(
            True, MIDI_NOTE_TYPE, 0, 99)  # tracks, return_tracks, master_track
        self.volume_down_button = ButtonElement(
            True, MIDI_NOTE_TYPE, 0, 91)  # tracks, return_tracks, master_track
        self.track_nav_encoder = EncoderElement(
            MIDI_CC_TYPE, 0, 14, Live.MidiMap.MapMode.relative_binary_offset)
        # mixer
        self.mixer = MixerComponent(7, 2)
        self.mixer.selected_strip().set_mute_button(self.mute_button)
        self.mixer.selected_strip().set_solo_button(self.solo_button)
        self.mixer.selected_strip().set_arm_button(self.arm_button)
        # send A/B, pan, volume
        self.senda_up_button.add_value_listener(self.on_senda_up_changed)
        self.senda_down_button.add_value_listener(self.on_senda_down_changed)
        self.sendb_up_button.add_value_listener(self.on_sendb_up_changed)
        self.sendb_down_button.add_value_listener(self.on_sendb_down_changed)
        self.pan_up_button.add_value_listener(self.on_pan_up_changed)
        self.pan_down_button.add_value_listener(self.on_pan_down_changed)
        self.volume_up_button.add_value_listener(self.on_volume_up_changed)
        self.volume_down_button.add_value_listener(self.on_volume_down_changed)
        # nav
        self.track_nav_encoder.add_value_listener(self.on_mixer_track_nav)

    def on_senda_up_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.sends[0]
            param.value = max(
                param.min,
                min(param.max,
                    param.value + ((param.max - param.min) / SEND_STEPS)))

    def on_senda_down_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.sends[0]
            param.value = max(
                param.min,
                min(param.max,
                    param.value - ((param.max - param.min) / SEND_STEPS)))

    def on_sendb_up_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.sends[1]
            param.value = max(
                param.min,
                min(param.max,
                    param.value + ((param.max - param.min) / SEND_STEPS)))

    def on_sendb_down_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.sends[1]
            param.value = max(
                param.min,
                min(param.max,
                    param.value - ((param.max - param.min) / SEND_STEPS)))

    def on_pan_up_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.panning
            param.value = max(
                param.min,
                min(param.max,
                    param.value + ((param.max - param.min) / PAN_STEPS)))

    def on_pan_down_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.panning
            param.value = max(
                param.min,
                min(param.max,
                    param.value - ((param.max - param.min) / PAN_STEPS)))

    def on_volume_up_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.volume
            param.value = max(
                param.min,
                min(param.max,
                    param.value + ((param.max - param.min) / VOLUME_STEPS)))

    def on_volume_down_changed(self, value):
        if value > 0:
            param = self.song().view.selected_track.mixer_device.volume
            param.value = max(
                param.min,
                min(param.max,
                    param.value - ((param.max - param.min) / VOLUME_STEPS)))

    def on_mixer_track_nav(self, value):
        move = -1 if value > 64 else +1
        # get tracks-info
        tracks = self.song().tracks
        return_tracks = self.song().return_tracks
        master_track = self.song().master_track
        all_tracks = list(chain(tracks, return_tracks))
        all_tracks.append(master_track)
        num_tracks = len(tracks)
        num_return_tracks = len(return_tracks)
        num_master_track = 1
        num_all_tracks = num_tracks + num_return_tracks + num_master_track
        # update selected-track
        index = index_if(lambda t: t == self.song().view.selected_track,
                         all_tracks)
        index += move
        index = min(max(index, 0), num_all_tracks - 1)
        self.song().view.selected_track = all_tracks[index]

    def setup_session(self):
        num_tracks = 7
        num_scenes = 1
        track_offset = 0
        scene_offset = 0
        # elements
        self.clip_launch_buttons = ButtonMatrixElement(rows=[[
            ButtonElement(True, MIDI_NOTE_TYPE, 0, 76 + i)
            for i in range(num_tracks)
        ]])
        self.clip_stop_buttons = [
            ButtonElement(True, MIDI_NOTE_TYPE, 0, 68 + i)
            for i in range(num_tracks)
        ]
        self.scene_launch_buttons = ButtonMatrixElement(rows=[[
            ButtonElement(True, MIDI_NOTE_TYPE, 0, 83 + i)
            for i in range(num_scenes)
        ]])
        self.scene_stop_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 75)
        self.session_scene_nav_encoder = EncoderElement(
            MIDI_CC_TYPE, 0, 15, Live.MidiMap.MapMode.relative_binary_offset)
        # session
        self.session = SessionComponent(num_tracks, num_scenes)
        self.session.set_offsets(track_offset, scene_offset)
        self.session.add_offset_listener(self.on_session_offset_changed)
        self.set_highlighting_session_component(self.session)
        # clips
        self.session.set_clip_launch_buttons(self.clip_launch_buttons)
        self.session.set_stop_track_clip_buttons(self.clip_stop_buttons)
        self.session.set_scene_launch_buttons(self.scene_launch_buttons)
        self.session.set_stop_all_clips_button(self.scene_stop_button)
        # nav
        self.session_scene_nav_encoder.add_value_listener(
            self.on_session_scene_nav)

    def on_session_offset_changed(self):
        pass

    def on_session_scene_nav(self, value):
        value -= 64
        value = -value
        track_offset = self.session.track_offset()
        scene_offset = max(0, self.session.scene_offset() + value)
        self.session.set_offsets(track_offset, scene_offset)

    def disconnect(self):
        u"""Live -> Script
        Called right before we get disconnected from Live.
        """
        self.log_message('disconnect')
        self.show_message('disconnect')
コード例 #4
0
ファイル: LemurPad.py プロジェクト: aumhaa/m4m7
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)
コード例 #5
0
ファイル: OP1.py プロジェクト: imaginando/op1
class OP1(ControlSurface):
	def __init__(self, c_instance):
		ControlSurface.__init__(self, c_instance)
		self.c_instance = c_instance

		self.retries_count = 0
		self.device_connected = False

		self.clip_color_callbacks = {}
		self.slot_callbacks = {}

		self.text_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x03)
		self.text_end_sequence = (0xf7,)
		self.enable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x02, 0xf7)
		self.disable_sequence = (0xf0, 0x00, 0x20, 0x76, 0x00, 0x01, 0x00, 0xf7)

		self.id_sequence = (0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7)

		self.text_color_start_sequence = (0xf0, 0x0, 0x20, 0x76, 0x00, 0x04)

		self.log('INITIALIZING')

		self.app = Live.Application.get_application()

		#maj = self.app.get_major_version()
		#min = self.app.get_minor_version()
		#bug = self.app.get_bugfix_version()
		#self.show_message(str(1) + "." + str(0) + "." + str(9))

		self.show_message("Version " + VERSION)

		# reseting text
		self.write_text(' ')

		# reset display clips
		self.reset_display_clips()

		# getting browser visible state
		self.session_browser_visible = self.app.view.is_view_visible("Browser")
		
		# getting browser visible state
		self.arrange_browser_visible = self.app.view.is_view_visible("Browser")

		# getting session view visible state
		self.session_visible = self.app.view.is_view_visible("Session")

		# getting arrange view visible state
		self.arrange_visible = self.app.view.is_view_visible("Arranger")

		# getting detail view visible state
		self.detail_visible = self.app.view.is_view_visible("Detail")

		# getting back to arranger state
		self.back_to_arranger_state = self.song().back_to_arranger

		# initializing channel strip to null
		self._channel_strip = None

		# initializing transport component
		self._transport = TransportComponent()

		# initializing mixer component
		self._mixer = MixerComponent(NUM_TRACKS,2)

		# initializing session component
		self._session = SessionComponent(NUM_TRACKS,NUM_ROWS)
		self._session.add_offset_listener(self.session_offset_changed)

		# configuring operation mode selector buttons
		self._operation_mode_buttons = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_1_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_2_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_3_BUTTON), ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MODE_4_BUTTON), 
		
		# initializing operation mode selector
		self._operation_mode_selector = OP1ModeSelectorComponent(self, self._transport, self._mixer, self._session)
		
		# setting operation mode selector buttons
		self._operation_mode_selector.set_mode_buttons(self._operation_mode_buttons)

		# adding value listener for operation mode index
		self._operation_mode_selector.add_mode_index_listener(self.mode_index_changed)

		# setting global transport assignments
		self._transport.set_record_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_REC_BUTTON))
		self._transport.set_play_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_PLAY_BUTTON))
		self._transport.set_stop_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_STOP_BUTTON))  
		self._transport.set_metronome_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_METRONOME_BUTTON))  
		self._transport.set_tap_tempo_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_HELP_BUTTON))
		self._transport.set_punch_buttons(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS1_BUTTON), ButtonElement(True,MIDI_CC_TYPE, CHANNEL, OP1_SS2_BUTTON))
		self._transport.set_loop_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS3_BUTTON))
		self._transport.set_overdub_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS4_BUTTON))

		# setting global session assignments
		self._session.set_scene_bank_buttons(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_COM),ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_MICRO))

		# setting misc listeners
		self.browser_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 15)
		self.browser_toggle_button.add_value_listener(self.browser_toggle_button_callback)

		self.mainview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 16)
		self.mainview_toggle_button.add_value_listener(self.mainview_toggle_button_callback)

		self.detailview_toggle_button = ButtonElement(False, MIDI_CC_TYPE, CHANNEL, 17)
		self.detailview_toggle_button.add_value_listener(self.detailview_toggle_button_callback)

		self.clear_track_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 25)
		self.clear_track_button.add_value_listener(self.clear_track_button_callback)

		self.back_to_arranger_button = ButtonElement(True, MIDI_CC_TYPE, CHANNEL, 26)
		self.back_to_arranger_button.add_value_listener(self.back_to_arranger_button_callback)

		# adding value listener for selected track change
		self.song().view.add_selected_track_listener(self.selected_track_changed)

		# adding value listener for selected scene change
		self.song().view.add_selected_scene_listener(self.selected_scene_changed)

		# setting assignments for currently selected track
		self.selected_track_changed()

		# setting assignments for currently selected scene
		self.selected_scene_changed()

	def handle_sysex(self, midi_bytes):
		if ((midi_bytes[6]==32) and (midi_bytes[7]==118)):
			self.device_connected = True
			self.log("OP-1 CONNECTED. SENDING ABLETON LIVE MODE INIT SEQUENCE")
			self._send_midi(self.enable_sequence)

	def add_clip_slot_listeners(self):
		#self.log('ADDING CLIP SLOT LISTENERS')
		
		# creating an empty list for all clip slots
		clip_slots = []

		# getting a reference to all tracks
		tracks = self.song().tracks
		
		# appending all tracks clip slots to clip_slots
		for track in tracks:
			clip_slots.append(track.clip_slots)

		# iterating over all clip slots
		for t in range(len(clip_slots)):
			for c in range(len(clip_slots[t])):
				clip_slot = clip_slots[t][c]

				# adding has clip listener to clip slot
				self.add_slot_listener(clip_slot)

				# if clip slot has clip
				if clip_slot.has_clip:
					# adding clip listeners
					self.add_clip_listener(clip_slot.clip)

	def rem_clip_slot_listeners(self):
		#self.log('REMOVING CLIP SLOT LISTENERS')

		# iterate over all clip color change callbacks
		for c in self.clip_color_callbacks:
			# if clip still exists
			if c != None:
				# and it has a has clip listener
				if c.color_has_listener(self.clip_color_callbacks[c]) == 1:
					# remove it
					c.remove_color_listener(self.clip_color_callbacks[c])

		# iterate over all clip slot callbacks
		for cs in self.slot_callbacks:
			# if clip slot still exists
			if cs != None:
				# and it has a has clip listener
				if cs.has_clip_has_listener(self.slot_callbacks[cs]) == 1:
					# remove it
					cs.remove_has_clip_listener(self.slot_callbacks[cs])

	def add_slot_listener(self, cs):
		# setting has clip listener
		callback = lambda :self.has_clip_listener(cs)

		# if we don't have a clip slot has clip listener for this clip slot yet
		if not(self.slot_callbacks.has_key(cs)):
			# adding has clip callback to clip slot
			cs.add_has_clip_listener(callback)

			# saving callback for future release
			self.slot_callbacks[cs] = callback

	def add_clip_listener(self, clip):
		# setting callback for clip color change
		color_callback = lambda :self.update_display_clips()

		# if we don't have a clip color change callback for this clip yet
		if not(self.clip_color_callbacks.has_key(clip)):
			# adding clip color change callback
			clip.add_color_listener(color_callback)

			# saving callback for future release
			self.clip_color_callbacks[clip] = color_callback

	def has_clip_listener(self, cs):
		# clip slot has clip listener callback
		if cs.has_clip:
			# add clip listener
			self.add_clip_listener(cs.clip)
		else:
			# update display if clip slot was removed
			self.update_display_clips()

	def session_offset_changed(self):
		# if session component offset changes, update display
		self.update_display_clips()

	def selected_scene_changed(self):
		# if on clip mode update display
		if (self._operation_mode_selector.mode_index==OP1_MODE_CLIP):
			self.update_display_clip_mode()

	def mode_index_changed(self):
		# update display to current mode info
		if (self._operation_mode_selector.mode_index==OP1_MODE_PERFORM):
			self.update_display_perform_mode()
		elif (self._operation_mode_selector.mode_index==OP1_MODE_CLIP):
			self.update_display_clip_mode()
		elif (self._operation_mode_selector.mode_index==OP1_MODE_TRANSPORT):
			self.update_display_transport_mode()
		elif (self._operation_mode_selector.mode_index==OP1_MODE_MIXER):
			self.update_display_mixer_mode()

	def	clear_track_button_callback(self, value):
		# if clear track button was called, reset track
		if (value==127):
			for i in range(len(self.song().tracks)):
				self.song().tracks[i].arm = 0
				self.song().tracks[i].solo = 0
				self.song().tracks[i].mute = 0

			for i in range(len(self.song().return_tracks)):
				self.song().tracks[i].solo = 0
				self.song().tracks[i].mute = 0

	def clear_return_track_assignment(self, strip):
		# clear return track assingments
		strip.set_volume_control(None)
		strip.set_pan_control(None)
		strip.set_mute_button(None)
		strip.set_solo_button(None)
	
	def clear_track_assignment(self, strip):
		# clear track assignments
		strip.set_volume_control(None)
		strip.set_pan_control(None)
		strip.set_mute_button(None)
		strip.set_solo_button(None)
		strip.set_arm_button(None)

	def clear_tracks_assigments(self):
		# for all normal tracks, clear assignments
		for i in range(NUM_TRACKS):
			strip = self._mixer.channel_strip(i)
			if (strip!=None):
				self.clear_track_assignment(strip)

		# for all return tracks, clear assignments
		for i in range(2):
			return_strip = self._mixer.return_strip(i)
			if (return_strip!=None):
				self.clear_return_track_assignment(return_strip)

	def selected_track_changed(self):
		# if on mixer mode update display
		if (self._operation_mode_selector.mode_index==OP1_MODE_MIXER):
			self.update_display_mixer_mode()

		# clear track assignments
		self.clear_tracks_assigments()

		# getting selected strip
		self._channel_strip = self._mixer.selected_strip()

		# perform track assignments 
		self._channel_strip.set_volume_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_1, Live.MidiMap.MapMode.relative_two_compliment))
		self._channel_strip.set_pan_control(EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_2, Live.MidiMap.MapMode.relative_two_compliment))

		# setting a tuple of encoders to control sends
		send_controls = EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_3, Live.MidiMap.MapMode.relative_two_compliment), EncoderElement(MIDI_CC_TYPE, CHANNEL, OP1_ENCODER_4, Live.MidiMap.MapMode.relative_two_compliment),

		# setting send encoders
		self._channel_strip.set_send_controls(tuple(send_controls))

		# setting solo button
		self._channel_strip.set_solo_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS6_BUTTON))

		# if track can be armed, set arm button
		if (self._channel_strip._track.can_be_armed):
			self._channel_strip.set_arm_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS7_BUTTON))

		# if track is no master, set mute button
		if (self._channel_strip._track!=self.song().master_track):
			self._channel_strip.set_mute_button(ButtonElement(True, MIDI_CC_TYPE, CHANNEL, OP1_SS5_BUTTON))


	def browser_toggle_button_callback(self, value):
		if (value==127):
			if (self.session_visible):
				if (self.session_browser_visible==True):
					self.session_browser_visible=False
					self.app.view.hide_view("Browser")
				else:
					self.session_browser_visible=True
					self.app.view.show_view("Browser")

			if (self.arrange_visible):
				if (self.arrange_browser_visible==True):
					self.arrange_browser_visible=False
					self.app.view.hide_view("Browser")
				else:
					self.arrange_browser_visible=True
					self.app.view.show_view("Browser")

	def back_to_arranger_button_callback(self, value):
		if (value==127):
			self.song().back_to_arranger = False

	def mainview_toggle_button_callback(self, value):
		if (value==127):
			if (self.session_visible==True):
				self.session_visible=False
				self.arrange_visible=True
				self.app.view.show_view("Arranger")
				self.arrange_browser_visible = self.app.view.is_view_visible("Browser");
			else:
				self.session_visible=True
				self.arrange_visible=False
				self.app.view.show_view("Session")
				self.session_browser_visible = self.app.view.is_view_visible("Browser");

	def detailview_toggle_button_callback(self, value):
		if (value==127):
			if (self.detail_visible==True):
				self.detail_visible=False
				self.app.view.hide_view("Detail")
			else:
				self.detail_visible=True
				self.app.view.show_view("Detail")

	def write_text(self, msg):
		text_list = []
		sequence = ()
		
		text_list.append(len(msg.strip()))
		
		for i in msg.strip():
   			text_list.append(ord(i))
   		
   		sequence = self.text_start_sequence + tuple(text_list) + self.text_end_sequence
		
		self._send_midi(sequence)

	def suggest_input_port(self):
		return "OP-1 Midi Device"

	def suggest_output_port(self):
		return "OP-1 Midi Device"

	def update_display_perform_mode(self):
		self.write_text("perform\rmode")

	def reset_display_clips(self):
		count = 0
		colors = []
		length = []
		sequence = ()
		
		for i in range (NUM_TRACKS):
			count+=1

			colors.append(0x00)
			colors.append(0x00)
			colors.append(0x00)

		length.append(count)
		sequence = self.text_color_start_sequence + tuple(length) + tuple(colors) + self.text_end_sequence
		self._send_midi(sequence)

	def update_display_clips(self):
		#self.log("UPDATING DISPLAY CLIPS")
		count = 0
		colors = []
		length = []
		sequence = ()
		
		tracks_len = len(self.song().tracks)-self._session._track_offset

		if (tracks_len>NUM_TRACKS):
			tracks_len = NUM_TRACKS

		for i in range (tracks_len):
			count+=1

			clip_slot = self._session.scene(0).clip_slot(i)
			
			if (clip_slot!=None):
				if (clip_slot.has_clip()!=False):
					clip_color = clip_slot._clip_slot.clip.color
					colors.append(((clip_color>>16)&0x000000ff)>>1)
					colors.append(((clip_color>>8)&0x000000ff)>>1)
					colors.append((clip_color&0x000000ff)>>1)
				else:
					colors.append(0x00)
					colors.append(0x00)
					colors.append(0x00)
			else:
				colors.append(0x00)
				colors.append(0x00)
				colors.append(0x00)

		length.append(count)
		sequence = self.text_color_start_sequence + tuple(length) + tuple(colors) + self.text_end_sequence
		self._send_midi(sequence)

	def update_display_clip_mode(self):
		self.write_text("sel. scene\r" + str(self.song().view.selected_scene.name.lower().strip()))

	def update_display_transport_mode(self):
		song_time = str(self.song().get_current_beats_song_time())
		self.write_text("song pos.\r" + song_time[:len(song_time)-4])

	def update_display_mixer_mode(self):
		self.write_text("sel. track\r" + str(self.song().view.selected_track.name.lower()))

	def update_display(self):
		if not(self.device_connected):
			if (self.retries_count<5):
				self.log("TRYING OP-1 CONNECTION")
				self.retries_count+=1
				self._send_midi(self.id_sequence)
				time.sleep(1)

		# if in transport mode, update display with song position
		if (self._operation_mode_selector.mode_index==OP1_MODE_TRANSPORT):
			self.update_display_transport_mode()

		# checking if app current view is session
		if (self.app.view.is_view_visible("Session")):
			# checking if session browser state is diferent from the internal
			if (self.session_browser_visible != self.app.view.is_view_visible("Browser")):
				self.session_browser_visible = self.app.view.is_view_visible("Browser")

		# checking if app current view is arrange
		if (self.app.view.is_view_visible("Arranger")):
			# checking if arrange browser state is diferent from the internal
			if (self.arrange_browser_visible != self.app.view.is_view_visible("Browser")):
				self.arrange_browser_visible = self.app.view.is_view_visible("Browser")

		# checking if app current view is detail
		if (self.app.view.is_view_visible("Detail")):
			# checking if detail state is diferent from the internal
			if (self.detail_visible != self.app.view.is_view_visible("Detail")):
				self.detail_visible = self.app.view.is_view_visible("Detail")

	def refresh_state(self):
		self.log("REFRESH STATE")
		self.retries_count = 0
		self.device_connected = False

	def build_midi_map(self, midi_map_handle):
		#self.log("BUILD MIDI MAP")

		assert (self._suppress_requests_counter == 0)
		self._in_build_midi_map = True
		self._midi_map_handle = midi_map_handle
		self._forwarding_registry = {}
		for control in self.controls:
			if isinstance(control, InputControlElement):
				control.install_connections()
		self._midi_map_handle = None
		self._in_build_midi_map = False
		if (self._pad_translations != None):
			self._c_instance.set_pad_translation(self._pad_translations)

		# remove clip listeners
		self.rem_clip_slot_listeners()
		
		# add clip listeners
		self.add_clip_slot_listeners()
		
		# update display
		self.update_display_clips()
		
	def log(self, msg):
		self.c_instance.log_message("[TE OP-1] " + msg)

	def disconnect(self):
		# removing clip slots listeners
		self.rem_clip_slot_listeners()

		# removing value listener for track changed
		self.song().view.remove_selected_track_listener(self.selected_track_changed)

		# removing value listener for scene changed
		self.song().view.remove_selected_scene_listener(self.selected_scene_changed)

		# removing value listener for operation mode index
		self._operation_mode_selector.remove_mode_index_listener(self.mode_index_changed)

		# removing global transport assignments
		self._transport.set_punch_buttons(None, None)
		self._transport.set_loop_button(None)
		self._transport.set_overdub_button(None)
		self._transport.set_record_button(None)
		self._transport.set_play_button(None)
		self._transport.set_stop_button(None)  
		self._transport.set_metronome_button(None)  
		self._transport.set_tap_tempo_button(None)

		# removing global session assignments
		self._session.set_scene_bank_buttons(None, None)
		
		# removing misc listeners
		self.browser_toggle_button.remove_value_listener(self.browser_toggle_button_callback)
		self.mainview_toggle_button.remove_value_listener(self.mainview_toggle_button_callback)
		self.detailview_toggle_button.remove_value_listener(self.detailview_toggle_button_callback)
		self.clear_track_button.remove_value_listener(self.clear_track_button_callback)
		self.back_to_arranger_button.remove_value_listener(self.back_to_arranger_button_callback)
		
		# sending special ableton mode disable sequence
		self._send_midi(self.disable_sequence)
		
		# disconnecting control surface
		ControlSurface.disconnect(self)
		
		self.log("DISCONNECTED")