music: cleanup

Clean up parts of the music loader.
This commit is contained in:
Alexander Capehart 2023-06-07 20:08:57 -06:00
parent 77d01a0c97
commit a9a6d1ccc1
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
3 changed files with 26 additions and 16 deletions

View file

@ -372,7 +372,6 @@ constructor(
// Do the initial query of the cache and media databases in parallel.
logD("Starting MediaStore query")
val mediaStoreQueryJob = worker.scope.tryAsync { mediaStoreExtractor.query() }
val userLibraryQueryJob = worker.scope.tryAsync { userLibraryFactory.query() }
val cache =
if (withCache) {
logD("Reading cache")
@ -431,6 +430,7 @@ constructor(
logD("Discovered ${rawSongs.size} songs, starting finalization")
emitLoading(IndexingProgress.Indeterminate)
logD("Starting UserLibrary query")
val userLibraryQueryJob = worker.scope.tryAsync { userLibraryFactory.query() }
if (cache == null || cache.invalidated) {
logD("Writing cache [why=${cache?.invalidated}]")
cacheRepository.writeCache(rawSongs)

View file

@ -97,6 +97,14 @@ interface DeviceLibrary {
/** Constructs a [DeviceLibrary] implementation in an asynchronous manner. */
interface Factory {
/**
* Creates a new [DeviceLibrary] instance asynchronously based on the incoming stream of
* [RawSong] instances.
*
* @param rawSongs A stream of [RawSong] instances to process.
* @param processedSongs A stream of [RawSong] instances that will have been processed by
* the instance.
*/
suspend fun create(
rawSongs: Channel<RawSong>,
processedSongs: Channel<RawSong>
@ -123,8 +131,11 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu
// causing severe issues elsewhere.
if (songGrouping.containsKey(song.uid)) {
logW(
"Duplicate song found: ${song.path} in " +
"Duplicate song found: ${song.path} " +
"collides with ${unlikelyToBeNull(songGrouping[song.uid]).path}")
// We still want to say that we "processed" the song so that the user doesn't
// get confused at why the bar was only partly filled by the end of the loading
// process.
processedSongs.send(rawSong)
continue
}
@ -140,9 +151,9 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu
// use for album information to ensure consistent metadata and UIDs. Fall back to
// the name otherwise.
val trackLower =
song.track != null && (prioritized.track == null || song.track < prioritized.track)
val nameLower =
song.name < prioritized.name
song.track != null &&
(prioritized.track == null || song.track < prioritized.track)
val nameLower = song.name < prioritized.name
if (trackLower || nameLower) {
albumBody.raw = PrioritizedRaw(song.rawAlbum, song)
}
@ -192,8 +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.raw.inner, musicSettings, it.music) }
for (album in albums) {
for (rawArtist in album.rawArtists) {
val key = RawArtist.Key(rawArtist)
@ -204,13 +214,14 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu
// Immediately replace any songs that initially held the priority position.
is SongImpl -> body.raw = PrioritizedRaw(rawArtist, album)
is AlbumImpl -> {
// Album information from later dates is prioritized, as it is more likely to
// Album information from later dates is prioritized, as it is more
// likely to
// contain the "modern" name of the artist if the information really is
// in-consistent. Fall back to the name otherwise.
val dateEarlier =
album.dates != null && (prioritized.dates == null || album.dates < prioritized.dates)
val nameLower =
album.name < prioritized.name
album.dates != null &&
(prioritized.dates == null || album.dates < prioritized.dates)
val nameLower = album.name < prioritized.name
if (dateEarlier || nameLower) {
body.raw = PrioritizedRaw(rawArtist, album)
}
@ -228,8 +239,7 @@ 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 genres = genreGrouping.values.map { GenreImpl(it.raw.inner, musicSettings, it.music) }
return DeviceLibraryImpl(songGrouping.values, albums, artists, genres)
}
@ -259,7 +269,7 @@ class DeviceLibraryImpl(
override fun hashCode() = songs.hashCode()
override fun toString() =
"DeviceLibrary(songs=${songs.size}, albums=${albums.size}, " +
"artists=${artists.size}, genres=${genres.size})"
"artists=${artists.size}, genres=${genres.size})"
override fun findSong(uid: Music.UID): Song? = songUidMap[uid]
override fun findAlbum(uid: Music.UID): Album? = albumUidMap[uid]

View file

@ -36,9 +36,9 @@ import org.oxycblt.auxio.util.logE
* is also not backed by library information, rather an app database with in-memory caching. It is
* generally not expected to create this yourself, and instead rely on MusicRepository.
*
* TODO: Communicate errors
*
* @author Alexander Capehart
*
* TODO: Communicate errors
*/
interface UserLibrary {
/** The current user-defined playlists. */