music: re-add song deduplication
This commit is contained in:
parent
3bf80073f4
commit
9d9f810356
4 changed files with 42 additions and 20 deletions
|
@ -26,6 +26,7 @@ import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.toList
|
import kotlinx.coroutines.flow.toList
|
||||||
|
import org.oxycblt.auxio.music.Music
|
||||||
import org.oxycblt.auxio.music.stack.Indexer
|
import org.oxycblt.auxio.music.stack.Indexer
|
||||||
import org.oxycblt.auxio.music.stack.explore.AudioFile
|
import org.oxycblt.auxio.music.stack.explore.AudioFile
|
||||||
import org.oxycblt.auxio.music.stack.explore.PlaylistFile
|
import org.oxycblt.auxio.music.stack.explore.PlaylistFile
|
||||||
|
@ -42,6 +43,7 @@ import org.oxycblt.auxio.music.stack.interpret.model.MutableLibrary
|
||||||
import org.oxycblt.auxio.music.stack.interpret.model.SongImpl
|
import org.oxycblt.auxio.music.stack.interpret.model.SongImpl
|
||||||
import org.oxycblt.auxio.music.stack.interpret.prepare.PreSong
|
import org.oxycblt.auxio.music.stack.interpret.prepare.PreSong
|
||||||
import org.oxycblt.auxio.music.stack.interpret.prepare.Preparer
|
import org.oxycblt.auxio.music.stack.interpret.prepare.Preparer
|
||||||
|
import timber.log.Timber as L
|
||||||
|
|
||||||
interface Interpreter {
|
interface Interpreter {
|
||||||
suspend fun interpret(
|
suspend fun interpret(
|
||||||
|
@ -88,8 +90,22 @@ class InterpreterImpl @Inject constructor(private val preparer: Preparer) : Inte
|
||||||
.toList()
|
.toList()
|
||||||
val albums = albumLinker.resolve()
|
val albums = albumLinker.resolve()
|
||||||
|
|
||||||
val songs = albumLinkedSongs.map { SongImpl(it) }
|
val uidMap = mutableMapOf<Music.UID, SongImpl>()
|
||||||
return LibraryImpl(songs, albums, artists, genres)
|
val songs = albumLinkedSongs.mapNotNull {
|
||||||
|
val uid = it.preSong.computeUid()
|
||||||
|
val other = uidMap[uid]
|
||||||
|
if (other == null) {
|
||||||
|
SongImpl(it)
|
||||||
|
} else {
|
||||||
|
L.d("Song @ $uid already exists at ${other.path}, ignoring")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LibraryImpl(
|
||||||
|
songs,
|
||||||
|
albums.onEach { it.finalize() },
|
||||||
|
artists.onEach { it.finalize() },
|
||||||
|
genres.onEach { it.finalize() })
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class LinkedSongImpl(private val albumLinkedSong: AlbumLinker.LinkedSong) :
|
private data class LinkedSongImpl(private val albumLinkedSong: AlbumLinker.LinkedSong) :
|
||||||
|
|
|
@ -43,23 +43,7 @@ import org.oxycblt.auxio.util.update
|
||||||
class SongImpl(linkedSong: LinkedSong) : Song {
|
class SongImpl(linkedSong: LinkedSong) : Song {
|
||||||
private val preSong = linkedSong.preSong
|
private val preSong = linkedSong.preSong
|
||||||
|
|
||||||
override val uid =
|
override val uid = preSong.computeUid()
|
||||||
// Attempt to use a MusicBrainz ID first before falling back to a hashed UID.
|
|
||||||
preSong.musicBrainzId?.let { Music.UID.musicBrainz(MusicType.SONGS, it) }
|
|
||||||
?: Music.UID.auxio(MusicType.SONGS) {
|
|
||||||
// Song UIDs are based on the raw data without parsing so that they remain
|
|
||||||
// consistent across music setting changes. Parents are not held up to the
|
|
||||||
// same standard since grouping is already inherently linked to settings.
|
|
||||||
update(preSong.rawName)
|
|
||||||
update(preSong.preAlbum.rawName)
|
|
||||||
update(preSong.date)
|
|
||||||
|
|
||||||
update(preSong.track)
|
|
||||||
update(preSong.disc?.number)
|
|
||||||
|
|
||||||
update(preSong.preArtists.map { it.rawName })
|
|
||||||
update(preSong.preAlbum.preArtists.map { it.rawName })
|
|
||||||
}
|
|
||||||
override val name = preSong.name
|
override val name = preSong.name
|
||||||
override val track = preSong.track
|
override val track = preSong.track
|
||||||
override val disc = preSong.disc
|
override val disc = preSong.disc
|
||||||
|
|
|
@ -47,6 +47,8 @@ class LibraryImpl(
|
||||||
) : MutableLibrary {
|
) : MutableLibrary {
|
||||||
override val playlists = emptySet<Playlist>()
|
override val playlists = emptySet<Playlist>()
|
||||||
|
|
||||||
|
private val songUidMap = songs.associ { it.uid }
|
||||||
|
|
||||||
override fun findSong(uid: Music.UID): Song? {
|
override fun findSong(uid: Music.UID): Song? {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ package org.oxycblt.auxio.music.stack.interpret.prepare
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import org.oxycblt.auxio.image.extractor.Cover
|
import org.oxycblt.auxio.image.extractor.Cover
|
||||||
|
import org.oxycblt.auxio.music.Music
|
||||||
|
import org.oxycblt.auxio.music.MusicType
|
||||||
import org.oxycblt.auxio.music.info.Date
|
import org.oxycblt.auxio.music.info.Date
|
||||||
import org.oxycblt.auxio.music.info.Disc
|
import org.oxycblt.auxio.music.info.Disc
|
||||||
import org.oxycblt.auxio.music.info.Name
|
import org.oxycblt.auxio.music.info.Name
|
||||||
|
@ -29,6 +31,7 @@ import org.oxycblt.auxio.music.stack.explore.PlaylistHandle
|
||||||
import org.oxycblt.auxio.music.stack.explore.fs.MimeType
|
import org.oxycblt.auxio.music.stack.explore.fs.MimeType
|
||||||
import org.oxycblt.auxio.music.stack.explore.fs.Path
|
import org.oxycblt.auxio.music.stack.explore.fs.Path
|
||||||
import org.oxycblt.auxio.playback.replaygain.ReplayGainAdjustment
|
import org.oxycblt.auxio.playback.replaygain.ReplayGainAdjustment
|
||||||
|
import org.oxycblt.auxio.util.update
|
||||||
|
|
||||||
data class PreSong(
|
data class PreSong(
|
||||||
val musicBrainzId: UUID?,
|
val musicBrainzId: UUID?,
|
||||||
|
@ -48,7 +51,24 @@ data class PreSong(
|
||||||
val preAlbum: PreAlbum,
|
val preAlbum: PreAlbum,
|
||||||
val preArtists: List<PreArtist>,
|
val preArtists: List<PreArtist>,
|
||||||
val preGenres: List<PreGenre>
|
val preGenres: List<PreGenre>
|
||||||
)
|
) {
|
||||||
|
fun computeUid() =
|
||||||
|
musicBrainzId?.let { Music.UID.musicBrainz(MusicType.SONGS, it) }
|
||||||
|
?: Music.UID.auxio(MusicType.SONGS) {
|
||||||
|
// Song UIDs are based on the raw data without parsing so that they remain
|
||||||
|
// consistent across music setting changes. Parents are not held up to the
|
||||||
|
// same standard since grouping is already inherently linked to settings.
|
||||||
|
update(rawName)
|
||||||
|
update(preAlbum.rawName)
|
||||||
|
update(date)
|
||||||
|
|
||||||
|
update(track)
|
||||||
|
update(disc?.number)
|
||||||
|
|
||||||
|
update(preArtists.map { artist -> artist.rawName })
|
||||||
|
update(preAlbum.preArtists.map { artist -> artist.rawName })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class PreAlbum(
|
data class PreAlbum(
|
||||||
val musicBrainzId: UUID?,
|
val musicBrainzId: UUID?,
|
||||||
|
|
Loading…
Reference in a new issue