music: cleanup
Clean up parts of the music loader.
This commit is contained in:
parent
77d01a0c97
commit
a9a6d1ccc1
3 changed files with 26 additions and 16 deletions
|
@ -372,7 +372,6 @@ constructor(
|
||||||
// Do the initial query of the cache and media databases in parallel.
|
// Do the initial query of the cache and media databases in parallel.
|
||||||
logD("Starting MediaStore query")
|
logD("Starting MediaStore query")
|
||||||
val mediaStoreQueryJob = worker.scope.tryAsync { mediaStoreExtractor.query() }
|
val mediaStoreQueryJob = worker.scope.tryAsync { mediaStoreExtractor.query() }
|
||||||
val userLibraryQueryJob = worker.scope.tryAsync { userLibraryFactory.query() }
|
|
||||||
val cache =
|
val cache =
|
||||||
if (withCache) {
|
if (withCache) {
|
||||||
logD("Reading cache")
|
logD("Reading cache")
|
||||||
|
@ -431,6 +430,7 @@ constructor(
|
||||||
logD("Discovered ${rawSongs.size} songs, starting finalization")
|
logD("Discovered ${rawSongs.size} songs, starting finalization")
|
||||||
emitLoading(IndexingProgress.Indeterminate)
|
emitLoading(IndexingProgress.Indeterminate)
|
||||||
logD("Starting UserLibrary query")
|
logD("Starting UserLibrary query")
|
||||||
|
val userLibraryQueryJob = worker.scope.tryAsync { userLibraryFactory.query() }
|
||||||
if (cache == null || cache.invalidated) {
|
if (cache == null || cache.invalidated) {
|
||||||
logD("Writing cache [why=${cache?.invalidated}]")
|
logD("Writing cache [why=${cache?.invalidated}]")
|
||||||
cacheRepository.writeCache(rawSongs)
|
cacheRepository.writeCache(rawSongs)
|
||||||
|
|
|
@ -97,6 +97,14 @@ interface DeviceLibrary {
|
||||||
|
|
||||||
/** Constructs a [DeviceLibrary] implementation in an asynchronous manner. */
|
/** Constructs a [DeviceLibrary] implementation in an asynchronous manner. */
|
||||||
interface Factory {
|
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(
|
suspend fun create(
|
||||||
rawSongs: Channel<RawSong>,
|
rawSongs: Channel<RawSong>,
|
||||||
processedSongs: Channel<RawSong>
|
processedSongs: Channel<RawSong>
|
||||||
|
@ -123,8 +131,11 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu
|
||||||
// causing severe issues elsewhere.
|
// causing severe issues elsewhere.
|
||||||
if (songGrouping.containsKey(song.uid)) {
|
if (songGrouping.containsKey(song.uid)) {
|
||||||
logW(
|
logW(
|
||||||
"Duplicate song found: ${song.path} in " +
|
"Duplicate song found: ${song.path} " +
|
||||||
"collides with ${unlikelyToBeNull(songGrouping[song.uid]).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)
|
processedSongs.send(rawSong)
|
||||||
continue
|
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
|
// use for album information to ensure consistent metadata and UIDs. Fall back to
|
||||||
// the name otherwise.
|
// the name otherwise.
|
||||||
val trackLower =
|
val trackLower =
|
||||||
song.track != null && (prioritized.track == null || song.track < prioritized.track)
|
song.track != null &&
|
||||||
val nameLower =
|
(prioritized.track == null || song.track < prioritized.track)
|
||||||
song.name < prioritized.name
|
val nameLower = song.name < prioritized.name
|
||||||
if (trackLower || nameLower) {
|
if (trackLower || nameLower) {
|
||||||
albumBody.raw = PrioritizedRaw(song.rawAlbum, song)
|
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
|
// Now that all songs are processed, also process albums and group them into their
|
||||||
// respective artists.
|
// respective artists.
|
||||||
val albums =
|
val albums = albumGrouping.values.map { AlbumImpl(it.raw.inner, musicSettings, it.music) }
|
||||||
albumGrouping.values.map { AlbumImpl(it.raw.inner, musicSettings, it.music) }
|
|
||||||
for (album in albums) {
|
for (album in albums) {
|
||||||
for (rawArtist in album.rawArtists) {
|
for (rawArtist in album.rawArtists) {
|
||||||
val key = RawArtist.Key(rawArtist)
|
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.
|
// Immediately replace any songs that initially held the priority position.
|
||||||
is SongImpl -> body.raw = PrioritizedRaw(rawArtist, album)
|
is SongImpl -> body.raw = PrioritizedRaw(rawArtist, album)
|
||||||
is AlbumImpl -> {
|
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
|
// contain the "modern" name of the artist if the information really is
|
||||||
// in-consistent. Fall back to the name otherwise.
|
// in-consistent. Fall back to the name otherwise.
|
||||||
val dateEarlier =
|
val dateEarlier =
|
||||||
album.dates != null && (prioritized.dates == null || album.dates < prioritized.dates)
|
album.dates != null &&
|
||||||
val nameLower =
|
(prioritized.dates == null || album.dates < prioritized.dates)
|
||||||
album.name < prioritized.name
|
val nameLower = album.name < prioritized.name
|
||||||
if (dateEarlier || nameLower) {
|
if (dateEarlier || nameLower) {
|
||||||
body.raw = PrioritizedRaw(rawArtist, album)
|
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.
|
// Artists and genres do not need to be grouped and can be processed immediately.
|
||||||
val artists =
|
val artists =
|
||||||
artistGrouping.values.map { ArtistImpl(it.raw.inner, musicSettings, it.music) }
|
artistGrouping.values.map { ArtistImpl(it.raw.inner, musicSettings, it.music) }
|
||||||
val genres =
|
val genres = genreGrouping.values.map { GenreImpl(it.raw.inner, musicSettings, it.music) }
|
||||||
genreGrouping.values.map { GenreImpl(it.raw.inner, musicSettings, it.music) }
|
|
||||||
|
|
||||||
return DeviceLibraryImpl(songGrouping.values, albums, artists, genres)
|
return DeviceLibraryImpl(songGrouping.values, albums, artists, genres)
|
||||||
}
|
}
|
||||||
|
@ -259,7 +269,7 @@ class DeviceLibraryImpl(
|
||||||
override fun hashCode() = songs.hashCode()
|
override fun hashCode() = songs.hashCode()
|
||||||
override fun toString() =
|
override fun toString() =
|
||||||
"DeviceLibrary(songs=${songs.size}, albums=${albums.size}, " +
|
"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 findSong(uid: Music.UID): Song? = songUidMap[uid]
|
||||||
override fun findAlbum(uid: Music.UID): Album? = albumUidMap[uid]
|
override fun findAlbum(uid: Music.UID): Album? = albumUidMap[uid]
|
||||||
|
|
|
@ -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
|
* 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.
|
* generally not expected to create this yourself, and instead rely on MusicRepository.
|
||||||
*
|
*
|
||||||
* TODO: Communicate errors
|
|
||||||
*
|
|
||||||
* @author Alexander Capehart
|
* @author Alexander Capehart
|
||||||
|
*
|
||||||
|
* TODO: Communicate errors
|
||||||
*/
|
*/
|
||||||
interface UserLibrary {
|
interface UserLibrary {
|
||||||
/** The current user-defined playlists. */
|
/** The current user-defined playlists. */
|
||||||
|
|
Loading…
Reference in a new issue