image: connect cover back up

This commit is contained in:
Alexander Capehart 2024-12-11 17:38:42 -07:00
parent 0ce3a11f82
commit 6d85f43304
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
2 changed files with 50 additions and 56 deletions

View file

@ -37,13 +37,13 @@ class CoilModule {
fun imageLoader( fun imageLoader(
@ApplicationContext context: Context, @ApplicationContext context: Context,
keyer: CoverKeyer, keyer: CoverKeyer,
// factory: CoverFetcher.Factory factory: CoverFetcher.Factory
) = ) =
ImageLoader.Builder(context) ImageLoader.Builder(context)
.components { .components {
// Add fetchers for Music components to make them usable with ImageRequest // Add fetchers for Music components to make them usable with ImageRequest
add(keyer) add(keyer)
// add(factory) add(factory)
} }
// Use our own crossfade with error drawable support // Use our own crossfade with error drawable support
.transitionFactory(ErrorCrossfadeTransitionFactory()) .transitionFactory(ErrorCrossfadeTransitionFactory())

View file

@ -23,11 +23,14 @@ import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.graphics.Canvas import android.graphics.Canvas
import androidx.core.graphics.drawable.toDrawable import androidx.core.graphics.drawable.toDrawable
import coil3.ImageLoader
import coil3.asImage import coil3.asImage
import coil3.decode.DataSource import coil3.decode.DataSource
import coil3.decode.ImageSource
import coil3.fetch.FetchResult import coil3.fetch.FetchResult
import coil3.fetch.Fetcher import coil3.fetch.Fetcher
import coil3.fetch.ImageFetchResult import coil3.fetch.ImageFetchResult
import coil3.fetch.SourceFetchResult
import coil3.key.Keyer import coil3.key.Keyer
import coil3.request.Options import coil3.request.Options
import coil3.size.Dimension import coil3.size.Dimension
@ -35,7 +38,13 @@ import coil3.size.Size
import coil3.size.pxOrElse import coil3.size.pxOrElse
import java.io.InputStream import java.io.InputStream
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okio.FileSystem
import okio.buffer
import okio.source
import org.oxycblt.musikr.cover.Cover import org.oxycblt.musikr.cover.Cover
import org.oxycblt.musikr.cover.StoredCovers
class CoverKeyer @Inject constructor() : Keyer<Cover> { class CoverKeyer @Inject constructor() : Keyer<Cover> {
override fun key(data: Cover, options: Options) = "${data.key}&${options.size}" override fun key(data: Cover, options: Options) = "${data.key}&${options.size}"
@ -47,60 +56,46 @@ private constructor(
private val cover: Cover, private val cover: Cover,
private val size: Size, private val size: Size,
) : Fetcher { ) : Fetcher {
private val storedCovers = StoredCovers.from(context, "covers")
override suspend fun fetch(): FetchResult? { override suspend fun fetch(): FetchResult? {
return null val streams =
// val streams = when (val cover = cover) {
// when (val cover = cover) { is Cover.Single -> listOfNotNull(storedCovers.read(cover))
// is Cover.Single -> listOfNotNull(coverRetriever.retrieve(cover)) is Cover.Multi ->
// is Cover.Multi -> buildList {
// buildList { for (single in cover.all) {
// for (single in cover.all) { storedCovers.read(single)?.let { add(it) }
// coverRetriever.retrieve(single)?.let { add(it) } if (size == 4) {
// if (size == 4) { break
// break }
// } }
// } }
// } }
// }
// We don't immediately check for mosaic feasibility from album count alone, as that // We don't immediately check for mosaic feasibility from album count alone, as that
// does not factor in InputStreams failing to load. Instead, only check once we // does not factor in InputStreams failing to load. Instead, only check once we
// definitely have image data to use. // definitely have image data to use.
// if (streams.size == 4) { if (streams.size == 4) {
// // Make sure we free the InputStreams once we've transformed them into a // Make sure we free the InputStreams once we've transformed them into a
// mosaic. // mosaic.
// return createMosaic(streams, size).also { return createMosaic(streams, size).also {
// withContext(Dispatchers.IO) { streams.forEach(InputStream::close) } withContext(Dispatchers.IO) { streams.forEach(InputStream::close) }
// } // Not enough covers for a mosaic, take the first one (if that even }
// exists) }
// val first = streams.firstOrNull() ?: return null // Not enough covers for a mosaic, take the first one (if that even exists)
// val first = streams.firstOrNull() ?: return null
// // All but the first stream will be unused, free their resources
// withContext(Dispatchers.IO) {
// for (i in 1 until streams.size) {
// streams[i].close()
// }
// }
//
// return SourceFetchResult(
// source = ImageSource(first.source().buffer(), FileSystem.SYSTEM, null),
// mimeType = null,
// dataSource = DataSource.DISK)
// }
// // Not enough covers for a mosaic, take the first one (if that even exists) // All but the first stream will be unused, free their resources
// val first = streams.firstOrNull() ?: return null withContext(Dispatchers.IO) {
// for (i in 1 until streams.size) {
// // All but the first stream will be unused, free their resources streams[i].close()
// withContext(Dispatchers.IO) { }
// for (i in 1 until streams.size) { }
// streams[i].close()
// } return SourceFetchResult(
// } source = ImageSource(first.source().buffer(), FileSystem.SYSTEM, null),
// mimeType = null,
// return SourceFetchResult( dataSource = DataSource.DISK)
// source = ImageSource(first.source().buffer(), FileSystem.SYSTEM, null),
// mimeType = null,
// dataSource = DataSource.DISK)
} }
/** Derived from phonograph: https://github.com/kabouzeid/Phonograph */ /** Derived from phonograph: https://github.com/kabouzeid/Phonograph */
@ -154,9 +149,8 @@ private constructor(
return if (size.mod(2) > 0) size + 1 else size return if (size.mod(2) > 0) size + 1 else size
} }
// class Factory @Inject constructor(private val coverRetriever: CoverRetriever) : class Factory @Inject constructor() : Fetcher.Factory<Cover> {
// Fetcher.Factory<Cover> { override fun create(data: Cover, options: Options, imageLoader: ImageLoader) =
// override fun create(data: Cover, options: Options, imageLoader: ImageLoader) = CoverFetcher(options.context, data, options.size)
// CoverFetcher(options.context, data, options.size, coverRetriever) }
// }
} }