musikr: add new storage config
Allowed TagCache to be configured alongside a new StoredCovers (to be implemented later)
This commit is contained in:
parent
df1faa11e4
commit
8adda19d1a
9 changed files with 63 additions and 35 deletions
|
@ -32,8 +32,13 @@ import org.oxycblt.musikr.Musikr
|
||||||
import org.oxycblt.musikr.MutableLibrary
|
import org.oxycblt.musikr.MutableLibrary
|
||||||
import org.oxycblt.musikr.Playlist
|
import org.oxycblt.musikr.Playlist
|
||||||
import org.oxycblt.musikr.Song
|
import org.oxycblt.musikr.Song
|
||||||
import org.oxycblt.musikr.tag.Interpretation
|
import org.oxycblt.musikr.Interpretation
|
||||||
|
import org.oxycblt.musikr.Storage
|
||||||
|
import org.oxycblt.musikr.cover.Cover
|
||||||
|
import org.oxycblt.musikr.cover.StoredCovers
|
||||||
import org.oxycblt.musikr.tag.Name
|
import org.oxycblt.musikr.tag.Name
|
||||||
|
import org.oxycblt.musikr.tag.cache.FullTagCache
|
||||||
|
import org.oxycblt.musikr.tag.cache.WriteOnlyTagCache
|
||||||
import org.oxycblt.musikr.tag.interpret.Separators
|
import org.oxycblt.musikr.tag.interpret.Separators
|
||||||
import timber.log.Timber as L
|
import timber.log.Timber as L
|
||||||
|
|
||||||
|
@ -203,7 +208,7 @@ interface MusicRepository {
|
||||||
|
|
||||||
class MusicRepositoryImpl
|
class MusicRepositoryImpl
|
||||||
@Inject
|
@Inject
|
||||||
constructor(private val musikr: Musikr, private val musicSettings: MusicSettings) :
|
constructor(private val musikr: Musikr, private val fullTagCache: FullTagCache, private val writeOnlyTagCache: WriteOnlyTagCache, private val musicSettings: MusicSettings) :
|
||||||
MusicRepository {
|
MusicRepository {
|
||||||
private val updateListeners = mutableListOf<MusicRepository.UpdateListener>()
|
private val updateListeners = mutableListOf<MusicRepository.UpdateListener>()
|
||||||
private val indexingListeners = mutableListOf<MusicRepository.IndexingListener>()
|
private val indexingListeners = mutableListOf<MusicRepository.IndexingListener>()
|
||||||
|
@ -349,8 +354,23 @@ constructor(private val musikr: Musikr, private val musicSettings: MusicSettings
|
||||||
}
|
}
|
||||||
val locations = musicSettings.musicLocations
|
val locations = musicSettings.musicLocations
|
||||||
|
|
||||||
|
val fakeCoverEditorTemporary = object : StoredCovers.Editor {
|
||||||
|
override suspend fun write(data: ByteArray): Cover.Single? {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun apply() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val storage = if (withCache) {
|
||||||
|
Storage(fullTagCache, fakeCoverEditorTemporary)
|
||||||
|
} else {
|
||||||
|
Storage(writeOnlyTagCache, fakeCoverEditorTemporary)
|
||||||
|
}
|
||||||
val newLibrary =
|
val newLibrary =
|
||||||
musikr.run(locations, Interpretation(nameFactory, separators), ::emitIndexingProgress)
|
musikr.run(locations, storage, Interpretation(nameFactory, separators), ::emitIndexingProgress)
|
||||||
|
|
||||||
emitIndexingCompletion(null)
|
emitIndexingCompletion(null)
|
||||||
|
|
||||||
|
|
10
app/src/main/java/org/oxycblt/musikr/Config.kt
Normal file
10
app/src/main/java/org/oxycblt/musikr/Config.kt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package org.oxycblt.musikr
|
||||||
|
|
||||||
|
import org.oxycblt.musikr.cover.StoredCovers
|
||||||
|
import org.oxycblt.musikr.tag.Name
|
||||||
|
import org.oxycblt.musikr.tag.cache.TagCache
|
||||||
|
import org.oxycblt.musikr.tag.interpret.Separators
|
||||||
|
|
||||||
|
data class Storage(val tagCache: TagCache, val coverEditor: StoredCovers.Editor)
|
||||||
|
|
||||||
|
data class Interpretation(val nameFactory: Name.Known.Factory, val separators: Separators)
|
|
@ -29,11 +29,11 @@ import org.oxycblt.musikr.fs.MusicLocation
|
||||||
import org.oxycblt.musikr.pipeline.EvaluateStep
|
import org.oxycblt.musikr.pipeline.EvaluateStep
|
||||||
import org.oxycblt.musikr.pipeline.ExploreStep
|
import org.oxycblt.musikr.pipeline.ExploreStep
|
||||||
import org.oxycblt.musikr.pipeline.ExtractStep
|
import org.oxycblt.musikr.pipeline.ExtractStep
|
||||||
import org.oxycblt.musikr.tag.Interpretation
|
|
||||||
|
|
||||||
interface Musikr {
|
interface Musikr {
|
||||||
suspend fun run(
|
suspend fun run(
|
||||||
locations: List<MusicLocation>,
|
locations: List<MusicLocation>,
|
||||||
|
storage: Storage,
|
||||||
interpretation: Interpretation,
|
interpretation: Interpretation,
|
||||||
onProgress: suspend (IndexingProgress) -> Unit = {}
|
onProgress: suspend (IndexingProgress) -> Unit = {}
|
||||||
): MutableLibrary
|
): MutableLibrary
|
||||||
|
@ -59,6 +59,7 @@ constructor(
|
||||||
) : Musikr {
|
) : Musikr {
|
||||||
override suspend fun run(
|
override suspend fun run(
|
||||||
locations: List<MusicLocation>,
|
locations: List<MusicLocation>,
|
||||||
|
storage: Storage,
|
||||||
interpretation: Interpretation,
|
interpretation: Interpretation,
|
||||||
onProgress: suspend (IndexingProgress) -> Unit
|
onProgress: suspend (IndexingProgress) -> Unit
|
||||||
) = coroutineScope {
|
) = coroutineScope {
|
||||||
|
@ -72,7 +73,7 @@ constructor(
|
||||||
.onEach { onProgress(IndexingProgress.Songs(extractedCount, ++exploredCount)) }
|
.onEach { onProgress(IndexingProgress.Songs(extractedCount, ++exploredCount)) }
|
||||||
val extracted =
|
val extracted =
|
||||||
extractStep
|
extractStep
|
||||||
.extract(explored)
|
.extract(storage, explored)
|
||||||
.buffer(Channel.UNLIMITED)
|
.buffer(Channel.UNLIMITED)
|
||||||
.onEach { onProgress(IndexingProgress.Songs(++extractedCount, exploredCount)) }
|
.onEach { onProgress(IndexingProgress.Songs(++extractedCount, exploredCount)) }
|
||||||
.onCompletion { onProgress(IndexingProgress.Indeterminate) }
|
.onCompletion { onProgress(IndexingProgress.Indeterminate) }
|
||||||
|
|
13
app/src/main/java/org/oxycblt/musikr/cover/StoredCovers.kt
Normal file
13
app/src/main/java/org/oxycblt/musikr/cover/StoredCovers.kt
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package org.oxycblt.musikr.cover
|
||||||
|
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
interface StoredCovers {
|
||||||
|
suspend fun read(cover: Cover.Single): InputStream?
|
||||||
|
|
||||||
|
interface Editor {
|
||||||
|
suspend fun write(data: ByteArray): Cover.Single?
|
||||||
|
|
||||||
|
suspend fun apply()
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ import kotlinx.coroutines.flow.map
|
||||||
import org.oxycblt.musikr.MutableLibrary
|
import org.oxycblt.musikr.MutableLibrary
|
||||||
import org.oxycblt.musikr.graph.MusicGraph
|
import org.oxycblt.musikr.graph.MusicGraph
|
||||||
import org.oxycblt.musikr.model.LibraryFactory
|
import org.oxycblt.musikr.model.LibraryFactory
|
||||||
import org.oxycblt.musikr.tag.Interpretation
|
import org.oxycblt.musikr.Interpretation
|
||||||
import org.oxycblt.musikr.tag.interpret.TagInterpreter
|
import org.oxycblt.musikr.tag.interpret.TagInterpreter
|
||||||
|
|
||||||
interface EvaluateStep {
|
interface EvaluateStep {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.filterIsInstance
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.merge
|
import kotlinx.coroutines.flow.merge
|
||||||
|
import org.oxycblt.musikr.Storage
|
||||||
import org.oxycblt.musikr.fs.query.DeviceFile
|
import org.oxycblt.musikr.fs.query.DeviceFile
|
||||||
import org.oxycblt.musikr.metadata.MetadataExtractor
|
import org.oxycblt.musikr.metadata.MetadataExtractor
|
||||||
import org.oxycblt.musikr.tag.cache.TagCache
|
import org.oxycblt.musikr.tag.cache.TagCache
|
||||||
|
@ -34,22 +35,21 @@ import org.oxycblt.musikr.tag.parse.ParsedTags
|
||||||
import org.oxycblt.musikr.tag.parse.TagParser
|
import org.oxycblt.musikr.tag.parse.TagParser
|
||||||
|
|
||||||
interface ExtractStep {
|
interface ExtractStep {
|
||||||
fun extract(nodes: Flow<ExploreNode>): Flow<ExtractedMusic>
|
fun extract(storage: Storage, nodes: Flow<ExploreNode>): Flow<ExtractedMusic>
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExtractStepImpl
|
class ExtractStepImpl
|
||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
private val tagCache: TagCache,
|
|
||||||
private val metadataExtractor: MetadataExtractor,
|
private val metadataExtractor: MetadataExtractor,
|
||||||
private val tagParser: TagParser
|
private val tagParser: TagParser
|
||||||
) : ExtractStep {
|
) : ExtractStep {
|
||||||
override fun extract(nodes: Flow<ExploreNode>): Flow<ExtractedMusic> {
|
override fun extract(storage: Storage, nodes: Flow<ExploreNode>): Flow<ExtractedMusic> {
|
||||||
val cacheResults =
|
val cacheResults =
|
||||||
nodes
|
nodes
|
||||||
.filterIsInstance<ExploreNode.Audio>()
|
.filterIsInstance<ExploreNode.Audio>()
|
||||||
.map {
|
.map {
|
||||||
val tags = tagCache.read(it.file)
|
val tags = storage.tagCache.read(it.file)
|
||||||
MaybeCachedSong(it.file, tags)
|
MaybeCachedSong(it.file, tags)
|
||||||
}
|
}
|
||||||
.flowOn(Dispatchers.IO)
|
.flowOn(Dispatchers.IO)
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2024 Auxio Project
|
|
||||||
* Interpretation.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.tag
|
|
||||||
|
|
||||||
import org.oxycblt.musikr.tag.interpret.Separators
|
|
||||||
|
|
||||||
data class Interpretation(val nameFactory: Name.Known.Factory, val separators: Separators)
|
|
|
@ -28,10 +28,17 @@ interface TagCache {
|
||||||
suspend fun write(file: DeviceFile, tags: ParsedTags)
|
suspend fun write(file: DeviceFile, tags: ParsedTags)
|
||||||
}
|
}
|
||||||
|
|
||||||
class TagCacheImpl @Inject constructor(private val tagDao: TagDao) : TagCache {
|
class FullTagCache @Inject constructor(private val tagDao: TagDao) : TagCache {
|
||||||
override suspend fun read(file: DeviceFile) =
|
override suspend fun read(file: DeviceFile) =
|
||||||
tagDao.selectTags(file.uri.toString(), file.lastModified)?.intoParsedTags()
|
tagDao.selectTags(file.uri.toString(), file.lastModified)?.intoParsedTags()
|
||||||
|
|
||||||
override suspend fun write(file: DeviceFile, tags: ParsedTags) =
|
override suspend fun write(file: DeviceFile, tags: ParsedTags) =
|
||||||
tagDao.updateTags(CachedTags.fromParsedTags(file, tags))
|
tagDao.updateTags(CachedTags.fromParsedTags(file, tags))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WriteOnlyTagCache @Inject constructor(private val tagDao: TagDao) : TagCache {
|
||||||
|
override suspend fun read(file: DeviceFile) = null
|
||||||
|
|
||||||
|
override suspend fun write(file: DeviceFile, tags: ParsedTags) =
|
||||||
|
tagDao.updateTags(CachedTags.fromParsedTags(file, tags))
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ import org.oxycblt.auxio.util.toUuidOrNull
|
||||||
import org.oxycblt.musikr.fs.MimeType
|
import org.oxycblt.musikr.fs.MimeType
|
||||||
import org.oxycblt.musikr.fs.query.DeviceFile
|
import org.oxycblt.musikr.fs.query.DeviceFile
|
||||||
import org.oxycblt.musikr.tag.Disc
|
import org.oxycblt.musikr.tag.Disc
|
||||||
import org.oxycblt.musikr.tag.Interpretation
|
import org.oxycblt.musikr.Interpretation
|
||||||
import org.oxycblt.musikr.tag.Name
|
import org.oxycblt.musikr.tag.Name
|
||||||
import org.oxycblt.musikr.tag.ReleaseType
|
import org.oxycblt.musikr.tag.ReleaseType
|
||||||
import org.oxycblt.musikr.tag.parse.ParsedTags
|
import org.oxycblt.musikr.tag.parse.ParsedTags
|
||||||
|
|
Loading…
Reference in a new issue