musikr: simplify cover storage boundaries
This commit is contained in:
parent
dc8cbc74e8
commit
b8178056f5
4 changed files with 40 additions and 42 deletions
|
@ -385,7 +385,7 @@ constructor(
|
|||
val currentRevision = musicSettings.revision
|
||||
val newRevision = currentRevision?.takeIf { withCache } ?: UUID.randomUUID()
|
||||
val cache = if (withCache) storedCache.visible() else storedCache.invisible()
|
||||
val covers = MutableRevisionedStoredCovers(context, newRevision)
|
||||
val covers = RevisionedCovers.at(context, newRevision)
|
||||
val storage = Storage(cache, covers, storedPlaylists)
|
||||
val interpretation = Interpretation(nameFactory, separators)
|
||||
|
||||
|
@ -432,7 +432,7 @@ constructor(
|
|||
// Old cover revisions may be lying around, even during a normal refresh due
|
||||
// to really lucky cancellations. Clean those up now that it's impossible for
|
||||
// the rest of the app to be using them.
|
||||
RevisionedStoredCovers.cleanup(context, newRevision)
|
||||
RevisionedCovers.cleanup(context, newRevision)
|
||||
}
|
||||
|
||||
private suspend fun emitIndexingProgress(progress: IndexingProgress) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Auxio Project
|
||||
* RevisionedLibrary.kt is part of Auxio.
|
||||
* RevisionedCovers.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
|
||||
|
@ -22,51 +22,50 @@ import android.content.Context
|
|||
import java.util.UUID
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||
import org.oxycblt.musikr.cover.Cover
|
||||
import org.oxycblt.musikr.cover.CoverFiles
|
||||
import org.oxycblt.musikr.cover.CoverFormat
|
||||
import org.oxycblt.musikr.cover.MutableStoredCovers
|
||||
import org.oxycblt.musikr.cover.StoredCovers
|
||||
|
||||
open class RevisionedStoredCovers(private val context: Context, private val revision: UUID?) :
|
||||
StoredCovers {
|
||||
protected val inner =
|
||||
revision?.let { StoredCovers.from(context, "covers_$it", CoverFormat.jpeg()) }
|
||||
|
||||
class RevisionedCovers(private val revision: UUID, private val inner: MutableStoredCovers) :
|
||||
MutableStoredCovers {
|
||||
override suspend fun obtain(id: String): RevisionedCover? {
|
||||
val (coverId, coverRevision) = parse(id) ?: return null
|
||||
if (coverRevision != revision) return null
|
||||
return inner.obtain(coverId)?.let { RevisionedCover(revision, it) }
|
||||
}
|
||||
|
||||
override suspend fun write(data: ByteArray): RevisionedCover? {
|
||||
return inner.write(data)?.let { RevisionedCover(revision, it) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
suspend fun at(context: Context, revision: UUID): RevisionedCovers {
|
||||
val dir =
|
||||
withContext(Dispatchers.IO) {
|
||||
context.filesDir.resolve("covers/${revision}").apply { mkdirs() }
|
||||
}
|
||||
return RevisionedCovers(
|
||||
revision, StoredCovers.from(CoverFiles.at(dir, CoverFormat.jpeg())))
|
||||
}
|
||||
|
||||
suspend fun cleanup(context: Context, exclude: UUID) =
|
||||
withContext(Dispatchers.IO) {
|
||||
val excludeName = exclude.toString()
|
||||
context.filesDir
|
||||
.resolve("covers")
|
||||
.listFiles { file -> file.name != excludeName }
|
||||
?.forEach { it.deleteRecursively() }
|
||||
}
|
||||
|
||||
private fun parse(id: String): Pair<String, UUID>? {
|
||||
val split = id.split('@', limit = 2)
|
||||
if (split.size != 2) return null
|
||||
val (coverId, coverRevisionStr) = split
|
||||
val coverRevision = coverRevisionStr.toUuidOrNull() ?: return null
|
||||
if (revision != null) {
|
||||
if (coverRevision != revision) {
|
||||
return null
|
||||
return coverId to coverRevision
|
||||
}
|
||||
val storedCovers = unlikelyToBeNull(inner)
|
||||
return storedCovers.obtain(coverId)?.let { RevisionedCover(revision, it) }
|
||||
} else {
|
||||
val storedCovers =
|
||||
StoredCovers.from(context, "covers_$coverRevision", CoverFormat.jpeg())
|
||||
return storedCovers.obtain(coverId)?.let { RevisionedCover(coverRevision, it) }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
suspend fun cleanup(context: Context, exclude: UUID) =
|
||||
withContext(Dispatchers.IO) {
|
||||
context.filesDir
|
||||
.listFiles { file ->
|
||||
file.name.startsWith("covers_") && file.name != "covers_$exclude"
|
||||
}
|
||||
?.forEach { it.deleteRecursively() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MutableRevisionedStoredCovers(context: Context, private val revision: UUID) :
|
||||
RevisionedStoredCovers(context, revision), MutableStoredCovers {
|
||||
override suspend fun write(data: ByteArray): RevisionedCover? {
|
||||
return unlikelyToBeNull(inner).write(data)?.let { RevisionedCover(revision, it) }
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
package org.oxycblt.musikr.cover
|
||||
|
||||
import android.content.Context
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
@ -27,18 +26,20 @@ import kotlinx.coroutines.sync.Mutex
|
|||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
internal interface CoverFiles {
|
||||
interface CoverFiles {
|
||||
suspend fun find(id: String): CoverFile?
|
||||
|
||||
suspend fun write(id: String, data: ByteArray): CoverFile?
|
||||
|
||||
companion object {
|
||||
fun at(context: Context, path: String, format: CoverFormat): CoverFiles =
|
||||
CoverFilesImpl(File(context.filesDir, path).also { it.mkdirs() }, format)
|
||||
suspend fun at(dir: File, format: CoverFormat): CoverFiles {
|
||||
withContext(Dispatchers.IO) { check(dir.exists() && dir.isDirectory) }
|
||||
return CoverFilesImpl(dir, format)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal interface CoverFile {
|
||||
interface CoverFile {
|
||||
suspend fun open(): InputStream?
|
||||
}
|
||||
|
||||
|
|
|
@ -18,14 +18,12 @@
|
|||
|
||||
package org.oxycblt.musikr.cover
|
||||
|
||||
import android.content.Context
|
||||
|
||||
interface StoredCovers {
|
||||
suspend fun obtain(id: String): Cover?
|
||||
|
||||
companion object {
|
||||
fun from(context: Context, path: String, format: CoverFormat): MutableStoredCovers =
|
||||
FileStoredCovers(CoverIdentifier.md5(), CoverFiles.at(context, path, format))
|
||||
fun from(files: CoverFiles): MutableStoredCovers =
|
||||
FileStoredCovers(CoverIdentifier.md5(), files)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue