diff --git a/musikr/src/main/java/org/oxycblt/musikr/pipeline/EvaluateStep.kt b/musikr/src/main/java/org/oxycblt/musikr/pipeline/EvaluateStep.kt
index 6484a41a8..2ccc992be 100644
--- a/musikr/src/main/java/org/oxycblt/musikr/pipeline/EvaluateStep.kt
+++ b/musikr/src/main/java/org/oxycblt/musikr/pipeline/EvaluateStep.kt
@@ -66,20 +66,20 @@ private class EvaluateStepImpl(
val rawSongs = filterFlow.right
val preSongs =
rawSongs
- .map { tagInterpreter.interpret(it) }
+ .map { wrap(it, tagInterpreter::interpret) }
.flowOn(Dispatchers.Default)
.buffer(Channel.UNLIMITED)
val prePlaylists =
filterFlow.left
- .map { playlistInterpreter.interpret(it) }
+ .map { wrap(it, playlistInterpreter::interpret) }
.flowOn(Dispatchers.Default)
.buffer(Channel.UNLIMITED)
val graphBuilder = MusicGraph.builder()
val graphBuild =
merge(
filterFlow.manager,
- preSongs.onEach { graphBuilder.add(it) },
- prePlaylists.onEach { graphBuilder.add(it) })
+ preSongs.onEach { wrap(it, graphBuilder::add) },
+ prePlaylists.onEach { wrap(it, graphBuilder::add) })
graphBuild.collect()
val graph = graphBuilder.build()
return libraryFactory.create(graph, storedPlaylists, playlistInterpreter)
diff --git a/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExtractStep.kt b/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExtractStep.kt
index 442449e30..72ff37768 100644
--- a/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExtractStep.kt
+++ b/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExtractStep.kt
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
+
package org.oxycblt.musikr.pipeline
import android.content.Context
@@ -48,7 +48,8 @@ internal interface ExtractStep {
MetadataExtractor.from(context),
TagParser.new(),
storage.cache,
- storage.storedCovers)
+ storage.storedCovers
+ )
}
}
@@ -70,7 +71,8 @@ private class ExtractStepImpl(
val playlistNodes = filterFlow.left.map { ExtractedMusic.Playlist(it) }
val cacheResults =
- audioNodes.map { cache.read(it) }.flowOn(Dispatchers.IO).buffer(Channel.UNLIMITED)
+ audioNodes.map { wrap(it, cache::read) }.flowOn(Dispatchers.IO)
+ .buffer(Channel.UNLIMITED)
val cacheFlow =
cacheResults.divert {
when (it) {
@@ -84,11 +86,13 @@ private class ExtractStepImpl(
val extractedSongs =
Array(distributedFlow.flows.size) { i ->
distributedFlow.flows[i]
- .mapNotNull { file ->
- val metadata = metadataExtractor.extract(file) ?: return@mapNotNull null
- val tags = tagParser.parse(file, metadata)
- val cover = metadata.cover?.let { storedCovers.write(it) }
- RawSong(file, metadata.properties, tags, cover)
+ .mapNotNull { it ->
+ wrap(it) { file ->
+ val metadata = metadataExtractor.extract(file) ?: return@wrap null
+ val tags = tagParser.parse(file, metadata)
+ val cover = metadata.cover?.let { storedCovers.write(it) }
+ RawSong(file, metadata.properties, tags, cover)
+ }
}
.flowOn(Dispatchers.IO)
.buffer(Channel.UNLIMITED)
@@ -96,7 +100,7 @@ private class ExtractStepImpl(
val writtenSongs =
merge(*extractedSongs)
.map {
- cache.write(it)
+ wrap(it, cache::write)
ExtractedMusic.Song(it)
}
.flowOn(Dispatchers.IO)
@@ -107,7 +111,8 @@ private class ExtractStepImpl(
cachedSongs,
distributedFlow.manager,
writtenSongs,
- playlistNodes)
+ playlistNodes
+ )
}
}
diff --git a/musikr/src/main/java/org/oxycblt/musikr/pipeline/PipelineException.kt b/musikr/src/main/java/org/oxycblt/musikr/pipeline/PipelineException.kt
new file mode 100644
index 000000000..f577976bd
--- /dev/null
+++ b/musikr/src/main/java/org/oxycblt/musikr/pipeline/PipelineException.kt
@@ -0,0 +1,72 @@
+package org.oxycblt.musikr.pipeline
+
+import org.oxycblt.musikr.fs.DeviceFile
+import org.oxycblt.musikr.playlist.PlaylistFile
+import org.oxycblt.musikr.playlist.interpret.PrePlaylist
+import org.oxycblt.musikr.tag.interpret.PreSong
+
+class PipelineException(
+ val processing: WhileProcessing,
+ val error: Exception
+) : Exception() {
+ override val cause = error
+
+ override val message = "Error while processing ${processing}: $error"
+}
+
+sealed interface WhileProcessing {
+ class AFile internal constructor(private val file: DeviceFile) : WhileProcessing {
+ override fun toString() = "File @ ${file.path}"
+ }
+
+ class ARawSong internal constructor(private val rawSong: RawSong) : WhileProcessing {
+ override fun toString() = "Raw Song @ ${rawSong.file.path}"
+ }
+
+ class APlaylistFile internal constructor(private val playlist: PlaylistFile) : WhileProcessing {
+ override fun toString() = "Playlist File @ ${playlist.name}"
+ }
+
+ class APreSong internal constructor(private val preSong: PreSong) : WhileProcessing {
+ override fun toString() = "Pre Song @ ${preSong.path}"
+ }
+
+ class APrePlaylist internal constructor(private val prePlaylist: PrePlaylist) : WhileProcessing {
+ override fun toString() = "Pre Playlist @ ${prePlaylist.name}"
+ }
+}
+
+internal suspend fun wrap(file: DeviceFile, block: suspend (DeviceFile) -> R): R =
+ try {
+ block(file)
+ } catch (e: Exception) {
+ throw PipelineException(WhileProcessing.AFile(file), e)
+ }
+
+internal suspend fun wrap(song: RawSong, block: suspend (RawSong) -> R): R =
+ try {
+ block(song)
+ } catch (e: Exception) {
+ throw PipelineException(WhileProcessing.ARawSong(song), e)
+ }
+
+internal suspend fun wrap(file: PlaylistFile, block: suspend (PlaylistFile) -> R): R =
+ try {
+ block(file)
+ } catch (e: Exception) {
+ throw PipelineException(WhileProcessing.APlaylistFile(file), e)
+ }
+
+internal suspend fun wrap(song: PreSong, block: suspend (PreSong) -> R): R =
+ try {
+ block(song)
+ } catch (e: Exception) {
+ throw PipelineException(WhileProcessing.APreSong(song), e)
+ }
+
+internal suspend fun wrap(playlist: PrePlaylist, block: suspend (PrePlaylist) -> R): R =
+ try {
+ block(playlist)
+ } catch (e: Exception) {
+ throw PipelineException(WhileProcessing.APrePlaylist(playlist), e)
+ }