Bläddra i källkod

album art for coil

Milan Jurkulak 3 år sedan
förälder
incheckning
b4898cdea0

+ 3 - 1
tvlib/build.gradle.kts

@@ -59,7 +59,9 @@ android {
     }
 
     packaging {
-        resources.excludes.add("/META-INF/{AL2.0,LGPL2.1}")
+        resources.excludes.apply {
+            add("/META-INF/{AL2.0,LGPL2.1}")
+        }
     }
 
     lint {

+ 2 - 0
tvlib/src/main/kotlin/org/mjdev/tvlib/extensions/ComposeExt.kt

@@ -36,6 +36,7 @@ import coil.decode.SvgDecoder
 import coil.decode.VideoFrameDecoder
 import coil.request.CachePolicy
 import org.mjdev.tvlib.extensions.ContextExt.isATv
+import org.mjdev.tvlib.helpers.AlbumArtDecoder
 
 @Suppress("MemberVisibilityCanBePrivate")
 object ComposeExt {
@@ -152,6 +153,7 @@ object ComposeExt {
                     }
                     add(VideoFrameDecoder.Factory())
                     add(SvgDecoder.Factory())
+                    add(AlbumArtDecoder.Factory())
                 }
                 .build()
         }

+ 88 - 0
tvlib/src/main/kotlin/org/mjdev/tvlib/helpers/AlbumArtDecoder.kt

@@ -0,0 +1,88 @@
+/*
+ *  Copyright (c) Milan Jurkulák 2023.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.tvlib.helpers
+
+import android.graphics.BitmapFactory
+import androidx.core.graphics.drawable.toDrawable
+import coil.ImageLoader
+import coil.decode.DecodeResult
+import coil.decode.Decoder
+import coil.decode.ImageSource
+import coil.fetch.SourceResult
+import coil.request.Options
+import android.media.MediaMetadataRetriever
+import coil.annotation.ExperimentalCoilApi
+import coil.decode.AssetMetadata
+import coil.decode.ContentMetadata
+import coil.decode.ResourceMetadata
+
+// todo downloader from net
+class AlbumArtDecoder(
+    private val source: ImageSource,
+    private val options: Options
+) : Decoder {
+
+    override suspend fun decode() = MediaMetadataRetriever().use { retriever ->
+        retriever.setDataSource(source)
+        val rawData = retriever.embeddedPicture
+        checkNotNull(rawData) {
+            "Failed to decode embedded album art picture."
+        }
+        val rawBitmap = BitmapFactory.decodeByteArray(rawData, 0, rawData.size)
+        DecodeResult(
+            drawable = rawBitmap.toDrawable(options.context.resources),
+            isSampled = true
+        )
+    }
+
+    @OptIn(ExperimentalCoilApi::class)
+    private fun MediaMetadataRetriever.setDataSource(source: ImageSource) {
+        when (val metadata = source.metadata) {
+            is AssetMetadata -> {
+                options.context.assets.openFd(metadata.filePath).use {
+                    setDataSource(it.fileDescriptor, it.startOffset, it.length)
+                }
+            }
+            is ContentMetadata -> {
+                setDataSource(options.context, metadata.uri)
+            }
+            is ResourceMetadata -> {
+                setDataSource("android.resource://${metadata.packageName}/${metadata.resId}")
+            }
+            else -> {
+                setDataSource(source.file().toFile().path)
+            }
+        }
+    }
+
+    class Factory : Decoder.Factory {
+
+        override fun create(
+            result: SourceResult,
+            options: Options,
+            imageLoader: ImageLoader
+        ): Decoder? {
+            return if (!isApplicable(result.mimeType)) {
+                null
+            } else {
+                AlbumArtDecoder(result.source, options)
+            }
+        }
+
+        private fun isApplicable(mimeType: String?): Boolean {
+            return mimeType != null && mimeType.startsWith("audio/")
+        }
+
+        override fun equals(other: Any?) = other is Factory
+
+        override fun hashCode() = javaClass.hashCode()
+
+    }
+
+}