def selected_target_note(self):
     slices = list(self._slices())
     selected_slice = self._selected_slice()
     if selected_slice in slices:
         return NamedTuple(note=BASE_SLICING_NOTE +
                           slices.index(selected_slice),
                           channel=PAD_FEEDBACK_CHANNEL)
     return NamedTuple(note=-1, channel=-1)
 def __init__(self,
              device_bank_registry=None,
              banking_info=None,
              info_layer=None,
              delete_handler=None,
              session_ring=None,
              *a,
              **k):
     super(DeviceNavigationComponent, self).__init__(*a, **k)
     self._make_navigation_node = partial(
         make_navigation_node,
         session_ring=session_ring,
         device_bank_registry=device_bank_registry,
         banking_info=banking_info)
     self._delete_handler = delete_handler
     self._updating_children = BooleanContext()
     self._device_list = self.register_component(
         ScrollableListWithTogglesComponent())
     self._on_selection_clicked_in_controller.subject = self._device_list
     self._on_selection_changed_in_controller.subject = self._device_list
     self._on_state_changed_in_controller.subject = self._device_list
     self._current_node = None
     self._message_box = self.register_component(
         MessageBoxComponent(layer=info_layer, is_enabled=False))
     self._message_box.text = consts.MessageBoxText.EMPTY_DEVICE_CHAIN
     self._selected_track = None
     self._on_selected_track_changed.subject = self.song.view
     with inject(selection=const(NamedTuple(
             selected_device=None))).everywhere():
         self._on_selected_track_changed()
     self._on_device_parameters_changed.subject = self._selected_track.view.selected_device
     return
 def selected_target_note(self):
     note_and_channel = (-1, -1)
     if liveobj_valid(self._drum_group_device) and liveobj_valid(self._selected_drum_pad):
         if self._selected_drum_pad in self.assigned_drum_pads:
             predicate = lambda b: self._pad_for_button(b) == self._selected_drum_pad
             button = find_if(predicate, self.matrix)
             if button != None and None not in (button.identifier, button.channel):
                 note_and_channel = (
                  button.identifier, button.channel)
         else:
             note_and_channel = (
              self._selected_drum_pad.note, NON_FEEDBACK_CHANNEL)
     return NamedTuple(note=note_and_channel[0], channel=note_and_channel[1])
 def selected_target_note(self):
     return NamedTuple(note=-1, channel=-1)
 def _create_items(self):
     bank_names = self.internal_bank_names(self._banking_info.device_bank_names(self._device))
     return [ (NamedTuple(name=b), 0) for b in bank_names ]
