예제 #1
0
class DrumGroupComponent(SlideableTouchStripComponent, DrumGroupComponentBase, Messenger):
    """
    Class representing a drum group pads in a matrix.
    """
    drum_matrix = control_matrix(PadControl)

    def __init__(self, *a, **k):
        super(DrumGroupComponent, self).__init__(touch_slideable=self, translation_channel=PAD_FEEDBACK_CHANNEL, dragging_enabled=True, *a, **k)

    position_count = 32
    page_length = 4
    page_offset = 1

    def set_drum_group_device(self, drum_group_device):
        super(DrumGroupComponent, self).set_drum_group_device(drum_group_device)
        self._on_chains_changed.subject = self._drum_group_device
        self.notify_contents()

    @drum_matrix.pressed
    def drum_matrix(self, pad):
        self._on_matrix_pressed(pad)

    @drum_matrix.released
    def drum_matrix(self, pad):
        self._on_matrix_released(pad)

    def set_select_button(self, button):
        self.select_button.set_control_element(button)

    def set_mute_button(self, button):
        self.mute_button.set_control_element(button)

    def set_solo_button(self, button):
        self.solo_button.set_control_element(button)

    def set_quantize_button(self, button):
        self.quantize_button.set_control_element(button)

    def set_delete_button(self, button):
        self.delete_button.set_control_element(button)

    @subject_slot('chains')
    def _on_chains_changed(self):
        self._update_led_feedback()
        self.notify_contents()

    def delete_pitch(self, drum_pad):
        clip = self.song().view.detail_clip
        if clip:
            loop_length = clip.loop_end - clip.loop_start
            clip.remove_notes(clip.loop_start, drum_pad.note, loop_length, 1)
            self.show_notification(MessageBoxText.DELETE_NOTES % drum_pad.name)

    def _update_control_from_script(self):
        super(DrumGroupComponent, self)._update_control_from_script()
        profile = 'default' if self._takeover_drums or self._selected_pads else 'drums'
        for button in self.drum_matrix:
            button.sensitivity_profile = profile
예제 #2
0
class AudioModeComponent(ControlSurfaceComponent):

    matrix = control_matrix(PlayableControl)

    def __init__(self, control_surface=None, *a, **k):
        self._control_surface = control_surface
        self._layout_set = False
        super(AudioModeComponent, self).__init__(*a, **k)

    def set_matrix(self, matrix):
        if not matrix or not self._layout_set:
            self.matrix.set_control_element(matrix)
            for index, button in enumerate(self.matrix):
                button.color = "DefaultButton.Disabled"
                #button.enabled = False
            self._layout_set = bool(matrix)
