public TrackViewModel(
            Track track,
            IAudioPlaybackEngine playbackService)
        {
            this._track           = track ?? throw new ArgumentNullException(nameof(track));
            this._playbackService = playbackService ?? throw new ArgumentNullException(nameof(playbackService));

            this._isLoaded_OAPH = this._playbackService.WhenTrackChanged
                                  .Select(loadedTrack => loadedTrack == this.Track)
                                  .ToProperty(this, nameof(this.IsLoaded))
                                  .DisposeWith(this._disposables);

            this._isLoved_OAPH = this.Track.WhenAnyValue(x => x.IsLoved)
                                 .ToProperty(this, nameof(this.IsLoved))
                                 .DisposeWith(this._disposables);

            this.PlayTrack = ReactiveCommand.CreateFromTask(
                async() =>
            {
                await this._playbackService.StopAsync();
                await this._playbackService.LoadAndPlayAsync(this._track);
            }
                , Observable.CombineLatest(
                    this._playbackService.WhenCanLoadChanged,
                    this._playbackService.WhenCanPlayChanged,
                    (canLoad, canPlay) => (canLoad || canPlay)))
                             .DisposeWith(this._disposables);
            this.PlayTrack.ThrownExceptions.Subscribe(ex => Debug.WriteLine(ex.Message)).DisposeWith(this._disposables);
        }
Example #2
0
        private static void loadOSLibrary()
        {
            OperatingSystem os = Environment.OSVersion;
            Assembly        asm;
            string          libName;

            if ((os.Platform == PlatformID.Unix) || (os.Platform == PlatformID.MacOSX))
            {
                // need to load the OpenAL devices
                asm     = Assembly.LoadFrom("SFX-Engine-OAL.dll");
                libName = "OpenAL";
            }
            else
            {
                // need to load the NAudio devices
                asm     = Assembly.LoadFrom("SFX-Engine-NAudio.dll");
                libName = "NAudio";
            }
            Type type = asm.GetType("com.kintoshmalae.SFXEngine." + libName + ".AudioFileFactory");

            _FileFactory = Activator.CreateInstance(type) as AudioFileFactory;

            type          = asm.GetType("com.kintoshmalae.SFXEngine." + libName + ".AudioPlaybackEngine");
            _LoadedDevice = Activator.CreateInstance(type) as IAudioPlaybackEngine;

            _DriverNames          = (type.GetMethod("driverNames").Invoke(null, null)) as ReadOnlyCollection <string>;
            _loadDriverByName     = Delegate.CreateDelegate(typeof(LoadDriverInstance), type.GetMethod("loadDevice", new Type[] { typeof(string) })) as LoadDriverInstance;
            _loadDriverWithSample = Delegate.CreateDelegate(typeof(LoadDriverWithSample), type.GetMethod("loadDevice", new Type[] { typeof(string), typeof(AudioSampleFormat) })) as LoadDriverWithSample;
        }
Example #3
0
        public SimplePlaylistViewModel(
            IAudioPlaybackEngine audioPlaybackEngine,
            IWriteLibraryService writeLibraryService,
            IDialogService dialogService,
            TracksSubsetViewModel parentTracksSubsetViewModel,
            IObservable <IChangeSet <TrackViewModel, uint> > sourceTrackViewModelsChangesFlow,
            SimplePlaylist playlist)
            : base(audioPlaybackEngine, writeLibraryService, dialogService, parentTracksSubsetViewModel, sourceTrackViewModelsChangesFlow, playlist)
        {
            this.RemoveTrackFromSubset = ReactiveCommand.CreateFromTask(
                async(TrackViewModel trackViewModel) =>
            {
                var selectedItem = this.SelectedTrackViewModel;

                if (this.SelectedTrackViewModel == trackViewModel)
                {
                    // TODO: use dynamicdata watch overload to expose selected item as filter by id
                    this.SelectedTrackViewModel = null;
                }

                try
                {
                    // TODO: handle null? should not happen
                    await this.Playlist?.Remove(trackViewModel.Id);
                }
                catch
                {
                    this.SelectedTrackViewModel = selectedItem;
                }
            })
                                         .DisposeWith(this._disposables);
            this.RemoveTrackFromSubset.ThrownExceptions
            .Subscribe(ex => Debug.WriteLine(ex))
            .DisposeWith(this._disposables);
        }
        public FolderPlaylistViewModel(
            IAudioPlaybackEngine audioPlaybackEngine,
            IDialogService dialogService,
            IObservable <IChangeSet <TrackViewModel, uint> > sourceTrackViewModelsChangesFlow,
            Func <Track, EditTrackTagsViewModel> editTrackViewModelFactoryMethod,
            FolderPlaylist playlistFolder,
            Func <PlaylistBase, PlaylistBaseViewModel> playlistViewModelFactoryMethod)
            : base(audioPlaybackEngine, dialogService, editTrackViewModelFactoryMethod, sourceTrackViewModelsChangesFlow, playlistFolder)
        {
            this._playlistViewModelFactoryMethod = playlistViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(playlistViewModelFactoryMethod));

            //this._serialChildrenPlaylistViewModelsSubscription = new SerialDisposable().DisposeWith(this._disposables);

            // TODO: move to Expand, if can expand is known from playlist entity
            (this._playlist as FolderPlaylist).Playlists
            .Connect()
            .Transform(playlistBaseImpl => this._playlistViewModelFactoryMethod.Invoke(playlistBaseImpl))
            .DisposeMany()
            .RefCount()
            .AddKey(x => x.PlaylistId)
            .Sort(SortExpressionComparer <PlaylistBaseViewModel> .Ascending(vm => vm.Name))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Bind(out var newRooc)
            .Subscribe()
            .DisposeWith(this._disposables);
            this.PlaylistViewModelsROOC = newRooc;
        }
Example #5
0
 public AllTracksViewModel(
     IAudioPlaybackEngine audioPlaybackEngine,
     IDialogService dialogService,
     Func <Track, EditTrackTagsViewModel> editTrackViewModelFactoryMethod,
     IObservable <IChangeSet <TrackViewModel, uint> > sourceTrackViewModelsChanges)
     : base(audioPlaybackEngine, dialogService, editTrackViewModelFactoryMethod, sourceTrackViewModelsChanges)
 {
 }
Example #6
0
        public AudioWaveformPlayerWrapper(IAudioPlaybackEngine audioPlaybackEngine)
        {
            this._audioPlaybackEngine = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));

            this._isPlayingOAPH = this._audioPlaybackEngine.WhenStatusChanged
                                  .Select(status => status == PlaybackStatus.Playing)
                                  .ToProperty(this, nameof(this.IsPlaying));
        }
 public SimplePlaylistViewModel(
     IAudioPlaybackEngine audioPlaybackEngine,
     IDialogService dialogService,
     Func <Track, EditTrackTagsViewModel> editTrackViewModelFactoryMethod,
     IObservable <IChangeSet <TrackViewModel, uint> > sourceTrackViewModelsChangesFlow,
     SimplePlaylist playlist)
     : base(audioPlaybackEngine, dialogService, editTrackViewModelFactoryMethod, sourceTrackViewModelsChangesFlow, playlist)
 {
 }
