Beispiel #1
0
        public PlaylistViewModel(IScreen hostScreen,
                                 IEventAggregator eventAggregator,
                                 IPlayerModel player,
                                 IPlaylistStore playlistStore)
            : base(eventAggregator)
        {
            HostScreen = hostScreen;
            Player     = player;

            this.playlistStore = playlistStore;

            GetPlaylistsCommand = ReactiveCommand.CreateFromTask(async _ => await GetPlaylists());
            GetPlaylistsCommand.IsExecuting.Subscribe(_ => IsPlaylistsBusy = _);

            InitPlaylistItemsCommand = ReactiveCommand.CreateFromTask <Playlist>(async _ => await LoadPlaylist(_));
            InitPlaylistItemsCommand.IsExecuting.Subscribe(_ => IsPlaylistItemsBusy = _);

            // detail
            this.WhenAnyValue(vm => vm.SelectedPlaylistItem)
            .NotNull()
            .Select(_ => _.Item)
            .Cast <IDetailEntity>()
            .ToProperty(this, _ => _.CurrentDetailEntity, out currentDetailEntity);

            // add to playlist
            AddPlaylistCommand = ReactiveCommand.CreateFromTask(async _ => await AddPlaylist());
            AddToPlaylist      = ReactiveCommand.CreateFromTask <Playlist>(async _ => await AddEpisodeToPlaylist(_));

            // remove from playlist
            RemoveFromPlaylist = ReactiveCommand.CreateFromTask(async _ => await RemoveItemFromPlaylist());

            // delete playlist
            DeletePlaylistCommand = ReactiveCommand.CreateFromTask <Playlist>(async _ => await DeletePlaylist(_));

            // play
            PlayItemCommand = ReactiveCommand.Create <IPlayable>(_ => OnPlayItem());

            // bring into view
            ScrollIntoView = ReactiveCommand.Create <int, int>(_ => _,
                                                               this.WhenAny(_ => _.Player.Playlist.Current, _ => _ != null));

            // sort order
            PlaylistItemOrderBy.OnNext(new IOrderByExpression <PlaylistItem>[]
            {
                new OrderByExpression <PlaylistItem, int>(e => e.OrderNumber)
            });

            // locate current track
            this.WhenAnyValue(vm => vm.Player.LocateCurrent)
            .NotNull()
            .Subscribe(c => c.Subscribe(_ => LocatePageForCurrent()));

            // selected playlist changed
            this.WhenAnyValue(_ => _.SelectedPlaylist)
            .NotNull()
            .DistinctUntilChanged()
            .Subscribe(async _ => await OnSelectedPlaylist(_));

            // on playlists changed
            this.WhenAnyValue(_ => _.Playlists).NotNull().Subscribe(_ => OnPlaylistsChanged());

            // detail
            ToggleShowDetailCommand = ReactiveCommand.Create <bool, bool>(_ => _);
            // deactivation
            DeactivateCommand = ReactiveCommand.Create(() => { });
        }