class DeviceNavigationComponent(Component):

    @depends(device_provider=None)
    def __init__(self, device_bank_registry=None, banking_info=None, info_layer=None, delete_handler=None, session_ring=None, device_provider=None, *a, **k):
        (super(DeviceNavigationComponent, self).__init__)(*a, **k)
        self._make_navigation_node = partial(make_navigation_node,
          session_ring=session_ring,
          device_bank_registry=device_bank_registry,
          banking_info=banking_info,
          device_provider=device_provider)
        self._delete_handler = delete_handler
        self._updating_children = BooleanContext()
        self._device_list = ScrollableListWithTogglesComponent(parent=self)
        self._on_selection_clicked_in_controller.subject = self._device_list
        self._on_selection_changed_in_controller.subject = self._device_list
        self._on_state_changed_in_controller.subject = self._device_list
        self._current_node = None
        self._message_box = MessageBoxComponent(parent=self,
          layer=info_layer,
          is_enabled=False)
        self._message_box.text = consts.MessageBoxText.EMPTY_DEVICE_CHAIN
        self._selected_track = None
        self._on_selected_track_changed.subject = self.song.view
        with inject(selection=(const(NamedTuple(selected_device=None)))).everywhere():
            self._on_selected_track_changed()
        self._on_device_parameters_changed.subject = self._selected_track.view.selected_device

    @property
    def current_node(self):
        return self._current_node

    def set_select_buttons(self, select_buttons):
        self._device_list.set_select_buttons(select_buttons)

    def set_state_buttons(self, state_buttons):
        self._device_list.set_state_buttons(state_buttons)

    def set_exit_button(self, exit_button):
        self._on_exit_value.subject = exit_button
        self._update_exit_button()

    def set_enter_button(self, enter_button):
        self._on_enter_value.subject = enter_button
        self._update_enter_button()

    def set_display_line(self, line):
        self._device_list.set_display_line(line)

    def set_blank_display_line(self, line):
        if line:
            line.reset()

    @property
    def selected_object(self):
        selected = None
        if self._current_node:
            children = self._current_node.children
            option = self._device_list.selected_option
            if children:
                if in_range(option, 0, len(children)):
                    _, selected = children[option]
        return selected

    def back_to_top(self):
        if consts.PROTO_SONG_IS_ROOT:
            self._set_current_node(self._make_navigation_node(self.song))
        else:
            self._set_current_node(self._make_navigation_node(self._selected_track))

    @listens('selected_track')
    def _on_selected_track_changed(self):
        self._selected_track = self.song.view.selected_track
        self._on_selected_device_changed.subject = self._selected_track.view
        self.back_to_top()

    @listens('selected_device')
    def _on_selected_device_changed(self):
        selected_device = self._selected_track.view.selected_device
        if selected_device == None:
            self._set_current_node(self._make_exit_node())
            return
        is_just_default_child_selection = False
        if self._current_node:
            if self._current_node.children:
                selected = self.selected_object
                if isinstance(selected, Live.DrumPad.DrumPad):
                    if is_first_device_on_pad(selected_device, selected):
                        is_just_default_child_selection = True
                if isinstance(selected, Live.Chain.Chain):
                    if selected_device:
                        if selected_device.canonical_parent == selected:
                            if selected.devices[0] == selected_device:
                                is_just_default_child_selection = True
        if not is_just_default_child_selection:
            target = selected_device and selected_device.canonical_parent
            if not self._current_node or self._current_node.object != target:
                node = self._make_navigation_node(target, is_entering=False)
                self._set_current_node(node)
        self._on_device_parameters_changed.subject = selected_device

    @listens('parameters')
    def _on_device_parameters_changed(self):
        self._update_enter_button()
        self._update_exit_button()

    def _set_current_node(self, node):
        if node is None:
            return
        self.disconnect_disconnectable(self._current_node)
        self._current_node = node
        self.register_disconnectable(node)
        self._on_children_changed_in_node.subject = node
        self._on_selected_child_changed_in_node.subject = node
        self._on_state_changed_in_node.subject = node
        self._on_children_changed_in_node()
        for index, value in enumerate(node.state):
            self._on_state_changed_in_node(index, value)

        node.preselect()

    @depends(selection=(lambda: NamedTuple(selected_device=None)))
    def _update_info(self, selection=None):
        if liveobj_valid(self._selected_track) and len(self._selected_track.devices) == 0 and selection.selected_device == None:
            self._message_box.set_enabled(True)
        else:
            self._message_box.set_enabled(False)

    def update(self):
        super(DeviceNavigationComponent, self).update()
        if self.is_enabled():
            self._update_enter_button()
            self._update_exit_button()
            self._update_info()

    @contextmanager
    def _deactivated_option_listener(self):
        old_subject = self._on_state_changed_in_controller.subject
        self._on_state_changed_in_controller.subject = None
        (yield)
        self._on_state_changed_in_controller.subject = old_subject

    @listens('state')
    def _on_state_changed_in_node(self, index, value):
        with self._deactivated_option_listener():
            self._device_list.set_option_state(index, value)

    @listens('children')
    def _on_children_changed_in_node(self):
        if self._updating_children:
            return
        with self._updating_children():
            if not self._current_node.children:
                self.back_to_top()
            names = [x[0] for x in self._current_node.children]
            self._device_list.option_names = names
            self._device_list.selected_option = self._current_node.selected_child
            self._update_enter_button()
            self._update_exit_button()

    @listens('selected_child')
    def _on_selected_child_changed_in_node(self, index):
        self._device_list.selected_option = index
        self._update_enter_button()
        self._update_exit_button()
        self._update_info()

    @property
    def _is_deleting(self):
        return self._delete_handler and self._delete_handler.is_deleting

    @listens('toggle_option')
    def _on_state_changed_in_controller(self, index, value):
        if self._current_node:
            if self._is_deleting:
                _, child = self._current_node.children[index]
                if not child != None or isinstance(child, Live.Device.Device):
                    self._delete_handler.delete_clip_envelope(child.parameters[0])
            else:
                self._current_node.set_state(index, value)
            if self._current_node.state[index] != value:
                with self._deactivated_option_listener():
                    self._device_list.set_option_state(index, self._current_node.state[index])

    @listens('change_option')
    def _on_selection_changed_in_controller(self, value):
        self._current_node.selected_child = value
        self._update_hotswap_target()
        self._update_enter_button()
        self._update_exit_button()

    @listens('press_option', in_front=True)
    def _on_selection_clicked_in_controller(self, index):
        if self._is_deleting:
            if self._current_node:
                self._current_node.delete_child(index)
            return True
        if consts.PROTO_FAST_DEVICE_NAVIGATION:
            if self._device_list.selected_option == index:
                self._set_current_node(self._make_enter_node())
                return True
            if not in_range(index, 0, len(self._device_list.option_names)):
                self._set_current_node(self._make_exit_node())
                return True
            return index == None

    @listens('value')
    def _on_enter_value(self, value):
        if self.is_enabled():
            self._update_enter_button()
            if value:
                self._set_current_node(self._make_enter_node())
                self._update_hotswap_target()

    @listens('value')
    def _on_exit_value(self, value):
        if self.is_enabled():
            self._update_exit_button()
            if value:
                self._set_current_node(self._make_exit_node())
                self._update_hotswap_target()

    def _update_hotswap_target(self):
        try:
            browser = self.application.browser
            if liveobj_valid(self.selected_object):
                if liveobj_valid(browser.hotswap_target):
                    browser.hotswap_target = self.selected_object
        except RuntimeError:
            pass

    def _make_enter_node(self):
        if self._device_list.selected_option is not None:
            if self._device_list.selected_option >= 0:
                if self._device_list.selected_option < len(self._current_node.children):
                    child = self._current_node.children[self._device_list.selected_option][1]
                    return self._make_navigation_node(child, is_entering=True)

    def _make_exit_node(self):
        return self._make_navigation_node((self._current_node and self._current_node.parent),
          is_entering=False)

    def _update_enter_button(self):
        button = self._on_enter_value.subject
        if self.is_enabled():
            if button:
                with disconnectable(self._make_enter_node()) as node:
                    button.set_light('DefaultButton.On' if node else 'DefaultButton.Disabled')

    def _update_exit_button(self):
        button = self._on_exit_value.subject
        if self.is_enabled():
            if button:
                with disconnectable(self._make_exit_node()) as node:
                    button.set_light('DefaultButton.On' if node else 'DefaultButton.Disabled')
Esempio n. 7
0
 def items(self):
     nesting_level = 0
     bank_names = self.internal_bank_names(
         self._banking_info.device_bank_names(self._device))
     return [(NamedTuple(name=b), nesting_level) for b in bank_names]