Example #8
0
 public AllTracksViewModel(
     IAudioPlaybackEngine audioPlaybackEngine,
     IWriteLibraryService writeLibraryService,
     IDialogService dialogService,
     TracksSubsetViewModel parentTracksSubsetViewModel,
     IObservable <IChangeSet <TrackViewModel, uint> > sourceTrackViewModelsChanges)
     : base(audioPlaybackEngine, writeLibraryService, dialogService, parentTracksSubsetViewModel, sourceTrackViewModelsChanges)
 {
 }
Example #9
0
        public Player(IAudioPlaybackEngine audioPlaybackEngine)
        {
            this._audioPlaybackEngine = audioPlaybackEngine;

            this._isPlayingOAPH = this._audioPlaybackEngine
                                  .WhenStatusChanged
                                  .Select(status => status == PlaybackStatus.Playing)
                                  .ToProperty(this, nameof(this.IsPlaying));
        }
Example #10
0
 public PlaylistBaseViewModel(
     IAudioPlaybackEngine audioPlaybackEngine,
     IDialogService dialogService,
     Func <Track, EditTrackTagsViewModel> editTrackViewModelFactoryMethod,
     IObservable <IChangeSet <TrackViewModel, uint> > sourceTrackViewModelsChangesFlow,
     PlaylistBase playlist)
     : base(audioPlaybackEngine, dialogService, editTrackViewModelFactoryMethod, sourceTrackViewModelsChangesFlow)
 {
     this._playlist = playlist ?? throw new ArgumentNullException(nameof(playlist));
 }
Example #11
0
 public PlaylistBaseViewModel(
     IAudioPlaybackEngine audioPlaybackEngine,
     IWriteLibraryService writeLibraryService,
     IDialogService dialogService,
     TracksSubsetViewModel parentTracksSubsetViewModel,
     IObservable <IChangeSet <TrackViewModel, uint> > sourceTrackViewModelsChangesFlow,
     PlaylistBase playlist)
     : base(audioPlaybackEngine, writeLibraryService, dialogService, parentTracksSubsetViewModel, sourceTrackViewModelsChangesFlow)
 {
     this._playlist = playlist ?? throw new ArgumentNullException(nameof(playlist));
 }
Example #12
0
        //private readonly Random _random = new Random((int)DateTime.Now.Ticks);

        #endregion

        #region ctor

        public PlaybackQueue(
            IAudioPlaybackEngine audioPlayer
            //, IObservable<IChangeSet<Track> tracksCacheChanges
            )
        {
            this._audioPlayer = audioPlayer ?? throw new ArgumentNullException(nameof(audioPlayer));

            this._sourcedEntries = new SourceList <PlaybackQueueEntry>().DisposeWith(this._disposables);

            Observable.CombineLatest(
                this._audioPlayer.WhenCanLoadChanged,
                this._audioPlayer.WhenCanPlayChanged,
                (canLoad, canPlay) => canLoad && !canPlay)
            .Where(canLoadButNotPlay => canLoadButNotPlay == true)
            .Subscribe(async(s) =>
            {
                PlaybackQueueEntry next = null;     // = this._playlistEntries.Items.FirstOrDefault();

                this._playlistEntries.Edit(list =>
                {
                    next = list.FirstOrDefault();
                    if (next == null)
                    {
                        // unsubscribe from playlist?
                        return;
                    }
                    list.RemoveAt(0);
                });

                if (next == null)
                {
                    return;
                }

                switch (next.Track)
                {
                case Track nextTrack:
                    await this._audioPlayer.LoadAsync(nextTrack);
                    await this._audioPlayer.PlayAsync();
                    break;
                }
            })
            .DisposeWith(this._disposables);

            //this._upNextEntries = new SourceList<PlaybackQueueEntry>().DisposeWith(this._disposables);
            this._playlistEntries = new SourceList <PlaybackQueueEntry>().DisposeWith(this._disposables);

            //this._upNextEntries.Connect().Bind(out this._upNextEntriesROOC);
            this._playlistEntries.Connect().Bind(out this._playlistEntriesROOC);
        }
Example #13
0
        public FolderPlaylistViewModel(
            IAudioPlaybackEngine audioPlaybackEngine,
            IWriteLibraryService writeLibraryService,
            IDialogService dialogService,
            TracksSubsetViewModel parentTracksSubsetViewModel,
            IObservable <IChangeSet <TrackViewModel, uint> > sourceTrackViewModelsChangesFlow,
            FolderPlaylist playlistFolder,
            Func <PlaylistBase, FolderPlaylistViewModel, PlaylistBaseViewModel> playlistViewModelFactoryMethod)
            : base(audioPlaybackEngine, writeLibraryService, dialogService, parentTracksSubsetViewModel, sourceTrackViewModelsChangesFlow, playlistFolder)
        {
            this._playlistViewModelFactoryMethod = playlistViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(playlistViewModelFactoryMethod));

            this._childrenSubscription = new SerialDisposable().DisposeWith(this._disposables);
        }
Example #14
0
        public static async Task LoadAndPlayAsync(this IAudioPlaybackEngine playbackService, Track track)
        {
            if (playbackService == null)
            {
                throw new ArgumentNullException(nameof(playbackService));
            }
            if (track == null)
            {
                throw new ArgumentNullException(nameof(track));
            }

            await playbackService.LoadAsync(track) /*.ConfigureAwait(false)*/;

            await playbackService.PlayAsync() /*.ConfigureAwait(false)*/;
        }
        public PlaybackHistory(IAudioPlaybackEngine audioPlaybackEngine)
        {
            this._audioPlaybackEngine = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));

            this.Entries = this._audioPlaybackEngine.WhenTrackChanged
                           .SkipLast(1)
                           .Where(t => t != null)
                           .ToObservableChangeSet(50)
                           //.Replay(3)
                           //.Select(track => new PlaybackHistoryEntry(track))
                           .Transform(track => new PlaybackHistoryEntry(track))
                           .DisposeMany()
                           .AsObservableList()
                           .DisposeWith(this._disposables);

            //this.Entries.CountChanged.Subscribe(c => Debug.WriteLine("items: " + c));
        }