Beispiel #2
0
        public PlayerViewModel(IEventAggregator eventAggregator, IPlaylistStore playlistStore, IPlayer player)
            : base(eventAggregator)
        {
            this.playlistStore = playlistStore;
            this.player        = player;

            // toggle play
            var canTogglePlay = this.WhenAnyValue(vm => vm.MediaUri).Select(_ => _ != null);

            TogglePlayCommand = ReactiveCommand.Create <Unit>(_ => TogglePlay(), canTogglePlay);
            TogglePlayCommand.ThrownExceptions.Subscribe(OnMediaFailed);

            // open media
            OpenMediaCommand = ReactiveCommand.CreateFromTask(async _ => await OpenMedia());
            OpenMediaCommand.IsExecuting.ToProperty(this, _ => _.IsBusy, out isBusy);

            // shortcut
            EventAggregator.GetEvent <ShortcutEvent>()
            .Where(_ => _.Type == ShortcutCommandType.TogglePlay)
            .Subscribe(_ => OnTogglePlayShortcut());

            //play next, previous
            PlayPrevious = ReactiveCommand.Create <Unit>(_ => Playlist.PlayPrevious(),
                                                         this.WhenAny(vm => vm.Playlist.Previous, e => e.Value != null));
            PlayNext = ReactiveCommand.Create <Unit>(_ => Playlist.PlayNext(),
                                                     this.WhenAny(vm => vm.Playlist.Next, e => e.Value != null));

            // playlist
            // TODO obsolete?
            ShowPlaylist = ReactiveCommand.Create <Unit>(_ => { },
                                                         this.WhenAny(vm => vm.Playlist, p => p.Value != null && p.Value.AnyItems()));

            // volume
            MuteVolumeToggle = ReactiveCommand.Create <Unit>(_ => ToggleMute());

            this.WhenAnyValue(vm => vm.Volume).Skip(1).Subscribe(v => Settings.Default.PlayerVolume = v);
            this.WhenAnyValue(vm => vm.Volume).Subscribe(volume => IsMuted = volume <= 0);

            // reset active / playing on change
            this.WhenAnyValue(_ => _.Playlist).Previous().NotNull().Subscribe(_ => _.ClearActive());

            // current episode
            this.WhenAnyValue(vm => vm.Playlist.Current).WithPrevious().Subscribe(async _ =>
            {
                if (_.OldValue?.ItemId != _.NewValue?.ItemId)
                {
                    await UpdateElapsed(_.OldValue?.Item);
                }
                SelectEpisode();
            });

            // volume
            this.WhenAnyValue(_ => _.Volume).Subscribe(_ => player.Volume = _);

            // set playlist element playing
            this.WhenAnyValue(_ => _.IsPlaying)
            .CombineLatest(this.WhenAnyValue(_ => _.Playlist.Current), (isPlaying, _) => isPlaying)
            .Where(_ => Playlist.Current != null)
            .Subscribe(_ => Playlist.SetCurrentPlaying(_));

            // sync stream position
            this.WhenAnyValue(_ => _.StreamPosition)
            .Where(_ => Playlist?.Current != null)
            .Select(_ => _.TotalSeconds)
            .Subscribe(_ => Playlist.Current.Item.ElapsedSeconds = _);

            // locate
            LocateCurrent = ReactiveCommand.Create <Unit>(_ => { });

            this.WhenAnyValue(_ => _.MediaUri).NotNull().Subscribe(async _ => await OpenMediaCommand.Execute());

            // player stopped
            player.PlaybackStopped.ObserveOn(RxApp.MainThreadScheduler).Subscribe(OnStreamStopped);
        }
