/// <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> /// Delete the specified ArtistAlbum from the storage and the collections /// </summary> /// <param name="artistAlbumToDelete"></param> /// <returns></returns> public static void DeleteArtistAlbum(ArtistAlbum artistAlbumToDelete) { // No need to wait for the ArtistAlbum to be deleted from storage DbAccess.DeleteAsync(artistAlbumToDelete); ArtistAlbumCollection.Remove(artistAlbumToDelete); IdLookup.Remove(artistAlbumToDelete.Id); }
public void GetArtistAlbumSongs(ArtistAlbum artistAlbum) { if (artistAlbum.Songs == null) { artistAlbum.Songs = Songs.GetArtistAlbumSongs(artistAlbum.Id); artistAlbum.Songs.Sort((a, b) => a.Track.CompareTo(b.Track)); } }
/// <summary> /// Add a new ArtistAlbum to the storage and the local collections /// </summary> /// <param name="artistAlbumToAdd"></param> public static async Task AddArtistAlbumAsync(ArtistAlbum artistAlbumToAdd) { ArtistAlbumCollection.Add(artistAlbumToAdd); // Need to wait for the ArtistAlbum to be added as that will set its ID await DbAccess.InsertAsync(artistAlbumToAdd); IdLookup[artistAlbumToAdd.Id] = artistAlbumToAdd; }
/// <summary> /// Either find an existing album or create a new album to hold the songs. /// If all songs are from the same artist then check is there is an existing album of the same name associated with that artist. /// If the songs are from different artists then check in the "Various Artists" artist. /// These artists may not exist at this stage /// </summary> /// <returns></returns> private async Task <Album> GetAlbumToHoldSongsAsync(ScannedAlbum album) { Album songAlbum = null; string artistName = (album.SingleArtist == true) ? album.Songs[0].ArtistName : VariousArtistsString; // Check if the artist already exists in the library. Artist songArtist = artistsInLibrary.GetValueOrDefault(artistName.ToUpper()); // If the artist exists then check for existing album. The artist will hold ArtistAlbum entries rather than Album entries, but the ArtistAlbum entries // have the same name as the albums. Cannot just use the album name as that may not be unique. if (songArtist != null) { ArtistAlbum songArtistAlbum = songArtist.ArtistAlbums.SingleOrDefault(p => (p.Name.ToUpper() == album.Songs[0].Tags.Album.ToUpper())); if (songArtistAlbum != null) { songAlbum = songArtistAlbum.Album; // The rest of the code expects the Album to have its songs populated, so check here songAlbum.GetSongs(); } } Logger.Log(string.Format("Album: {0} {1} for artist {2}", album.Name, (songAlbum != null) ? "found" : "not found", artistName)); // If no existing album create a new one if (songAlbum == null) { songAlbum = new Album() { Name = album.Name, Songs = new List <Song>(), LibraryId = scanLibrary }; await Albums.AddAlbumAsync(songAlbum); } return(songAlbum); }
public void DisplayAlbum(ArtistAlbum artistAlbum, bool actionMode) { // Save the default colour if not already done so if (albumNameColour == Color.Fuchsia) { albumNameColour = new Color(AlbumName.CurrentTextColor); } AlbumName.Text = artistAlbum.Name; AlbumName.SetTextColor((artistAlbum.Album.Played == true) ? Color.Black : albumNameColour); // A very nasty workaround here. If action mode is in effect then remove the AlignParentLeft from the album name. // When the Checkbox is being shown then the album name can be positioned between the checkbox and the album year, // but when there is no checkbox this does not work and the name has to be aligned with the parent. // This seems to be too complicated for static layout ((RelativeLayout.LayoutParams)AlbumName.LayoutParameters).AddRule(LayoutRules.AlignParentLeft, (actionMode == true) ? 0 : 1); // Set the year text Year.Text = (artistAlbum.Album.Year > 0) ? artistAlbum.Album.Year.ToString() : " "; // Display the genres. Replace any spaces in the genres with non-breaking space characters. This prevents a long genres string with a // space near the start being broken at the start, It just looks funny. Genre.Text = artistAlbum.Album.Genre.Replace(' ', '\u00a0'); }
/// <summary> /// Get the contents for the specified ArtistAlbum /// </summary> /// <param name="artistAlbum"></param> /// <returns></returns> public static void GetArtistAlbumContents(ArtistAlbum artistAlbum) => artistAlbum.Artist.GetArtistAlbumSongs(artistAlbum);
/// <summary> /// Called to process a group of songs belonging to the same album name ( but not necessarily the same artist ) /// </summary> /// <param name="album"></param> private async Task StoreAlbumAsync(ScannedAlbum album) { // Set the modified flag LibraryModified = true; Logger.Log(string.Format("Album: {0} Single artist: {1}", album.Name, album.SingleArtist)); // Get an existing or new Album entry for the songs Album songAlbum = await GetAlbumToHoldSongsAsync(album); // Keep track of Artist and ArtistAlbum entries in case they can be reused for different artists ArtistAlbum songArtistAlbum = null; Artist songArtist = null; // Add all the songs in the album foreach (ScannedSong songScanned in album.Songs) { // If there is no existing Artist entry or the current one if for the wrong Artist name then get or create a new one if ((songArtist == null) || (songArtist.Name != songScanned.ArtistName)) { // As this is a new Artist the ArtistAlbum needs to be re-initialised. if (songArtistAlbum != null) { songArtistAlbum.Songs.Sort((a, b) => a.Track.CompareTo(b.Track)); } songArtistAlbum = null; // Find the Artist for this song songArtist = await GetArtistToHoldSongsAsync(songScanned.ArtistName); } // If there is an existing ArtistAlbum then use it as it will be for the correct Artist, i.e. not cleared above if (songArtistAlbum == null) { // Find an existing or create a new ArtistAlbum entry songArtistAlbum = await GetArtistAlbumToHoldSongsAsync(songArtist, songAlbum); } // Add the song to the database, the album and the album artist Song songToAdd = new() { Title = songScanned.Tags.Title, Track = songScanned.Track, Path = songScanned.SourcePath, ModifiedTime = songScanned.Modified, Length = songScanned.Length, AlbumId = songAlbum.Id, ArtistAlbumId = songArtistAlbum.Id, SourceId = sourceBeingScanned.Id }; // No need to wait for this Songs.AddSongAsync(songToAdd); Logger.Log(string.Format("Artist: {0} Title: {1} Track: {2} Modified: {3} Length {4} Year {5}", songScanned.Tags.Artist, songScanned.Tags.Title, songScanned.Tags.Track, songScanned.Modified, songScanned.Length, songScanned.Year)); // Add to the Album songAlbum.Songs.Add(songToAdd); // Keep track whether or not to update the album bool updateAlbum = false; // Store the artist name with the album if ((songAlbum.ArtistName == null) || (songAlbum.ArtistName.Length == 0)) { songAlbum.ArtistName = songArtist.Name; updateAlbum = true; } else { // The artist has already been stored - check if it is the same artist if (songAlbum.ArtistName != songArtist.Name) { songAlbum.ArtistName = VariousArtistsString; updateAlbum = true; } } // Update the album year if not already set and this song has a year set if ((songAlbum.Year != songScanned.Year) && (songAlbum.Year == 0)) { songAlbum.Year = songScanned.Year; updateAlbum = true; } // Update the album genre. // Only try updating if a genre is defined for the song // If the album does not have a genre then get one for the song and store it in the album if ((songScanned.Tags.Genre.Length > 0) && (songAlbum.Genre.Length == 0)) { songAlbum.Genre = songScanned.Tags.Genre; updateAlbum = true; } if (updateAlbum == true) { await ConnectionDetailsModel.AsynchConnection.UpdateAsync(songAlbum); } // Add to the source sourceBeingScanned.Songs.Add(songToAdd); // Add to the ArtistAlbum songArtistAlbum.Songs.Add(songToAdd); } if (songArtistAlbum != null) { songArtistAlbum.Songs.Sort((a, b) => a.Track.CompareTo(b.Track)); } }
/// <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); }