Example #16
0
        public LocalLibraryService(
            IReadLibraryService readLibraryService,
            IWriteLibraryService writeLibraryService,
            IAudioPlaybackEngine audioPlaybackEngine,
            IDialogService dialogService,
            Func <Track, TrackViewModel> trackViewModelFactoryMethod)
        {
            this._readLibraryService          = readLibraryService ?? throw new ArgumentNullException(nameof(readLibraryService));
            this._writeLibraryService         = writeLibraryService ?? throw new ArgumentNullException(nameof(writeLibraryService));
            this._audioPlaybackEngine         = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));
            this._dialogService               = dialogService ?? throw new ArgumentNullException(nameof(dialogService));
            this._trackViewModelFactoryMethod = trackViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(trackViewModelFactoryMethod));

            //this._readLibraryService.TracksChanges.DeferUntilLoaded().Subscribe().DisposeWith(this._disposables);
            //this._readLibraryService.PlaylistsChanges.DeferUntilLoaded().Subscribe().DisposeWith(this._disposables);

            this._tracksSubscription    = new SerialDisposable().DisposeWith(this._disposables);
            this._playlistsSubscription = new SerialDisposable().DisposeWith(this._disposables);

            this.TrackViewModelsChangeSets = this._readLibraryService.TracksChanges
                                             .Transform(track => this._trackViewModelFactoryMethod.Invoke(track), new ParallelisationOptions(ParallelType.Parallelise))
                                             .DisposeMany()
                                             // TODO: is RefCount needed with multicast+replay?
                                             .Multicast(new ReplaySubject <IChangeSet <TrackViewModel, uint> >())
                                             .AutoConnect(1, subscription => this._tracksSubscription.Disposable = subscription);
            //.RefCount();

            this.PlaylistViewModelsChanges = this._readLibraryService.PlaylistsChanges
                                             .Transform(playlist => this.CreatePlaylistViewModel(playlist, null), new ParallelisationOptions(ParallelType.Parallelise))
                                             .DisposeMany()
                                             .Multicast(new ReplaySubject <IChangeSet <PlaylistBaseViewModel, uint> >())
                                             .AutoConnect(1, subscription => this._playlistsSubscription.Disposable = subscription);
            //.RefCount();

            //this.TrackViewModelsChangeSets.DeferUntilLoaded().Subscribe().DisposeWith(this._disposables);
            //this.PlaylistViewModelsChanges.DeferUntilLoaded().Subscribe().DisposeWith(this._disposables);

            this.AllTracksViewModel = new AllTracksViewModel(
                this._audioPlaybackEngine,
                //this._readLibraryService,
                this._writeLibraryService,
                this._dialogService,
                null,
                this.TrackViewModelsChangeSets);
        }
Example #17
0
        public TracksViewModel(
            IAudioPlaybackEngine audioPlaybackEngine,
            IReadLibraryService readLibraryService,
            Func <Track, TrackViewModel> trackViewModelFactoryMethod)
        {
            this._audioPlaybackEngine                 = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));
            this._readLibraryService                  = readLibraryService ?? throw new ArgumentNullException(nameof(readLibraryService));
            this._trackViewModelFactoryMethod         = trackViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(trackViewModelFactoryMethod));
            this._serialViewModelsChangesSubscription = new SerialDisposable().DisposeWith(this._disposables);

            this._tracksSubscriber = this._readLibraryService.TracksChanges
                                     //.RefCount()
                                     .Transform(track => this._trackViewModelFactoryMethod(track), new ParallelisationOptions(ParallelType.Parallelise))
                                     .DisposeMany()
                                     //.Sort(SortExpressionComparer<TrackViewModel>.Ascending(vm => this._random.Next()))
                                     .Sort(SortExpressionComparer <TrackViewModel> .Ascending(vm => vm.Id))
                                     .Multicast(new ReplaySubject <IChangeSet <TrackViewModel, uint> >())
                                     .AutoConnect(1, subscription => this._serialViewModelsChangesSubscription.Disposable = subscription)
                                     .ObserveOn(RxApp.MainThreadScheduler)
                                     .SubscribeOn(RxApp.TaskpoolScheduler)
                                     .Bind(out this._trackViewModels)
            ;

            this.PlayTrack = ReactiveCommand.CreateFromTask(
                async(TrackViewModel trackVM) =>
            {
                // TODO: add ConfigureAwait
                await this._audioPlaybackEngine.StopAsync() /*.ConfigureAwait(false)*/;
                await this._audioPlaybackEngine.LoadAndPlayAsync(trackVM.Track) /*.ConfigureAwait(false)*/;
            },
                Observable.CombineLatest(
                    this.WhenAnyValue(subset => subset.SelectedTrackViewModel),
                    this._audioPlaybackEngine.WhenCanLoadChanged,
                    this._audioPlaybackEngine.WhenCanPlayChanged,
                    this._audioPlaybackEngine.WhenCanStopChanged,
                    (selectedTrackViewModel, canLoad, canPlay, canStop) => selectedTrackViewModel != null && (canLoad || canPlay || canStop)));
            this.PlayTrack.ThrownExceptions
            //.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(ex => Debug.WriteLine(ex.Message))
            .DisposeWith(this._disposables);
            this.PlayTrack.DisposeWith(this._disposables);
        }
        public TracksSubsetViewModel(
            IAudioPlaybackEngine audioPlaybackEngine,
            IDialogService dialogService,
            Func <Track, EditTrackTagsViewModel> editTrackViewModelFactoryMethod,
            IObservable <IChangeSet <TrackViewModel, uint> > sourceTrackViewModelsChanges)
        {
            this._audioPlaybackEngine = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));
            this._dialogService       = dialogService ?? throw new ArgumentNullException(nameof(dialogService));
            this._editTrackTagsViewModelFactoryMethod = editTrackViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(editTrackViewModelFactoryMethod));
            this._sourceTrackViewModelsChanges        = sourceTrackViewModelsChanges ?? throw new ArgumentNullException(nameof(sourceTrackViewModelsChanges));

            this._serialViewModelsChangesSubscription = new SerialDisposable().DisposeWith(this._disposables);

            this.PlayTrack = ReactiveCommand.CreateFromTask(
                async(TrackViewModel trackVM) =>
            {
                // TODO: add ConfigureAwait
                await this._audioPlaybackEngine.StopAsync() /*.ConfigureAwait(false)*/;
                await this._audioPlaybackEngine.LoadAndPlayAsync(trackVM.Track) /*.ConfigureAwait(false)*/;
            },
                Observable.CombineLatest(
                    this.WhenAnyValue(t => t.SelectedTrackViewModel),
                    this._audioPlaybackEngine.WhenCanLoadChanged,
                    this._audioPlaybackEngine.WhenCanPlayChanged,
                    this._audioPlaybackEngine.WhenCanStopChanged,
                    (selectedTrackViewModel, canLoad, canPlay, canStop) => selectedTrackViewModel != null && (canLoad || canPlay || canStop)))
                             .DisposeWith(this._disposables);
            this.PlayTrack.ThrownExceptions
            .Subscribe(ex => Debug.WriteLine(ex.Message))
            .DisposeWith(this._disposables);

            this.EditTrackTags = ReactiveCommand.Create(
                (TrackViewModel vm) =>
            {
                this._dialogService.ShowDialog(this._editTrackTagsViewModelFactoryMethod(vm.Track));
            },
                this.WhenAny(x => x.SelectedTrackViewModel, x => x.Value != null))
                                 .DisposeWith(this._disposables);
            this.EditTrackTags.ThrownExceptions
            .Subscribe(ex => Debug.WriteLine(ex.Message))
            .DisposeWith(this._disposables);
        }
