/// <summary>
        /// Add the songs from the playlist to the Now Playing list
        /// If this set is replacing the current contents (clearFirst == true ) then clear the Now Playimng list
        /// first.
        /// If a resume has been selected and the current contents are being replaced then add all of the
        /// playlist's songs but set the current song to the resume point. If resume has been selected and the playlist is
        /// being added to then only add the playlist songs from its resume point. Don't change the resume point in the source playlist.
        /// If resume has not been selected then add all the playlist's contents and reset the playlist's restore point
        /// </summary>
        /// <param name="playlistToAdd"></param>
        /// <param name="clearFirst"></param>
        /// <param name="resume"></param>
        public static void AddPlaylistToNowPlayingList(Playlist playlistToAdd, bool clearFirst, bool resume)
        {
            // Should the Now Playing playlist be cleared first
            if (clearFirst == true)
            {
                ClearNowPlayingList();
            }

            // Assume we're going to play a new list from the start
            int newCurrentIndex = 0;

            if (resume == true)
            {
                if (clearFirst == true)
                {
                    NowPlayingViewModel.NowPlayingPlaylist.AddSongs(playlistToAdd.GetSongsForPlayback(false));
                    newCurrentIndex = playlistToAdd.InProgressIndex;
                }
                else
                {
                    NowPlayingViewModel.NowPlayingPlaylist.AddSongs(playlistToAdd.GetSongsForPlayback(true));
                }
            }
            else
            {
                NowPlayingViewModel.NowPlayingPlaylist.AddSongs(ApplyShuffle(playlistToAdd.GetSongsForPlayback(false)));
                playlistToAdd.SongIndex = 0;
            }

            // If the Now Playing list was cleared then play the specified song
            SetStartingPointForNewList(clearFirst, newCurrentIndex);

            // Report change to UI
            DataReporter?.DataAvailable();
        }
Example #2
0
 /// <summary>
 /// Called when a AlbumPlayedStateChangedMessage had been received.
 /// If the album is in the library being displayed then refresh the display
 /// </summary>
 /// <param name="message"></param>
 private static void AlbumChanged(Album changedAlbum)
 {
     // Only process this album if it is in the same library as is being displayed
     // It may be in another library if this is being called as part of a library synchronisation process
     if (changedAlbum.LibraryId == ArtistsViewModel.LibraryId)
     {
         DataReporter?.DataAvailable();
     }
 }
Example #3
0
 /// <summary>
 /// Called when a AlbumPlayedStateChangedMessage had been received.
 /// If this album is being displayed then inform the adapter of the data change
 /// </summary>
 /// <param name="changedAlbum"></param>
 private static void AlbumChanged(Album changedAlbum)
 {
     // Only process this if this album is in the library being displayed
     if (changedAlbum.LibraryId == AlbumsViewModel.LibraryId)
     {
         // Is this album being displayed
         if (AlbumsViewModel.Albums.Any(album => album.Id == changedAlbum.Id) == true)
         {
             DataReporter?.DataAvailable();
         }
     }
 }
