diff --git a/musikr/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt b/musikr/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt index 2b634ae5e..1d2bb75db 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt @@ -23,6 +23,7 @@ import org.oxycblt.musikr.playlist.SongPointer import org.oxycblt.musikr.playlist.interpret.PrePlaylist import org.oxycblt.musikr.tag.interpret.PreAlbum import org.oxycblt.musikr.tag.interpret.PreArtist +import org.oxycblt.musikr.tag.interpret.PreArtistsFrom import org.oxycblt.musikr.tag.interpret.PreGenre import org.oxycblt.musikr.tag.interpret.PreSong import org.oxycblt.musikr.util.unlikelyToBeNull @@ -75,7 +76,7 @@ private class MusicGraphBuilderImpl : MusicGraph.Builder { // Albums themselves have their own parent artists that also need to be // linked up. val albumArtistVertices = - preSong.preAlbum.preArtists.map { preArtist -> + preSong.preAlbum.preArtists.preArtists.map { preArtist -> artistVertices.getOrPut(preArtist) { ArtistVertex(preArtist) } } val albumVertex = AlbumVertex(preSong.preAlbum, albumArtistVertices.toMutableList()) @@ -288,7 +289,7 @@ private class MusicGraphBuilderImpl : MusicGraph.Builder { return } // No full MBID coverage, discard the MBIDs from the graph. - val strippedCluster = + val strippedMbidCluster = cluster.map { val noMbidPreAlbum = it.preAlbum.copy(musicBrainzId = null) val simpleMbidVertex = @@ -298,7 +299,31 @@ private class MusicGraphBuilderImpl : MusicGraph.Builder { meldAlbumVertices(it, simpleMbidVertex) simpleMbidVertex } - simplifyAlbumClusterImpl(strippedCluster) + val fullAlbumArtistCoverage = + strippedMbidCluster.all { it.preAlbum.preArtists is PreArtistsFrom.Album } + if (fullAlbumArtistCoverage) { + // All albums have album artists, we can reasonably cluster around artists + // rather than just name. + val albumArtistClusters = + strippedMbidCluster.groupBy { it.preAlbum.preArtists.preArtists } + for (albumArtistCluster in albumArtistClusters.values) { + simplifyAlbumClusterImpl(albumArtistCluster) + } + return + } + val strippedAlbumArtistCluster = + strippedMbidCluster.map { + val noAlbumArtistPreAlbum = + it.preAlbum.copy( + preArtists = PreArtistsFrom.Individual(it.preAlbum.preArtists.preArtists)) + val simpleAlbumArtistVertex = + albumVertices.getOrPut(noAlbumArtistPreAlbum) { + AlbumVertex(noAlbumArtistPreAlbum, it.artistVertices.toMutableList()) + } + meldAlbumVertices(it, simpleAlbumArtistVertex) + simpleAlbumArtistVertex + } + simplifyAlbumClusterImpl(strippedAlbumArtistCluster) } private fun simplifyAlbumClusterImpl(cluster: Collection) { diff --git a/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt b/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt index 62f6f3689..4fc5822c0 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt @@ -54,16 +54,24 @@ internal data class PreSong( val preAlbum: PreAlbum, val preArtists: List, val preGenres: List -) {} +) internal data class PreAlbum( val musicBrainzId: UUID?, val name: Name, val rawName: String?, val releaseType: ReleaseType, - val preArtists: List + val preArtists: PreArtistsFrom, ) +internal sealed interface PreArtistsFrom { + val preArtists: List + + data class Individual(override val preArtists: List) : PreArtistsFrom + + data class Album(override val preArtists: List) : PreArtistsFrom +} + internal data class PreArtist(val musicBrainzId: UUID?, val name: Name, val rawName: String?) internal data class PreGenre( diff --git a/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt b/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt index eb2787e7a..246892685 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt @@ -165,9 +165,9 @@ private class TagInterpreterImpl(private val interpretation: Interpretation) : T ReleaseType.parse(interpretation.separators.split(parsedTags.releaseTypes)) ?: ReleaseType.Album(null), preArtists = - albumPreArtists - .ifEmpty { individualPreArtists } - .ifEmpty { listOf(unknownPreArtist()) }) + PreArtistsFrom.Album(albumPreArtists).takeIf { it.preArtists.isNotEmpty() } + ?: PreArtistsFrom.Individual( + individualPreArtists.ifEmpty { listOf(unknownPreArtist()) })) } private fun makePreArtists(