diff --git a/app/src/main/java/com/futo/platformplayer/Utility.kt b/app/src/main/java/com/futo/platformplayer/Utility.kt index b154cb67..5713fac7 100644 --- a/app/src/main/java/com/futo/platformplayer/Utility.kt +++ b/app/src/main/java/com/futo/platformplayer/Utility.kt @@ -444,15 +444,9 @@ fun addressScore(addr: InetAddress): Int { fun Enumeration.toList(): List = Collections.list(this) -fun RequestBuilder.withMaxSizePx(maxSizePx: Int = 1920, useCenterCrop: Boolean = false): RequestBuilder { - var builder = this +fun RequestBuilder.withMaxSizePx(maxSizePx: Int = 1920): RequestBuilder { + return this .downsample(DownsampleStrategy.AT_MOST) .override(maxSizePx, maxSizePx) - builder = if (useCenterCrop) { - builder.centerCrop() - } else { - builder.fitCenter() - } - - return builder + .centerInside() } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/http/server/handlers/HttpContentUriHandler.kt b/app/src/main/java/com/futo/platformplayer/api/http/server/handlers/HttpContentUriHandler.kt index 6407e552..63745991 100644 --- a/app/src/main/java/com/futo/platformplayer/api/http/server/handlers/HttpContentUriHandler.kt +++ b/app/src/main/java/com/futo/platformplayer/api/http/server/handlers/HttpContentUriHandler.kt @@ -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? { diff --git a/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt b/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt index e531354a..5c38f12f 100644 --- a/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt +++ b/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt @@ -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); } diff --git a/app/src/main/java/com/futo/platformplayer/states/StateLibrary.kt b/app/src/main/java/com/futo/platformplayer/states/StateLibrary.kt index 06f7dfb3..b2d4149b 100644 --- a/app/src/main/java/com/futo/platformplayer/states/StateLibrary.kt +++ b/app/src/main/java/com/futo/platformplayer/states/StateLibrary.kt @@ -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 {