예제 #3
0
class DrumGroupComponent(ResettableSlideComponent, Slideable):
	__subject_events__ = ('pressed_pads',)
	mute_button = ButtonControl(color='DrumGroup.Mute.Off', pressed_color='DrumGroup.Mute.On', disabled_color='DefaultButton.Disabled')
	solo_button = ButtonControl(color='DrumGroup.Solo.Off', pressed_color='DrumGroup.Solo.On', disabled_color='DefaultButton.Disabled')
	delete_button = ButtonControl(**ACTION_BUTTON_COLORS)
	quantize_button = ButtonControl(**ACTION_BUTTON_COLORS)
	select_button = ButtonControl(color='Misc.Shift', pressed_color='Misc.ShiftOn')
	drum_matrix = control_matrix(PlayableControl)

	@depends(set_pad_translations=None)
	def __init__(self, pitch_deleter, translation_channel = None, set_pad_translations = None, control_surface = None, *a, **k):
		self._pitch_deleter = pitch_deleter
		self._takeover_drums = False
		self._drum_group_device = None
		self._control_surface = control_surface
		self._selected_drum_pad = None
		self._all_drum_pads = []
		self._selected_pads = []
		self._visible_drum_pads = []
		self._translation_channel = translation_channel
		self._coordinate_to_pad_map = {}
		super(DrumGroupComponent, self).__init__(*a, **k)
		self._set_pad_translations = set_pad_translations
		self._on_selected_clip_changed.subject = self._pitch_deleter
		self._layout_set = False

	position_count = 32
	page_length = 4
	page_offset = 1

	def contents_range(self, pmin, pmax):
		pos_count = self.position_count
		first_pos = max(int(pmin - 0.05), 0)
		last_pos = min(int(pmax + 0.2), pos_count)
		return xrange(first_pos, last_pos)

	def contents(self, index):
		drum = self._drum_group_device
		if drum:
			return any(imap(lambda pad: pad.chains, drum.drum_pads[index * 4:index * 4 + 4]))
		return False

	def _get_position(self):
		if self._drum_group_device:
			return self._drum_group_device.view.drum_pads_scroll_position
		return 0

	def _set_position(self, index):
		if not 0 <= index <= 28:
			raise AssertionError
			self._drum_group_device.view.drum_pads_scroll_position = self._drum_group_device and index

	position = property(_get_position, _set_position)

	@property
	def width(self):
		return self.drum_matrix.width if self.drum_matrix.width else 4

	@property
	def height(self):
		return self.drum_matrix.height if self.drum_matrix.height else 4

	@property
	def pressed_pads(self):
		return self._selected_pads

	@property
	def visible_drum_pads(self):
		if self._visible_drum_pads and self._all_drum_pads:
			first_pad = first(self._visible_drum_pads)
			if first_pad:
				size = self.width * self.height
				first_note = first_pad.note
				if first_note > 128 - size:
					size = 128 - first_note
				offset = clamp(first_note, 0, 128 - len(self._visible_drum_pads))
				return self._all_drum_pads[offset:offset + size]
		return []

	def update(self):
		super(DrumGroupComponent, self).update()
		self._set_control_pads_from_script(False)
		self._update_led_feedback()

	def set_drum_matrix(self, matrix):
		if not matrix or not self._layout_set:
			self.drum_matrix.set_control_element(matrix)
			for button in self.drum_matrix:
				button.channel = self._translation_channel

			if self._selected_pads:
				self._selected_pads = []
				self.notify_pressed_pads()
			self._create_and_set_pad_translations()
			self._update_control_from_script()
			self._update_identifier_translations()
			self._layout_set = bool(matrix)
			self._update_led_feedback()

	@subject_slot('selected_clip')
	def _on_selected_clip_changed(self):
		if self.is_enabled():
			self.delete_button.enabled = self._pitch_deleter.can_perform_midi_clip_action()

	def set_drum_group_device(self, drum_group_device):
		if drum_group_device and not drum_group_device.can_have_drum_pads:
			drum_group_device = None
		if drum_group_device != self._drum_group_device:
			self._on_visible_drum_pads_changed.subject = drum_group_device
			drum_group_view = drum_group_device.view if drum_group_device else None
			self._on_selected_drum_pad_changed.subject = drum_group_view
			self._on_drum_pads_scroll_position_changed.subject = drum_group_view
			self._drum_group_device = drum_group_device
			self._update_drum_pad_listeners()
			self._on_selected_drum_pad_changed()
			self._update_identifier_translations()
			super(DrumGroupComponent, self).update()

	def _update_drum_pad_listeners(self):
		"""
		add and remove listeners for visible drum pads, including
		mute and solo state
		"""
		if self._drum_group_device:
			self._all_drum_pads = self._drum_group_device.drum_pads
			self._visible_drum_pads = self._drum_group_device.visible_drum_pads
			self._on_solo_changed.replace_subjects(self._visible_drum_pads)
			self._on_mute_changed.replace_subjects(self._visible_drum_pads)
			self._update_identifier_translations()

	@subject_slot_group('solo')
	def _on_solo_changed(self, pad):
		self._update_led_feedback()

	@subject_slot_group('mute')
	def _on_mute_changed(self, pad):
		self._update_led_feedback()

	def _update_led_feedback(self):
		if self._drum_group_device:
			soloed_pads = find_if(lambda pad: pad.solo, self._all_drum_pads)
			for button in self.drum_matrix:
				pad = self._coordinate_to_pad_map.get(button.coordinate, None)
				if pad:
					self._update_pad_led(pad, button, soloed_pads)


	def _gong_get_pad_color(self, pad, button):
		# log("Yo pad: {} {} {} {}", pad.name, button, dir(pad), dir(button))
		# <DrumPad.DrumPad object at 0x120372e20> ['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_live_ptr', 'add_chains_listener', 'add_mute_listener', 'add_name_listener', 'add_solo_listener', 'canonical_parent', 'chains', 'chains_has_listener', 'delete_all_chains', 'mute', 'mute_has_listener', 'name', 'name_has_listener', 'note', 'remove_chains_listener', 'remove_mute_listener', 'remove_name_listener', 'remove_solo_listener', 'solo', 'solo_has_listener']
		# <_Framework.Control.State object at 0x12036e150> ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_channel', '_color', '_control_element', '_delay_task', '_disabled_color', '_enabled', '_event_listener_required', '_event_listeners', '_get_channel', '_get_color', '_get_disabled_color', '_get_enabled', '_get_identifier', '_get_pressed_color', '_has_delayed_event', '_identifier', '_is_pressed', '_manager', '_notifications_enabled', '_on_pressed_delayed', '_on_value', '_playable', '_press_button', '_pressed_color', '_pressed_delayed_listener', '_pressed_listener', '_register_value_slot', '_registered_disconnectables', '_release_button', '_released_delayed_listener', '_released_immediately_listener', '_released_listener', '_repeat', '_repeat_task', '_send_current_color', '_set_channel', '_set_color', '_set_disabled_color', '_set_enabled', '_set_identifier', '_set_pressed_color', '_update_script_forwarding', '_value_listener', '_value_slot', 'channel', 'color', 'coordinate', 'disabled_color', 'disconnect', 'disconnect_disconnectable', 'enabled', 'find_disconnectable', 'has_disconnectable', 'identifier', 'index', 'is_momentary', 'is_pressed', 'pressed_color', 'register_disconnectable', 'register_slot', 'register_slot_manager', 'set_control_element', 'set_playable', 'unregister_disconnectable', 'update']
		# log("Yo pad: {}", pad.name)
		name = pad.name.lower()
		# if self.SNARE_RX.match(name):
		for x in Colors.DrumGroup.GONG_PADS:
			if x in name:
				return 'DrumGroup.%s' % x
		return 'DrumGroup.PadFilled'

	def _update_pad_led(self, pad, button, soloed_pads):
		button_color = 'DrumGroup.PadEmpty'
		"""if pad == self._selected_drum_pad:
			if soloed_pads and not pad.solo and not pad.mute:
				button_color = 'DrumGroup.PadSelectedNotSoloed'
			elif pad.mute and not pad.solo:
				button_color = 'DrumGroup.PadMutedSelected'
			elif soloed_pads and pad.solo:
				button_color = 'DrumGroup.PadSoloedSelected'
			else:
				button_color = 'DrumGroup.PadSelected'"""
		if pad.chains:
			if soloed_pads and not pad.solo:
				if not pad.mute:
					button_color = self._gong_get_pad_color(pad, button)
				else:
					button_color = 'DrumGroup.PadMuted'
			elif not soloed_pads and pad.mute:
				button_color = 'DrumGroup.PadMuted'
			elif soloed_pads and pad.solo:
				button_color = 'DrumGroup.PadSoloed'
			else:
				button_color = self._gong_get_pad_color(pad, button)
		else:
			button_color = 'DrumGroup.PadEmpty'
		button.color = button_color

	def _button_coordinates_to_pad_index(self, first_note, coordinates):
		y, x = coordinates
		y = self.height - y - 1
		if x < 4 and y >= 4:
			first_note += 16
		elif x >= 4 and y < 4:
			first_note += 4 * self.width
		elif x >= 4 and y >= 4:
			first_note += 4 * self.width + 16
		index = x % 4 + y % 4 * 4 + first_note
		return index

	@drum_matrix.pressed
	def drum_matrix(self, pad):
		self._on_matrix_pressed(pad)

	@drum_matrix.released
	def drum_matrix(self, pad):
		self._on_matrix_released(pad)

	def _on_matrix_released(self, pad):
		selected_drum_pad = self._coordinate_to_pad_map[pad.coordinate]
		if selected_drum_pad in self._selected_pads:
			self._selected_pads.remove(selected_drum_pad)
			if not self._selected_pads:
				self._update_control_from_script()
			self.notify_pressed_pads()
		self._update_led_feedback()

	def _on_matrix_pressed(self, pad):
		selected_drum_pad = self._coordinate_to_pad_map[pad.coordinate]
		if self.mute_button.is_pressed:
			selected_drum_pad.mute = not selected_drum_pad.mute
		if self.solo_button.is_pressed:
			selected_drum_pad.solo = not selected_drum_pad.solo
		if self.quantize_button.is_pressed:
			pad.color = 'DrumGroup.PadAction'
			self.quantize_pitch(selected_drum_pad.note)
		if self.delete_button.is_pressed:
			pad.color = 'DrumGroup.PadAction'
			self.delete_pitch(selected_drum_pad)
		if self.select_button.is_pressed:
			self._drum_group_device.view.selected_drum_pad = selected_drum_pad
			self.select_drum_pad(selected_drum_pad)
			self._selected_pads.append(selected_drum_pad)
			if len(self._selected_pads) == 1:
				self._update_control_from_script()
			self.notify_pressed_pads()
		if self.mute_button.is_pressed or self.solo_button.is_pressed:
			self._update_led_feedback()

	@subject_slot('visible_drum_pads')
	def _on_visible_drum_pads_changed(self):
		self._update_drum_pad_listeners()
		self._update_led_feedback()

	@subject_slot('drum_pads_scroll_position')
	def _on_drum_pads_scroll_position_changed(self):
		self._update_identifier_translations()
		self._update_led_feedback()
		self.notify_position()

	@subject_slot('selected_drum_pad')
	def _on_selected_drum_pad_changed(self):
		self._selected_drum_pad = self._drum_group_device.view.selected_drum_pad if self._drum_group_device else None
		self._update_led_feedback()

	@mute_button.value
	def mute_button(self, value, button):
		self._set_control_pads_from_script(bool(value))

	@solo_button.value
	def solo_button(self, value, button):
		self._set_control_pads_from_script(bool(value))

	@delete_button.value
	def delete_button(self, value, button):
		self._set_control_pads_from_script(bool(value))

	@quantize_button.value
	def quantize_button(self, value, button):
		self._set_control_pads_from_script(bool(value))

	@select_button.value
	def select_button(self, value, button):
		self._set_control_pads_from_script(bool(value))

	def _set_control_pads_from_script(self, takeover_drums):
		"""
		If takeover_drums, the matrix buttons will be controlled from
		the script. Otherwise they send midi notes to the track
		associated to this drum group.
		"""
		if takeover_drums != self._takeover_drums:
			self._takeover_drums = takeover_drums
			self._update_control_from_script()

	def _update_control_from_script(self):
		takeover_drums = self._takeover_drums or bool(self._selected_pads)
		for button in self.drum_matrix:
			button.set_playable(not takeover_drums)

	def _update_identifier_translations(self):
		if not self._can_set_pad_translations():
			self._set_non_pad_translated_identifiers()
		else:
			self._set_pad_translated_identifiers()

	def _set_non_pad_translated_identifiers(self):
		visible_drum_pads = self.visible_drum_pads
		if visible_drum_pads:
			for button in self.drum_matrix:
				identifier = self._button_coordinates_to_pad_index(first(visible_drum_pads).note, button.coordinate)
				if identifier < 128:
					button.identifier = identifier
					button.enabled = True
					self._coordinate_to_pad_map[button.coordinate] = self._all_drum_pads[button.identifier]
				else:
					button.enabled = False

	def _set_pad_translated_identifiers(self):
		visible_drum_pads = self.visible_drum_pads
		if visible_drum_pads:
			for index, button in enumerate(self.drum_matrix):
				row, col = button.coordinate
				self._coordinate_to_pad_map[self.width - 1 - row, col] = visible_drum_pads[index]

	def _can_set_pad_translations(self):
		return self.width <= 4 and self.height <= 4

	def _create_and_set_pad_translations(self):

		def create_translation_entry(button):
			row, col = button.coordinate
			button.identifier = self._button_coordinates_to_pad_index(BASE_DRUM_RACK_NOTE, button.coordinate)
			return (col,
			 row,
			 button.identifier,
			 button.channel)

		if self._can_set_pad_translations():
			translations = tuple(map(create_translation_entry, self.drum_matrix))
			self._set_pad_translated_identifiers()
		else:
			translations = None
			self._set_non_pad_translated_identifiers()
		self._set_pad_translations(translations)

	def select_drum_pad(self, drum_pad):
		""" Override when you give it a select button """
		pass

	def quantize_pitch(self, note):
		""" Override when you give it a quantize button """
		raise NotImplementedError

	def delete_pitch(self, drum_pad):
		self._pitch_deleter.delete_pitch(drum_pad.note)