Example #4
0
        /// <summary>
        /// Sort the Artists according to the currently selected sort order
        /// </summary>
        public static void SortArtists() => Task.Run(() =>
        {
            // Clear the indexing collections (in case they are not used in the new sort order)
            ArtistsViewModel.FastScrollSections      = null;
            ArtistsViewModel.FastScrollSectionLookup = null;

            switch (ArtistsViewModel.BaseModel.SortSelector.CurrentSortOrder)
            {
            case SortSelector.SortOrder.alphaDescending:
            case SortSelector.SortOrder.alphaAscending:
                {
                    if (ArtistsViewModel.BaseModel.SortSelector.CurrentSortOrder == SortSelector.SortOrder.alphaAscending)
                    {
                        ArtistsViewModel.Artists.Sort((a, b) => a.Name.RemoveThe().CompareTo(b.Name.RemoveThe()));
                    }
                    else
                    {
                        ArtistsViewModel.Artists.Sort((a, b) => b.Name.RemoveThe().CompareTo(a.Name.RemoveThe()));
                    }

                    // Prepare the combined Artist/ArtistAlbum list - this has to be done after the Artists have been sorted but before the scroll indexing
                    PrepareCombinedList();

                    // Generate the fast scroll data for alpha sorting
                    GenerateIndex((artist) => artist.Name.RemoveThe().Substring(0, 1).ToUpper());

                    break;
                }

            case SortSelector.SortOrder.idAscending:
            case SortSelector.SortOrder.idDescending:
                {
                    if (ArtistsViewModel.BaseModel.SortSelector.CurrentSortOrder == SortSelector.SortOrder.idAscending)
                    {
                        ArtistsViewModel.Artists.Sort((a, b) => a.Id.CompareTo(b.Id));
                    }
                    else
                    {
                        ArtistsViewModel.Artists.Sort((a, b) => b.Id.CompareTo(a.Id));
                    }

                    // Prepare the combined Artist/ArtistAlbum list - this has to be done after the Artists have been sorted.
                    // No fast scroll indexing is required for Id sort order
                    PrepareCombinedList();

                    break;
                }
            }

            // Publish the data
            DataReporter?.DataAvailable();
        });
        /// <summary>
        /// Called when the SongPlaylist data is available to be displayed, or needs to be refreshed
        /// </summary>
        private static void StorageDataAvailable()
        {
            // Save the libray being used locally to detect changes
            NowPlayingViewModel.LibraryId = ConnectionDetailsModel.LibraryId;

            // Get the NowPlaying playlist.
            NowPlayingViewModel.NowPlayingPlaylist = ( SongPlaylist )Playlists.GetNowPlayingPlaylist(NowPlayingViewModel.LibraryId);

            // Let the playback manager know the current song but don't play it yet
            NowPlayingViewModel.CurrentSongIndex = Playlists.CurrentSongIndex;
            new PlaySongMessage()
            {
                SongToPlay = NowPlayingViewModel.CurrentSong, DontPlay = true
            }.Send();

            DataReporter?.DataAvailable();
        }
        /// <summary>
        /// Add a list of Songs to the Now Playing list
        /// </summary>
        /// <param name="songsToAdd"></param>
        /// <param name="clearFirst"></param>
        public static void AddSongsToNowPlayingList(IEnumerable <Song> songsToAdd, bool clearFirst)
        {
            // Should the Now Playing playlist be cleared first
            if (clearFirst == true)
            {
                ClearNowPlayingList();
            }

            // Add the songs to the playlist. Shuffled if necessary
            NowPlayingViewModel.NowPlayingPlaylist.AddSongs(ApplyShuffle(songsToAdd.ToList()));

            // If the Now Playing list was cleared then play the first song
            SetStartingPointForNewList(clearFirst, 0);

            // Report change to UI
            DataReporter?.DataAvailable();
        }
        /// <summary>
        /// Called during startup, or library change, when the storage data is available
        /// </summary>
        /// <param name="message"></param>
        private static async void StorageDataAvailable()
        {
            // Save the libray being used locally to detect changes
            PlaylistsViewModel.LibraryId = ConnectionDetailsModel.LibraryId;

            // Get the Playlists and playlist names. Make sure a copy of the list is used as we're going to sort it
            PlaylistsViewModel.Playlists     = Playlists.GetPlaylistsForLibrary(PlaylistsViewModel.LibraryId).ToList();
            PlaylistsViewModel.PlaylistNames = PlaylistsViewModel.Playlists.Select(i => i.Name).ToList();

            // To generate the data to be displayed the Playlists need to be sorted. Not a simple sort of course, but the SongPlaylists followed by the
            // AlbumPlaylists
            await Task.Run(() =>
            {
                PlaylistsViewModel.AlbumPlaylists.Clear();
                PlaylistsViewModel.SongPlaylists.Clear();

                foreach (Playlist playlist in PlaylistsViewModel.Playlists)
                {
                    if (playlist is SongPlaylist songPlaylist)
                    {
                        PlaylistsViewModel.SongPlaylists.Add(songPlaylist);
                    }
                    else
                    {
                        PlaylistsViewModel.AlbumPlaylists.Add(( AlbumPlaylist )playlist);
                    }
                }

                // Sort the playlists by name
                PlaylistsViewModel.SongPlaylists.Sort((a, b) => a.Name.CompareTo(b.Name));
                PlaylistsViewModel.AlbumPlaylists.Sort((a, b) => a.Name.CompareTo(b.Name));

                // Now copy to the combined list
                PlaylistsViewModel.Playlists.Clear();
                PlaylistsViewModel.Playlists.AddRange(PlaylistsViewModel.SongPlaylists);
                PlaylistsViewModel.Playlists.AddRange(PlaylistsViewModel.AlbumPlaylists);
            });

            DataReporter?.DataAvailable();
        }
        /// <summary>
        /// Called to delete one or more items from the Now Playing playlist.
        /// We need to determine the affect that this deletion may have on the index of the currently playing song.
        /// This can be done by examining the track numbers of the items to be deleted
        /// </summary>
        /// <param name="items"></param>
        public static void DeleteNowPlayingItems(IEnumerable <PlaylistItem> items)
        {
            // Record the currently selected song so its track number can be checked after the delete
            PlaylistItem currentPlaylistItem = null;

            // If the currently selected song is going to be deleted then invalidate it now
            // Only carry out these checks if a song has been selected
            if (NowPlayingViewModel.CurrentSongIndex != -1)
            {
                // Check if the items to delete contains the currently selected song
                if (items.Any(item => (item.Index == NowPlayingViewModel.CurrentSongIndex)) == true)
                {
                    // The currently selected song is going to be deleted. Set it to invalid
                    NowPlayingViewModel.CurrentSongIndex = -1;
                    new PlaySongMessage()
                    {
                        SongToPlay = NowPlayingViewModel.CurrentSong
                    }.Send();
                }
                else
                {
                    // Save the current item
                    currentPlaylistItem = NowPlayingViewModel.NowPlayingPlaylist.PlaylistItems[NowPlayingViewModel.CurrentSongIndex];
                }
            }

            // Delete the entries and report that the list has been updated
            NowPlayingViewModel.NowPlayingPlaylist.DeletePlaylistItems(items);

            // Adjust the track numbers
            NowPlayingViewModel.NowPlayingPlaylist.AdjustTrackNumbers();

            // Determine the index of the currently selected song from it's possibly new track number
            AdjustSelectedSongIndex(currentPlaylistItem);

            // Report change to UI
            DataReporter?.DataAvailable();
        }
Example #9
0
        /// <summary>
        /// Sort the available data according to the current sort option
        /// </summary>
        public static void SortData() => Task.Run(() =>
        {
            // Use the sort order stored in the model
            SortSelector.SortOrder sortOrder = AlbumsViewModel.BaseModel.SortSelector.CurrentSortOrder;

            // Clear the indexing collections (in case they are not used in the new sort order)
            AlbumsViewModel.FastScrollSections      = null;
            AlbumsViewModel.FastScrollSectionLookup = null;

            // Now do the sorting and indexing according to the sort order
            switch (sortOrder)
            {
            case SortSelector.SortOrder.alphaAscending:
            case SortSelector.SortOrder.alphaDescending:
                {
                    if (sortOrder == SortSelector.SortOrder.alphaAscending)
                    {
                        AlbumsViewModel.FilteredAlbums.Sort((a, b) => a.Name.RemoveThe().CompareTo(b.Name.RemoveThe()));
                    }
                    else
                    {
                        AlbumsViewModel.FilteredAlbums.Sort((a, b) => b.Name.RemoveThe().CompareTo(a.Name.RemoveThe()));
                    }

                    AlbumsViewModel.Albums = AlbumsViewModel.FilteredAlbums;
                    GenerateIndex((album, index) => album.Name.RemoveThe().Substring(0, 1).ToUpper());
                    break;
                }

            case SortSelector.SortOrder.idAscending:
            case SortSelector.SortOrder.idDescending:
                {
                    // If these entries are filtered then order them by the tag id rather than the album id
                    if (AlbumsViewModel.FilterSelector.CurrentFilter == null)
                    {
                        if (sortOrder == SortSelector.SortOrder.idAscending)
                        {
                            AlbumsViewModel.FilteredAlbums.Sort((a, b) => a.Id.CompareTo(b.Id));
                        }
                        else
                        {
                            AlbumsViewModel.FilteredAlbums.Sort((a, b) => b.Id.CompareTo(a.Id));
                        }
                    }
                    else
                    {
                        // Form a lookup table from album identity to index in tagged albums.
                        Dictionary <int, int> albumIdLookup = AlbumsViewModel.FilterSelector.CurrentFilter.TaggedAlbums
                                                              .Select((ta, index) => new { ta.AlbumId, index }).ToDictionary(pair => pair.AlbumId, pair => pair.index);

                        // Order the albums by the album id list
                        if (sortOrder == SortSelector.SortOrder.idAscending)
                        {
                            AlbumsViewModel.FilteredAlbums = AlbumsViewModel.FilteredAlbums.OrderBy(album => albumIdLookup[album.Id]).ToList();
                        }
                        else
                        {
                            AlbumsViewModel.FilteredAlbums = AlbumsViewModel.FilteredAlbums.OrderByDescending(album => albumIdLookup[album.Id]).ToList();
                        }
                    }

                    // No index required when sorted by Id
                    AlbumsViewModel.Albums = AlbumsViewModel.FilteredAlbums;
                    break;
                }

            case SortSelector.SortOrder.yearAscending:
            case SortSelector.SortOrder.yearDescending:
                {
                    if (sortOrder == SortSelector.SortOrder.yearAscending)
                    {
                        AlbumsViewModel.FilteredAlbums.Sort((a, b) => a.Year.CompareTo(b.Year));
                    }
                    else
                    {
                        AlbumsViewModel.FilteredAlbums.Sort((a, b) => b.Year.CompareTo(a.Year));
                    }

                    AlbumsViewModel.Albums = AlbumsViewModel.FilteredAlbums;
                    GenerateIndex((album, index) => album.Year.ToString());
                    break;
                }

            case SortSelector.SortOrder.genreAscending:
            case SortSelector.SortOrder.genreDescending:
                {
                    // If there is no GenreSortAlbums collection then make one now
                    if (AlbumsViewModel.GenreSortedAlbums == null)
                    {
                        GenerateGenreAlbumList();
                    }

                    // We want to keep the AlbumsViewModel.GenreSortedAlbums in ascending order.
                    // So rather than sort the AlbumsViewModel.GenreSortedAlbums we copy it and sort the copy.
                    AlbumsViewModel.Albums = AlbumsViewModel.GenreSortedAlbums.ToList();

                    // We only need to sort if the order is descending
                    if (sortOrder == SortSelector.SortOrder.genreDescending)
                    {
                        // Reverse it
                        AlbumsViewModel.Albums.Reverse();
                    }

                    // Generate the fast lookup indexes. If in reverse order do the genre lookup in reverse order as well
                    GenerateIndex((album, index) => AlbumsViewModel.AlbumIndexToGenreLookup[
                                      sortOrder == SortSelector.SortOrder.genreAscending ? index : AlbumsViewModel.Albums.Count - 1 - index]);

                    break;
                }
            }

            // Publish the data
            DataReporter?.DataAvailable();
        });