From 105a61c11f7cc7ac10f15535555ef16d20af83db Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Fri, 12 Feb 2016 17:19:32 -0600 Subject: [PATCH] Reworking media scanning to handle multiple artists/albums. Untested. --- .../com/jdbernard/wdiwtlt/MediaLibrary.groovy | 97 ++++++++++++------- 1 file changed, 60 insertions(+), 37 deletions(-) diff --git a/core/src/main/groovy/com/jdbernard/wdiwtlt/MediaLibrary.groovy b/core/src/main/groovy/com/jdbernard/wdiwtlt/MediaLibrary.groovy index e3091ad..774f316 100644 --- a/core/src/main/groovy/com/jdbernard/wdiwtlt/MediaLibrary.groovy +++ b/core/src/main/groovy/com/jdbernard/wdiwtlt/MediaLibrary.groovy @@ -63,29 +63,29 @@ public class MediaLibrary { mf.name = fileTag?.getFirst(TITLE)?.trim() ?: f.name mf.filePath = relPath - mf.comment = fileTag?.getFirst(COMMENT)?.trim() + mf.comment = fileTag?.getAll(COMMENT)?.collect { it.trim() }.join('\n\n') mf.trackNumber = safeToInteger(fileTag?.getFirst(TRACK)) def folderParts = mf.filePath.split("[\\\\/]")[1..<-1] as LinkedList // Find artist and album names (if any) - def artistName = fileTag?.getFirst(ARTIST)?.trim() - def albumName = fileTag?.getFirst(ALBUM)?.trim() + def artistNames = fileTag?.getAll(ARTIST)?.collect { it.trim() } + def albumNames = fileTag?.getAll(ALBUM)?.collect { it.trim() } - if (!artistName) { + if (!artistNames) { mf.metaInfoSource = MediaFile.FILE_LOCATION - artistName = folderParts.size() >= 2 ? folderParts[0] : null } + artistNames = folderParts.size() >= 2 ? [folderParts[0]] : [] } - if (!albumName) { + if (!albumNames) { mf.metaInfoSource = MediaFile.FILE_LOCATION - albumName = folderParts.peekLast() } + albumNames = [folderParts.peekLast()] } // Hash the file mf.fileHash = f.withInputStream { DigestUtils.md5Hex(it) } orm.withTransaction { orm.create(mf) - associateWithArtistAndAlbum(mf, artistName, albumName, fileTag) + associateWithArtistsAndAlbums(mf, artistNames, albumNames, fileTag) } } @@ -98,42 +98,65 @@ public class MediaLibrary { return match } public List getArtistsByName(String name) { - return orm.getArtistByName(name) ?: orm.getArtistsLikeName(name) } + return [orm.getArtistByName(name)] ?: orm.getArtistsLikeName(name) } public List getAlbumsByName(String name) { - return orm.getAlbumByName(name) ?: orm.getAlbumsLikeName(name) } + return orm.getAlbumsByName(name) ?: orm.getAlbumsLikeName(name) } - private void associateWithArtistAndAlbum(MediaFile mf, String artistName, - String albumName, JATag fileTag) { - Artist artist = null - Album album = null - boolean newAlbumOrArtist = false + private void associateWithArtistsAndAlbums(MediaFile mf, String artistNames, + String albumNames, Integer albumYear) { - if (artistName) { - artist = orm.getArtistByName(artistName) - if (!artist) { - newAlbumOrArtist = true - artist = new Artist(name: artistName) - orm.create(artist) } } + def albums = [] - if (albumName) { - album = orm.getAlbumByName(albumName) - if (!album) { - newAlbumOrArtist = true - try { - album = new Album(name: albumName, - year: safeToInteger(fileTag?.getFirst(YEAR)), - trackTotal: safeToInteger(fileTag?.getFirst(TRACK_TOTAL))) } - catch (UnsupportedOperationException use) { - album = new Album(name: albumName, - year: safeToInteger(fileTag?.getFirst(YEAR))) } - orm.create(album) } } + // Find or create artists. + def artists = artistNames.collect { artistName -> + Artist artist = orm.getArtistByName(artistName) + if (!artist) artist = orm.create(new Artist(name: artistName)) + return artist } - if (artist && album && newAlbumOrArtist) - orm.addAlbumArtist(album.id, artist.id) + // Associate file with artists. + artists.each { orm.associate(artist, mf) } - if (artist) orm.associateMediaFileWithArtist(mf.id, artist.id) - if (album) orm.associateMediaFileWithAlbum(mf.id, album.id) + // Find or create albums + def albums = albumNames.collect { albumName -> + Album album + + // If we know what year the album was released we can use that to + // narrow down the list of matching albums. + if (albumYear != null) { + // Look first to see if we already know about this album + // associated with one of the artists for this piece. + album = artists.inject(null, { foundAlbum, artist -> + if (foundAlbum) return foundAlbum + return orm.getAlbumByNameAndYearAndArtistId(albumName, + albumYear, artist.id) } + // If we don't have it with one of the artists, see if we have + // one that matches the name and year. + if (!album) + album = orm.getAlbumByNameAndYear(albumName, albumYear) } + + else { + album = artists.inject(null, { foundAlbum, artist -> + if (foundAlbum) return foundAlbum + return orm.getAlbumByNameAndArtistId(albumName, artist.id) } + if (!album) { + def foundAlbums = org.getAlbumsByName(albumName) + album = foundAlbums ? foundAlbums[0] : 0 } } + + // We still can't find the album at all. We'll need to create it + if (!album) + album = orm.create(new Album(name: albumName, albumYear)) + + return album } + + // Associate file with albums + albums.each { orm.associate(album, mf) } + + // Make sure we have association between all of the artists and albums. + artists.each { artist -> + def albumsForArtist = orm.getAlbumsByArtistId(artist.id) + def albumsMissing = albums - albumsForArtist + albumsMissing.each { album -> orm.associate(artist, album) } } } /** #### `getRelativePath`