Reworking media scanning to handle multiple artists/albums. Untested.

This commit is contained in:
Jonathan Bernard 2016-02-12 17:19:32 -06:00
parent b4ce76063b
commit 105a61c11f

View File

@ -63,29 +63,29 @@ public class MediaLibrary {
mf.name = fileTag?.getFirst(TITLE)?.trim() ?: f.name mf.name = fileTag?.getFirst(TITLE)?.trim() ?: f.name
mf.filePath = relPath 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)) mf.trackNumber = safeToInteger(fileTag?.getFirst(TRACK))
def folderParts = mf.filePath.split("[\\\\/]")[1..<-1] as LinkedList def folderParts = mf.filePath.split("[\\\\/]")[1..<-1] as LinkedList
// Find artist and album names (if any) // Find artist and album names (if any)
def artistName = fileTag?.getFirst(ARTIST)?.trim() def artistNames = fileTag?.getAll(ARTIST)?.collect { it.trim() }
def albumName = fileTag?.getFirst(ALBUM)?.trim() def albumNames = fileTag?.getAll(ALBUM)?.collect { it.trim() }
if (!artistName) { if (!artistNames) {
mf.metaInfoSource = MediaFile.FILE_LOCATION 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 mf.metaInfoSource = MediaFile.FILE_LOCATION
albumName = folderParts.peekLast() } albumNames = [folderParts.peekLast()] }
// Hash the file // Hash the file
mf.fileHash = f.withInputStream { DigestUtils.md5Hex(it) } mf.fileHash = f.withInputStream { DigestUtils.md5Hex(it) }
orm.withTransaction { orm.withTransaction {
orm.create(mf) orm.create(mf)
associateWithArtistAndAlbum(mf, artistName, albumName, fileTag) associateWithArtistsAndAlbums(mf, artistNames, albumNames, fileTag)
} }
} }
@ -98,42 +98,65 @@ public class MediaLibrary {
return match } return match }
public List<Artist> getArtistsByName(String name) { public List<Artist> getArtistsByName(String name) {
return orm.getArtistByName(name) ?: orm.getArtistsLikeName(name) } return [orm.getArtistByName(name)] ?: orm.getArtistsLikeName(name) }
public List<Album> getAlbumsByName(String name) { public List<Album> getAlbumsByName(String name) {
return orm.getAlbumByName(name) ?: orm.getAlbumsLikeName(name) } return orm.getAlbumsByName(name) ?: orm.getAlbumsLikeName(name) }
private void associateWithArtistAndAlbum(MediaFile mf, String artistName, private void associateWithArtistsAndAlbums(MediaFile mf, String artistNames,
String albumName, JATag fileTag) { String albumNames, Integer albumYear) {
Artist artist = null
Album album = null
boolean newAlbumOrArtist = false
if (artistName) { def albums = []
artist = orm.getArtistByName(artistName)
if (!artist) {
newAlbumOrArtist = true
artist = new Artist(name: artistName)
orm.create(artist) } }
if (albumName) { // Find or create artists.
album = orm.getAlbumByName(albumName) def artists = artistNames.collect { artistName ->
Artist artist = orm.getArtistByName(artistName)
if (!artist) artist = orm.create(new Artist(name: artistName))
return artist }
// Associate file with artists.
artists.each { orm.associate(artist, mf) }
// 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) { if (!album) {
newAlbumOrArtist = true def foundAlbums = org.getAlbumsByName(albumName)
try { album = foundAlbums ? foundAlbums[0] : 0 } }
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) } }
if (artist && album && newAlbumOrArtist) // We still can't find the album at all. We'll need to create it
orm.addAlbumArtist(album.id, artist.id) if (!album)
album = orm.create(new Album(name: albumName, albumYear))
if (artist) orm.associateMediaFileWithArtist(mf.id, artist.id) return album }
if (album) orm.associateMediaFileWithAlbum(mf.id, album.id)
// 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` /** #### `getRelativePath`