Example #19
0
        public PlaybackProgressViewModel(
            IAudioPlaybackEngine audioPlaybackEngine)
        {
            this._audioPlaybackEngine = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));

            // timespans
            this._positionOAPH = this._audioPlaybackEngine.WhenPositionChanged.ToProperty(this, nameof(this.Position)).DisposeWith(this._disposables);
            this._durationOAPH = this._audioPlaybackEngine.WhenDurationChanged.ToProperty(this, nameof(this.Duration)).DisposeWith(this._disposables);

            this._isDurationKnownOAPH = this._audioPlaybackEngine
                                        .WhenDurationChanged
                                        .Select(duration => duration.HasValue)
                                        .ToProperty(this, nameof(this.IsDurationKnown))
                                        .DisposeWith(this._disposables);
            this._isPositionKnownOAPH = this._audioPlaybackEngine
                                        .WhenPositionChanged
                                        .Select(position => position.HasValue)
                                        .ToProperty(this, nameof(this.IsPositionKnown))
                                        .DisposeWith(this._disposables);
        }
        public ShellViewModel(
            IAudioPlaybackEngine playbackService,
            //IWriteLibraryService writeLibraryService,
            IReadLibraryService readLibraryService,
            IDialogService dialogService,
            LibraryViewModel libraryViewModel,
            PlaybackControlsViewModel playbackControlsViewModel,
            PlaybackHistoryViewModel playbackHistoryViewModel,
            ShellMenuViewModel shellMenuViewModel)
        {
            this._playbackService = playbackService ?? throw new ArgumentNullException(nameof(playbackService));
            //this._writeLibraryService = writeLibraryService ?? throw new ArgumentNullException(nameof(writeLibraryService));
            this._readLibraryService       = readLibraryService ?? throw new ArgumentNullException(nameof(readLibraryService));
            this._dialogService            = dialogService ?? throw new ArgumentNullException(nameof(dialogService));
            this.LibraryViewModel          = libraryViewModel ?? throw new ArgumentNullException(nameof(libraryViewModel));
            this.PlaybackControlsViewModel = playbackControlsViewModel ?? throw new ArgumentNullException(nameof(playbackControlsViewModel));
            this.PlaybackHistoryViewModel  = playbackHistoryViewModel ?? throw new ArgumentNullException(nameof(playbackHistoryViewModel));
            this.ShellMenuViewModel        = shellMenuViewModel ?? throw new ArgumentNullException(nameof(shellMenuViewModel));

            this._isEnabled_OAPH = Observable
                                   .Return(true)
                                   .ToProperty(this, nameof(this.IsEnabled))
                                   .DisposeWith(this._disposables);

            this._taskbarProgressState_OAPH = Observable.CombineLatest(
                this._playbackService.WhenStatusChanged,
                this._playbackService.WhenDurationChanged,
                this._playbackService.WhenPositionChanged,
                (status, duration, position) =>
            {
                switch (status)
                {
                case PlaybackStatus.Loaded:
                case PlaybackStatus.PlayedToEnd:
                case PlaybackStatus.ManuallyInterrupted:
                case PlaybackStatus.None:
                    return(TaskbarItemProgressState.None);

                case PlaybackStatus.Playing:
                    if (duration.HasValue && position.HasValue)
                    {
                        return(TaskbarItemProgressState.Normal);
                    }
                    return(TaskbarItemProgressState.Indeterminate);

                case PlaybackStatus.Paused:
                    return(TaskbarItemProgressState.Paused);

                case PlaybackStatus.Loading:
                    return(TaskbarItemProgressState.Indeterminate);

                case PlaybackStatus.Exploded:
                    return(TaskbarItemProgressState.Error);

                default:
                    return(TaskbarItemProgressState.None);
                }
            })
                                              .DistinctUntilChanged()
                                              .ToProperty(this, nameof(this.TaskbarProgressState))
                                              .DisposeWith(this._disposables);

            this._taskbarProgressValue_OAPH = Observable.CombineLatest(
                this._playbackService.WhenDurationChanged,
                this._playbackService.WhenPositionChanged,
                (duration, position) =>
            {
                if (duration.HasValue && position.HasValue)
                {
                    return(position.Value.TotalMilliseconds / duration.Value.TotalMilliseconds);
                }

                return(Double.NaN);
            })
                                              .DistinctUntilChanged()
                                              .ToProperty(this, nameof(this.TaskbarProgressValue))
                                              .DisposeWith(this._disposables);

            this._playbackService.WhenTrackChanged
            .Subscribe(track => this.UpdateDisplayName(track))
            .DisposeWith(this._disposables);

            this.ActivateItem(this.LibraryViewModel);
            this.ActivateItem(this.PlaybackControlsViewModel);
            this.ActivateItem(this.PlaybackHistoryViewModel);
            this.ActivateItem(this.ShellMenuViewModel);
        }
Example #21
0
        public TrackViewModel(
            Track track,
            IAudioPlaybackEngine playbackService,
            IDialogService dialogService,
            Func <Track, EditTrackViewModel> editTrackViewModelFactoryMethod)
        {
            this._track           = track ?? throw new ArgumentNullException(nameof(track));
            this._playbackService = playbackService ?? throw new ArgumentNullException(nameof(playbackService));
            this._dialogService   = dialogService ?? throw new ArgumentNullException(nameof(dialogService));
            this._editTrackViewModelFactoryMethod = editTrackViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(editTrackViewModelFactoryMethod));

            this._isLoaded_OAPH = this._playbackService.WhenTrackChanged
                                  .ObserveOn(RxApp.MainThreadScheduler)
                                  .Select(loadedTrack => loadedTrack == this.Track)
                                  .ToProperty(this, nameof(this.IsLoaded), deferSubscription: true)
                                  .DisposeWith(this._disposables);

            // TODO: or use whenanyvalue?
            this._isLoved_OAPH =
                //this.Track.ObservableForProperty(x => x.IsLoved, skipInitial: false)
                this.WhenAnyValue(x => x.Track.IsLoved)
                //.ObserveOn(RxApp.MainThreadScheduler)
                //.Select(x => x.Value)
                .ToProperty(this, nameof(this.IsLoved), deferSubscription: true)
                .DisposeWith(this._disposables);

            this.PlayTrack = ReactiveCommand.CreateFromTask(
                async() =>
            {
                await this._playbackService.StopAsync();
                await this._playbackService.LoadAndPlayAsync(this._track);
            },
                Observable.CombineLatest(
                    this._playbackService.WhenCanLoadChanged,
                    this._playbackService.WhenCanPlayChanged,
                    (canLoad, canPlay) => canLoad || canPlay))
                             .DisposeWith(this._disposables);
            this.PlayTrack.ThrownExceptions.Subscribe(ex => Debug.WriteLine(ex)).DisposeWith(this._disposables);

            this.EditTrackTags = ReactiveCommand.CreateFromTask(
                async() =>
            {
                await this._dialogService.ShowDialogAsync(this._editTrackViewModelFactoryMethod?.Invoke(this.Track));
            })
                                 .DisposeWith(this._disposables);
            this.EditTrackTags.ThrownExceptions.Subscribe(ex => Debug.WriteLine(ex)).DisposeWith(this._disposables);

            this.ShowInFileManager = ReactiveCommand.Create(
                () =>
            {
                // TODO: handle exceptions
                if (this.TrackLocation.IsFile)
                {
                    Process.Start(
                        "explorer.exe",
                        $"/select, \"{this.TrackLocation.GetComponents(UriComponents.AbsoluteUri, UriFormat.UriEscaped)}\"");
                }
                else
                {
                    Process.Start(this.TrackLocation.GetComponents(UriComponents.AbsoluteUri, UriFormat.UriEscaped));
                }
            },
                this.WhenAnyValue(x => x.TrackLocation).Select(x => x != null))
                                     .DisposeWith(this._disposables);
            this.ShowInFileManager.ThrownExceptions.Subscribe(ex => Debug.WriteLine(ex)).DisposeWith(this._disposables);
        }