예제 #4
0
class DrumGroupComponent(ResettableSlideComponent, Slideable):
    __subject_events__ = ('pressed_pads', )
    mute_button = ButtonControl()
    solo_button = ButtonControl()
    delete_button = ButtonControl(**ACTION_BUTTON_COLORS)
    quantize_button = ButtonControl()
    select_button = ButtonControl(color=b'Misc.Shift', pressed_color=b'Misc.ShiftOn')
    drum_matrix = control_matrix(PlayableControl)

    @depends(set_pad_translations=None)
    def __init__(self, pitch_deleter, translation_channel=None, set_pad_translations=None, *a, **k):
        self._pitch_deleter = pitch_deleter
        self._takeover_drums = False
        self._drum_group_device = None
        self._selected_drum_pad = None
        self._all_drum_pads = []
        self._selected_pads = []
        self._visible_drum_pads = []
        self._translation_channel = translation_channel
        self._coordinate_to_pad_map = {}
        super(DrumGroupComponent, self).__init__(*a, **k)
        self._set_pad_translations = set_pad_translations
        self._on_selected_clip_changed.subject = self._pitch_deleter
        self._layout_set = False
        return

    position_count = 32
    page_length = 4
    page_offset = 1

    def contents_range(self, pmin, pmax):
        pos_count = self.position_count
        first_pos = max(int(pmin - 0.05), 0)
        last_pos = min(int(pmax + 0.2), pos_count)
        return xrange(first_pos, last_pos)

    def contents(self, index):
        drum = self._drum_group_device
        if drum:
            return any(imap(lambda pad: pad.chains, drum.drum_pads[index * 4:index * 4 + 4]))
        return False

    def _get_position(self):
        if self._drum_group_device:
            return self._drum_group_device.view.drum_pads_scroll_position
        return 0

    def _set_position(self, index):
        assert 0 <= index <= 28
        if self._drum_group_device:
            self._drum_group_device.view.drum_pads_scroll_position = index

    position = property(_get_position, _set_position)

    @property
    def width(self):
        if self.drum_matrix.width:
            return self.drum_matrix.width
        return 4

    @property
    def height(self):
        if self.drum_matrix.height:
            return self.drum_matrix.height
        return 4

    @property
    def pressed_pads(self):
        return self._selected_pads

    @property
    def visible_drum_pads(self):
        if self._visible_drum_pads and self._all_drum_pads:
            first_pad = first(self._visible_drum_pads)
            if first_pad:
                size = self.width * self.height
                first_note = first_pad.note
                if first_note > 128 - size:
                    size = 128 - first_note
                offset = clamp(first_note, 0, 128 - len(self._visible_drum_pads))
                return self._all_drum_pads[offset:offset + size]
        return []

    def update(self):
        super(DrumGroupComponent, self).update()
        self._set_control_pads_from_script(False)
        self._update_led_feedback()

    def set_drum_matrix(self, matrix):
        if not matrix or not self._layout_set:
            self.drum_matrix.set_control_element(matrix)
            for button in self.drum_matrix:
                button.channel = self._translation_channel

            if self._selected_pads:
                self._selected_pads = []
                self.notify_pressed_pads()
            self._create_and_set_pad_translations()
            self._update_control_from_script()
            self._update_identifier_translations()
            self._layout_set = bool(matrix)
            self._update_led_feedback()

    @subject_slot(b'selected_clip')
    def _on_selected_clip_changed(self):
        if self.is_enabled():
            self.delete_button.enabled = self._pitch_deleter.can_perform_midi_clip_action()

    def set_drum_group_device(self, drum_group_device):
        if drum_group_device and not drum_group_device.can_have_drum_pads:
            drum_group_device = None
        if drum_group_device != self._drum_group_device:
            self._on_visible_drum_pads_changed.subject = drum_group_device
            drum_group_view = drum_group_device.view if drum_group_device else None
            self._on_selected_drum_pad_changed.subject = drum_group_view
            self._on_drum_pads_scroll_position_changed.subject = drum_group_view
            self._drum_group_device = drum_group_device
            self._update_drum_pad_listeners()
            self._on_selected_drum_pad_changed()
            self._update_identifier_translations()
            super(DrumGroupComponent, self).update()
        return

    def _update_drum_pad_listeners(self):
        """
        add and remove listeners for visible drum pads, including
        mute and solo state
        """
        if self._drum_group_device:
            self._all_drum_pads = self._drum_group_device.drum_pads
            self._visible_drum_pads = self._drum_group_device.visible_drum_pads
            self._on_solo_changed.replace_subjects(self._visible_drum_pads)
            self._on_mute_changed.replace_subjects(self._visible_drum_pads)
            self._update_identifier_translations()

    @subject_slot_group(b'solo')
    def _on_solo_changed(self, pad):
        self._update_led_feedback()

    @subject_slot_group(b'mute')
    def _on_mute_changed(self, pad):
        self._update_led_feedback()

    def _update_led_feedback(self):
        if self._drum_group_device:
            soloed_pads = find_if(lambda pad: pad.solo, self._all_drum_pads)
            for button in self.drum_matrix:
                pad = self._coordinate_to_pad_map.get(button.coordinate, None)
                if pad:
                    self._update_pad_led(pad, button, soloed_pads)

        return

    def _update_pad_led(self, pad, button, soloed_pads):
        button_color = b'DrumGroup.PadEmpty'
        if pad == self._selected_drum_pad:
            if soloed_pads and not pad.solo and not pad.mute:
                button_color = b'DrumGroup.PadSelectedNotSoloed'
            elif pad.mute and not pad.solo:
                button_color = b'DrumGroup.PadMutedSelected'
            elif soloed_pads and pad.solo:
                button_color = b'DrumGroup.PadSoloedSelected'
            else:
                button_color = b'DrumGroup.PadSelected'
        elif pad.chains:
            if soloed_pads and not pad.solo:
                if not pad.mute:
                    button_color = b'DrumGroup.PadFilled'
                else:
                    button_color = b'DrumGroup.PadMuted'
            elif not soloed_pads and pad.mute:
                button_color = b'DrumGroup.PadMuted'
            elif soloed_pads and pad.solo:
                button_color = b'DrumGroup.PadSoloed'
            else:
                button_color = b'DrumGroup.PadFilled'
        else:
            button_color = b'DrumGroup.PadEmpty'
        button.color = button_color

    def _button_coordinates_to_pad_index(self, first_note, coordinates):
        y, x = coordinates
        y = self.height - y - 1
        if x < 4 and y >= 4:
            first_note += 16
        elif x >= 4 and y < 4:
            first_note += 4 * self.width
        elif x >= 4 and y >= 4:
            first_note += 4 * self.width + 16
        index = x % 4 + y % 4 * 4 + first_note
        return index

    @drum_matrix.pressed
    def drum_matrix(self, pad):
        self._on_matrix_pressed(pad)

    @drum_matrix.released
    def drum_matrix(self, pad):
        self._on_matrix_released(pad)

    def _on_matrix_released(self, pad):
        selected_drum_pad = self._coordinate_to_pad_map[pad.coordinate]
        if selected_drum_pad in self._selected_pads:
            self._selected_pads.remove(selected_drum_pad)
            if not self._selected_pads:
                self._update_control_from_script()
            self.notify_pressed_pads()
        self._update_led_feedback()

    def _on_matrix_pressed(self, pad):
        selected_drum_pad = self._coordinate_to_pad_map[pad.coordinate]
        if self.mute_button.is_pressed:
            selected_drum_pad.mute = not selected_drum_pad.mute
        if self.solo_button.is_pressed:
            selected_drum_pad.solo = not selected_drum_pad.solo
        if self.quantize_button.is_pressed:
            pad.color = b'DrumGroup.PadAction'
            self.quantize_pitch(selected_drum_pad.note)
        if self.delete_button.is_pressed:
            pad.color = b'DrumGroup.PadAction'
            self.delete_pitch(selected_drum_pad)
        if self.select_button.is_pressed:
            self._drum_group_device.view.selected_drum_pad = selected_drum_pad
            self.select_drum_pad(selected_drum_pad)
            self._selected_pads.append(selected_drum_pad)
            if len(self._selected_pads) == 1:
                self._update_control_from_script()
            self.notify_pressed_pads()
        if self.mute_button.is_pressed or self.solo_button.is_pressed:
            self._update_led_feedback()

    @subject_slot(b'visible_drum_pads')
    def _on_visible_drum_pads_changed(self):
        self._update_drum_pad_listeners()
        self._update_led_feedback()

    @subject_slot(b'drum_pads_scroll_position')
    def _on_drum_pads_scroll_position_changed(self):
        self._update_identifier_translations()
        self._update_led_feedback()
        self.notify_position()

    @subject_slot(b'selected_drum_pad')
    def _on_selected_drum_pad_changed(self):
        self._selected_drum_pad = self._drum_group_device.view.selected_drum_pad if self._drum_group_device else None
        self._update_led_feedback()
        return

    @mute_button.value
    def mute_button(self, value, button):
        self._set_control_pads_from_script(bool(value))

    @solo_button.value
    def solo_button(self, value, button):
        self._set_control_pads_from_script(bool(value))

    @delete_button.value
    def delete_button(self, value, button):
        self._set_control_pads_from_script(bool(value))

    @quantize_button.value
    def quantize_button(self, value, button):
        self._set_control_pads_from_script(bool(value))

    @select_button.value
    def select_button(self, value, button):
        self._set_control_pads_from_script(bool(value))

    def _set_control_pads_from_script(self, takeover_drums):
        """
        If takeover_drums, the matrix buttons will be controlled from
        the script. Otherwise they send midi notes to the track
        associated to this drum group.
        """
        if takeover_drums != self._takeover_drums:
            self._takeover_drums = takeover_drums
            self._update_control_from_script()

    def _update_control_from_script(self):
        takeover_drums = self._takeover_drums or bool(self._selected_pads)
        for button in self.drum_matrix:
            button.set_playable(not takeover_drums)

    def _update_identifier_translations(self):
        if not self._can_set_pad_translations():
            self._set_non_pad_translated_identifiers()
        else:
            self._set_pad_translated_identifiers()

    def _set_non_pad_translated_identifiers(self):
        visible_drum_pads = self.visible_drum_pads
        if visible_drum_pads:
            for button in self.drum_matrix:
                identifier = self._button_coordinates_to_pad_index(first(visible_drum_pads).note, button.coordinate)
                if identifier < 128:
                    button.identifier = identifier
                    button.enabled = True
                    self._coordinate_to_pad_map[button.coordinate] = self._all_drum_pads[button.identifier]
                else:
                    button.enabled = False

    def _set_pad_translated_identifiers(self):
        visible_drum_pads = self.visible_drum_pads
        if visible_drum_pads:
            for index, button in enumerate(self.drum_matrix):
                row, col = button.coordinate
                self._coordinate_to_pad_map[(self.width - 1 - row, col)] = visible_drum_pads[index]

    def _can_set_pad_translations(self):
        return self.width <= 4 and self.height <= 4

    def _create_and_set_pad_translations(self):

        def create_translation_entry(button):
            row, col = button.coordinate
            button.identifier = self._button_coordinates_to_pad_index(BASE_DRUM_RACK_NOTE, button.coordinate)
            return (
             col, row, button.identifier, button.channel)

        if self._can_set_pad_translations():
            translations = tuple(map(create_translation_entry, self.drum_matrix))
            self._set_pad_translated_identifiers()
        else:
            translations = None
            self._set_non_pad_translated_identifiers()
        self._set_pad_translations(translations)
        return

    def select_drum_pad(self, drum_pad):
        """ Override when you give it a select button """
        pass

    def quantize_pitch(self, note):
        """ Override when you give it a quantize button """
        raise NotImplementedError

    def delete_pitch(self, drum_pad):
        self._pitch_deleter.delete_pitch(drum_pad.note)
