示例#1
0
 def __init__(self, tracks_provider=None, trigger_recording_on_release_callback=nop, color_chooser=None, clip_phase_enabler=None, *a, **k):
     assert tracks_provider is not None
     super(TrackListComponent, self).__init__(*a, **k)
     self.locked_mode = None
     self._button_handler = self._select_mixable
     self._button_feedback_provider = mixable_button_color
     self._color_chooser = color_chooser
     self._track_selected_when_pressed = [
      False] * self.track_action_buttons.control_count
     self._playheads_real_time_data = [ RealTimeDataComponent(parent=self, channel_type='playhead', is_enabled=False) for _ in xrange(8)
                                      ]
     self.clip_phase_enabler = Component(parent=self)
     self.__on_clip_phase_enabler_changed.subject = self.clip_phase_enabler
     self._setup_action_mode('select', handler=self._select_mixable)
     self._setup_action_mode('lock_override', handler=self._select_mixable)
     self._setup_action_mode('delete', handler=self._delete_mixable)
     self._setup_action_mode('duplicate', handler=self._duplicate_mixable)
     self._setup_action_mode('arm', handler=self._arm_track)
     self._setup_action_mode('mute', handler=partial(toggle_mixable_mute, song=self.song))
     self._setup_action_mode('solo', handler=partial(toggle_mixable_solo, song=self.song))
     self._setup_action_mode('stop', handler=self._stop_track_clip, feedback_provider=stop_clip_button_color)
     self._setup_action_mode('select_color', handler=self._select_mixable_color, exit_handler=partial(self._select_mixable_color, None))
     self.selected_mode = 'select'
     self._can_trigger_recording_callback = trigger_recording_on_release_callback
     self._track_provider = tracks_provider
     self._selected_track = self.register_disconnectable(SelectedMixerTrackProvider())
     self.__on_items_changed.subject = self._track_provider
     self.__on_selected_item_changed.subject = self._track_provider
     self.__on_tracks_changed.subject = self.song
     self.__on_selected_track_changed.subject = self.song.view
     self.__on_is_playing_changed.subject = self.song
     self._update_track_and_chain_listeners()
     self._update_playheads_real_time_data()
     self._update_realtime_channels_ability()
     return