Example #22
0
        //private readonly PlaybackQueue _playbackQueue;
        //private readonly PlaybackHistory _playbackHistory;
        //private readonly IReadLibraryService _readLibraryService;

        #endregion

        #region constructors

        public PlaybackControlsViewModel(
            //IPlaybackService playbackService,
            IAudioPlaybackEngine audioPlaybackEngine,
            //PlaybackQueue playbackQueue,
            //PlaybackHistory playbackHistory,
            //IReadLibraryService readLibraryService
            PlaybackTimelineViewModel playbackTimelineViewModel
            )
        {
            // TODO: log
            //this._playbackService = playbackService ?? throw new ArgumentNullException(nameof(playbackService));
            this._audioPlaybackEngine = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));
            //this._playbackQueue = playbackQueue ?? throw new ArgumentNullException(nameof(playbackQueue));
            //this._playbackHistory = playbackHistory ?? throw new ArgumentNullException(nameof(playbackHistory));
            //this._readLibraryService = readLibraryService ?? throw new ArgumentNullException(nameof(readLibraryService));
            this.PlaybackTimelineViewModel = playbackTimelineViewModel ?? throw new ArgumentNullException(nameof(playbackTimelineViewModel));

            this.Pause  = ReactiveCommand.CreateFromTask(() => this._audioPlaybackEngine.PauseAsync(), this._audioPlaybackEngine.WhenCanPauseChanged).DisposeWith(this._disposables);
            this.Resume = ReactiveCommand.CreateFromTask(() => this._audioPlaybackEngine.ResumeAsync(), this._audioPlaybackEngine.WhenCanResumeChanged).DisposeWith(this._disposables);
            this.Stop   = ReactiveCommand.CreateFromTask(() => this._audioPlaybackEngine.StopAsync(), this._audioPlaybackEngine.WhenCanStopChanged).DisposeWith(this._disposables);

            //this.PlayPrevious = ReactiveCommand
            //    .CreateFromTask(async () =>
            //    {
            //        await this._playbackService.StopAsync();
            //        var next = this._playbackQueue.Remove();
            //        if (next != null)
            //        {
            //            await this._playbackService.LoadAsync(next);
            //            await this._playbackService.PlayAsync();
            //        }
            //    }, Observable.CombineLatest(
            //        this._playbackQueue.Items.Connect().IsEmpty(),
            //        this._playbackService.WhenCanStopChanged,
            //        (isEmpty, canStop) => !isEmpty && canStop))
            //    .DisposeWith(this._disposables);
            //this.PlayNext = ReactiveCommand
            //    .CreateFromTask(async () =>
            //    {
            //        await this._playbackService.StopAsync();
            //        var next = this._playbackQueue.Remove();
            //        if (next != null)
            //        {
            //            await this._playbackService.LoadAsync(next);
            //            await this._playbackService.PlayAsync();
            //        }
            //    }, Observable.CombineLatest(
            //        this._playbackQueue.Items.Connect().IsEmpty(),
            //        this._playbackService.WhenCanStopChanged,
            //        (isEmpty, canStop) => !isEmpty && canStop))
            //    .DisposeWith(this._disposables);

            this._volumeOAPH = this._audioPlaybackEngine.WhenVolumeChanged
                               .ToProperty(this, nameof(this.Volume))
                               .DisposeWith(this._disposables);
            this._canPauseOAPH = this._audioPlaybackEngine.WhenCanPauseChanged
                                 .ToProperty(this, nameof(this.CanPause))
                                 .DisposeWith(this._disposables);
            this._canResumeOAPH = this._audioPlaybackEngine.WhenCanResumeChanged
                                  .ToProperty(this, nameof(this.CanResume))
                                  .DisposeWith(this._disposables);
        }
