musikr: introduce cover cleanup
Helps reduce overall memory use.
This commit is contained in:
parent
7b35ba840b
commit
8b58f357cb
4 changed files with 40 additions and 15 deletions
|
@ -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.
|
||||
covers.cleanup(context)
|
||||
covers.cleanup(newLibrary)
|
||||
}
|
||||
|
||||
private suspend fun emitIndexingProgress(progress: IndexingProgress) {
|
||||
|
|
|
@ -19,9 +19,11 @@
|
|||
package org.oxycblt.auxio.music
|
||||
|
||||
import android.content.Context
|
||||
import java.io.File
|
||||
import java.util.UUID
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.oxycblt.musikr.Library
|
||||
import org.oxycblt.musikr.cover.Cover
|
||||
import org.oxycblt.musikr.cover.CoverFiles
|
||||
import org.oxycblt.musikr.cover.CoverFormat
|
||||
|
@ -29,8 +31,11 @@ import org.oxycblt.musikr.cover.CoverParams
|
|||
import org.oxycblt.musikr.cover.MutableStoredCovers
|
||||
import org.oxycblt.musikr.cover.StoredCovers
|
||||
|
||||
class RevisionedCovers(private val revision: UUID, private val inner: MutableStoredCovers) :
|
||||
MutableStoredCovers {
|
||||
class RevisionedCovers(
|
||||
private val rootDir: File,
|
||||
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
|
||||
|
@ -41,24 +46,27 @@ class RevisionedCovers(private val revision: UUID, private val inner: MutableSto
|
|||
return inner.write(data)?.let { RevisionedCover(revision, it) }
|
||||
}
|
||||
|
||||
suspend fun cleanup(context: Context) =
|
||||
override suspend fun cleanup(assuming: Library) {
|
||||
inner.cleanup(assuming)
|
||||
|
||||
// Destroy old revisions no longer being used.
|
||||
withContext(Dispatchers.IO) {
|
||||
val exclude = revision.toString()
|
||||
context.filesDir
|
||||
.resolve("covers")
|
||||
.listFiles { file -> file.name != exclude }
|
||||
?.forEach { it.deleteRecursively() }
|
||||
rootDir.listFiles { file -> file.name != exclude }?.forEach { it.deleteRecursively() }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
suspend fun at(context: Context, revision: UUID): RevisionedCovers {
|
||||
val dir =
|
||||
val rootDir: File
|
||||
val revisionDir: File
|
||||
withContext(Dispatchers.IO) {
|
||||
context.filesDir.resolve("covers/${revision}").apply { mkdirs() }
|
||||
rootDir = context.filesDir.resolve("covers").apply { mkdirs() }
|
||||
revisionDir = rootDir.resolve(revision.toString()).apply { mkdirs() }
|
||||
}
|
||||
return RevisionedCovers(
|
||||
revision,
|
||||
StoredCovers.from(CoverFiles.at(dir), CoverFormat.jpeg(CoverParams.of(750, 80))))
|
||||
val files = CoverFiles.at(revisionDir)
|
||||
val format = CoverFormat.jpeg(CoverParams.of(750, 80))
|
||||
return RevisionedCovers(rootDir, revision, StoredCovers.from(files, format))
|
||||
}
|
||||
|
||||
private fun parse(id: String): Pair<String, UUID>? {
|
||||
|
|
|
@ -32,6 +32,8 @@ interface CoverFiles {
|
|||
|
||||
suspend fun write(name: String, block: suspend (OutputStream) -> Unit): CoverFile?
|
||||
|
||||
suspend fun deleteWhere(block: (String) -> Boolean)
|
||||
|
||||
companion object {
|
||||
suspend fun at(dir: File): CoverFiles {
|
||||
withContext(Dispatchers.IO) { check(dir.exists() && dir.isDirectory) }
|
||||
|
@ -83,6 +85,12 @@ private class CoverFilesImpl(private val dir: File) : CoverFiles {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun deleteWhere(block: (String) -> Boolean) {
|
||||
withContext(Dispatchers.IO) {
|
||||
dir.listFiles { file -> block(file.name) }?.forEach { it.deleteRecursively() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class CoverFileImpl(private val file: File) : CoverFile {
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
package org.oxycblt.musikr.cover
|
||||
|
||||
import org.oxycblt.musikr.Library
|
||||
|
||||
interface StoredCovers {
|
||||
suspend fun obtain(id: String): Cover?
|
||||
|
||||
|
@ -32,6 +34,8 @@ interface StoredCovers {
|
|||
|
||||
interface MutableStoredCovers : StoredCovers {
|
||||
suspend fun write(data: ByteArray): Cover?
|
||||
|
||||
suspend fun cleanup(assuming: Library)
|
||||
}
|
||||
|
||||
private class FileStoredCovers(
|
||||
|
@ -49,6 +53,11 @@ private class FileStoredCovers(
|
|||
?.let { FileCover(id, it) }
|
||||
}
|
||||
|
||||
override suspend fun cleanup(assuming: Library) {
|
||||
val used = assuming.songs.mapNotNullTo(mutableSetOf()) { it.cover?.id?.let(::getFileName) }
|
||||
coverFiles.deleteWhere { it !in used }
|
||||
}
|
||||
|
||||
private fun getFileName(id: String) = "$id.${coverFormat.extension}"
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue