Example #1
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);
        }
Example #2
0
 public AllTracksViewModel(
     IAudioPlaybackEngine audioPlaybackEngine,
     IWriteLibraryService writeLibraryService,
     IDialogService dialogService,
     TracksSubsetViewModel parentTracksSubsetViewModel,
     IObservable <IChangeSet <TrackViewModel, uint> > sourceTrackViewModelsChanges)
     : base(audioPlaybackEngine, writeLibraryService, dialogService, parentTracksSubsetViewModel, sourceTrackViewModelsChanges)
 {
 }
Example #3
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 #4
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 #5
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 #6
0
        public EditTrackViewModel(
            IReadLibraryService readLibraryService,
            IWriteLibraryService writeLibraryService,
            Track track,
            Func <Track, EditTrackTagsViewModel> editTrackTagsViewModelFactoryMethod)
        {
            this._track = track ?? throw new ArgumentNullException(nameof(track));
            this._readLibraryService  = readLibraryService ?? throw new ArgumentNullException(nameof(readLibraryService));
            this._writeLibraryService = writeLibraryService ?? throw new ArgumentNullException(nameof(writeLibraryService));
            this._editTrackTagsViewModelFactoryMethod = editTrackTagsViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(editTrackTagsViewModelFactoryMethod));

            this.EditTrackTagsViewModel = this._editTrackTagsViewModelFactoryMethod.Invoke(this._track);

            this.FakeEdit = ReactiveCommand.Create(
                (TrackViewModel trackVM) =>
            {
                throw new NotImplementedException();
            });
        }
Example #7
0
        public EditTrackViewModel(
            IReadLibraryService readLibraryService,
            IWriteLibraryService writeLibraryService,
            Track track,
            Func <Track, EditTrackTagsViewModel> editTrackTagsViewModelFactoryMethod)
        {
            this._track = track ?? throw new ArgumentNullException(nameof(track));
            this._readLibraryService  = readLibraryService ?? throw new ArgumentNullException(nameof(readLibraryService));
            this._writeLibraryService = writeLibraryService ?? throw new ArgumentNullException(nameof(writeLibraryService));
            this._editTrackTagsViewModelFactoryMethod = editTrackTagsViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(editTrackTagsViewModelFactoryMethod));

            this.EditTrackTagsViewModel = this._editTrackTagsViewModelFactoryMethod.Invoke(this._track);

            this.CancelAndClose = ReactiveCommand.CreateFromTask(() => this.TryCloseAsync(false)).DisposeWith(this._disposables);
            this.CancelAndClose.ThrownExceptions.Subscribe(ex => Debug.WriteLine(ex)).DisposeWith(this._disposables);

            this.ConfirmAndClose = ReactiveCommand.CreateFromTask(() => this.TryCloseAsync(true)).DisposeWith(this._disposables);
            this.CancelAndClose.ThrownExceptions.Subscribe(ex => Debug.WriteLine(ex)).DisposeWith(this._disposables);

            this.DisplayName = "Edit";
        }
Example #8
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 #9
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);
        }