Example #23
0
        public LibraryViewModel(
            IAudioFileInfoProvider audioFileInfoProvider,
            //IReadLibraryService readLibraryService,
            IWriteLibraryService writeLibraryService,
            IAudioPlaybackEngine audioPlaybackEngine,
            IDialogService dialogService,
            Services.LocalLibraryService libraryViewModelsProxy
            //Func<Track, EditTrackTagsViewModel> editTrackViewModelFactoryMethod,
            //Func<PlaylistBase, PlaylistBaseViewModel> playlistBaseViewModelFactoryMethod
            )
        {
            this._audioFileInfoProvider = audioFileInfoProvider ?? throw new ArgumentNullException(nameof(audioFileInfoProvider));
            //this._readLibraryService = readLibraryService ?? throw new ArgumentNullException(nameof(readLibraryService));
            this._writeLibraryService    = writeLibraryService ?? throw new ArgumentNullException(nameof(writeLibraryService));
            this._audioPlaybackEngine    = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));
            this._dialogService          = dialogService ?? throw new ArgumentNullException(nameof(dialogService));
            this._libraryViewModelsProxy = libraryViewModelsProxy ?? throw new ArgumentNullException(nameof(libraryViewModelsProxy));

            //this._editTrackTagsViewModelFactoryMethod = editTrackViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(editTrackViewModelFactoryMethod));
            //this._playlistBaseViewModelFactoryMethod = playlistBaseViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(playlistBaseViewModelFactoryMethod));

            this._serialViewModelsChangesSubscription = new SerialDisposable().DisposeWith(this._disposables);

            this.ShowFilePicker = ReactiveCommand.CreateFromTask(
                async() =>
            {
                var openFileDialogResult = await this._dialogService.OpenFileDialogAsync(
                    "Add files to library ...",
                    Environment.GetFolderPath(Environment.SpecialFolder.MyMusic),
                    true,
                    new Dictionary <string, IReadOnlyCollection <string> >
                {
                    { "Audio files", this._audioPlaybackEngine.SupportedExtensions }
                });

                if (openFileDialogResult.IsConfirmed != true)
                {
                    return;
                }

                IList <AddTrackCommand> atc = new List <AddTrackCommand>();

                foreach (var filePath in openFileDialogResult.Content)
                {
                    var audioFileInfo = await this._audioFileInfoProvider.ExtractAudioFileInfo(new Uri(filePath));
                    if (audioFileInfo == null)
                    {
                        // TODO: handle exceptions
                        // TODO: log
                    }

                    atc.Add(new AddTrackCommand(
                                audioFileInfo.Location,
                                audioFileInfo.Duration,
                                audioFileInfo.LastModifiedDateTime,
                                audioFileInfo.SizeBytes,
                                audioFileInfo.Tags.Title,
                                audioFileInfo.Tags.PerformersNames,
                                audioFileInfo.Tags.ComposersNames,
                                audioFileInfo.Tags.Year,
                                new TrackAlbumAssociation(
                                    new Album(
                                        audioFileInfo.Tags.AlbumTitle,
                                        audioFileInfo.Tags.AlbumAuthors,
                                        audioFileInfo.Tags.AlbumTracksCount,
                                        audioFileInfo.Tags.AlbumDiscsCount),
                                    audioFileInfo.Tags.AlbumTrackNumber,
                                    audioFileInfo.Tags.AlbumDiscNumber)));
                }

                //var addedTracks =
                await this._writeLibraryService.AddTracksAsync(atc);
            })
                                  .DisposeWith(this._disposables);
            this.ShowFilePicker.ThrownExceptions
            .Subscribe(ex => Debug.WriteLine(ex))
            .DisposeWith(this._disposables);

            this.AllTracksViewModel = this._libraryViewModelsProxy.AllTracksViewModel;

            //this._libraryViewModelsProxy.PlaylistViewModelsChanges.Bind(out var playlists).Subscribe(_ => this.PlaylistViewModelsROOC = playlists).DisposeWith(this._disposables);
            //this._libraryViewModelsProxy.PlaylistViewModels
            //    .Cast<IChangeSet<TracksSubsetViewModel, uint>>()
            //    .StartWithItem(this.AllTracksViewModel, 0u)
            //    .Bind(out var subsets).Subscribe(_ => this.PlaylistViewModelsROOC = playlists).DisposeWith(this._disposables);
        }
Example #24
0
        public PlaybackControlsViewModel(
            //IPlaybackService playbackService,
            IAudioPlaybackEngine audioPlaybackEngine,
            //PlaybackQueue playbackQueue,
            //PlaybackHistory playbackHistory,
            //IReadLibraryService readLibraryService
            PlaybackTimelineViewModel playbackTimelineViewModel,
            IDialogService dialogService
            )
        {
            // TODO: log
            //this._playbackService = playbackService ?? throw new ArgumentNullException(nameof(playbackService));
            this._audioPlaybackEngine = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));
            //this._playbackQueue = playbackQueue ?? throw new ArgumentNullException(nameof(playbackQueue));
            //this._playbackHistory = playbackHistory ?? throw new ArgumentNullException(nameof(playbackHistory));
            //this._readLibraryService = readLibraryService ?? throw new ArgumentNullException(nameof(readLibraryService));
            this.PlaybackTimelineViewModel = playbackTimelineViewModel ?? throw new ArgumentNullException(nameof(playbackTimelineViewModel));
            this._dialogService            = dialogService ?? throw new ArgumentNullException(nameof(dialogService));
            this._volume_OAPH = this._audioPlaybackEngine.WhenVolumeChanged
                                .ObserveOn(RxApp.MainThreadScheduler)
                                .ToProperty(this, nameof(this.Volume))
                                .DisposeWith(this._disposables);
            this._hasLoadedTrack_OAPH = this._audioPlaybackEngine.WhenTrackChanged
                                        .ObserveOn(RxApp.MainThreadScheduler)
                                        .Select(x => x == null)
                                        .ToProperty(this, nameof(this.HasLoadedTrack))
                                        .DisposeWith(this._disposables);
            this._canPause_OAPH = this._audioPlaybackEngine.WhenCanPauseChanged
                                  .ObserveOn(RxApp.MainThreadScheduler)
                                  .ToProperty(this, nameof(this.CanPause))
                                  .DisposeWith(this._disposables);
            this._canResume_OAPH = this._audioPlaybackEngine.WhenCanResumeChanged
                                   .ObserveOn(RxApp.MainThreadScheduler)
                                   .ToProperty(this, nameof(this.CanResume))
                                   .DisposeWith(this._disposables);

            this.PlayAll = ReactiveCommand.Create(
                () => throw new NotImplementedException(),
                Observable.Return(false))
                           .DisposeWith(this._disposables);
            this.PlayAll.ThrownExceptions
            .Subscribe(ex => Debug.WriteLine(ex))
            .DisposeWith(this._disposables);

            this.Pause = ReactiveCommand.CreateFromTask(
                () => this._audioPlaybackEngine.PauseAsync(),
                this._audioPlaybackEngine.WhenCanPauseChanged.ObserveOn(RxApp.MainThreadScheduler))
                         .DisposeWith(this._disposables);
            this.Pause.ThrownExceptions
            .Subscribe(ex => Debug.WriteLine(ex))
            .DisposeWith(this._disposables);

            this.Resume = ReactiveCommand.CreateFromTask(
                () => this._audioPlaybackEngine.ResumeAsync(),
                this._audioPlaybackEngine.WhenCanResumeChanged.ObserveOn(RxApp.MainThreadScheduler))
                          .DisposeWith(this._disposables);
            this.Resume.ThrownExceptions
            .Subscribe(ex => Debug.WriteLine(ex))
            .DisposeWith(this._disposables);

            this.Stop = ReactiveCommand.CreateFromTask(
                () => this._audioPlaybackEngine.StopAsync(),
                this._audioPlaybackEngine.WhenCanStopChanged.ObserveOn(RxApp.MainThreadScheduler))
                        .DisposeWith(this._disposables);
            this.Stop.ThrownExceptions
            .Subscribe(ex => Debug.WriteLine(ex))
            .DisposeWith(this._disposables);

            //this.PlayPrevious = ReactiveCommand
            //    .CreateFromTask(async () =>
            //    {
            //        await this._playbackService.StopAsync();
            //        var next = this._playbackQueue.Remove();
            //        if (next != null)
            //        {
            //            await this._playbackService.LoadAsync(next);
            //            await this._playbackService.PlayAsync();
            //        }
            //    }, Observable.CombineLatest(
            //        this._playbackQueue.Items.Connect().IsEmpty(),
            //        this._playbackService.WhenCanStopChanged,
            //        (isEmpty, canStop) => !isEmpty && canStop))
            //    .DisposeWith(this._disposables);
            //this.PlayNext = ReactiveCommand
            //    .CreateFromTask(async () =>
            //    {
            //        await this._playbackService.StopAsync();
            //        var next = this._playbackQueue.Remove();
            //        if (next != null)
            //        {
            //            await this._playbackService.LoadAsync(next);
            //            await this._playbackService.PlayAsync();
            //        }
            //    }, Observable.CombineLatest(
            //        this._playbackQueue.Items.Connect().IsEmpty(),
            //        this._playbackService.WhenCanStopChanged,
            //        (isEmpty, canStop) => !isEmpty && canStop))
            //    .DisposeWith(this._disposables);
        }
