coil: disable exoplayer loading
Disable exoplayer loading since apparently the way I use a blocking call in the coil coroutine causes it to be uncancellable. This ends up resulting in errors continuing to apply themselves to whatever view they were requested from, even if it was an error. Because you know. Android.
This commit is contained in:
parent
1ea3ddb2e0
commit
71b15a3a6a
2 changed files with 92 additions and 94 deletions
|
@ -27,11 +27,6 @@ import coil.fetch.FetchResult
|
||||||
import coil.fetch.Fetcher
|
import coil.fetch.Fetcher
|
||||||
import coil.fetch.SourceResult
|
import coil.fetch.SourceResult
|
||||||
import coil.size.Size
|
import coil.size.Size
|
||||||
import com.google.android.exoplayer2.MediaItem
|
|
||||||
import com.google.android.exoplayer2.MediaMetadata
|
|
||||||
import com.google.android.exoplayer2.MetadataRetriever
|
|
||||||
import com.google.android.exoplayer2.metadata.flac.PictureFrame
|
|
||||||
import com.google.android.exoplayer2.metadata.id3.ApicFrame
|
|
||||||
import okio.buffer
|
import okio.buffer
|
||||||
import okio.source
|
import okio.source
|
||||||
import org.oxycblt.auxio.music.Album
|
import org.oxycblt.auxio.music.Album
|
||||||
|
@ -39,9 +34,7 @@ import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.music.toAlbumArtURI
|
import org.oxycblt.auxio.music.toAlbumArtURI
|
||||||
import org.oxycblt.auxio.music.toURI
|
import org.oxycblt.auxio.music.toURI
|
||||||
import org.oxycblt.auxio.settings.SettingsManager
|
import org.oxycblt.auxio.settings.SettingsManager
|
||||||
import org.oxycblt.auxio.util.logD
|
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetcher that returns the album art for a given [Album]. Handles settings on whether to use
|
* Fetcher that returns the album art for a given [Album]. Handles settings on whether to use
|
||||||
|
@ -91,14 +84,14 @@ class AlbumArtFetcher(private val context: Context) : Fetcher<Album> {
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
//
|
||||||
// Our next fallback is to rely on ExoPlayer's largely half-baked and undocumented
|
// // Our next fallback is to rely on ExoPlayer's largely half-baked and undocumented
|
||||||
// metadata system.
|
// // metadata system.
|
||||||
val exoResult = fetchExoplayerCover(song)
|
// val exoResult = fetchExoplayerCover(song)
|
||||||
|
//
|
||||||
if (exoResult != null) {
|
// if (exoResult != null) {
|
||||||
return exoResult
|
// return exoResult
|
||||||
}
|
// }
|
||||||
|
|
||||||
// If the previous two failed, we resort to MediaStore's covers despite it literally
|
// If the previous two failed, we resort to MediaStore's covers despite it literally
|
||||||
// going against the point of this setting. The previous two calls are just too unreliable
|
// going against the point of this setting. The previous two calls are just too unreliable
|
||||||
|
@ -156,84 +149,86 @@ class AlbumArtFetcher(private val context: Context) : Fetcher<Album> {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchExoplayerCover(song: Song): FetchResult? {
|
// Disabled until I can figure out how the hell I can get a blocking call to play along in
|
||||||
val uri = song.id.toURI()
|
// a suspend function. I doubt it's possible.
|
||||||
|
// private fun fetchExoplayerCover(song: Song): FetchResult? {
|
||||||
val future = MetadataRetriever.retrieveMetadata(
|
// val uri = song.id.toURI()
|
||||||
context, MediaItem.fromUri(song.id.toURI())
|
//
|
||||||
)
|
// val future = MetadataRetriever.retrieveMetadata(
|
||||||
|
// context, MediaItem.fromUri(song.id.toURI())
|
||||||
// Coil is async, we can just spin until the loading has ended
|
// )
|
||||||
while (future.isDone) { /* no-op */ }
|
//
|
||||||
|
// // Coil is async, we can just spin until the loading has ended
|
||||||
val tracks = try {
|
// while (future.isDone) { /* no-op */ }
|
||||||
future.get()
|
//
|
||||||
} catch (e: Exception) {
|
// val tracks = try {
|
||||||
null
|
// future.get()
|
||||||
}
|
// } catch (e: Exception) {
|
||||||
|
// null
|
||||||
if (tracks == null || tracks.isEmpty) {
|
// }
|
||||||
// Unrecognized format. This is expected, as ExoPlayer only supports a
|
//
|
||||||
// subset of formats.
|
// if (tracks == null || tracks.isEmpty) {
|
||||||
return null
|
// // Unrecognized format. This is expected, as ExoPlayer only supports a
|
||||||
}
|
// // subset of formats.
|
||||||
|
// return null
|
||||||
// The metadata extraction process of ExoPlayer is normalized into a superclass.
|
// }
|
||||||
// That means we have to iterate through and find the cover art ourselves.
|
//
|
||||||
val metadata = tracks[0].getFormat(0).metadata
|
// // The metadata extraction process of ExoPlayer is normalized into a superclass.
|
||||||
|
// // That means we have to iterate through and find the cover art ourselves.
|
||||||
if (metadata == null || metadata.length() == 0) {
|
// val metadata = tracks[0].getFormat(0).metadata
|
||||||
// No (parsable) metadata. This is also expected.
|
//
|
||||||
return null
|
// if (metadata == null || metadata.length() == 0) {
|
||||||
}
|
// // No (parsable) metadata. This is also expected.
|
||||||
|
// return null
|
||||||
var stream: ByteArrayInputStream? = null
|
// }
|
||||||
|
//
|
||||||
for (i in 0 until metadata.length()) {
|
// var stream: ByteArrayInputStream? = null
|
||||||
// We can only extract pictures from two tags with this method, ID3v2's APIC or
|
//
|
||||||
// FLAC's PICTURE.
|
// for (i in 0 until metadata.length()) {
|
||||||
val pic: ByteArray?
|
// // We can only extract pictures from two tags with this method, ID3v2's APIC or
|
||||||
val type: Int
|
// // FLAC's PICTURE.
|
||||||
|
// val pic: ByteArray?
|
||||||
when (val entry = metadata.get(i)) {
|
// val type: Int
|
||||||
is ApicFrame -> {
|
//
|
||||||
pic = entry.pictureData
|
// when (val entry = metadata.get(i)) {
|
||||||
type = entry.pictureType
|
// is ApicFrame -> {
|
||||||
}
|
// pic = entry.pictureData
|
||||||
is PictureFrame -> {
|
// type = entry.pictureType
|
||||||
pic = entry.pictureData
|
// }
|
||||||
type = entry.pictureType
|
// is PictureFrame -> {
|
||||||
}
|
// pic = entry.pictureData
|
||||||
else -> continue
|
// type = entry.pictureType
|
||||||
}
|
// }
|
||||||
|
// else -> continue
|
||||||
// Ensure the picture type here is a front cover image so that we don't extract
|
// }
|
||||||
// an incorrect cover image.
|
//
|
||||||
// Yes, this does add some latency, but its quality covers so we can prioritize
|
// // Ensure the picture type here is a front cover image so that we don't extract
|
||||||
// correctness over speed.
|
// // an incorrect cover image.
|
||||||
if (type == MediaMetadata.PICTURE_TYPE_FRONT_COVER) {
|
// // Yes, this does add some latency, but its quality covers so we can prioritize
|
||||||
logD("Front cover successfully found")
|
// // correctness over speed.
|
||||||
|
// if (type == MediaMetadata.PICTURE_TYPE_FRONT_COVER) {
|
||||||
// We have a front cover image. Great.
|
// logD("Front cover successfully found")
|
||||||
stream = ByteArrayInputStream(pic)
|
//
|
||||||
break
|
// // We have a front cover image. Great.
|
||||||
} else if (stream != null) {
|
// stream = ByteArrayInputStream(pic)
|
||||||
// In the case a front cover is not found, use the first image in the tag instead.
|
// break
|
||||||
// This can be corrected later on if a front cover frame is found.
|
// } else if (stream != null) {
|
||||||
logD("Image not a front cover, assigning image of type $type for now")
|
// // In the case a front cover is not found, use the first image in the tag instead.
|
||||||
|
// // This can be corrected later on if a front cover frame is found.
|
||||||
stream = ByteArrayInputStream(pic)
|
// logD("Image not a front cover, assigning image of type $type for now")
|
||||||
}
|
//
|
||||||
}
|
// stream = ByteArrayInputStream(pic)
|
||||||
|
// }
|
||||||
return stream?.use { stm ->
|
// }
|
||||||
return SourceResult(
|
//
|
||||||
source = stm.source().buffer(),
|
// return stream?.use { stm ->
|
||||||
mimeType = context.contentResolver.getType(uri),
|
// return SourceResult(
|
||||||
dataSource = DataSource.DISK
|
// source = stm.source().buffer(),
|
||||||
)
|
// mimeType = context.contentResolver.getType(uri),
|
||||||
}
|
// dataSource = DataSource.DISK
|
||||||
}
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
override fun key(data: Album) = data.id.toString()
|
override fun key(data: Album) = data.id.toString()
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import androidx.annotation.DrawableRes
|
||||||
import androidx.core.graphics.drawable.toBitmap
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import androidx.databinding.BindingAdapter
|
import androidx.databinding.BindingAdapter
|
||||||
import coil.Coil
|
import coil.Coil
|
||||||
|
import coil.clear
|
||||||
import coil.fetch.Fetcher
|
import coil.fetch.Fetcher
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import coil.size.OriginalSize
|
import coil.size.OriginalSize
|
||||||
|
@ -83,7 +84,9 @@ inline fun <reified T : BaseModel> ImageView.load(
|
||||||
@DrawableRes error: Int,
|
@DrawableRes error: Int,
|
||||||
fetcher: Fetcher<T>,
|
fetcher: Fetcher<T>,
|
||||||
) {
|
) {
|
||||||
val disposable = Coil.imageLoader(context).enqueue(
|
clear()
|
||||||
|
|
||||||
|
Coil.imageLoader(context).enqueue(
|
||||||
ImageRequest.Builder(context)
|
ImageRequest.Builder(context)
|
||||||
.target(this)
|
.target(this)
|
||||||
.data(data)
|
.data(data)
|
||||||
|
|
Loading…
Reference in a new issue