From 033a237488e9156e8e9f64391e8efeb309b39ce8 Mon Sep 17 00:00:00 2001 From: Koen J Date: Thu, 29 May 2025 13:03:51 +0200 Subject: [PATCH] Changed getLocalUrl logic. --- .../casting/ChomecastCastingDevice.kt | 2 +- .../platformplayer/casting/StateCasting.kt | 45 ++++++++++++++----- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/futo/platformplayer/casting/ChomecastCastingDevice.kt b/app/src/main/java/com/futo/platformplayer/casting/ChomecastCastingDevice.kt index 32bee98d..b25240bc 100644 --- a/app/src/main/java/com/futo/platformplayer/casting/ChomecastCastingDevice.kt +++ b/app/src/main/java/com/futo/platformplayer/casting/ChomecastCastingDevice.kt @@ -536,7 +536,7 @@ class ChromecastCastingDevice : CastingDevice { Logger.i(TAG, "Player not found, launching."); launchPlayer(); } else { - Logger.i(TAG, "Player not found, disconnecting."); + Logger.i(TAG, "Player not found, disconnecting."); //TODO: Add recovery from this scenario ? stop(); } } else { 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 647aaae6..a1ece8b4 100644 --- a/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt +++ b/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt @@ -10,6 +10,8 @@ import android.os.Build import android.os.Looper import android.util.Base64 import android.util.Log +import java.net.NetworkInterface +import java.net.Inet4Address import androidx.annotation.OptIn import androidx.media3.common.util.UnstableApi import com.futo.platformplayer.R @@ -55,6 +57,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json +import java.net.Inet6Address import java.net.InetAddress import java.net.URLDecoder import java.net.URLEncoder @@ -483,7 +486,7 @@ class StateCasting { } } else { val proxyStreams = Settings.instance.casting.alwaysProxyRequests; - val url = "http://${ad.localAddress.toUrlAddress().trim('/')}:${_castServer.port}"; + val url = getLocalUrl(ad); val id = UUID.randomUUID(); if (videoSource is IVideoUrlSource) { @@ -578,7 +581,7 @@ class StateCasting { private fun castLocalVideo(video: IPlatformVideoDetails, videoSource: LocalVideoSource, resumePosition: Double, speed: Double?) : List { val ad = activeDevice ?: return listOf(); - val url = "http://${ad.localAddress.toUrlAddress().trim('/')}:${_castServer.port}"; + val url = getLocalUrl(ad); val id = UUID.randomUUID(); val videoPath = "/video-${id}" val videoUrl = url + videoPath; @@ -597,7 +600,7 @@ class StateCasting { private fun castLocalAudio(video: IPlatformVideoDetails, audioSource: LocalAudioSource, resumePosition: Double, speed: Double?) : List { val ad = activeDevice ?: return listOf(); - val url = "http://${ad.localAddress.toUrlAddress().trim('/')}:${_castServer.port}"; + val url = getLocalUrl(ad); val id = UUID.randomUUID(); val audioPath = "/audio-${id}" val audioUrl = url + audioPath; @@ -616,7 +619,7 @@ class StateCasting { private fun castLocalHls(video: IPlatformVideoDetails, videoSource: LocalVideoSource?, audioSource: LocalAudioSource?, subtitleSource: LocalSubtitleSource?, resumePosition: Double, speed: Double?): List { val ad = activeDevice ?: return listOf() - val url = "http://${ad.localAddress.toUrlAddress().trim('/')}:${_castServer.port}" + val url = getLocalUrl(ad) val id = UUID.randomUUID() val hlsPath = "/hls-${id}" @@ -712,7 +715,7 @@ class StateCasting { private fun castLocalDash(video: IPlatformVideoDetails, videoSource: LocalVideoSource?, audioSource: LocalAudioSource?, subtitleSource: LocalSubtitleSource?, resumePosition: Double, speed: Double?) : List { val ad = activeDevice ?: return listOf(); - val url = "http://${ad.localAddress.toUrlAddress().trim('/')}:${_castServer.port}"; + val url = getLocalUrl(ad); val id = UUID.randomUUID(); val dashPath = "/dash-${id}" @@ -762,7 +765,7 @@ class StateCasting { val ad = activeDevice ?: return listOf(); val proxyStreams = Settings.instance.casting.alwaysProxyRequests || ad !is FCastCastingDevice; - val url = "http://${ad.localAddress.toUrlAddress().trim('/')}:${_castServer.port}"; + val url = getLocalUrl(ad); val id = UUID.randomUUID(); val videoPath = "/video-${id}" @@ -827,7 +830,7 @@ class StateCasting { _castServer.removeAllHandlers("castProxiedHlsMaster") val ad = activeDevice ?: return listOf(); - val url = "http://${ad.localAddress.toUrlAddress().trim('/')}:${_castServer.port}"; + val url = getLocalUrl(ad); val id = UUID.randomUUID(); val hlsPath = "/hls-${id}" @@ -997,7 +1000,7 @@ class StateCasting { private suspend fun castHlsIndirect(contentResolver: ContentResolver, video: IPlatformVideoDetails, videoSource: IVideoUrlSource?, audioSource: IAudioUrlSource?, subtitleSource: ISubtitleSource?, resumePosition: Double, speed: Double?) : List { val ad = activeDevice ?: return listOf(); - val url = "http://${ad.localAddress.toUrlAddress().trim('/')}:${_castServer.port}"; + val url = getLocalUrl(ad); val id = UUID.randomUUID(); val hlsPath = "/hls-${id}" @@ -1127,7 +1130,7 @@ class StateCasting { val ad = activeDevice ?: return listOf(); val proxyStreams = Settings.instance.casting.alwaysProxyRequests || ad !is FCastCastingDevice; - val url = "http://${ad.localAddress.toUrlAddress().trim('/')}:${_castServer.port}"; + val url = getLocalUrl(ad); val id = UUID.randomUUID(); val dashPath = "/dash-${id}" @@ -1213,6 +1216,28 @@ class StateCasting { } } + private fun findFirstIPv4(): InetAddress? { + val interfaces = NetworkInterface.getNetworkInterfaces() + for (intf in interfaces) { + if (!intf.isUp || intf.isLoopback) continue + for (addr in intf.inetAddresses) { + if (addr is Inet4Address && !addr.isLoopbackAddress) { + return addr + } + } + } + return null + } + + private fun getLocalUrl(ad: CastingDevice): String { + var address = ad.localAddress!! + if (address is Inet6Address && address.isLinkLocalAddress) { + address = findFirstIPv4() ?: address + Logger.i(TAG, "Selected casting address: $address") + } + return "http://${ad.localAddress.toUrlAddress().trim('/')}:${_castServer.port}"; + } + @OptIn(UnstableApi::class) private suspend fun castDashRaw(contentResolver: ContentResolver, video: IPlatformVideoDetails, videoSource: JSDashManifestRawSource?, audioSource: JSDashManifestRawAudioSource?, subtitleSource: ISubtitleSource?, resumePosition: Double, speed: Double?) : List { val ad = activeDevice ?: return listOf(); @@ -1220,7 +1245,7 @@ class StateCasting { cleanExecutors() _castServer.removeAllHandlers("castDashRaw") - val url = "http://${ad.localAddress.toUrlAddress().trim('/')}:${_castServer.port}"; + val url = getLocalUrl(ad); val id = UUID.randomUUID(); val dashPath = "/dash-${id}"