Example #25
0
        public PlaybackTimelineViewModel(
            IAudioPlaybackEngine audioPlaybackEngine)
        {
            this._audioPlaybackEngine = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));

            this._seekingSemaphore = new SemaphoreSlim(1, 1).DisposeWith(this._disposables);

            // timespans
            this._positionOAPH = this._audioPlaybackEngine.WhenPositionChanged
                                 .ObserveOn(RxApp.MainThreadScheduler)
                                 .ToProperty(this, nameof(this.Position))
                                 .DisposeWith(this._disposables);
            this._durationOAPH = this._audioPlaybackEngine.WhenDurationChanged
                                 .ObserveOn(RxApp.MainThreadScheduler)
                                 .ToProperty(this, nameof(this.Duration))
                                 .DisposeWith(this._disposables);
            // milliseconds
            this._positionAsTickssOAPH = this._audioPlaybackEngine.WhenPositionChanged
                                         .ObserveOn(RxApp.MainThreadScheduler)
                                         .Where(p => !this._isSeeking) // TODO: use an observable to toggle observing
                                         .Select(p => p != null && p.HasValue ? Convert.ToInt64(p.Value.Ticks) : 0L)
                                         .ToProperty(this, nameof(this.PositionAsTicks))
                                         .DisposeWith(this._disposables);
            this._durationAsTicksOAPH = this._audioPlaybackEngine.WhenDurationChanged
                                        .ObserveOn(RxApp.MainThreadScheduler)
                                        .Select(p => p != null && p.HasValue ? Convert.ToInt64(p.Value.Ticks) : 0L)
                                        .ToProperty(this, nameof(this.DurationAsTicks))
                                        .DisposeWith(this._disposables);

            //this._currentTrackLocationOAPH = this._audioPlaybackEngine
            //    .WhenAudioSourceLocationChanged
            //    .Select(l => l?.ToString())
            //    .ToProperty(this, nameof(this.CurrentTrackLocation))
            //    .DisposeWith(this._disposables);
            //this._isSeekableStatusOAPH = this._audioPlaybackEngine
            //    .WhenStatusChanged
            //    .Select(status => PlaybackStatusHelper.CanSeekPlaybackStatuses.Contains(status))
            //    .ToProperty(this, nameof(this.IsSeekableStatus))
            //    .DisposeWith(this._disposables);
            //this._isPositionSeekableOAPH = this._audioPlaybackEngine
            //    .WhenCanSeekChanged
            //    .ToProperty(this, nameof(this.IsPositionSeekable))
            //    .DisposeWith(this._disposables);

            this._isDurationKnownOAPH = this._audioPlaybackEngine.WhenDurationChanged
                                        .ObserveOn(RxApp.MainThreadScheduler)
                                        .Select(duration => duration.HasValue)
                                        .ToProperty(this, nameof(this.IsDurationKnown))
                                        .DisposeWith(this._disposables);
            this._isPositionKnownOAPH = this._audioPlaybackEngine.WhenPositionChanged
                                        .ObserveOn(RxApp.MainThreadScheduler)
                                        .Select(position => position.HasValue)
                                        .ToProperty(this, nameof(this.IsPositionKnown))
                                        .DisposeWith(this._disposables);
            this._isLoadingOAPH = this._audioPlaybackEngine.WhenStatusChanged
                                  .ObserveOn(RxApp.MainThreadScheduler) // TODO: can remove? should others use it?
                                  .Select(status => status == PlaybackStatus.Loading)
                                  .ToProperty(this, nameof(this.IsLoading))
                                  .DisposeWith(this._disposables);

            this.StartSeeking = ReactiveCommand.CreateFromTask(async() =>
            {
                await this._seekingSemaphore.WaitAsync();
                this._isSeeking       = true;
                this._lastSoughtTicks = null;
                this._seekingSemaphore.Release();
            },
                                                               this._audioPlaybackEngine.WhenCanSeekChanged.ObserveOn(RxApp.MainThreadScheduler))
                                .DisposeWith(this._disposables);
            this.StartSeeking.ThrownExceptions.Subscribe(ex => Debug.WriteLine(ex)).DisposeWith(this._disposables);

            this.SeekTo = ReactiveCommand.CreateFromTask <long>(
                async ticks =>
            {
                await this._seekingSemaphore.WaitAsync();
                if (this._isSeeking)
                {
                    this._lastSoughtTicks = ticks;
                    await this._audioPlaybackEngine.SeekToAsync(TimeSpan.FromTicks(ticks));
                }
                this._seekingSemaphore.Release();
            },
                this._audioPlaybackEngine.WhenCanSeekChanged.ObserveOn(RxApp.MainThreadScheduler))
                          .DisposeWith(this._disposables);
            this.SeekTo.ThrownExceptions.Subscribe(ex => Debug.WriteLine(ex)).DisposeWith(this._disposables);

            this.EndSeeking =
                //ReactiveCommand.CreateFromTask<long>(async () => { this._isSeeking = false; await this._audioPlaybackEngine.ResumeAsync(); }
                ReactiveCommand.CreateFromTask <long>(async ticks =>
            {
                await this._seekingSemaphore.WaitAsync();

                //if (!this._lastSoughtTicks.HasValue || this._lastSoughtTicks.Value != ticks)
                //{
                await this._audioPlaybackEngine.SeekToAsync(TimeSpan.FromTicks(ticks));
                //}

                this._isSeeking = false;

                this._seekingSemaphore.Release();
            },
                                                      this._audioPlaybackEngine.WhenCanSeekChanged.ObserveOn(RxApp.MainThreadScheduler))
                .DisposeWith(this._disposables);
            this.EndSeeking.ThrownExceptions.Subscribe(ex => Debug.WriteLine(ex)).DisposeWith(this._disposables);
        }
