music: fix threading problems
Fix issues with the current threading approach with the new parallel music loader.
This commit is contained in:
parent
1df1d40408
commit
4afe91e4e8
4 changed files with 17 additions and 6 deletions
|
@ -28,6 +28,7 @@ import androidx.core.database.getIntOrNull
|
||||||
import androidx.core.database.getStringOrNull
|
import androidx.core.database.getStringOrNull
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.yield
|
||||||
import org.oxycblt.auxio.music.MusicSettings
|
import org.oxycblt.auxio.music.MusicSettings
|
||||||
import org.oxycblt.auxio.music.library.RealSong
|
import org.oxycblt.auxio.music.library.RealSong
|
||||||
import org.oxycblt.auxio.music.metadata.Date
|
import org.oxycblt.auxio.music.metadata.Date
|
||||||
|
@ -231,6 +232,7 @@ private abstract class RealMediaStoreExtractor(private val context: Context) : M
|
||||||
populateMetadata(cursor, rawSong)
|
populateMetadata(cursor, rawSong)
|
||||||
incompleteSongs.send(rawSong)
|
incompleteSongs.send(rawSong)
|
||||||
}
|
}
|
||||||
|
yield()
|
||||||
}
|
}
|
||||||
// Free the cursor and signal that no more incomplete songs will be produced by
|
// Free the cursor and signal that no more incomplete songs will be produced by
|
||||||
// this extractor.
|
// this extractor.
|
||||||
|
|
|
@ -22,6 +22,7 @@ import androidx.core.text.isDigitsOnly
|
||||||
import com.google.android.exoplayer2.MediaItem
|
import com.google.android.exoplayer2.MediaItem
|
||||||
import com.google.android.exoplayer2.MetadataRetriever
|
import com.google.android.exoplayer2.MetadataRetriever
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.yield
|
||||||
import org.oxycblt.auxio.music.library.RealSong
|
import org.oxycblt.auxio.music.library.RealSong
|
||||||
import org.oxycblt.auxio.music.metadata.Date
|
import org.oxycblt.auxio.music.metadata.Date
|
||||||
import org.oxycblt.auxio.music.metadata.TextTags
|
import org.oxycblt.auxio.music.metadata.TextTags
|
||||||
|
@ -53,7 +54,13 @@ class MetadataExtractor(private val context: Context) {
|
||||||
for (i in taskPool.indices) {
|
for (i in taskPool.indices) {
|
||||||
val task = taskPool[i]
|
val task = taskPool[i]
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
completeSongs.send(task.get() ?: continue)
|
val finishedRawSong = task.get()
|
||||||
|
if (finishedRawSong != null) {
|
||||||
|
completeSongs.send(finishedRawSong)
|
||||||
|
yield()
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val result = incompleteSongs.tryReceive()
|
val result = incompleteSongs.tryReceive()
|
||||||
if (result.isClosed) {
|
if (result.isClosed) {
|
||||||
|
@ -73,6 +80,7 @@ class MetadataExtractor(private val context: Context) {
|
||||||
if (finishedRawSong != null) {
|
if (finishedRawSong != null) {
|
||||||
completeSongs.send(finishedRawSong)
|
completeSongs.send(finishedRawSong)
|
||||||
taskPool[i] = null
|
taskPool[i] = null
|
||||||
|
yield()
|
||||||
} else {
|
} else {
|
||||||
ongoingTasks = true
|
ongoingTasks = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import java.util.LinkedList
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -99,8 +100,9 @@ interface Indexer {
|
||||||
* @param withCache Whether to use the cache or not when loading. If false, the cache will still
|
* @param withCache Whether to use the cache or not when loading. If false, the cache will still
|
||||||
* be written, but no cache entries will be loaded into the new library.
|
* be written, but no cache entries will be loaded into the new library.
|
||||||
* @param scope The [CoroutineScope] to run the indexing job in.
|
* @param scope The [CoroutineScope] to run the indexing job in.
|
||||||
|
* @return The [Job] stacking the indexing status.
|
||||||
*/
|
*/
|
||||||
fun index(context: Context, withCache: Boolean, scope: CoroutineScope)
|
fun index(context: Context, withCache: Boolean, scope: CoroutineScope): Job
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request that the music library should be reloaded. This should be used by components that do
|
* Request that the music library should be reloaded. This should be used by components that do
|
||||||
|
@ -293,7 +295,7 @@ private class RealIndexer : Indexer {
|
||||||
this.listener = null
|
this.listener = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun index(context: Context, withCache: Boolean, scope: CoroutineScope) {
|
override fun index(context: Context, withCache: Boolean, scope: CoroutineScope) =
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val result =
|
val result =
|
||||||
try {
|
try {
|
||||||
|
@ -315,7 +317,6 @@ private class RealIndexer : Indexer {
|
||||||
}
|
}
|
||||||
emitCompletion(result)
|
emitCompletion(result)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun requestReindex(withCache: Boolean) {
|
override fun requestReindex(withCache: Boolean) {
|
||||||
|
|
|
@ -119,11 +119,11 @@ class IndexerService : Service(), Indexer.Controller, MusicSettings.Listener {
|
||||||
override fun onStartIndexing(withCache: Boolean) {
|
override fun onStartIndexing(withCache: Boolean) {
|
||||||
if (indexer.isIndexing) {
|
if (indexer.isIndexing) {
|
||||||
// Cancel the previous music loading job.
|
// Cancel the previous music loading job.
|
||||||
indexScope.cancel()
|
currentIndexJob?.cancel()
|
||||||
indexer.reset()
|
indexer.reset()
|
||||||
}
|
}
|
||||||
// Start a new music loading job on a co-routine.
|
// Start a new music loading job on a co-routine.
|
||||||
indexer.index(this@IndexerService, withCache, indexScope)
|
currentIndexJob = indexer.index(this@IndexerService, withCache, indexScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onIndexerStateChanged(state: Indexer.State?) {
|
override fun onIndexerStateChanged(state: Indexer.State?) {
|
||||||
|
|
Loading…
Reference in a new issue