예제 #5
0
class APCDrumGroupComponent(DrumGroupComponent, APCMessenger):
  """ Customized to use its own feedback channel """

  """
  Class representing a drum group pads in a matrix.
  """  
  
  matrix = control_matrix(PadControl)  # switched 10/17
  
#  drum_matrix = control_matrix(PadControl)      # added
  
  
  #switched 10/17
  def __init__(self, *a, **k):
      super(DrumGroupComponent, self).__init__(touch_slideable=self, translation_channel=DRUM_FEEDBACK_CHANNEL, dragging_enabled=True, *a, **k)

  position_count = 32
  page_length = 4
  page_offset = 1 
 
  def set_drum_group_device(self, drum_group_device):
    super(DrumGroupComponent, self).set_drum_group_device(drum_group_device)
    self._on_chains_changed.subject = self._drum_group_device
    self.notify_contents() 
 
 # untill here 10/17
 
 
 
 # def set_drum_matrix(self, matrix): 
 #   "Added from cylabs APsequencer_master/APCDrumGroupComponent "    # added to stop log error
 #   self.drum_matrix.set_control_element(matrix)
 #   for button in self.drum_matrix:
 #     button.channel = PAD_FEEDBACK_CHANNEL  
  
  
  #added temp to sort select button 
  
  
#  @drum_matrix.pressed
#  def drum_matrix(self, pad):
#      self._on_matrix_pressed(pad)

#  @drum_matrix.released
#  def drum_matrix(self, pad):
#      self._on_matrix_released(pad)  
  
  
  @matrix.pressed                                # switched 10/17
  def matrix(self, pad):
      self._on_matrix_pressed(pad)
      
  @matrix.released
  def matrix(self, pad):
      self._on_matrix_released(pad)  
  
  
  
  
  
  
  
  def set_select_button(self, button):
    self.select_button.set_control_element(button)  
  
  def set_delete_button(self, button):
    self.delete_button.set_control_element(button)  
  
  
 

  @subject_slot('chains')         # added 10/17
  def _on_chains_changed(self):
      self._update_led_feedback()
      self.notify_contents() 
 
 
  # not sure if needed   10/17
  
  def delete_pitch(self, drum_pad):
      clip = self.song().view.detail_clip
      if clip:
          loop_length = clip.loop_end - clip.loop_start
          clip.remove_notes(clip.loop_start, drum_pad.note, loop_length, 1)
      #    self.show_notification(MessageBoxText.DELETE_NOTES % drum_pad.name)   # im assuming push display for this line  10/17
 
 
 
 

  
  def _update_control_from_script(self):
    super(DrumGroupComponent, self)._update_control_from_script()
    profile = 'default' if self._takeover_drums or self._selected_pads else 'drums'
    for button in self.drum_matrix:
      button.sensitivity_profile = profile  
예제 #6
0
class NoteComponent(ControlSurfaceComponent):

    matrix = control_matrix(PlayableControl)

    def __init__(self,
                 control_surface=None,
                 feedback_channels=[0, 1, 2],
                 non_feedback_channel=15,
                 get_pattern=None,
                 *a,
                 **k):
        self._get_pattern = get_pattern
        self._control_surface = control_surface
        self._layout_set = False
        self._non_feedback_channel = non_feedback_channel
        self._feedback_channels = feedback_channels
        super(NoteComponent, self).__init__(*a, **k)

    def update_matrix_mapping(self, playable=False):
        pattern = self._get_pattern()
        max_j = 8 - 1  #self.matrix.width - 1
        note_channel = [0 for i in range(128)]

        lala = 1
        for index, button in enumerate(self.matrix):
            row, col = button.coordinate
            note_info = pattern.note(col, max_j - row)
            if note_info.index != None and note_info.index < 128:
                if note_info.root:
                    button.color = "Note.Pads.Root"
                elif note_info.highlight:
                    button.color = "Note.Pads.Highlight"
                elif note_info.in_scale:
                    button.color = "Note.Pads.InScale"
                elif note_info.valid:
                    button.color = "Note.Pads.OutOfScale"
                else:
                    button.color = "Note.Pads.Invalid"
                button.identifier = note_info.index
                button.channel = self._feedback_channels[note_channel[
                    note_info.index]]
                button.set_playable(not playable)
                note_channel[
                    note_info.index] = note_channel[note_info.index] + 1
            else:
                button.identifier = lala
                lala = lala + 1
                button.channel = self._non_feedback_channel
                button.color = "Note.Pads.Invalid"
                button.set_playable(False)

    def set_matrix(self, matrix):
        if not matrix or not self._layout_set:
            self.matrix.set_control_element(matrix)
            self.update_matrix_mapping()
            self._layout_set = bool(matrix)

    # def set_scene_buttons(self, matrix):
    # 		if not matrix or not self._layout_set_scene:
    # 			self.scene_buttons.set_control_element(matrix)
    # 			self._layout_set_scene = bool(matrix)

    @matrix.pressed
    def drum_matrix(self, pad):
        pass
        # selected_drum_pad = self._coordinate_to_pad_map[pad.coordinate]
        # 		if self.mute_button.is_pressed:
        # 			selected_drum_pad.mute = not selected_drum_pad.mute
        # 		if self.solo_button.is_pressed:
        # 			selected_drum_pad.solo = not selected_drum_pad.solo
        # 		if self.quantize_button.is_pressed:
        # 			pad.color = 'DrumGroup.PadAction'
        # 			self.quantize_pitch(selected_drum_pad.note)
        # 		if self.delete_button.is_pressed:
        # 			pad.color = 'DrumGroup.PadAction'
        # 			self.delete_pitch(selected_drum_pad)
        # 		if self.select_button.is_pressed:
        # 			self._drum_group_device.view.selected_drum_pad = selected_drum_pad
        # 			self.select_drum_pad(selected_drum_pad)
        # 			self._selected_pads.append(selected_drum_pad)
        # 			if len(self._selected_pads) == 1:
        # 				self._update_control_from_script()
        # 			self.notify_pressed_pads()
        # 		if self.mute_button.is_pressed or self.solo_button.is_pressed:
        # 			self._update_led_feedback()

    @matrix.released
    def drum_matrix(self, pad):
        pass