Example #26
0
        public ShellViewModel(
            IAudioPlaybackEngine audioPlaybackEngine,
            //IWriteLibraryService writeLibraryService,
            IReadLibraryService readLibraryService,
            IDialogService dialogService,
            LibraryViewModel libraryViewModel,
            PlaybackControlsViewModel playbackControlsViewModel,
            //PlaybackHistoryViewModel playbackHistoryViewModel,
            ShellMenuViewModel shellMenuViewModel,
            Func <MiniPlayerViewModel> _miniplayerViewModelFactoryMethod)
        {
            this._audioPlaybackEngine = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));
            //this._writeLibraryService = writeLibraryService ?? throw new ArgumentNullException(nameof(writeLibraryService));
            this._readLibraryService       = readLibraryService ?? throw new ArgumentNullException(nameof(readLibraryService));
            this._dialogService            = dialogService ?? throw new ArgumentNullException(nameof(dialogService));
            this.LibraryViewModel          = libraryViewModel ?? throw new ArgumentNullException(nameof(libraryViewModel));
            this.PlaybackControlsViewModel = playbackControlsViewModel ?? throw new ArgumentNullException(nameof(playbackControlsViewModel));
            //this.PlaybackHistoryViewModel = playbackHistoryViewModel ?? throw new ArgumentNullException(nameof(playbackHistoryViewModel));
            this.ShellMenuViewModel = shellMenuViewModel ?? throw new ArgumentNullException(nameof(shellMenuViewModel));
            this.miniplayerViewModelFactoryMethod = _miniplayerViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(_miniplayerViewModelFactoryMethod));

            this._isEnabled_OAPH = Observable
                                   .Return(true)
                                   .ToProperty(this, nameof(this.IsEnabled))
                                   .DisposeWith(this._disposables);

            this._taskbarProgressState_OAPH = Observable.CombineLatest(
                this._audioPlaybackEngine.WhenStatusChanged,
                this._audioPlaybackEngine.WhenDurationChanged,
                this._audioPlaybackEngine.WhenPositionChanged,
                (status, duration, position) =>
            {
                switch (status)
                {
                case PlaybackStatus.Loaded:
                case PlaybackStatus.PlayedToEnd:
                case PlaybackStatus.ManuallyInterrupted:
                case PlaybackStatus.None:
                    return(TaskbarItemProgressState.None);

                case PlaybackStatus.Playing:
                    if (duration.HasValue && position.HasValue)
                    {
                        return(TaskbarItemProgressState.Normal);
                    }
                    return(TaskbarItemProgressState.Indeterminate);

                case PlaybackStatus.Paused:
                    return(TaskbarItemProgressState.Paused);

                case PlaybackStatus.Loading:
                    return(TaskbarItemProgressState.Indeterminate);

                case PlaybackStatus.Exploded:
                    return(TaskbarItemProgressState.Error);

                default:
                    return(TaskbarItemProgressState.None);
                }
            })
                                              .DistinctUntilChanged()
                                              .ToProperty(this, nameof(this.TaskbarProgressState))
                                              .DisposeWith(this._disposables);

            this._taskbarProgressValue_OAPH = Observable.CombineLatest(
                this._audioPlaybackEngine.WhenDurationChanged,
                this._audioPlaybackEngine.WhenPositionChanged,
                (duration, position) =>
            {
                if (duration.HasValue && position.HasValue)
                {
                    return(position.Value.TotalMilliseconds / duration.Value.TotalMilliseconds);
                }

                return(Double.NaN);
            })
                                              .DistinctUntilChanged()
                                              .ToProperty(this, nameof(this.TaskbarProgressValue))
                                              .DisposeWith(this._disposables);

            this._audioPlaybackEngine.WhenTrackChanged
            //.ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(track => this.UpdateDisplayName(track))
            .DisposeWith(this._disposables);

            this.HideShellAndShowMiniPlayer = ReactiveCommand.CreateFromTask(
                async() =>
            {
                var miniPlayerVM = this.miniplayerViewModelFactoryMethod.Invoke();

                this.IsVisible = false;

                await this._dialogService.ShowWindowAsync(miniPlayerVM);

                //this.IsVisible = true;
            })
                                              .DisposeWith(this._disposables);

            this.Items.Add(this.LibraryViewModel);
            this.Items.Add(this.PlaybackHistoryViewModel);
            this.Items.Add(this.PlaybackControlsViewModel);
            this.Items.Add(this.ShellMenuViewModel);
        }
Example #27
0
        public TracksSubsetViewModel(
            IAudioPlaybackEngine audioPlaybackEngine,
            IWriteLibraryService writeLibraryService,
            IDialogService dialogService,
            TracksSubsetViewModel parentTracksSubsetViewModel,
            IObservable <IChangeSet <TrackViewModel, uint> > sourceTrackViewModelsChanges)
        {
            this._audioPlaybackEngine          = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));
            this._writeLibraryService          = writeLibraryService ?? throw new ArgumentNullException(nameof(writeLibraryService));
            this._dialogService                = dialogService ?? throw new ArgumentNullException(nameof(dialogService));
            this._sourceTrackViewModelsChanges = sourceTrackViewModelsChanges ?? throw new ArgumentNullException(nameof(sourceTrackViewModelsChanges));

            this.ParentTracksSubsetViewModel = parentTracksSubsetViewModel;

            this._serialViewModelsChangesSubscription = new SerialDisposable().DisposeWith(this._disposables);

            this._areTracksLoaded = this
                                    .WhenAnyValue(x => x.SortedFilteredTrackViewModelsROOC)
                                    .Select(x => x != null)
                                    .StartWith(this.SortedFilteredTrackViewModelsROOC != null)
                                    .ToProperty(this, nameof(this.AreTracksLoaded), deferSubscription: true)
                                    .DisposeWith(this._disposables);

            //this._tracksCount_OAPH = this
            //    .WhenAnyObservable(
            //        x => x.WhenPropertyChanged(e => e.SortedFilteredTrackViewModelsROOC, true, null)
            //    )
            //    .Select(p => p?.Value?.Count)
            //    .ToProperty(this, nameof(this.TracksCount))
            //    .DisposeWith(this._disposables);

            this.PlayTrack = ReactiveCommand.CreateFromTask(
                async(TrackViewModel trackVM) =>
            {
                // TODO: add ConfigureAwait
                await this._audioPlaybackEngine.StopAsync() /*.ConfigureAwait(false)*/;
                await this._audioPlaybackEngine.LoadAndPlayAsync(trackVM.Track) /*.ConfigureAwait(false)*/;
            },
                Observable.CombineLatest(
                    this.WhenAnyValue(t => t.SelectedTrackViewModel),
                    this._audioPlaybackEngine.WhenCanLoadChanged,
                    this._audioPlaybackEngine.WhenCanPlayChanged,
                    this._audioPlaybackEngine.WhenCanStopChanged,
                    (selectedTrackViewModel, canLoad, canPlay, canStop) => selectedTrackViewModel != null && (canLoad || canPlay || canStop)))
                             .DisposeWith(this._disposables);
            this.PlayTrack.ThrownExceptions
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(ex => Debug.WriteLine(ex))
            .DisposeWith(this._disposables);

            this.RemoveTrackFromLibrary = ReactiveCommand.CreateFromTask(
                async(TrackViewModel trackViewModel) =>
            {
                if (this.SelectedTrackViewModel == trackViewModel)
                {
                    this.SelectedTrackViewModel = null;
                }

                await this._writeLibraryService.RemoveTrackAsync(new RemoveTrackCommand(trackViewModel.Id));
            })
                                          .DisposeWith(this._disposables);
            this.RemoveTrackFromLibrary.ThrownExceptions
            .Subscribe(ex => Debug.WriteLine(ex))
            .DisposeWith(this._disposables);
        }