Fixed thumbnails acting up and added support for library content thumbnail when casting.

This commit is contained in:
Koen J
2025-12-03 15:37:53 +01:00
parent eba995f87d
commit 961710cc8b
4 changed files with 50 additions and 32 deletions
@@ -444,15 +444,9 @@ fun addressScore(addr: InetAddress): Int {
fun <T> Enumeration<T>.toList(): List<T> = Collections.list(this)
fun <T> RequestBuilder<T>.withMaxSizePx(maxSizePx: Int = 1920, useCenterCrop: Boolean = false): RequestBuilder<T> {
var builder = this
fun <T> RequestBuilder<T>.withMaxSizePx(maxSizePx: Int = 1920): RequestBuilder<T> {
return this
.downsample(DownsampleStrategy.AT_MOST)
.override(maxSizePx, maxSizePx)
builder = if (useCenterCrop) {
builder.centerCrop()
} else {
builder.fitCenter()
}
return builder
.centerInside()
}
@@ -137,14 +137,7 @@ class HttpContentUriHandler(
var size: Long? = null
var lastModifiedMillis: Long? = null
val projection = arrayOf(
OpenableColumns.DISPLAY_NAME,
OpenableColumns.SIZE,
MediaStore.MediaColumns.DATE_MODIFIED,
MediaStore.MediaColumns.DATE_ADDED
)
resolver.query(uri, projection, null, null, null)?.use { cursor ->
resolver.query(uri, null, null, null, null)?.use { cursor ->
if (cursor.moveToFirst()) {
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
if (nameIndex != -1 && !cursor.isNull(nameIndex)) {
@@ -177,6 +170,10 @@ class HttpContentUriHandler(
}
}
if (displayName == null) {
displayName = uri.lastPathSegment
}
if (size == null) {
try {
resolver.openAssetFileDescriptor(uri, "r")?.use { afd ->
@@ -188,7 +185,11 @@ class HttpContentUriHandler(
} catch (_: Exception) { }
}
return ContentMeta(displayName = displayName, size = size, lastModifiedMillis = lastModifiedMillis)
return ContentMeta(
displayName = displayName,
size = size,
lastModifiedMillis = lastModifiedMillis
)
}
private fun parseRange(header: String, totalLength: Long): LongRange? {
@@ -239,9 +239,9 @@ abstract class StateCasting {
Logger.i(TAG, "Connect to device ${device.name}")
}
fun metadataFromVideo(video: IPlatformVideoDetails): Metadata {
fun metadataFromVideo(video: IPlatformVideoDetails, videoThumbnailOverrideUrl: String? = null): Metadata {
return Metadata(
title = video.name, thumbnailUrl = video.thumbnails.getHQThumbnail()
title = video.name, thumbnailUrl = videoThumbnailOverrideUrl ?: video.thumbnails.getHQThumbnail()
)
}
@@ -479,6 +479,16 @@ abstract class StateCasting {
val id = UUID.randomUUID();
val videoPath = "/video-${id}"
val videoUrl = url + videoPath;
val thumbnailPath = "/thumbnail-${id}"
val thumbnailUrl = url + thumbnailPath;
val thumbnailContentUrl = video.thumbnails.getHQThumbnail()
if (thumbnailContentUrl != null) {
_castServer.addHandlerWithAllowAllOptions(
HttpContentUriHandler("GET", thumbnailPath, contentResolver, thumbnailContentUrl.toUri())
.withHeader("Access-Control-Allow-Origin", "*"), true
).withTag("cast");
}
_castServer.addHandlerWithAllowAllOptions(
HttpContentUriHandler("GET", videoPath, contentResolver, videoSource.contentUrl.toUri())
@@ -486,7 +496,7 @@ abstract class StateCasting {
).withTag("cast");
Logger.i(TAG, "Casting local video (videoUrl: $videoUrl).");
ad.loadVideo("BUFFERED", videoSource.container, videoUrl, resumePosition, video.duration.toDouble(), speed, metadataFromVideo(video));
ad.loadVideo("BUFFERED", videoSource.container, videoUrl, resumePosition, video.duration.toDouble(), speed, metadataFromVideo(video, if (thumbnailContentUrl != null) thumbnailUrl else null));
return listOf(videoUrl);
}
@@ -498,6 +508,16 @@ abstract class StateCasting {
val id = UUID.randomUUID();
val audioPath = "/audio-${id}"
val audioUrl = url + audioPath;
val thumbnailPath = "/thumbnail-${id}"
val thumbnailUrl = url + thumbnailPath;
val thumbnailContentUrl = video.thumbnails.getHQThumbnail()
if (thumbnailContentUrl != null) {
_castServer.addHandlerWithAllowAllOptions(
HttpContentUriHandler("GET", thumbnailPath, contentResolver, thumbnailContentUrl.toUri())
.withHeader("Access-Control-Allow-Origin", "*"), true
).withTag("cast");
}
_castServer.addHandlerWithAllowAllOptions(
HttpContentUriHandler("GET", audioPath, contentResolver, audioSource.contentUrl.toUri())
@@ -505,7 +525,7 @@ abstract class StateCasting {
).withTag("cast");
Logger.i(TAG, "Casting local audio (audioUrl: $audioUrl).");
ad.loadVideo("BUFFERED", audioSource.container, audioUrl, resumePosition, video.duration.toDouble(), speed, metadataFromVideo(video));
ad.loadVideo("BUFFERED", audioSource.container, audioUrl, resumePosition, video.duration.toDouble(), speed, metadataFromVideo(video, if (thumbnailContentUrl != null) thumbnailUrl else null));
return listOf(audioUrl);
}
@@ -488,9 +488,10 @@ class StateLibrary {
"";
val albumContentUrl = if(albumId > 0)
ContentUris.withAppendedId(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, albumId)?.toString()
else null;
val albumArtBase = Uri.parse("content://media/external/audio/albumart")
val albumContentUrl = if (albumId > 0)
ContentUris.withAppendedId(albumArtBase, albumId).toString()
else null
val dateObj = if(date > 0)
OffsetDateTime.ofInstant(Instant.ofEpochSecond(date), ZoneOffset.UTC)
@@ -625,11 +626,12 @@ class Artist {
val numTracks = cursor.getInt(2);
val numAlbums = cursor.getInt(3);
val idLong = id.toLongOrNull();
val uri = if(idLong != null) ContentUris.withAppendedId(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, idLong) else null;
val idLong = id.toLongOrNull()
val uri = if (idLong != null)
ContentUris.withAppendedId(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, idLong)
else null
return Artist(artist, numTracks, numAlbums, null, id, uri?.toString());
}
return Artist(artist, numTracks, numAlbums, null, id, uri?.toString()) }
fun getArtist(id: Long): Artist? {
val resolver = StateApp.instance.contextOrNull?.contentResolver;
@@ -733,9 +735,10 @@ class Album {
val numTracks = cursor.getInt(2);
val artist = cursor.getString(3);
val idLong = id.toLongOrNull();
val uri = if(idLong != null) ContentUris.withAppendedId(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, idLong) else null;
return Album(album, numTracks, artist, id, uri?.toString());
val idLong = id.toLongOrNull()
val albumArtBase = Uri.parse("content://media/external/audio/albumart")
val uri = if (idLong != null) ContentUris.withAppendedId(albumArtBase, idLong) else null
return Album(album, numTracks, artist, id, uri?.toString())
}
fun getAlbumTracks(albumId: Long): List<IPlatformVideo> {