Beispiel #3
0
        public PodcastViewModel(IScreen hostScreen,
                                IPlayerModel player,
                                IEventAggregator eventAggregator,
                                IDialogService dialogService,
                                IFeedParser feedParser,
                                IChannelStore channelStore,
                                IPlaylistStore playlistStore)
            : base(eventAggregator)
        {
            HostScreen    = hostScreen;
            Player        = player;
            DialogService = dialogService;
            FeedParser    = feedParser;

            this.channelStore  = channelStore;
            this.playlistStore = playlistStore;

            GetChannelsCommand = ReactiveCommand.CreateFromTask(async _ => await GetChannels());
            GetChannelsCommand.IsExecuting.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => OnChannelsBusy(GetChannelsCommand.GetHashCode(), _));

            PlayItemCommand = ReactiveCommand.CreateFromTask <IPlayable>(async _ => await OnPlayEpisode(_ as Episode));

            // open url
            OpenUrlDialogCommand = ReactiveCommand.CreateFromTask(async _ => await OpenUrlDialog());
            OpenUrlDialogCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_LOAD));

            // channels busy indicator
            this.WhenAnyObservable(_ => _.ChannelsBusyList.CountChanged).DistinctUntilChanged()
            .Subscribe(_ => IsChannelsBusy = _ > 0);

            // episodes busy indicator
            this.WhenAnyObservable(_ => _.EpisodesBusyList.CountChanged).DistinctUntilChanged()
            .Subscribe(_ => IsEpisodesBusy = _ > 0);

            OpenUrlCommand = ReactiveCommand.CreateFromTask <string>(async _ => await OnOpenUrl(_));
            OpenUrlCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_LOAD));

            // load channel
            LoadChannelFromUrlCommand = ReactiveCommand.CreateFromTask <string>(LoadChannelFromUrlAsync);
            OpenUrlCommand.IsExecuting.ObserveOn(RxApp.MainThreadScheduler).Subscribe(_ =>
            {
                OnChannelsBusy(OpenUrlCommand.GetHashCode(), _);
                OnEpisodesBusy(OpenUrlCommand.GetHashCode(), _);
            });

            LoadChannelFromUrlCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_LOAD));

            // delete channel
            ConfirmDeleteChannelCommand = ReactiveCommand.CreateFromTask <Channel>(async _ => await ConfirmDelete(_));
            DeleteChannelCommand        = ReactiveCommand.CreateFromTask <Channel>(async _ => await DeleteChannel(_));
            DeleteChannelCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_DELETE));
            DeleteChannelCommand.IsExecuting.Subscribe(_ =>
            {
                OnChannelsBusy(DeleteChannelCommand.GetHashCode(), _);
                OnEpisodesBusy(DeleteChannelCommand.GetHashCode(), _);
            });

            var existsSelectedChannel = this.WhenAny(vm => vm.SelectedChannel, _ => SelectedChannel != null);

            this.WhenAnyValue(vm => vm.SelectedChannel).Select(_ => _ == null ? 0 : SelectedChannel.Id)
            .ToProperty(this, _ => _.SelectedChannelId, out selectedChannelId);
            RemoveFilterCommand = ReactiveCommand.Create <Unit>(_ => SelectedChannel = null, existsSelectedChannel);

            MarkAllPlayedCommand = ReactiveCommand.CreateFromTask <Channel>(async _ => await MarkChannelPlayed(_));

            CopyUrlCommand = ReactiveCommand.Create <Channel>(_ => Clipboard.SetText(_.Link));

            var episodeSet = this.WhenAnyValue(_ => _.SelectedEpisode);

            // detail
            this.WhenAnyValue(vm => vm.SelectedChannel).NotNull().Cast <IDetailEntity>()
            .Merge(episodeSet.Cast <IDetailEntity>())
            .ToProperty(this, _ => _.CurrentDetailEntity, out currentDetailEntity);

            this.WhenAnyValue(vm => vm.Player.LocateCurrent).NotNull()
            .Subscribe(c => c.Subscribe(_ => LocatePageForCurrent()));

            // episode list is loading
            this.WhenAnyValue(_ => _.EpisodeList.IsLoading).SubscribeOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => OnEpisodesBusy(EpisodeList.GetHashCode(), _));

            ScrollIntoView = ReactiveCommand.Create <int, int>(_ => _);

            // playlist
            AddToPlaylist = ReactiveCommand.CreateFromTask <Playlist>(async _ => await AddEpisodeToPlaylist(_));

            // sort order
            this.WhenAnyValue(_ => _.SelectedEpisodeSortOrder)
            .Subscribe(_ => EpisodeOrderBy.OnNext(GetEpisodeSortOrder(_)));
            ToggleSortDirectionCommand =
                ReactiveCommand.Create(
                    () => EpisodeOrderBy.OnNext(GetEpisodeSortOrder(SelectedEpisodeSortOrder, false)));

            // on channels changed
            this.WhenAnyValue(_ => _.Channels).NotNull().Subscribe(_ => OnChannelsChanged());

            // update channels
            var canUpdate = new BehaviorSubject <bool>(false);

            UpdateChannelsCommand = ReactiveCommand.CreateFromTask(async _ => await UpdateChannelsAsync(),
                                                                   canUpdate.DistinctUntilChanged());

            UpdateChannelsCommand.IsExecuting.CombineLatest(this.WhenAnyValue(_ => _.Channels.IsEmpty),
                                                            (exec, empty) => !exec && !empty && IsUpdateEnabled).DistinctUntilChanged()
            .Subscribe(_ => canUpdate.OnNext(_));

            UpdateChannelsCommand.IsExecuting.ObserveOn(RxApp.MainThreadScheduler).Subscribe(_ => IsUpdating = _);
            UpdateChannelsCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_UPDATE));

            // init episodes
            EpisodeList = InitEpisodeList();
            EpisodeList.Changed.Subscribe(_ => InitActivePlaylist());

            // detail
            ToggleShowDetailCommand = ReactiveCommand.Create <bool, bool>(_ => _);
            DeactivateCommand       = ReactiveCommand.Create(() => { });
        }