musikr: start logging framework
This commit is contained in:
parent
b2073f2213
commit
0f034255af
7 changed files with 123 additions and 15 deletions
|
@ -40,6 +40,7 @@ import org.oxycblt.musikr.Playlist
|
||||||
import org.oxycblt.musikr.Song
|
import org.oxycblt.musikr.Song
|
||||||
import org.oxycblt.musikr.Storage
|
import org.oxycblt.musikr.Storage
|
||||||
import org.oxycblt.musikr.cache.MutableSongCache
|
import org.oxycblt.musikr.cache.MutableSongCache
|
||||||
|
import org.oxycblt.musikr.log.Logger
|
||||||
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
||||||
import org.oxycblt.musikr.tag.interpret.Naming
|
import org.oxycblt.musikr.tag.interpret.Naming
|
||||||
import org.oxycblt.musikr.tag.interpret.Separators
|
import org.oxycblt.musikr.tag.interpret.Separators
|
||||||
|
@ -394,7 +395,8 @@ constructor(
|
||||||
val interpretation = Interpretation(nameFactory, separators)
|
val interpretation = Interpretation(nameFactory, separators)
|
||||||
|
|
||||||
val result =
|
val result =
|
||||||
Musikr.new(context, storage, interpretation).run(locations, ::emitIndexingProgress)
|
Musikr.new(context, storage, interpretation, Logger.root())
|
||||||
|
.run(locations, ::emitIndexingProgress)
|
||||||
// Music loading completed, update the revision right now so we re-use this work
|
// Music loading completed, update the revision right now so we re-use this work
|
||||||
// later.
|
// later.
|
||||||
musicSettings.revision = newRevision
|
musicSettings.revision = newRevision
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.oxycblt.musikr
|
package org.oxycblt.musikr
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.flow.buffer
|
import kotlinx.coroutines.flow.buffer
|
||||||
|
@ -28,6 +29,7 @@ import kotlinx.coroutines.flow.onCompletion
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.onStart
|
import kotlinx.coroutines.flow.onStart
|
||||||
import org.oxycblt.musikr.fs.MusicLocation
|
import org.oxycblt.musikr.fs.MusicLocation
|
||||||
|
import org.oxycblt.musikr.log.Logger
|
||||||
import org.oxycblt.musikr.pipeline.Divert
|
import org.oxycblt.musikr.pipeline.Divert
|
||||||
import org.oxycblt.musikr.pipeline.EvaluateStep
|
import org.oxycblt.musikr.pipeline.EvaluateStep
|
||||||
import org.oxycblt.musikr.pipeline.ExploreStep
|
import org.oxycblt.musikr.pipeline.ExploreStep
|
||||||
|
@ -68,18 +70,25 @@ interface Musikr {
|
||||||
* Create a new instance from the given configuration.
|
* Create a new instance from the given configuration.
|
||||||
*
|
*
|
||||||
* @param context The context to use for loading resources.
|
* @param context The context to use for loading resources.
|
||||||
|
* @param logger The logger to use for logging events.
|
||||||
* @param storage Side-effect laden storage for use within the music loader **and** when
|
* @param storage Side-effect laden storage for use within the music loader **and** when
|
||||||
* mutating [MutableLibrary]. You should take responsibility for managing their long-term
|
* mutating [MutableLibrary]. You should take responsibility for managing their long-term
|
||||||
* state.
|
* state.
|
||||||
* @param interpretation The configuration to use for interpreting certain vague tags. This
|
* @param interpretation The configuration to use for interpreting certain vague tags. This
|
||||||
* should be configured by the user, if possible.
|
* should be configured by the user, if possible.
|
||||||
*/
|
*/
|
||||||
fun new(context: Context, storage: Storage, interpretation: Interpretation): Musikr =
|
fun new(
|
||||||
|
context: Context,
|
||||||
|
storage: Storage,
|
||||||
|
interpretation: Interpretation,
|
||||||
|
logger: Logger
|
||||||
|
): Musikr =
|
||||||
MusikrImpl(
|
MusikrImpl(
|
||||||
|
logger,
|
||||||
storage,
|
storage,
|
||||||
ExploreStep.from(context, storage),
|
ExploreStep.from(context, storage, logger),
|
||||||
ExtractStep.from(context, storage),
|
ExtractStep.from(context, storage, logger),
|
||||||
EvaluateStep.new(storage, interpretation))
|
EvaluateStep.new(storage, interpretation, logger))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +125,7 @@ sealed interface IndexingProgress {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MusikrImpl(
|
private class MusikrImpl(
|
||||||
|
private val logger: Logger,
|
||||||
private val storage: Storage,
|
private val storage: Storage,
|
||||||
private val exploreStep: ExploreStep,
|
private val exploreStep: ExploreStep,
|
||||||
private val extractStep: ExtractStep,
|
private val extractStep: ExtractStep,
|
||||||
|
@ -125,6 +135,16 @@ private class MusikrImpl(
|
||||||
locations: List<MusicLocation>,
|
locations: List<MusicLocation>,
|
||||||
onProgress: suspend (IndexingProgress) -> Unit
|
onProgress: suspend (IndexingProgress) -> Unit
|
||||||
) = coroutineScope {
|
) = coroutineScope {
|
||||||
|
logger.d(
|
||||||
|
"musikr start.",
|
||||||
|
"hw:",
|
||||||
|
Build.MANUFACTURER,
|
||||||
|
Build.MODEL,
|
||||||
|
Build.SUPPORTED_ABIS.joinToString(" "),
|
||||||
|
"sw:",
|
||||||
|
Build.VERSION.SDK_INT,
|
||||||
|
Build.DISPLAY)
|
||||||
|
|
||||||
var exploredCount = 0
|
var exploredCount = 0
|
||||||
var extractedCount = 0
|
var extractedCount = 0
|
||||||
val explored =
|
val explored =
|
||||||
|
|
63
musikr/src/main/java/org/oxycblt/musikr/log/Logger.kt
Normal file
63
musikr/src/main/java/org/oxycblt/musikr/log/Logger.kt
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Auxio Project
|
||||||
|
* Logger.kt is part of Auxio.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.oxycblt.musikr.log
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
interface Logger {
|
||||||
|
fun v(vararg msgs: Any)
|
||||||
|
|
||||||
|
fun d(vararg msgs: Any)
|
||||||
|
|
||||||
|
fun w(vararg msgs: Any)
|
||||||
|
|
||||||
|
fun e(vararg msgs: Any)
|
||||||
|
|
||||||
|
fun primary(tag: String): Logger
|
||||||
|
|
||||||
|
fun secondary(tag: String): Logger
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun root(): Logger = LoggerImpl("mskr", null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LoggerImpl(private val primaryTag: String, private val secondaryTag: String?) :
|
||||||
|
Logger {
|
||||||
|
override fun v(vararg msgs: Any) {
|
||||||
|
Log.v(primaryTag, "[$secondaryTag] ${msgs.joinToString(" ")}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun d(vararg msgs: Any) {
|
||||||
|
Log.d(primaryTag, "[$secondaryTag] ${msgs.joinToString(" ")}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun w(vararg msgs: Any) {
|
||||||
|
Log.w(primaryTag, "[$secondaryTag] ${msgs.joinToString(" ")}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun e(vararg msgs: Any) {
|
||||||
|
Log.e(primaryTag, "[$secondaryTag] ${msgs.joinToString(" ")}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun primary(tag: String) = LoggerImpl("${primaryTag}.${tag}", secondaryTag)
|
||||||
|
|
||||||
|
override fun secondary(tag: String) =
|
||||||
|
LoggerImpl(primaryTag, secondaryTag?.let { "$it.$tag" } ?: tag)
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ import org.oxycblt.musikr.Interpretation
|
||||||
import org.oxycblt.musikr.MutableLibrary
|
import org.oxycblt.musikr.MutableLibrary
|
||||||
import org.oxycblt.musikr.Storage
|
import org.oxycblt.musikr.Storage
|
||||||
import org.oxycblt.musikr.graph.MusicGraph
|
import org.oxycblt.musikr.graph.MusicGraph
|
||||||
|
import org.oxycblt.musikr.log.Logger
|
||||||
import org.oxycblt.musikr.model.LibraryFactory
|
import org.oxycblt.musikr.model.LibraryFactory
|
||||||
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
||||||
import org.oxycblt.musikr.playlist.interpret.PlaylistInterpreter
|
import org.oxycblt.musikr.playlist.interpret.PlaylistInterpreter
|
||||||
|
@ -39,12 +40,13 @@ internal interface EvaluateStep {
|
||||||
suspend fun evaluate(complete: Flow<Complete>): MutableLibrary
|
suspend fun evaluate(complete: Flow<Complete>): MutableLibrary
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun new(storage: Storage, interpretation: Interpretation): EvaluateStep =
|
fun new(storage: Storage, interpretation: Interpretation, logger: Logger): EvaluateStep =
|
||||||
EvaluateStepImpl(
|
EvaluateStepImpl(
|
||||||
Interpreter.new(interpretation),
|
Interpreter.new(interpretation),
|
||||||
PlaylistInterpreter.new(interpretation),
|
PlaylistInterpreter.new(interpretation),
|
||||||
storage.storedPlaylists,
|
storage.storedPlaylists,
|
||||||
LibraryFactory.new())
|
LibraryFactory.new(),
|
||||||
|
logger.primary("eval"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,9 +54,11 @@ private class EvaluateStepImpl(
|
||||||
private val interpreter: Interpreter,
|
private val interpreter: Interpreter,
|
||||||
private val playlistInterpreter: PlaylistInterpreter,
|
private val playlistInterpreter: PlaylistInterpreter,
|
||||||
private val storedPlaylists: StoredPlaylists,
|
private val storedPlaylists: StoredPlaylists,
|
||||||
private val libraryFactory: LibraryFactory
|
private val libraryFactory: LibraryFactory,
|
||||||
|
private val logger: Logger
|
||||||
) : EvaluateStep {
|
) : EvaluateStep {
|
||||||
override suspend fun evaluate(complete: Flow<Complete>): MutableLibrary {
|
override suspend fun evaluate(complete: Flow<Complete>): MutableLibrary {
|
||||||
|
logger.d("evaluate start.")
|
||||||
val filterFlow =
|
val filterFlow =
|
||||||
complete.divert {
|
complete.divert {
|
||||||
when (it) {
|
when (it) {
|
||||||
|
@ -80,7 +84,9 @@ private class EvaluateStepImpl(
|
||||||
preSongs.onEach { graphBuilder.add(it) },
|
preSongs.onEach { graphBuilder.add(it) },
|
||||||
prePlaylists.onEach { graphBuilder.add(it) })
|
prePlaylists.onEach { graphBuilder.add(it) })
|
||||||
graphBuild.collect()
|
graphBuild.collect()
|
||||||
|
logger.d("starting graph build")
|
||||||
val graph = graphBuilder.build()
|
val graph = graphBuilder.build()
|
||||||
|
logger.d("graph build done, creating library")
|
||||||
return libraryFactory.create(graph, storedPlaylists, playlistInterpreter)
|
return libraryFactory.create(graph, storedPlaylists, playlistInterpreter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.oxycblt.musikr.cover.Covers
|
||||||
import org.oxycblt.musikr.cover.ObtainResult
|
import org.oxycblt.musikr.cover.ObtainResult
|
||||||
import org.oxycblt.musikr.fs.MusicLocation
|
import org.oxycblt.musikr.fs.MusicLocation
|
||||||
import org.oxycblt.musikr.fs.device.DeviceFS
|
import org.oxycblt.musikr.fs.device.DeviceFS
|
||||||
|
import org.oxycblt.musikr.log.Logger
|
||||||
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
||||||
import org.oxycblt.musikr.playlist.m3u.M3U
|
import org.oxycblt.musikr.playlist.m3u.M3U
|
||||||
|
|
||||||
|
@ -43,9 +44,14 @@ internal interface ExploreStep {
|
||||||
fun explore(locations: List<MusicLocation>): Flow<Explored>
|
fun explore(locations: List<MusicLocation>): Flow<Explored>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun from(context: Context, storage: Storage): ExploreStep =
|
fun from(context: Context, storage: Storage, logger: Logger): ExploreStep =
|
||||||
ExploreStepImpl(
|
ExploreStepImpl(
|
||||||
DeviceFS.from(context), storage.storedPlaylists, storage.cache, storage.covers)
|
DeviceFS.from(context),
|
||||||
|
storage.storedPlaylists,
|
||||||
|
storage.cache,
|
||||||
|
storage.covers,
|
||||||
|
logger.primary("expl"),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,9 +59,11 @@ private class ExploreStepImpl(
|
||||||
private val deviceFS: DeviceFS,
|
private val deviceFS: DeviceFS,
|
||||||
private val storedPlaylists: StoredPlaylists,
|
private val storedPlaylists: StoredPlaylists,
|
||||||
private val songCache: SongCache,
|
private val songCache: SongCache,
|
||||||
private val covers: Covers
|
private val covers: Covers,
|
||||||
|
private val logger: Logger,
|
||||||
) : ExploreStep {
|
) : ExploreStep {
|
||||||
override fun explore(locations: List<MusicLocation>): Flow<Explored> {
|
override fun explore(locations: List<MusicLocation>): Flow<Explored> {
|
||||||
|
logger.d("explore start.")
|
||||||
val audioFiles =
|
val audioFiles =
|
||||||
deviceFS
|
deviceFS
|
||||||
.explore(locations.asFlow())
|
.explore(locations.asFlow())
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.oxycblt.musikr.Storage
|
||||||
import org.oxycblt.musikr.cache.CachedSong
|
import org.oxycblt.musikr.cache.CachedSong
|
||||||
import org.oxycblt.musikr.cache.MutableSongCache
|
import org.oxycblt.musikr.cache.MutableSongCache
|
||||||
import org.oxycblt.musikr.cover.MutableCovers
|
import org.oxycblt.musikr.cover.MutableCovers
|
||||||
|
import org.oxycblt.musikr.log.Logger
|
||||||
import org.oxycblt.musikr.metadata.Metadata
|
import org.oxycblt.musikr.metadata.Metadata
|
||||||
import org.oxycblt.musikr.metadata.MetadataExtractor
|
import org.oxycblt.musikr.metadata.MetadataExtractor
|
||||||
import org.oxycblt.musikr.metadata.MetadataHandle
|
import org.oxycblt.musikr.metadata.MetadataHandle
|
||||||
|
@ -40,9 +41,14 @@ internal interface ExtractStep {
|
||||||
fun extract(nodes: Flow<Explored.New>): Flow<Extracted>
|
fun extract(nodes: Flow<Explored.New>): Flow<Extracted>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun from(context: Context, storage: Storage): ExtractStep =
|
fun from(context: Context, storage: Storage, logger: Logger): ExtractStep =
|
||||||
ExtractStepImpl(
|
ExtractStepImpl(
|
||||||
MetadataExtractor.new(context), TagParser.new(), storage.cache, storage.covers)
|
MetadataExtractor.new(context),
|
||||||
|
TagParser.new(),
|
||||||
|
storage.cache,
|
||||||
|
storage.covers,
|
||||||
|
logger.primary("exct"),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,9 +56,12 @@ private class ExtractStepImpl(
|
||||||
private val metadataExtractor: MetadataExtractor,
|
private val metadataExtractor: MetadataExtractor,
|
||||||
private val tagParser: TagParser,
|
private val tagParser: TagParser,
|
||||||
private val cache: MutableSongCache,
|
private val cache: MutableSongCache,
|
||||||
private val storedCovers: MutableCovers
|
private val storedCovers: MutableCovers,
|
||||||
|
private val logger: Logger
|
||||||
) : ExtractStep {
|
) : ExtractStep {
|
||||||
override fun extract(nodes: Flow<Explored.New>): Flow<Extracted> {
|
override fun extract(nodes: Flow<Explored.New>): Flow<Extracted> {
|
||||||
|
logger.d("extract start.")
|
||||||
|
|
||||||
val newSongs = nodes.filterIsInstance<NewSong>()
|
val newSongs = nodes.filterIsInstance<NewSong>()
|
||||||
|
|
||||||
val handles =
|
val handles =
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2024 Auxio Project
|
* Copyright (c) 2024 Auxio Project
|
||||||
* TagInterpreter.kt is part of Auxio.
|
* Interpreter.kt is part of Auxio.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
Loading…
Reference in a new issue