示例#2
0
class TrackListComponent(ModesComponent, Messenger):
    u"""
    Notifies whenever a track action is executed, e.g. deleting or duplicating. But
    selection does *not* count as an action.
    """
    __events__ = (u'mute_solo_stop_cancel_action_performed', )
    track_action_buttons = control_list(ButtonControl, control_count=8)

    def __init__(self,
                 tracks_provider=None,
                 trigger_recording_on_release_callback=nop,
                 color_chooser=None,
                 clip_phase_enabler=None,
                 *a,
                 **k):
        assert tracks_provider is not None
        super(TrackListComponent, self).__init__(*a, **k)
        self.locked_mode = None
        self._button_handler = self._select_mixable
        self._button_feedback_provider = mixable_button_color
        self._color_chooser = color_chooser
        self._track_selected_when_pressed = [
            False
        ] * self.track_action_buttons.control_count
        self._playheads_real_time_data = [
            RealTimeDataComponent(parent=self,
                                  channel_type='playhead',
                                  is_enabled=False) for _ in xrange(8)
        ]
        self.clip_phase_enabler = Component(parent=self)
        self.__on_clip_phase_enabler_changed.subject = self.clip_phase_enabler
        self._setup_action_mode('select', handler=self._select_mixable)
        self._setup_action_mode('lock_override', handler=self._select_mixable)
        self._setup_action_mode('delete', handler=self._delete_mixable)
        self._setup_action_mode('duplicate', handler=self._duplicate_mixable)
        self._setup_action_mode('arm', handler=self._arm_track)
        self._setup_action_mode('mute',
                                handler=partial(toggle_mixable_mute,
                                                song=self.song))
        self._setup_action_mode('solo',
                                handler=partial(toggle_mixable_solo,
                                                song=self.song))
        self._setup_action_mode('stop',
                                handler=self._stop_track_clip,
                                feedback_provider=stop_clip_button_color)
        self._setup_action_mode('select_color',
                                handler=self._select_mixable_color,
                                exit_handler=partial(
                                    self._select_mixable_color, None))
        self.selected_mode = 'select'
        self._can_trigger_recording_callback = trigger_recording_on_release_callback
        self._track_provider = tracks_provider
        self._selected_track = self.register_disconnectable(
            SelectedMixerTrackProvider())
        self.__on_items_changed.subject = self._track_provider
        self.__on_selected_item_changed.subject = self._track_provider
        self.__on_tracks_changed.subject = self.song
        self.__on_selected_track_changed.subject = self.song.view
        self.__on_is_playing_changed.subject = self.song
        self._update_track_and_chain_listeners()
        self._update_playheads_real_time_data()
        self._update_realtime_channels_ability()
        return

    @listenable_property
    def playhead_real_time_channels(self):
        return self._playheads_real_time_data

    @listenable_property
    def tracks(self):
        return self._track_provider.items

    @listenable_property
    def selected_track(self):
        return self._track_provider.selected_item

    @listenable_property
    def absolute_selected_track_index(self):
        song = self.song
        tracks = song.tracks + song.return_tracks + (song.master_track, )
        selected_track = song.view.selected_track
        return list(tracks).index(selected_track)

    def _setup_action_mode(self,
                           name,
                           handler,
                           exit_handler=nop,
                           feedback_provider=mixable_button_color):
        self.add_mode(
            name,
            [(partial(self._enter_action_mode,
                      handler=handler,
                      feedback_provider=feedback_provider), exit_handler)],
            behaviour=TrackListBehaviour())
        self.get_mode_button(
            name).mode_selected_color = 'DefaultButton.Transparent'
        self.get_mode_button(
            name).mode_unselected_color = 'DefaultButton.Transparent'

    def _enter_action_mode(self, handler, feedback_provider):
        self._button_handler = handler
        if feedback_provider != self._button_feedback_provider:
            self._button_feedback_provider = feedback_provider
            self._update_all_button_colors()

    @listens('tracks')
    def __on_tracks_changed(self):
        self._update_track_and_chain_listeners()
        self._update_playheads_real_time_data()

    @listens_group('mute')
    def __on_track_mute_state_changed(self, mixable):
        self._update_mixable_color(self.tracks.index(mixable), mixable)

    @listens_group('solo')
    def __on_track_solo_state_changed(self, mixable):
        self._update_mixable_color(self.tracks.index(mixable), mixable)

    @listens_group('fired_slot_index')
    def __on_track_fired_slot_changed(self, track):
        self._update_all_button_colors()

    @listens_group('playing_slot_index')
    def __on_track_playing_slot_changed(self, _):
        self._update_all_button_colors()
        self._update_playheads_real_time_data()

    @listens('items')
    def __on_items_changed(self):
        self._update_track_and_chain_listeners()
        self._update_playheads_real_time_data()

    @listens('is_playing')
    def __on_is_playing_changed(self):
        self._update_playheads_real_time_data()

    @listens_group('is_frozen')
    def __on_track_is_frozen_state_changed(self, track):
        self._update_all_button_colors()

    def _update_playheads_real_time_data(self):
        if self.song.is_playing:
            for track, real_time_data in zip(self.tracks,
                                             self._playheads_real_time_data):
                real_time_data.set_data(playing_clip(track))

        else:
            for track, real_time_data in zip(self.tracks,
                                             self._playheads_real_time_data):
                real_time_data.set_data(None)

        self.notify_playhead_real_time_channels()
        return

    def _update_track_and_chain_listeners(self):
        self.notify_tracks()
        tracks = self.tracks
        self.__on_track_color_index_changed.replace_subjects(tracks)
        self.__on_track_mute_state_changed.replace_subjects(tracks)
        self.__on_track_muted_via_solo_changed.replace_subjects(tracks)
        self.__on_track_solo_state_changed.replace_subjects(tracks)
        tracks_without_chains = filter(can_play_clips, tracks)
        self.__on_track_fired_slot_changed.replace_subjects(
            tracks_without_chains)
        self.__on_track_playing_slot_changed.replace_subjects(
            tracks_without_chains)
        self.__on_track_is_frozen_state_changed.replace_subjects(
            tracks_without_chains)
        self._update_button_enabled_state()
        self._update_all_button_colors()

    def _update_button_enabled_state(self):
        tracks = self.tracks
        for track, control in izip(tracks, self.track_action_buttons):
            control.enabled = liveobj_valid(track)

    @listens_group('color_index')
    def __on_track_color_index_changed(self, mixable):
        self._update_mixable_color(self.tracks.index(mixable), mixable)

    @listens('selected_item')
    def __on_selected_item_changed(self):
        self.notify_selected_track()
        self._update_all_button_colors()

    @listens('selected_track')
    def __on_selected_track_changed(self):
        self.notify_absolute_selected_track_index()

    @listens_group('muted_via_solo')
    def __on_track_muted_via_solo_changed(self, mixable):
        self._update_mixable_color(self.tracks.index(mixable), mixable)

    def _update_mixable_color(self, button_index, mixable):
        self.track_action_buttons[
            button_index].color = self._button_feedback_provider(
                mixable, self.song, self.selected_track)

    def _update_all_button_colors(self):
        for index, mixable in enumerate(self.tracks):
            self._update_mixable_color(index, mixable)

    @track_action_buttons.pressed
    def track_action_buttons(self, button):
        self._track_selected_when_pressed[
            button.index] = self._track_provider.selected_item == self.tracks[
                button.index]
        self._button_handler(self.tracks[button.index])
        if self.selected_mode != 'select':
            self.notify_mute_solo_stop_cancel_action_performed()

    @track_action_buttons.pressed_delayed
    def track_action_buttons(self, button):
        if self.selected_mode == 'select':
            (self._arm_track(self.tracks[button.index]), )

    @track_action_buttons.released_immediately
    def track_action_buttons(self, button):
        if self.selected_mode == 'select' and self._track_selected_when_pressed[
                button.index]:
            self._toggle_track_fold(self.tracks[button.index])

    def _toggle_track_fold(self, track):
        if hasattr(track, 'is_foldable') and track.is_foldable:
            track.fold_state = not track.fold_state
        elif hasattr(track, 'is_showing_chains') and track.can_show_chains:
            track.is_showing_chains = not track.is_showing_chains
        else:
            instruments = list(find_instrument_devices(track))
            if instruments:
                instrument = instruments[0]
                if hasattr(instrument,
                           'is_showing_chains') and instrument.can_show_chains:
                    instrument.is_showing_chains = not instrument.is_showing_chains

    def _select_mixable(self, track):
        if liveobj_valid(track) and liveobj_changed(
                self._track_provider.selected_item, track):
            self._track_provider.selected_item = track

    @staticmethod
    def can_duplicate(track_or_chain, return_tracks):
        unwrapped = track_or_chain.proxied_object
        return isinstance(
            unwrapped,
            Live.Track.Track) and unwrapped not in list(return_tracks)

    def _delete_mixable(self, track_or_chain):
        if liveobj_valid(track_or_chain) and not is_chain(track_or_chain):
            try:
                name = track_or_chain.name
                delete_track_or_return_track(self.song, track_or_chain)
                self.show_notification(MessageBoxText.DELETE_TRACK % name)
            except RuntimeError:
                self.show_notification(MessageBoxText.TRACK_DELETE_FAILED)

    def _duplicate_mixable(self, track_or_chain):
        if self.can_duplicate(track_or_chain, self.song.return_tracks):
            try:
                track_index = list(self.song.tracks).index(track_or_chain)
                self.song.duplicate_track(track_index)
                self.show_notification(MessageBoxText.DUPLICATE_TRACK %
                                       track_or_chain.name)
                self._update_all_button_colors()
            except Live.Base.LimitationError:
                self.show_notification(MessageBoxText.TRACK_LIMIT_REACHED)
            except RuntimeError:
                self.show_notification(MessageBoxText.TRACK_DUPLICATION_FAILED)

    def _arm_track(self, track_or_chain):
        if not is_chain(track_or_chain) and track_or_chain.can_be_armed:
            song = self.song
            toggle_arm(track_or_chain, song, exclusive=song.exclusive_arm)
        self._can_trigger_recording_callback(False)

    def _stop_track_clip(self, mixable):
        if not is_chain(mixable):
            mixable.stop_all_clips()

    def _select_mixable_color(self, mixable):
        if self._color_chooser is not None:
            self._color_chooser.object = mixable
        return

    @listens('enabled')
    def __on_clip_phase_enabler_changed(self, _):
        self._update_realtime_channels_ability()

    def _update_realtime_channels_ability(self):
        for playhead in self._playheads_real_time_data:
            playhead.set_enabled(self.is_enabled()
                                 and self.clip_phase_enabler.is_enabled())

    def on_enabled_changed(self):
        super(TrackListComponent, self).on_enabled_changed()
        self._update_realtime_channels_ability()
        if not self.is_enabled():
            self.selected_mode = 'select'
            self.pop_unselected_modes()
        elif self.locked_mode is not None:
            self.push_mode(self.locked_mode)
        return
示例#3
0
	def __init__(self, script, dials = None):
		"""everything except the '_on_selected_track_changed' override and 'disconnect' runs from here"""
		Component.__init__(self)
		self._script = script
		self._dials = dials