// Copyright (c) Arlo Godfrey. All Rights Reserved. // Licensed under the GNU Lesser General Public License, Version 3.0 with additional terms. // See the LICENSE, LICENSE.LESSER and LICENSE.ADDITIONAL files in the project root for more information. using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using CommunityToolkit.Diagnostics; using OwlCore.Events; using OwlCore.Extensions; using StrixMusic.Sdk.AppModels; using StrixMusic.Sdk.BaseModels; using StrixMusic.Sdk.CoreModels; using StrixMusic.Sdk.Extensions; using StrixMusic.Sdk.MediaPlayback; namespace StrixMusic.Sdk.AdapterModels { /// /// A base that merges multiple s. /// public abstract class MergedPlayableCollectionGroupBase : IPlayableCollectionGroup, IMergedMutable where TCoreBase : class, ICorePlayableCollectionGroup, IAsyncDisposable { private readonly MergedCollectionMap _albumCollectionMap; private readonly MergedCollectionMap _artistCollectionMap; private readonly MergedCollectionMap _playlistCollectionMap; private readonly MergedCollectionMap _trackCollectionMap; private readonly MergedCollectionMap _playableCollectionGroupMap; private readonly MergedCollectionMap _imageCollectionMap; private readonly MergedCollectionMap _urlCollectionMap; private readonly SemaphoreSlim _disposeSemaphore = new(1, 1); private bool _isDisposed; /// /// Initializes a new instance of the class. /// protected MergedPlayableCollectionGroupBase(IEnumerable sources, MergedCollectionConfig config) { // TODO: Use top Preferred core. if (sources is null) throw new ArgumentNullException(nameof(sources)); StoredSources = sources.ToList(); Guard.HasSizeGreaterThan(StoredSources, 0, nameof(StoredSources)); PreferredSource = StoredSources[0]; _albumCollectionMap = new MergedCollectionMap(this, config); _artistCollectionMap = new MergedCollectionMap(this, config); _playlistCollectionMap = new MergedCollectionMap(this, config); _trackCollectionMap = new MergedCollectionMap(this, config); _playableCollectionGroupMap = new MergedCollectionMap(this, config); _imageCollectionMap = new MergedCollectionMap(this, config); _urlCollectionMap = new MergedCollectionMap(this, config); AttachPropertyChangedEvents(PreferredSource); AttachCollectionChangedEvents(); foreach (var item in StoredSources) { TotalChildrenCount += item.TotalChildrenCount; TotalPlaylistItemsCount += item.TotalPlaylistItemsCount; TotalTrackCount += item.TotalTrackCount; TotalAlbumItemsCount += item.TotalAlbumItemsCount; TotalArtistItemsCount += item.TotalArtistItemsCount; TotalImageCount += item.TotalImageCount; TotalUrlCount += item.TotalUrlCount; Duration += item.Duration; } Name = PreferredSource.Name; Description = PreferredSource.Description; PlaybackState = PreferredSource.PlaybackState; LastPlayed = PreferredSource.LastPlayed; AddedAt = PreferredSource.AddedAt; } /// /// The top preferred source for this item, used for property getters. /// protected ICorePlayableCollectionGroup PreferredSource { get; } /// /// The source items that were merged to create this /// protected List StoredSources { get; } private void AttachPropertyChangedEvents(ICorePlayableCollectionGroup source) { source.PlaybackStateChanged += PlaybackStateChanged; source.NameChanged += NameChanged; source.DescriptionChanged += DescriptionChanged; source.DurationChanged += DurationChanged; source.LastPlayedChanged += LastPlayedChanged; source.IsPlayTrackCollectionAsyncAvailableChanged += IsPlayTrackCollectionAsyncAvailableChanged; source.IsPauseTrackCollectionAsyncAvailableChanged += IsPauseTrackCollectionAsyncAvailableChanged; source.IsPlayArtistCollectionAsyncAvailableChanged += IsPlayArtistCollectionAsyncAvailableChanged; source.IsPauseArtistCollectionAsyncAvailableChanged += IsPauseArtistCollectionAsyncAvailableChanged; source.IsPlayAlbumCollectionAsyncAvailableChanged += IsPlayAlbumCollectionAsyncAvailableChanged; source.IsPauseAlbumCollectionAsyncAvailableChanged += IsPauseAlbumCollectionAsyncAvailableChanged; source.IsChangeNameAsyncAvailableChanged += IsChangeNameAsyncAvailableChanged; source.IsChangeDurationAsyncAvailableChanged += IsChangeDurationAsyncAvailableChanged; source.IsChangeDescriptionAsyncAvailableChanged += IsChangeDescriptionAsyncAvailableChanged; } private void DetachPropertyChangedEvents(ICorePlayableCollectionGroup source) { source.PlaybackStateChanged -= PlaybackStateChanged; source.NameChanged -= NameChanged; source.DescriptionChanged -= DescriptionChanged; source.DurationChanged -= DurationChanged; source.LastPlayedChanged -= LastPlayedChanged; source.IsPlayTrackCollectionAsyncAvailableChanged -= IsPlayTrackCollectionAsyncAvailableChanged; source.IsPauseTrackCollectionAsyncAvailableChanged -= IsPauseTrackCollectionAsyncAvailableChanged; source.IsPlayArtistCollectionAsyncAvailableChanged -= IsPlayArtistCollectionAsyncAvailableChanged; source.IsPauseArtistCollectionAsyncAvailableChanged -= IsPauseArtistCollectionAsyncAvailableChanged; source.IsPlayAlbumCollectionAsyncAvailableChanged -= IsPlayAlbumCollectionAsyncAvailableChanged; source.IsPauseAlbumCollectionAsyncAvailableChanged -= IsPauseAlbumCollectionAsyncAvailableChanged; source.IsChangeNameAsyncAvailableChanged -= IsChangeNameAsyncAvailableChanged; source.IsChangeDurationAsyncAvailableChanged -= IsChangeDurationAsyncAvailableChanged; source.IsChangeDescriptionAsyncAvailableChanged -= IsChangeDescriptionAsyncAvailableChanged; } private void AttachCollectionChangedEvents() { _albumCollectionMap.ItemsChanged += AlbumCollectionMap_ItemsChanged; _artistCollectionMap.ItemsChanged += ArtistCollectionMap_ItemsChanged; _playlistCollectionMap.ItemsChanged += PlaylistCollectionMap_ItemsChanged; _playableCollectionGroupMap.ItemsChanged += PlayableCollectionGroupMap_ItemsChanged; _trackCollectionMap.ItemsChanged += TrackCollectionMap_ItemsChanged; _imageCollectionMap.ItemsChanged += ImagesCollectionMap_ItemsChanged; _urlCollectionMap.ItemsChanged += UrlsCollectionMap_ItemsChanged; _albumCollectionMap.ItemsCountChanged += AlbumCollectionMap_ItemsCountChanged; _artistCollectionMap.ItemsCountChanged += ArtistCollectionMap_ItemsCountChanged; _trackCollectionMap.ItemsCountChanged += TrackCollectionMap_ItemsCountChanged; _playlistCollectionMap.ItemsCountChanged += PlaylistCollectionMap_ItemsCountChanged; _playableCollectionGroupMap.ItemsCountChanged += PlayableCollectionGroupMap_ItemsCountChanged; _imageCollectionMap.ItemsCountChanged += ImagesCollectionMap_ItemsCountChanged; _urlCollectionMap.ItemsCountChanged += UrlsCollectionMap_ItemsCountChanged; } private void DetachCollectionChangedEvents() { _albumCollectionMap.ItemsChanged -= AlbumCollectionMap_ItemsChanged; _artistCollectionMap.ItemsChanged -= ArtistCollectionMap_ItemsChanged; _playlistCollectionMap.ItemsChanged -= PlaylistCollectionMap_ItemsChanged; _playableCollectionGroupMap.ItemsChanged -= PlayableCollectionGroupMap_ItemsChanged; _trackCollectionMap.ItemsChanged -= TrackCollectionMap_ItemsChanged; _imageCollectionMap.ItemsChanged -= ImagesCollectionMap_ItemsChanged; _urlCollectionMap.ItemsChanged -= UrlsCollectionMap_ItemsChanged; _albumCollectionMap.ItemsCountChanged -= AlbumCollectionMap_ItemsCountChanged; _artistCollectionMap.ItemsCountChanged -= ArtistCollectionMap_ItemsCountChanged; _playlistCollectionMap.ItemsCountChanged -= PlaylistCollectionMap_ItemsCountChanged; _playableCollectionGroupMap.ItemsCountChanged -= PlayableCollectionGroupMap_ItemsCountChanged; _imageCollectionMap.ItemsCountChanged -= ImagesCollectionMap_ItemsCountChanged; _trackCollectionMap.ItemsCountChanged -= TrackCollectionMap_ItemsCountChanged; _urlCollectionMap.ItemsCountChanged -= UrlsCollectionMap_ItemsCountChanged; } /// public event EventHandler? PlaybackStateChanged; /// public event EventHandler? NameChanged; /// public event EventHandler? DescriptionChanged; /// public event EventHandler? DurationChanged; /// public event EventHandler? LastPlayedChanged; /// public event EventHandler? IsPlayAlbumCollectionAsyncAvailableChanged; /// public event EventHandler? IsPauseAlbumCollectionAsyncAvailableChanged; /// public event EventHandler? IsPlayArtistCollectionAsyncAvailableChanged; /// public event EventHandler? IsPauseArtistCollectionAsyncAvailableChanged; /// public event EventHandler? IsPlayPlaylistCollectionAsyncAvailableChanged; /// public event EventHandler? IsPausePlaylistCollectionAsyncAvailableChanged; /// public event EventHandler? IsPlayTrackCollectionAsyncAvailableChanged; /// public event EventHandler? IsPauseTrackCollectionAsyncAvailableChanged; /// public event EventHandler? IsChangeNameAsyncAvailableChanged; /// public event EventHandler? IsChangeDescriptionAsyncAvailableChanged; /// public event EventHandler? IsChangeDurationAsyncAvailableChanged; /// public event EventHandler? TracksCountChanged; /// public event EventHandler? ArtistItemsCountChanged; /// public event EventHandler? AlbumItemsCountChanged; /// public event EventHandler? PlaylistItemsCountChanged; /// public event EventHandler? ChildrenCountChanged; /// public event EventHandler? ImagesCountChanged; /// public event EventHandler? UrlsCountChanged; /// public event CollectionChangedEventHandler? TracksChanged; /// public event CollectionChangedEventHandler? ArtistItemsChanged; /// public event CollectionChangedEventHandler? AlbumItemsChanged; /// public event CollectionChangedEventHandler? PlaylistItemsChanged; /// public event CollectionChangedEventHandler? ChildItemsChanged; /// public event CollectionChangedEventHandler? ImagesChanged; /// public event CollectionChangedEventHandler? UrlsChanged; /// public event EventHandler? DownloadInfoChanged; private void ImagesCollectionMap_ItemsCountChanged(object sender, int e) { TotalImageCount = e; ImagesCountChanged?.Invoke(this, e); } private void UrlsCollectionMap_ItemsCountChanged(object sender, int e) { TotalUrlCount = e; UrlsCountChanged?.Invoke(this, e); } private void PlayableCollectionGroupMap_ItemsCountChanged(object sender, int e) { TotalChildrenCount = e; ChildrenCountChanged?.Invoke(this, e); } private void PlaylistCollectionMap_ItemsCountChanged(object sender, int e) { TotalPlaylistItemsCount = e; PlaylistItemsCountChanged?.Invoke(this, e); } private void ArtistCollectionMap_ItemsCountChanged(object sender, int e) { TotalArtistItemsCount = e; ArtistItemsCountChanged?.Invoke(this, e); } private void AlbumCollectionMap_ItemsCountChanged(object sender, int e) { TotalAlbumItemsCount = e; AlbumItemsCountChanged?.Invoke(this, e); } private void TrackCollectionMap_ItemsCountChanged(object sender, int e) { TotalTrackCount = e; TracksCountChanged?.Invoke(this, e); } private void TrackCollectionMap_ItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) { TracksChanged?.Invoke(this, addedItems, removedItems); } private void PlayableCollectionGroupMap_ItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) { ChildItemsChanged?.Invoke(this, addedItems, removedItems); } private void PlaylistCollectionMap_ItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) { PlaylistItemsChanged?.Invoke(this, addedItems, removedItems); } private void AlbumCollectionMap_ItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) { AlbumItemsChanged?.Invoke(this, addedItems, removedItems); } private void ArtistCollectionMap_ItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) { ArtistItemsChanged?.Invoke(this, addedItems, removedItems); } private void ImagesCollectionMap_ItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) { ImagesChanged?.Invoke(this, addedItems, removedItems); } private void UrlsCollectionMap_ItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) { UrlsChanged?.Invoke(this, addedItems, removedItems); } /// public event EventHandler? SourcesChanged; /// IReadOnlyList IMerged.Sources => StoredSources; /// IReadOnlyList IMerged.Sources => StoredSources; /// IReadOnlyList IMerged.Sources => StoredSources; /// IReadOnlyList IMerged.Sources => StoredSources; /// IReadOnlyList IMerged.Sources => StoredSources; /// IReadOnlyList IMerged.Sources => StoredSources; /// IReadOnlyList IMerged.Sources => StoredSources; /// IReadOnlyList IMerged.Sources => StoredSources; /// IReadOnlyList IMerged.Sources => StoredSources; /// IReadOnlyList IMerged.Sources => StoredSources; /// IReadOnlyList IMerged.Sources => StoredSources; /// public virtual IReadOnlyList Sources => StoredSources; /// public string Id => PreferredSource.Id; /// public string Name { get; internal set; } /// public string? Description { get; internal set; } /// public PlaybackState PlaybackState { get; internal set; } /// public DownloadInfo DownloadInfo => default; /// public TimeSpan Duration { get; internal set; } = new TimeSpan(0); /// public DateTime? LastPlayed { get; internal set; } /// public DateTime? AddedAt { get; internal set; } /// public int TotalChildrenCount { get; internal set; } /// public int TotalPlaylistItemsCount { get; internal set; } /// public int TotalTrackCount { get; internal set; } /// public int TotalAlbumItemsCount { get; internal set; } /// public int TotalArtistItemsCount { get; internal set; } /// public int TotalImageCount { get; internal set; } /// public int TotalUrlCount { get; internal set; } /// public virtual bool IsPlayAlbumCollectionAsyncAvailable => PreferredSource.IsPlayAlbumCollectionAsyncAvailable; /// public virtual bool IsPauseAlbumCollectionAsyncAvailable => PreferredSource.IsPauseAlbumCollectionAsyncAvailable; /// public virtual bool IsPlayArtistCollectionAsyncAvailable => PreferredSource.IsPlayArtistCollectionAsyncAvailable; /// public virtual bool IsPauseArtistCollectionAsyncAvailable => PreferredSource.IsPauseArtistCollectionAsyncAvailable; /// public virtual bool IsPlayPlaylistCollectionAsyncAvailable => PreferredSource.IsPlayPlaylistCollectionAsyncAvailable; /// public virtual bool IsPausePlaylistCollectionAsyncAvailable => PreferredSource.IsPausePlaylistCollectionAsyncAvailable; /// public virtual bool IsPlayTrackCollectionAsyncAvailable => PreferredSource.IsPlayTrackCollectionAsyncAvailable; /// public virtual bool IsPauseTrackCollectionAsyncAvailable => PreferredSource.IsPauseTrackCollectionAsyncAvailable; /// public virtual bool IsChangeNameAsyncAvailable => PreferredSource.IsChangeNameAsyncAvailable; /// public virtual bool IsChangeDescriptionAsyncAvailable => PreferredSource.IsChangeDescriptionAsyncAvailable; /// public virtual bool IsChangeDurationAsyncAvailable => PreferredSource.IsChangeDurationAsyncAvailable; /// public Task IsAddTrackAvailableAsync(int index, CancellationToken cancellationToken = default) => _trackCollectionMap.IsAddItemAvailableAsync(index, cancellationToken); /// public Task IsAddAlbumItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _albumCollectionMap.IsAddItemAvailableAsync(index, cancellationToken); /// public Task IsAddArtistItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _artistCollectionMap.IsAddItemAvailableAsync(index, cancellationToken); /// public Task IsAddPlaylistItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _playlistCollectionMap.IsAddItemAvailableAsync(index, cancellationToken); /// public Task IsAddChildAvailableAsync(int index, CancellationToken cancellationToken = default) => _playableCollectionGroupMap.IsAddItemAvailableAsync(index, cancellationToken); /// public Task IsAddImageAvailableAsync(int index, CancellationToken cancellationToken = default) => _imageCollectionMap.IsAddItemAvailableAsync(index, cancellationToken); /// public Task IsAddUrlAvailableAsync(int index, CancellationToken cancellationToken = default) => _urlCollectionMap.IsAddItemAvailableAsync(index, cancellationToken); /// public Task IsRemoveTrackAvailableAsync(int index, CancellationToken cancellationToken = default) => _trackCollectionMap.IsRemoveItemAvailableAsync(index, cancellationToken); /// public Task IsRemoveArtistItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _artistCollectionMap.IsRemoveItemAvailableAsync(index, cancellationToken); /// public Task IsRemoveAlbumItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _albumCollectionMap.IsRemoveItemAvailableAsync(index, cancellationToken); /// public Task IsRemovePlaylistItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _playableCollectionGroupMap.IsRemoveItemAvailableAsync(index, cancellationToken); /// public Task IsRemoveChildAvailableAsync(int index, CancellationToken cancellationToken = default) => _playableCollectionGroupMap.IsRemoveItemAvailableAsync(index, cancellationToken); /// public Task IsRemoveImageAvailableAsync(int index, CancellationToken cancellationToken = default) => _imageCollectionMap.IsRemoveItemAvailableAsync(index, cancellationToken); /// public Task IsRemoveUrlAvailableAsync(int index, CancellationToken cancellationToken = default) => _urlCollectionMap.IsRemoveItemAvailableAsync(index, cancellationToken); /// public Task PauseAlbumCollectionAsync(CancellationToken cancellationToken) => PreferredSource.PauseAlbumCollectionAsync(cancellationToken); /// public Task PlayAlbumCollectionAsync(CancellationToken cancellationToken) => PreferredSource.PlayAlbumCollectionAsync(cancellationToken); /// public Task PauseArtistCollectionAsync(CancellationToken cancellationToken) => PreferredSource.PauseArtistCollectionAsync(cancellationToken); /// public Task PlayArtistCollectionAsync(CancellationToken cancellationToken) => PreferredSource.PlayArtistCollectionAsync(cancellationToken); /// public Task PausePlaylistCollectionAsync(CancellationToken cancellationToken) => PreferredSource.PausePlaylistCollectionAsync(cancellationToken); /// public Task PlayPlaylistCollectionAsync(CancellationToken cancellationToken) => PreferredSource.PlayPlaylistCollectionAsync(cancellationToken); /// public Task PauseTrackCollectionAsync(CancellationToken cancellationToken) => PreferredSource.PauseTrackCollectionAsync(cancellationToken); /// public Task PlayTrackCollectionAsync(CancellationToken cancellationToken) => PreferredSource.PlayTrackCollectionAsync(cancellationToken); /// public Task PlayPlayableCollectionGroupAsync(CancellationToken cancellationToken) => PreferredSource.PlayPlayableCollectionGroupAsync(cancellationToken); /// public Task PausePlayableCollectionGroupAsync(CancellationToken cancellationToken) => PreferredSource.PausePlayableCollectionGroupAsync(cancellationToken); /// public Task PlayTrackCollectionAsync(ITrack track, CancellationToken cancellationToken = default) { var targetCore = PreferredSource.SourceCore; var source = track.GetSources().FirstOrDefault(x => x.SourceCore.InstanceId == targetCore.InstanceId); Guard.IsNotNull(source, nameof(source)); return PreferredSource.PlayTrackCollectionAsync(source, cancellationToken); } /// public Task PlayArtistCollectionAsync(IArtistCollectionItem artistItem, CancellationToken cancellationToken = default) { var targetCore = PreferredSource.SourceCore; ICoreArtistCollectionItem? source = null; if (artistItem is IArtist artist) source = artist.GetSources().FirstOrDefault(x => x.SourceCore.InstanceId == targetCore.InstanceId); if (artistItem is IArtistCollection collection) source = collection.GetSources().FirstOrDefault(x => x.SourceCore.InstanceId == targetCore.InstanceId); Guard.IsNotNull(source, nameof(source)); return PreferredSource.PlayArtistCollectionAsync(source, cancellationToken); } /// public Task PlayAlbumCollectionAsync(IAlbumCollectionItem albumItem, CancellationToken cancellationToken = default) { var targetCore = PreferredSource.SourceCore; ICoreAlbumCollectionItem? source = null; if (albumItem is IAlbum album) source = album.GetSources().FirstOrDefault(x => x.SourceCore.InstanceId == targetCore.InstanceId); if (albumItem is IAlbumCollection collection) source = collection.GetSources().FirstOrDefault(x => x.SourceCore.InstanceId == targetCore.InstanceId); Guard.IsNotNull(source, nameof(source)); return PreferredSource.PlayAlbumCollectionAsync(source, cancellationToken); } /// public Task PlayPlaylistCollectionAsync(IPlaylistCollectionItem playlistItem, CancellationToken cancellationToken = default) { var targetCore = PreferredSource.SourceCore; ICorePlaylistCollectionItem? source = null; if (playlistItem is IPlaylist playlist) source = playlist.GetSources().FirstOrDefault(x => x.SourceCore.InstanceId == targetCore.InstanceId); if (playlistItem is IPlaylistCollection collection) source = collection.GetSources().FirstOrDefault(x => x.SourceCore.InstanceId == targetCore.InstanceId); Guard.IsNotNull(source, nameof(source)); return PreferredSource.PlayPlaylistCollectionAsync(source, cancellationToken); } /// public Task PlayPlayableCollectionGroupAsync(IPlayableCollectionGroup collectionGroup, CancellationToken cancellationToken = default) { var targetCore = PreferredSource.SourceCore; var source = collectionGroup.GetSources().FirstOrDefault(x => x.SourceCore.InstanceId == targetCore.InstanceId); Guard.IsNotNull(source, nameof(source)); return PreferredSource.PlayPlayableCollectionGroupAsync(source, cancellationToken); } /// public IAsyncEnumerable GetAlbumItemsAsync(int limit, int offset, CancellationToken cancellationToken = default) { return _albumCollectionMap.GetItemsAsync(limit, offset, cancellationToken); } /// public IAsyncEnumerable GetArtistItemsAsync(int limit, int offset, CancellationToken cancellationToken = default) { return _artistCollectionMap.GetItemsAsync(limit, offset, cancellationToken); } /// public IAsyncEnumerable GetChildrenAsync(int limit, int offset, CancellationToken cancellationToken = default) { return _playableCollectionGroupMap.GetItemsAsync(limit, offset, cancellationToken); } /// public IAsyncEnumerable GetPlaylistItemsAsync(int limit, int offset, CancellationToken cancellationToken = default) { return _playlistCollectionMap.GetItemsAsync(limit, offset, cancellationToken); } /// public IAsyncEnumerable GetTracksAsync(int limit, int offset, CancellationToken cancellationToken = default) { return _trackCollectionMap.GetItemsAsync(limit, offset, cancellationToken); } /// public IAsyncEnumerable GetImagesAsync(int limit, int offset, CancellationToken cancellationToken = default) { return _imageCollectionMap.GetItemsAsync(limit, offset, cancellationToken); } /// public IAsyncEnumerable GetUrlsAsync(int limit, int offset, CancellationToken cancellationToken = default) { return _urlCollectionMap.GetItemsAsync(limit, offset, cancellationToken); } /// public Task ChangeNameAsync(string name, CancellationToken cancellationToken = default) { return Sources.InParallel(source => source.IsChangeNameAsyncAvailable ? source.ChangeNameAsync(name) : Task.CompletedTask); } /// public Task ChangeDescriptionAsync(string? description, CancellationToken cancellationToken = default) { return Sources.InParallel(source => source.IsChangeDescriptionAsyncAvailable ? source.ChangeDescriptionAsync(description) : Task.CompletedTask); } /// public Task ChangeDurationAsync(TimeSpan duration, CancellationToken cancellationToken = default) { return Sources.InParallel(source => source.IsChangeDurationAsyncAvailable ? source.ChangeDurationAsync(duration) : Task.CompletedTask); } /// public Task AddTrackAsync(ITrack track, int index, CancellationToken cancellationToken = default) { return _trackCollectionMap.InsertItemAsync(track, index, cancellationToken); } /// public Task AddArtistItemAsync(IArtistCollectionItem artistItem, int index, CancellationToken cancellationToken = default) { return _artistCollectionMap.InsertItemAsync(artistItem, index, cancellationToken); } /// public Task AddAlbumItemAsync(IAlbumCollectionItem albumItem, int index, CancellationToken cancellationToken = default) { return _albumCollectionMap.InsertItemAsync(albumItem, index, cancellationToken); } /// public Task AddPlaylistItemAsync(IPlaylistCollectionItem playlistItem, int index, CancellationToken cancellationToken = default) { return _playlistCollectionMap.InsertItemAsync(playlistItem, index, cancellationToken); } /// public Task AddChildAsync(IPlayableCollectionGroup child, int index, CancellationToken cancellationToken = default) { return _playableCollectionGroupMap.InsertItemAsync(child, index, cancellationToken); } /// public Task AddImageAsync(IImage image, int index, CancellationToken cancellationToken = default) { return _imageCollectionMap.InsertItemAsync(image, index, cancellationToken); } /// public Task AddUrlAsync(IUrl url, int index, CancellationToken cancellationToken = default) { return _urlCollectionMap.InsertItemAsync(url, index, cancellationToken); } /// public Task RemoveTrackAsync(int index, CancellationToken cancellationToken = default) { return _trackCollectionMap.RemoveAtAsync(index, cancellationToken); } /// public Task RemoveArtistItemAsync(int index, CancellationToken cancellationToken = default) { return _artistCollectionMap.RemoveAtAsync(index, cancellationToken); } /// public Task RemoveAlbumItemAsync(int index, CancellationToken cancellationToken = default) { return _albumCollectionMap.RemoveAtAsync(index, cancellationToken); } /// public Task RemovePlaylistItemAsync(int index, CancellationToken cancellationToken = default) { return _playlistCollectionMap.RemoveAtAsync(index, cancellationToken); } /// public Task RemoveChildAsync(int index, CancellationToken cancellationToken = default) { return _playableCollectionGroupMap.RemoveAtAsync(index, cancellationToken); } /// public Task RemoveImageAsync(int index, CancellationToken cancellationToken = default) { return _imageCollectionMap.RemoveAtAsync(index, cancellationToken); } /// public Task RemoveUrlAsync(int index, CancellationToken cancellationToken = default) { return _urlCollectionMap.RemoveAtAsync(index, cancellationToken); } /// public Task StartDownloadOperationAsync(DownloadOperation operation, CancellationToken cancellationToken = default) { throw new NotSupportedException(); } /// public void AddSource(TCoreBase itemToAdd) { Guard.IsNotNull(itemToAdd, nameof(itemToAdd)); if (!Equals(itemToAdd)) ThrowHelper.ThrowArgumentException("Tried to merge an artistItem that doesn't match. Verify that the item matches before merging the source."); StoredSources.Add(itemToAdd); _albumCollectionMap.AddSource(itemToAdd); _artistCollectionMap.AddSource(itemToAdd); _playableCollectionGroupMap.AddSource(itemToAdd); _playlistCollectionMap.AddSource(itemToAdd); _trackCollectionMap.AddSource(itemToAdd); _imageCollectionMap.AddSource(itemToAdd); _urlCollectionMap.AddSource(itemToAdd); SourcesChanged?.Invoke(this, EventArgs.Empty); } /// public void RemoveSource(TCoreBase itemToRemove) { Guard.IsNotNull(itemToRemove, nameof(itemToRemove)); StoredSources.Remove(itemToRemove); _albumCollectionMap.RemoveSource(itemToRemove); _artistCollectionMap.RemoveSource(itemToRemove); _playableCollectionGroupMap.RemoveSource(itemToRemove); _playlistCollectionMap.RemoveSource(itemToRemove); _trackCollectionMap.RemoveSource(itemToRemove); _imageCollectionMap.RemoveSource(itemToRemove); _urlCollectionMap.RemoveSource(itemToRemove); SourcesChanged?.Invoke(this, EventArgs.Empty); } /// public bool Equals(ICorePlaylistCollectionItem other) => Equals(other as ICorePlayableCollectionGroup); /// public bool Equals(ICorePlaylistCollection other) => Equals(other as ICorePlayableCollectionGroup); /// public bool Equals(ICoreTrackCollection other) => Equals(other as ICorePlayableCollectionGroup); /// public bool Equals(ICoreAlbumCollectionItem other) => Equals(other as ICorePlayableCollectionGroup); /// public bool Equals(ICoreAlbumCollection other) => Equals(other as ICorePlayableCollectionGroup); /// public bool Equals(ICoreArtistCollectionItem other) => Equals(other as ICorePlayableCollectionGroup); /// public bool Equals(ICoreArtistCollection other) => Equals(other as ICorePlayableCollectionGroup); /// public bool Equals(ICorePlayableCollectionGroupChildren other) => Equals(other as ICorePlayableCollectionGroup); /// public bool Equals(ICoreImageCollection other) => Equals(other as ICorePlayableCollectionGroup); /// public bool Equals(ICoreUrlCollection other) => Equals(other as ICorePlayableCollectionGroup); /// public bool Equals(ICorePlayableCollectionGroup? other) { return Equals(other as TCoreBase); } /// /// Overrides the default equality comparer. /// /// The object to compare. /// True if this is a match, otherwise false. public virtual bool Equals(TCoreBase? other) { return other != null && other.Name.Equals(Name, StringComparison.InvariantCulture); } /// public async ValueTask DisposeAsync() { if (_isDisposed) return; using (await OwlCore.Flow.EasySemaphore(_disposeSemaphore)) { if (_isDisposed) return; DetachCollectionChangedEvents(); DetachPropertyChangedEvents(PreferredSource); await _albumCollectionMap.DisposeAsync(); await _artistCollectionMap.DisposeAsync(); await _playableCollectionGroupMap.DisposeAsync(); await _playlistCollectionMap.DisposeAsync(); await _trackCollectionMap.DisposeAsync(); await _imageCollectionMap.DisposeAsync(); await _urlCollectionMap.DisposeAsync(); await Sources.InParallel(x => x.DisposeAsync().AsTask()); _isDisposed = true; } } } }