From d0b2fb85171bcfafd58ba55f617159f2b037708b Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Mon, 13 Feb 2023 09:19:50 -0700 Subject: [PATCH] music: simplify tag extraction spin Simplify the tag extraction loop to not depend on the co-routine primitives. This actually makes the music loading process a bit faster since the loop isn't as tight. --- app/src/main/java/org/oxycblt/auxio/Auxio.kt | 1 + .../auxio/music/metadata/TagExtractor.kt | 29 +++++++++---------- .../org/oxycblt/auxio/music/system/Indexer.kt | 6 ++++ 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/Auxio.kt b/app/src/main/java/org/oxycblt/auxio/Auxio.kt index 0c652e922..01f4eecab 100644 --- a/app/src/main/java/org/oxycblt/auxio/Auxio.kt +++ b/app/src/main/java/org/oxycblt/auxio/Auxio.kt @@ -47,6 +47,7 @@ class Auxio : Application() { // Adding static shortcuts in a dynamic manner is better than declaring them // manually, as it will properly handle the difference between debug and release // Auxio instances. + // TODO: Switch to static shortcuts ShortcutManagerCompat.addDynamicShortcuts( this, listOf( diff --git a/app/src/main/java/org/oxycblt/auxio/music/metadata/TagExtractor.kt b/app/src/main/java/org/oxycblt/auxio/music/metadata/TagExtractor.kt index 640dd54f3..53ebf6999 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/metadata/TagExtractor.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/metadata/TagExtractor.kt @@ -57,25 +57,22 @@ class TagExtractorImpl @Inject constructor(@ApplicationContext private val conte // producing similar throughput's to other kinds of manual metadata extraction. val taskPool: Array = arrayOfNulls(TASK_CAPACITY) - spin@ while (true) { - // Spin until there is an open slot we can insert a task in. - for (i in taskPool.indices) { - val task = taskPool[i] - if (task != null) { - val finishedRawSong = task.get() - if (finishedRawSong != null) { - completeSongs.send(finishedRawSong) - yield() - } else { - continue + for (song in incompleteSongs) { + spin@ while (true) { + for (i in taskPool.indices) { + val task = taskPool[i] + if (task != null) { + val finishedRawSong = task.get() + if (finishedRawSong != null) { + completeSongs.send(finishedRawSong) + yield() + } else { + continue + } } - } - val result = incompleteSongs.tryReceive() - if (result.isClosed) { - taskPool[i] = null + taskPool[i] = Task(context, song) break@spin } - taskPool[i] = result.getOrNull()?.let { Task(context, it) } } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt b/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt index cd6a591a9..5820a096d 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt @@ -328,6 +328,7 @@ constructor( ): Library { if (ContextCompat.checkSelfPermission(context, Indexer.PERMISSION_READ_AUDIO) == PackageManager.PERMISSION_DENIED) { + logE("Permission check failed") // No permissions, signal that we can't do anything. throw Indexer.NoPermissionException() } @@ -337,6 +338,7 @@ constructor( emitIndexing(Indexer.Indexing.Indeterminate) // Do the initial query of the cache and media databases in parallel. + logD("Starting queries") val mediaStoreQueryJob = scope.async { mediaStoreExtractor.query() } val cache = if (withCache) { @@ -349,6 +351,7 @@ constructor( // Now start processing the queried song information in parallel. Songs that can't be // received from the cache are consisted incomplete and pushed to a separate channel // that will eventually be processed into completed raw songs. + logD("Starting song discovery") val completeSongs = Channel(Channel.UNLIMITED) val incompleteSongs = Channel(Channel.UNLIMITED) val mediaStoreJob = @@ -363,15 +366,18 @@ constructor( rawSongs.add(rawSong) emitIndexing(Indexer.Indexing.Songs(rawSongs.size, query.projectedTotal)) } + // These should be no-ops mediaStoreJob.await() metadataJob.await() if (rawSongs.isEmpty()) { + logE("Music library was empty") throw Indexer.NoMusicException() } // Successfully loaded the library, now save the cache and create the library in // parallel. + logD("Discovered ${rawSongs.size} songs, starting finalization") emitIndexing(Indexer.Indexing.Indeterminate) val libraryJob = scope.async(Dispatchers.Main) { Library.from(rawSongs, musicSettings) } if (cache == null || cache.invalidated) {