From 6d85f4330448003e0d92ed032bfb3365d8109484 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Wed, 11 Dec 2024 17:38:42 -0700 Subject: [PATCH] image: connect cover back up --- .../oxycblt/auxio/image/coil/CoilModule.kt | 4 +- .../oxycblt/auxio/image/coil/Components.kt | 102 +++++++++--------- 2 files changed, 50 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/image/coil/CoilModule.kt b/app/src/main/java/org/oxycblt/auxio/image/coil/CoilModule.kt index cd5bc8e07..3766ce5fb 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/coil/CoilModule.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/coil/CoilModule.kt @@ -37,13 +37,13 @@ class CoilModule { fun imageLoader( @ApplicationContext context: Context, keyer: CoverKeyer, - // factory: CoverFetcher.Factory + factory: CoverFetcher.Factory ) = ImageLoader.Builder(context) .components { // Add fetchers for Music components to make them usable with ImageRequest add(keyer) - // add(factory) + add(factory) } // Use our own crossfade with error drawable support .transitionFactory(ErrorCrossfadeTransitionFactory()) diff --git a/app/src/main/java/org/oxycblt/auxio/image/coil/Components.kt b/app/src/main/java/org/oxycblt/auxio/image/coil/Components.kt index 5f713b22d..73e56b29f 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/coil/Components.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/coil/Components.kt @@ -23,11 +23,14 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Canvas import androidx.core.graphics.drawable.toDrawable +import coil3.ImageLoader import coil3.asImage import coil3.decode.DataSource +import coil3.decode.ImageSource import coil3.fetch.FetchResult import coil3.fetch.Fetcher import coil3.fetch.ImageFetchResult +import coil3.fetch.SourceFetchResult import coil3.key.Keyer import coil3.request.Options import coil3.size.Dimension @@ -35,7 +38,13 @@ import coil3.size.Size import coil3.size.pxOrElse import java.io.InputStream 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.StoredCovers class CoverKeyer @Inject constructor() : Keyer { override fun key(data: Cover, options: Options) = "${data.key}&${options.size}" @@ -47,60 +56,46 @@ private constructor( private val cover: Cover, private val size: Size, ) : Fetcher { + private val storedCovers = StoredCovers.from(context, "covers") + override suspend fun fetch(): FetchResult? { - return null - // val streams = - // when (val cover = cover) { - // is Cover.Single -> listOfNotNull(coverRetriever.retrieve(cover)) - // is Cover.Multi -> - // buildList { - // for (single in cover.all) { - // coverRetriever.retrieve(single)?.let { add(it) } - // if (size == 4) { - // break - // } - // } - // } - // } + val streams = + when (val cover = cover) { + is Cover.Single -> listOfNotNull(storedCovers.read(cover)) + is Cover.Multi -> + buildList { + for (single in cover.all) { + storedCovers.read(single)?.let { add(it) } + if (size == 4) { + break + } + } + } + } // 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 // definitely have image data to use. - // if (streams.size == 4) { - // // Make sure we free the InputStreams once we've transformed them into a - // mosaic. - // return createMosaic(streams, size).also { - // 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 - // - // // 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) - // } + if (streams.size == 4) { + // Make sure we free the InputStreams once we've transformed them into a + // mosaic. + return createMosaic(streams, size).also { + 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) + // 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) } /** Derived from phonograph: https://github.com/kabouzeid/Phonograph */ @@ -154,9 +149,8 @@ private constructor( return if (size.mod(2) > 0) size + 1 else size } - // class Factory @Inject constructor(private val coverRetriever: CoverRetriever) : - // Fetcher.Factory { - // override fun create(data: Cover, options: Options, imageLoader: ImageLoader) = - // CoverFetcher(options.context, data, options.size, coverRetriever) - // } + class Factory @Inject constructor() : Fetcher.Factory { + override fun create(data: Cover, options: Options, imageLoader: ImageLoader) = + CoverFetcher(options.context, data, options.size) + } }