/// <summary> /// Add a list of songs to the playlist /// </summary> /// <param name="playlist"></param> /// <param name="songs"></param> public void AddSongs(IEnumerable <Song> songs) { List <SongPlaylistItem> songPlaylistItems = new(); // For each song create a PlayListItem and add to the PlayList foreach (Song song in songs) { song.Artist = Artists.GetArtistById(ArtistAlbums.GetArtistAlbumById(song.ArtistAlbumId).ArtistId); SongPlaylistItem itemToAdd = new() { Artist = song.Artist, PlaylistId = Id, Song = song, SongId = song.Id, Index = PlaylistItems.Count }; songPlaylistItems.Add(itemToAdd); PlaylistItems.Add(itemToAdd); } // No need to wait for this DbAccess.InsertAllAsync(songPlaylistItems); }
/// <summary> /// Read all the managed collections and then tell any registered listeners /// </summary> private static async void ReadManagedCollections() { await Songs.GetDataAsync(); await Albums.GetDataAsync(); await Sources.GetDataAsync(); await Artists.GetDataAsync(); await ArtistAlbums.GetDataAsync(); await Libraries.GetDataAsync(); await Playback.GetDataAsync(); await Playlists.GetDataAsync(); await Autoplays.GetDataAsync(); await Tags.GetDataAsync(); await TaggedAlbums.GetDataAsync(); await GenrePopulations.GetDataAsync(); // Carry out some one-off data linking await PopulateArtistsAsync(); await FilterManagementController.FormGenreTagsAsync(); DataAvailable = true; new StorageDataAvailableMessage().Send(); }
/// <summary> /// Get an existing or new ArtistAlbum entry to hold the songs associated with a particular Artist /// </summary> /// <param name="songArtist"></param> /// <param name="songAlbum"></param> /// <returns></returns> private async Task <ArtistAlbum> GetArtistAlbumToHoldSongsAsync(Artist songArtist, Album songAlbum) { ArtistAlbum songArtistAlbum = null; // Find an existing or create a new ArtistAlbum entry songArtistAlbum = songArtist.ArtistAlbums.SingleOrDefault(p => (p.Name.ToUpper() == songAlbum.Name.ToUpper())); Logger.Log(string.Format("ArtistAlbum: {0} {1}", songAlbum.Name, (songArtistAlbum != null) ? "found" : "not found creating in db")); if (songArtistAlbum == null) { // Create a new ArtistAlbum and add it to the database and the Artist songArtistAlbum = new ArtistAlbum() { Name = songAlbum.Name, Album = songAlbum, Songs = new List <Song>(), ArtistId = songArtist.Id, Artist = songArtist, AlbumId = songAlbum.Id }; await ArtistAlbums.AddArtistAlbumAsync(songArtistAlbum); songArtist.ArtistAlbums.Add(songArtistAlbum); } else { // Get the children of the existing ArtistAlbum if (songArtistAlbum.Songs == null) { songArtistAlbum.Songs = Songs.GetArtistAlbumSongs(songArtistAlbum.Id); } } return(songArtistAlbum); }
/// <summary> /// Duplicate the SongPlaylist in the specified library /// </summary> /// <param name="playlistToDuplicate"></param> /// <returns></returns> private static async void DuplicateSongPlaylistAsync(SongPlaylist playlistToDuplicate, int libraryId) { // Attempt to find matching songs for each SongPlaylistItem in the SongPlaylist // Need to access the songs via the Sources associated with the Library List <Source> sources = Sources.GetSourcesForLibrary(libraryId); // Keep track of the matching songs List <Song> songsToAdd = new(); foreach (SongPlaylistItem item in playlistToDuplicate.PlaylistItems) { Song matchingSong = null; int sourceIndex = 0; while ((matchingSong == null) && (sourceIndex < sources.Count)) { // Get a list of all the songs with matching Titles in the source List <Song> matchingTitles = Songs.GetSourceSongsWithName(sources[sourceIndex++].Id, item.Song.Title); // Now for each song access the associated artist int titleIndex = 0; while ((matchingSong == null) && (titleIndex < matchingTitles.Count)) { Artist nameCheck = Artists.GetArtistById(ArtistAlbums.GetArtistAlbumById(matchingTitles[titleIndex].ArtistAlbumId).ArtistId); // Correct name? if (nameCheck.Name == item.Artist.Name) { matchingSong = matchingTitles[titleIndex]; songsToAdd.Add(matchingSong); // Make sure that the Artist is stored with the song matchingSong.Artist = nameCheck; } titleIndex++; } } } // Only create the playlist if at least one of the songs was found if (songsToAdd.Count > 0) { SongPlaylist duplicatedPlaylist = new() { Name = playlistToDuplicate.Name, LibraryId = libraryId }; // Wait for the playlist to be added as we're going to use its id await Playlists.AddPlaylistAsync(duplicatedPlaylist); // Add the songs to the new SongPlaylist. duplicatedPlaylist.AddSongs(songsToAdd); } }
/// <summary> /// Get the PlaylistItems and associated songs for this playlist /// </summary> /// <param name="playlistItems"></param> public void GetContents(IEnumerable <SongPlaylistItem> playlistItems) { // Get all the SongPlaylistItem entries associated with this SongPlaylist and then the Song entries for each of them PlaylistItems.AddRange(playlistItems.Where(item => item.PlaylistId == Id)); foreach (SongPlaylistItem playlistItem in PlaylistItems) { playlistItem.Song = Songs.GetSongById(playlistItem.SongId); playlistItem.Artist = Artists.GetArtistById(ArtistAlbums.GetArtistAlbumById(playlistItem.Song.ArtistAlbumId).ArtistId); playlistItem.Song.Artist = playlistItem.Artist; } PlaylistItems.Sort((a, b) => a.Index.CompareTo(b.Index)); }
/// <summary> /// Called to handle the command. /// </summary> /// <param name="commandIdentity"></param> public override void HandleCommand(int commandIdentity) { List <string> selectedGenres = new List <string>(); // If an Artist has been selected then the starting point for generation will be the albums associated with the Artist. // If an Album has been selected then that album will be the starting point. // If a Song has been selected then that song will be the starting point. if (selectedObjects.Artists.Count > 0) { // Get all the genres associated with all the selected artists foreach (Artist selectedArtist in selectedObjects.Artists) { foreach (ArtistAlbum artistAlbum in selectedArtist.ArtistAlbums) { selectedGenres.AddRange(artistAlbum.Album.Genre.Split(';').ToList()); } } } else if (selectedObjects.ArtistAlbums.Count > 0) { // Get all the genres associated with the albums from all the selected artistalbums foreach (ArtistAlbum selectedArtistAlbum in selectedObjects.ArtistAlbums) { selectedGenres.AddRange(selectedArtistAlbum.Album.Genre.Split(';').ToList()); } } else if (selectedObjects.Albums.Count > 0) { // Get all the genres associated with the albums from all the selected albums foreach (Album selectedAlbum in selectedObjects.Albums) { selectedGenres.AddRange(selectedAlbum.Genre.Split(';').ToList()); } } else if (selectedObjects.Songs.Count > 0) { foreach (Song selectedSong in selectedObjects.Songs) { selectedGenres.AddRange(ArtistAlbums.GetArtistAlbumById(selectedSong.ArtistAlbumId).Album.Genre.Split(';').ToList()); } } // Make genre list unique selectedGenres = selectedGenres.Distinct().ToList(); AutoplayController.StartAutoplay(selectedObjects.Songs, selectedGenres, commandIdentity == Resource.Id.auto_play); commandCallback.PerformAction(); }
/// <summary> /// Categorise the specified selected objects /// </summary> /// <param name="selectedObjects"></param> public GroupedSelection(IEnumerable <object> selectedObjects) { // Save the unprocessed objects. SelectedObjects = selectedObjects; // Group the objects into sets of Song, PlaylistItem, IPlaylist, Artist, ArtistAlbum, Album and Genre (string) items foreach (object selectedObject in selectedObjects) { if (selectedObject is Song song) { Songs.Add(song); } else if (selectedObject is PlaylistItem playlistItem) { PlaylistItems.Add(playlistItem); } else if (selectedObject is Playlist playlist) { Playlists.Add(playlist); } else if (selectedObject is Artist artist) { Artists.Add(artist); } else if (selectedObject is ArtistAlbum artistAlbum) { ArtistAlbums.Add(artistAlbum); } else if (selectedObject is Album album) { Albums.Add(album); } else if (selectedObject is string str) { Genres.Add(str); } } // Determine if there is a parent playlist if (PlaylistItems.Count > 0) { ParentPlaylist = DBTest.Playlists.GetParentPlaylist(PlaylistItems[0]); } }
/// <summary> /// Clear the contents of the specified library /// </summary> /// <param name="libraryToClear"></param> /// <returns></returns> public static void ClearLibrary(Library libraryToClear) { int libId = libraryToClear.Id; // Delete all the artists in the library and their associated ArtistAlbum entries List <Artist> artists = Artists.ArtistCollection.Where(art => art.LibraryId == libId).ToList(); Artists.DeleteArtists(artists); ArtistAlbums.DeleteArtistAlbums( ArtistAlbums.ArtistAlbumCollection.Where(artAlb => artists.Any(art => art.Id == artAlb.ArtistId)).Distinct().ToList()); // Delete all the albums in the library and any tags associated with them List <Album> albums = Albums.AlbumCollection.Where(alb => alb.LibraryId == libId).ToList(); Albums.DeleteAlbums(albums); // We can use the FilterManagementController to carry out the Tag deletions. new AlbumsDeletedMessage() { DeletedAlbumIds = albums.Select(alb => alb.Id).ToList() }.Send(); // Delete all the user playlists and thier contents Playlists.GetPlaylistsForLibrary(libId).ForEach(play => Playlists.DeletePlaylist(play)); // Delete the contents of the NowPlayingList but keep the playlist itself Playlist nowPlaying = Playlists.GetNowPlayingPlaylist(libId); nowPlaying.Clear(); nowPlaying.SongIndex = -1; // Delete all the songs in each of the sources associated with the library List <Source> sources = Sources.GetSourcesForLibrary(libId); foreach (Source source in sources) { Songs.DeleteSongs(Songs.GetSourceSongs(source.Id)); source.Songs = null; } }
/// <summary> /// Called to determine whether a song that has been scanned requires adding to the library, or just an existing entry updated /// </summary> /// <param name="song"></param> /// <returns></returns> private async Task <bool> DoesSongRequireAdding(ScannedSong song) { bool needsAdding = true; // Lookup the path of this song in the dictionary if ((songLookup.TryGetValue(song.SourcePath, out Song matchedSong) == true) && (matchedSong.ScanAction == Song.ScanActionType.Differ)) { // The library is about to be changed in some way so set the modified flag LibraryModified = true; // Need to check whether the matched Artist or Album names have changed. If they have then treat this as a new song and mark // the matched song for deletion ArtistAlbum matchedArtistAlbum = ArtistAlbums.GetArtistAlbumById(matchedSong.ArtistAlbumId); Artist matchedArtist = Artists.GetArtistById(matchedArtistAlbum.ArtistId); // If the artist or album name has changed then treat this as a new song. Otherwise update the existing song in the library if ((matchedArtist.Name.ToUpper() != song.ArtistName.ToUpper()) || (matchedArtistAlbum.Name.ToUpper() != song.Tags.Album.ToUpper())) { // The existing song needs to be deleted now. // If the song is not deleted then there will be more than one associated with the same storage location. // This is much less complicated than trying to move the existing song to a new Artist or Album // If an Artist has been deleted due to this song deletion then remove it from the dictionary being used here Artist deletedArtist = LibraryScanController.DeleteSong(matchedSong); if (deletedArtist != null) { artistsInLibrary.Remove(deletedArtist.Name.ToUpper()); } matchedSong.ScanAction = Song.ScanActionType.Matched; } else { // No need to add a new song, update the existing one needsAdding = false; matchedSong.Length = song.Length; matchedSong.ModifiedTime = song.Modified; matchedSong.Title = song.Tags.Title; matchedSong.Track = song.Track; await ConnectionDetailsModel.AsynchConnection.UpdateAsync(matchedSong); // Check if the year or genre fields on the album needs updating // Don't update the Album if it is a 'various artists' album as the these fields is not applicable Album matchedAlbum = Albums.GetAlbumById(matchedArtistAlbum.AlbumId); if (matchedAlbum.ArtistName != SongStorage.VariousArtistsString) { // Update the stored year if it is different to the artist year and the artist year is defined. // Log when a valid year is overwritten by different year if (matchedAlbum.Year != song.Year) { if (song.Year != 0) { matchedAlbum.Year = song.Year; await ConnectionDetailsModel.AsynchConnection.UpdateAsync(matchedAlbum); } } if (song.Tags.Genre.Length > 0) { // If this album does not already have a genre, or the genre has been changed then set it now if ((matchedAlbum.Genre == null) || (matchedAlbum.Genre != song.Tags.Genre)) { matchedAlbum.Genre = song.Tags.Genre; await ConnectionDetailsModel.AsynchConnection.UpdateAsync(matchedAlbum); } } } } } return(needsAdding); }