music: sort song information
Sort song informtion in all MusicParent instances. This is a temporary hack to band-aid music consistency between reloads, as with the aggressive parallelization song order is no longer consistent.
This commit is contained in:
parent
530e427b79
commit
5b44c31689
3 changed files with 37 additions and 45 deletions
|
@ -203,7 +203,7 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu
|
|||
|
||||
// Now that all songs are processed, also process albums and group them into their
|
||||
// respective artists.
|
||||
val albums = albumGrouping.values.map { AlbumImpl(it.raw.inner, musicSettings, it.music) }
|
||||
val albums = albumGrouping.values.map { AlbumImpl(it, musicSettings) }
|
||||
for (album in albums) {
|
||||
for (rawArtist in album.rawArtists) {
|
||||
val key = RawArtist.Key(rawArtist)
|
||||
|
@ -236,19 +236,11 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu
|
|||
}
|
||||
|
||||
// Artists and genres do not need to be grouped and can be processed immediately.
|
||||
val artists =
|
||||
artistGrouping.values.map { ArtistImpl(it.raw.inner, musicSettings, it.music) }
|
||||
val genres = genreGrouping.values.map { GenreImpl(it.raw.inner, musicSettings, it.music) }
|
||||
val artists = artistGrouping.values.map { ArtistImpl(it, musicSettings) }
|
||||
val genres = genreGrouping.values.map { GenreImpl(it, musicSettings) }
|
||||
|
||||
return DeviceLibraryImpl(songGrouping.values, albums, artists, genres)
|
||||
}
|
||||
|
||||
private data class Grouping<R, M : Music>(
|
||||
var raw: PrioritizedRaw<R, M>,
|
||||
val music: MutableList<M>
|
||||
)
|
||||
|
||||
private data class PrioritizedRaw<R, M : Music>(val inner: R, val src: M)
|
||||
}
|
||||
|
||||
class DeviceLibraryImpl(
|
||||
|
|
|
@ -231,17 +231,16 @@ class SongImpl(private val rawSong: RawSong, musicSettings: MusicSettings) : Son
|
|||
/**
|
||||
* Library-backed implementation of [Album].
|
||||
*
|
||||
* @param rawAlbum The [RawAlbum] to derive the member data from.
|
||||
* @param grouping [Grouping] to derive the member data from.
|
||||
* @param musicSettings [MusicSettings] to for user parsing configuration.
|
||||
* @param songs The [Song]s that are a part of this [Album]. These items will be linked to this
|
||||
* [Album].
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
class AlbumImpl(
|
||||
private val rawAlbum: RawAlbum,
|
||||
grouping: Grouping<RawAlbum, SongImpl>,
|
||||
musicSettings: MusicSettings,
|
||||
override val songs: List<SongImpl>
|
||||
) : Album {
|
||||
private val rawAlbum = grouping.raw.inner
|
||||
|
||||
override val uid =
|
||||
// Attempt to use a MusicBrainz ID first before falling back to a hashed UID.
|
||||
rawAlbum.musicBrainzId?.let { Music.UID.musicBrainz(MusicMode.ALBUMS, it) }
|
||||
|
@ -259,6 +258,7 @@ class AlbumImpl(
|
|||
override val durationMs: Long
|
||||
override val dateAdded: Long
|
||||
|
||||
override val songs: List<Song>
|
||||
private val _artists = mutableListOf<ArtistImpl>()
|
||||
override val artists: List<Artist>
|
||||
get() = _artists
|
||||
|
@ -272,7 +272,7 @@ class AlbumImpl(
|
|||
var earliestDateAdded: Long = Long.MAX_VALUE
|
||||
|
||||
// Do linking and value generation in the same loop for efficiency.
|
||||
for (song in songs) {
|
||||
for (song in grouping.music) {
|
||||
song.link(this)
|
||||
|
||||
if (song.date != null) {
|
||||
|
@ -298,6 +298,7 @@ class AlbumImpl(
|
|||
dates = if (min != null && max != null) Date.Range(min, max) else null
|
||||
durationMs = totalDuration
|
||||
dateAdded = earliestDateAdded
|
||||
songs = Sort(Sort.Mode.ByName, Sort.Direction.ASCENDING).songs(grouping.music)
|
||||
|
||||
hashCode = 31 * hashCode + rawAlbum.hashCode()
|
||||
hashCode = 31 * hashCode + songs.hashCode()
|
||||
|
@ -347,18 +348,13 @@ class AlbumImpl(
|
|||
/**
|
||||
* Library-backed implementation of [Artist].
|
||||
*
|
||||
* @param rawArtist The [RawArtist] to derive the member data from.
|
||||
* @param grouping [Grouping] to derive the member data from.
|
||||
* @param musicSettings [MusicSettings] to for user parsing configuration.
|
||||
* @param songAlbums A list of the [Song]s and [Album]s that are a part of this [Artist] , either
|
||||
* through artist or album artist tags. Providing [Song]s to the artist is optional. These
|
||||
* instances will be linked to this [Artist].
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
class ArtistImpl(
|
||||
private val rawArtist: RawArtist,
|
||||
musicSettings: MusicSettings,
|
||||
songAlbums: List<Music>
|
||||
) : Artist {
|
||||
class ArtistImpl(grouping: Grouping<RawArtist, Music>, musicSettings: MusicSettings) : Artist {
|
||||
private val rawArtist = grouping.raw.inner
|
||||
|
||||
override val uid =
|
||||
// Attempt to use a MusicBrainz ID first before falling back to a hashed UID.
|
||||
rawArtist.musicBrainzId?.let { Music.UID.musicBrainz(MusicMode.ARTISTS, it) }
|
||||
|
@ -381,7 +377,7 @@ class ArtistImpl(
|
|||
val distinctSongs = mutableSetOf<Song>()
|
||||
val albumMap = mutableMapOf<Album, Boolean>()
|
||||
|
||||
for (music in songAlbums) {
|
||||
for (music in grouping.music) {
|
||||
when (music) {
|
||||
is SongImpl -> {
|
||||
music.link(this)
|
||||
|
@ -398,7 +394,7 @@ class ArtistImpl(
|
|||
}
|
||||
}
|
||||
|
||||
songs = distinctSongs.toList()
|
||||
songs = Sort(Sort.Mode.ByName, Sort.Direction.ASCENDING).songs(distinctSongs)
|
||||
albums = Sort(Sort.Mode.ByDate, Sort.Direction.DESCENDING).albums(albumMap.keys)
|
||||
explicitAlbums = albums.filter { unlikelyToBeNull(albumMap[it]) }
|
||||
implicitAlbums = albums.filterNot { unlikelyToBeNull(albumMap[it]) }
|
||||
|
@ -449,40 +445,38 @@ class ArtistImpl(
|
|||
/**
|
||||
* Library-backed implementation of [Genre].
|
||||
*
|
||||
* @param rawGenre [RawGenre] to derive the member data from.
|
||||
* @param grouping [Grouping] to derive the member data from.
|
||||
* @param musicSettings [MusicSettings] to for user parsing configuration.
|
||||
* @param songs Child [SongImpl]s of this instance.
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
class GenreImpl(
|
||||
private val rawGenre: RawGenre,
|
||||
musicSettings: MusicSettings,
|
||||
override val songs: List<SongImpl>
|
||||
) : Genre {
|
||||
class GenreImpl(grouping: Grouping<RawGenre, SongImpl>, musicSettings: MusicSettings) : Genre {
|
||||
private val rawGenre = grouping.raw.inner
|
||||
|
||||
override val uid = Music.UID.auxio(MusicMode.GENRES) { update(rawGenre.name) }
|
||||
override val name =
|
||||
rawGenre.name?.let { Name.Known.from(it, rawGenre.name, musicSettings) }
|
||||
?: Name.Unknown(R.string.def_genre)
|
||||
|
||||
override val songs: List<Song>
|
||||
override val artists: List<Artist>
|
||||
override val durationMs: Long
|
||||
|
||||
private var hashCode = uid.hashCode()
|
||||
|
||||
init {
|
||||
val distinctAlbums = mutableSetOf<Album>()
|
||||
val distinctArtists = mutableSetOf<Artist>()
|
||||
var totalDuration = 0L
|
||||
|
||||
for (song in songs) {
|
||||
for (song in grouping.music) {
|
||||
song.link(this)
|
||||
distinctAlbums.add(song.album)
|
||||
distinctArtists.addAll(song.artists)
|
||||
totalDuration += song.durationMs
|
||||
}
|
||||
|
||||
songs = Sort(Sort.Mode.ByName, Sort.Direction.ASCENDING).songs(grouping.music)
|
||||
artists = Sort(Sort.Mode.ByName, Sort.Direction.ASCENDING).artists(distinctArtists)
|
||||
durationMs = totalDuration
|
||||
|
||||
hashCode = 31 * hashCode + rawGenre.hashCode()
|
||||
hashCode = 31 * hashCode + songs.hashCode()
|
||||
}
|
||||
|
@ -516,3 +510,7 @@ class GenreImpl(
|
|||
return this
|
||||
}
|
||||
}
|
||||
|
||||
data class Grouping<R, M : Music>(var raw: PrioritizedRaw<R, M>, val music: MutableList<M>)
|
||||
|
||||
data class PrioritizedRaw<R, M : Music>(val inner: R, val src: M)
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.oxycblt.auxio.music.Song
|
|||
import org.oxycblt.auxio.music.fs.Directory
|
||||
import org.oxycblt.auxio.music.info.Date
|
||||
import org.oxycblt.auxio.music.info.ReleaseType
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* Raw information about a [SongImpl] obtained from the filesystem/Extractor instances.
|
||||
|
@ -120,7 +119,10 @@ data class RawAlbum(
|
|||
) {
|
||||
val key = Key(this)
|
||||
|
||||
/** Exposed information that denotes [RawAlbum] uniqueness. */
|
||||
/**
|
||||
* Allows [RawAlbum]s to be compared by "fundamental" information that is unlikely to change on
|
||||
* an item-by-item basis.
|
||||
*/
|
||||
data class Key(private val inner: RawAlbum) {
|
||||
// Albums are grouped as follows:
|
||||
// - If we have a MusicBrainz ID, only group by it. This allows different Albums with the
|
||||
|
@ -167,7 +169,7 @@ data class RawArtist(
|
|||
|
||||
/**
|
||||
* Allows [RawArtist]s to be compared by "fundamental" information that is unlikely to change on
|
||||
* an item-by-item
|
||||
* an item-by-item basis.
|
||||
*/
|
||||
data class Key(private val inner: RawArtist) {
|
||||
// Artists are grouped as follows:
|
||||
|
@ -179,10 +181,6 @@ data class RawArtist(
|
|||
// Cache the hashCode for HashMap efficiency.
|
||||
val hashCode = inner.musicBrainzId?.hashCode() ?: inner.name?.lowercase().hashCode()
|
||||
|
||||
init {
|
||||
logD("${inner.name} ${inner.name?.lowercase().hashCode()} $hashCode")
|
||||
}
|
||||
|
||||
// Compare names and MusicBrainz IDs in order to differentiate artists with the
|
||||
// same name in large libraries.
|
||||
|
||||
|
@ -216,6 +214,10 @@ data class RawGenre(
|
|||
) {
|
||||
val key = Key(this)
|
||||
|
||||
/**
|
||||
* Allows [RawGenre]s to be compared by "fundamental" information that is unlikely to change on
|
||||
* an item-by-item basis.
|
||||
*/
|
||||
data class Key(private val inner: RawGenre) {
|
||||
// Cache the hashCode for HashMap efficiency.
|
||||
private val hashCode = inner.name?.lowercase().hashCode()
|
||||
|
|
Loading…
Reference in a new issue