musikr: cleanup
This commit is contained in:
parent
6feee93438
commit
22249cc95b
10 changed files with 57 additions and 49 deletions
|
@ -24,13 +24,13 @@ import javax.inject.Inject
|
|||
import org.oxycblt.auxio.image.CoverMode
|
||||
import org.oxycblt.auxio.image.ImageSettings
|
||||
import org.oxycblt.musikr.covers.Cover
|
||||
import org.oxycblt.musikr.covers.Covers
|
||||
import org.oxycblt.musikr.covers.MutableCovers
|
||||
import org.oxycblt.musikr.covers.fs.FSCovers
|
||||
import org.oxycblt.musikr.covers.fs.MutableFSCovers
|
||||
import org.oxycblt.musikr.covers.internal.CoverIdentifier
|
||||
import org.oxycblt.musikr.covers.internal.CoverParams
|
||||
import org.oxycblt.musikr.covers.Covers
|
||||
import org.oxycblt.musikr.covers.internal.FileCover
|
||||
import org.oxycblt.musikr.covers.fs.FSCovers
|
||||
import org.oxycblt.musikr.covers.MutableCovers
|
||||
import org.oxycblt.musikr.covers.fs.MutableFSCovers
|
||||
|
||||
interface SettingCovers {
|
||||
suspend fun mutate(context: Context, revision: UUID): MutableCovers<out Cover>
|
||||
|
@ -57,6 +57,5 @@ constructor(private val imageSettings: ImageSettings, private val identifier: Co
|
|||
private suspend fun siloedCovers(context: Context, revision: UUID, with: CoverParams?) =
|
||||
MutableCovers.chain(
|
||||
MutableSiloedCovers.from(context, CoverSilo(revision, with), identifier),
|
||||
MutableFSCovers(context)
|
||||
)
|
||||
MutableFSCovers(context))
|
||||
}
|
||||
|
|
|
@ -23,13 +23,13 @@ import java.io.File
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.oxycblt.musikr.covers.Cover
|
||||
import org.oxycblt.musikr.covers.internal.CoverFormat
|
||||
import org.oxycblt.musikr.covers.internal.CoverIdentifier
|
||||
import org.oxycblt.musikr.covers.CoverResult
|
||||
import org.oxycblt.musikr.covers.Covers
|
||||
import org.oxycblt.musikr.covers.MutableCovers
|
||||
import org.oxycblt.musikr.covers.internal.CoverFormat
|
||||
import org.oxycblt.musikr.covers.internal.CoverIdentifier
|
||||
import org.oxycblt.musikr.covers.internal.FileCover
|
||||
import org.oxycblt.musikr.covers.internal.InternalCovers
|
||||
import org.oxycblt.musikr.covers.MutableCovers
|
||||
import org.oxycblt.musikr.covers.internal.MutableInternalCovers
|
||||
import org.oxycblt.musikr.fs.app.AppFS
|
||||
import org.oxycblt.musikr.fs.device.DeviceFile
|
||||
|
@ -96,8 +96,7 @@ private constructor(
|
|||
): MutableSiloedCovers {
|
||||
val core = SiloCore.from(context, silo)
|
||||
return MutableSiloedCovers(
|
||||
core.rootDir, silo, MutableInternalCovers(core.files, core.format, coverIdentifier)
|
||||
)
|
||||
core.rootDir, silo, MutableInternalCovers(core.files, core.format, coverIdentifier))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ import org.oxycblt.musikr.tag.interpret.Separators
|
|||
/** Side-effect laden [Storage] for use during music loading and [MutableLibrary] operation. */
|
||||
data class Storage(
|
||||
/**
|
||||
* A factory producing a repository of cached metadata to read and write from over the course of
|
||||
* music loading. This will only be used during music loading.
|
||||
* A repository of cached metadata to read and write from over the course of music loading. This
|
||||
* will only be used during music loading.
|
||||
*/
|
||||
val cache: MutableCache,
|
||||
|
||||
|
@ -57,5 +57,5 @@ data class Interpretation(
|
|||
val separators: Separators,
|
||||
|
||||
/** Whether to ignore hidden files and directories (those starting with a dot). */
|
||||
val ignoreHidden: Boolean = true
|
||||
val ignoreHidden: Boolean
|
||||
)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.oxycblt.musikr.covers
|
||||
|
||||
import android.os.ParcelFileDescriptor
|
||||
import java.io.InputStream
|
||||
import org.oxycblt.musikr.fs.device.DeviceFile
|
||||
import org.oxycblt.musikr.metadata.Metadata
|
||||
|
@ -94,6 +95,10 @@ interface Cover {
|
|||
override fun hashCode(): Int
|
||||
}
|
||||
|
||||
interface FDCover : Cover {
|
||||
suspend fun fd(): ParcelFileDescriptor?
|
||||
}
|
||||
|
||||
class CoverCollection private constructor(val covers: List<Cover>) {
|
||||
override fun hashCode() = covers.hashCode()
|
||||
|
||||
|
|
|
@ -29,20 +29,19 @@ import kotlinx.coroutines.withContext
|
|||
import org.oxycblt.musikr.covers.Cover
|
||||
import org.oxycblt.musikr.covers.CoverResult
|
||||
import org.oxycblt.musikr.covers.Covers
|
||||
import org.oxycblt.musikr.covers.FDCover
|
||||
import org.oxycblt.musikr.covers.MutableCovers
|
||||
import org.oxycblt.musikr.covers.internal.FileCover
|
||||
import org.oxycblt.musikr.fs.device.DeviceDirectory
|
||||
import org.oxycblt.musikr.fs.device.DeviceFile
|
||||
import org.oxycblt.musikr.metadata.Metadata
|
||||
|
||||
open class FSCovers(private val context: Context) : Covers<FolderCover> {
|
||||
override suspend fun obtain(id: String): CoverResult<FolderCover> {
|
||||
open class FSCovers(private val context: Context) : Covers<FDCover> {
|
||||
override suspend fun obtain(id: String): CoverResult<FDCover> {
|
||||
// Parse the ID to get the directory URI
|
||||
if (!id.startsWith("folder:")) {
|
||||
return CoverResult.Miss()
|
||||
}
|
||||
|
||||
// TODO: Check if the dir actually exists still to avoid stale uris
|
||||
val directoryUri = id.substring("folder:".length)
|
||||
val uri = Uri.parse(directoryUri)
|
||||
|
||||
|
@ -65,9 +64,8 @@ open class FSCovers(private val context: Context) : Covers<FolderCover> {
|
|||
}
|
||||
}
|
||||
|
||||
class MutableFSCovers(private val context: Context) :
|
||||
FSCovers(context), MutableCovers<FolderCover> {
|
||||
override suspend fun create(file: DeviceFile, metadata: Metadata): CoverResult<FolderCover> {
|
||||
class MutableFSCovers(private val context: Context) : FSCovers(context), MutableCovers<FDCover> {
|
||||
override suspend fun create(file: DeviceFile, metadata: Metadata): CoverResult<FDCover> {
|
||||
val parent = file.parent
|
||||
val coverFile = findCoverInDirectory(parent) ?: return CoverResult.Miss()
|
||||
return CoverResult.Hit(FolderCoverImpl(context, coverFile.uri))
|
||||
|
@ -88,12 +86,10 @@ class MutableFSCovers(private val context: Context) :
|
|||
val filename = requireNotNull(file.path.name).lowercase()
|
||||
val mimeType = file.mimeType.lowercase()
|
||||
|
||||
// Check if the file is an image
|
||||
if (!mimeType.startsWith("image/")) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Common cover art filenames
|
||||
val coverNames =
|
||||
listOf(
|
||||
"cover",
|
||||
|
@ -103,11 +99,8 @@ class MutableFSCovers(private val context: Context) :
|
|||
"front",
|
||||
"artwork",
|
||||
"art",
|
||||
"folder",
|
||||
"cover")
|
||||
"folder")
|
||||
|
||||
// Check if the filename matches any common cover art names
|
||||
// Also check for case variations (e.g., Cover.jpg, COVER.JPG)
|
||||
val filenameWithoutExt = filename.substringBeforeLast(".")
|
||||
val extension = filename.substringAfterLast(".", "")
|
||||
|
||||
|
@ -120,12 +113,10 @@ class MutableFSCovers(private val context: Context) :
|
|||
}
|
||||
}
|
||||
|
||||
interface FolderCover : FileCover
|
||||
|
||||
private data class FolderCoverImpl(
|
||||
private val context: Context,
|
||||
private val uri: Uri,
|
||||
) : FolderCover {
|
||||
) : FDCover {
|
||||
override val id = "folder:$uri"
|
||||
|
||||
override suspend fun fd(): ParcelFileDescriptor? =
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Auxio Project
|
||||
* CoverFormat.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.covers.internal
|
||||
|
||||
import android.graphics.Bitmap
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Auxio Project
|
||||
* FileCovers.kt is part of Auxio.
|
||||
* InternalCovers.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
|
||||
|
@ -18,22 +18,22 @@
|
|||
|
||||
package org.oxycblt.musikr.covers.internal
|
||||
|
||||
import android.os.ParcelFileDescriptor
|
||||
import org.oxycblt.musikr.covers.Cover
|
||||
import org.oxycblt.musikr.covers.CoverResult
|
||||
import org.oxycblt.musikr.covers.Covers
|
||||
import org.oxycblt.musikr.covers.FDCover
|
||||
import org.oxycblt.musikr.covers.MutableCovers
|
||||
import org.oxycblt.musikr.fs.app.AppFile
|
||||
import org.oxycblt.musikr.fs.app.AppFS
|
||||
import org.oxycblt.musikr.fs.app.AppFile
|
||||
import org.oxycblt.musikr.fs.device.DeviceFile
|
||||
import org.oxycblt.musikr.metadata.Metadata
|
||||
|
||||
open class InternalCovers(private val appFS: AppFS, private val coverFormat: CoverFormat) :
|
||||
Covers<FileCover> {
|
||||
override suspend fun obtain(id: String): CoverResult<FileCover> {
|
||||
Covers<FDCover> {
|
||||
override suspend fun obtain(id: String): CoverResult<FDCover> {
|
||||
val file = appFS.find(getFileName(id))
|
||||
return if (file != null) {
|
||||
CoverResult.Hit(FileCoverImpl(id, file))
|
||||
CoverResult.Hit(InternalCoverImpl(id, file))
|
||||
} else {
|
||||
CoverResult.Miss()
|
||||
}
|
||||
|
@ -46,12 +46,12 @@ class MutableInternalCovers(
|
|||
private val appFS: AppFS,
|
||||
private val coverFormat: CoverFormat,
|
||||
private val coverIdentifier: CoverIdentifier
|
||||
) : InternalCovers(appFS, coverFormat), MutableCovers<FileCover> {
|
||||
override suspend fun create(file: DeviceFile, metadata: Metadata): CoverResult<FileCover> {
|
||||
) : InternalCovers(appFS, coverFormat), MutableCovers<FDCover> {
|
||||
override suspend fun create(file: DeviceFile, metadata: Metadata): CoverResult<FDCover> {
|
||||
val data = metadata.cover ?: return CoverResult.Miss()
|
||||
val id = coverIdentifier.identify(data)
|
||||
val coverFile = appFS.write(getFileName(id)) { coverFormat.transcodeInto(data, it) }
|
||||
return CoverResult.Hit(FileCoverImpl(id, coverFile))
|
||||
return CoverResult.Hit(InternalCoverImpl(id, coverFile))
|
||||
}
|
||||
|
||||
override suspend fun cleanup(excluding: Collection<Cover>) {
|
||||
|
@ -60,12 +60,8 @@ class MutableInternalCovers(
|
|||
}
|
||||
}
|
||||
|
||||
interface FileCover : Cover {
|
||||
suspend fun fd(): ParcelFileDescriptor?
|
||||
}
|
||||
|
||||
private data class FileCoverImpl(override val id: String, private val appFile: AppFile) :
|
||||
FileCover {
|
||||
private data class InternalCoverImpl(override val id: String, private val appFile: AppFile) :
|
||||
FDCover {
|
||||
override suspend fun fd() = appFile.fd()
|
||||
|
||||
override suspend fun open() = appFile.open()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Auxio Project
|
||||
* AppFiles.kt is part of Auxio.
|
||||
* AppFS.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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Auxio Project
|
||||
* DeviceFiles.kt is part of Auxio.
|
||||
* DeviceFS.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
|
||||
|
@ -31,7 +31,7 @@ import org.oxycblt.musikr.fs.MusicLocation
|
|||
import org.oxycblt.musikr.fs.Path
|
||||
|
||||
internal interface DeviceFS {
|
||||
fun explore(locations: Flow<MusicLocation>, ignoreHidden: Boolean = true): Flow<DeviceNode>
|
||||
fun explore(locations: Flow<MusicLocation>, ignoreHidden: Boolean): Flow<DeviceNode>
|
||||
|
||||
companion object {
|
||||
fun from(context: Context): DeviceFS = DeviceFSImpl(context.contentResolverSafe)
|
||||
|
|
|
@ -38,8 +38,8 @@ import org.oxycblt.musikr.covers.CoverResult
|
|||
import org.oxycblt.musikr.covers.Covers
|
||||
import org.oxycblt.musikr.fs.MusicLocation
|
||||
import org.oxycblt.musikr.fs.device.DeviceDirectory
|
||||
import org.oxycblt.musikr.fs.device.DeviceFile
|
||||
import org.oxycblt.musikr.fs.device.DeviceFS
|
||||
import org.oxycblt.musikr.fs.device.DeviceFile
|
||||
import org.oxycblt.musikr.fs.device.DeviceNode
|
||||
import org.oxycblt.musikr.playlist.db.StoredPlaylists
|
||||
import org.oxycblt.musikr.playlist.m3u.M3U
|
||||
|
|
Loading…
Reference in a new issue