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