casting: update SDK to 0.2.1

This commit is contained in:
Marcus Hanestad 2025-08-21 17:20:47 +02:00
commit 5a74b714b8
5 changed files with 41 additions and 26 deletions

View file

@ -233,5 +233,8 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
//Rust casting SDK
implementation "net.java.dev.jna:jna:5.12.0@aar"
implementation('org.futo.gitlab.videostreaming.fcast-sdk-jitpack:sender-sdk-minimal:0.2.1') {
// Polycentricandroid includes this
exclude group: 'net.java.dev.jna'
}
}

View file

@ -108,7 +108,12 @@ class ConnectedCastingDialog(context: Context?) : AlertDialog(context) {
_buttonClose.setOnClickListener { dismiss(); };
_buttonDisconnect.setOnClickListener {
if (Settings.instance.casting.experimentalCasting) {
ExpStateCasting.instance.activeDevice?.device?.stopCasting()
try {
ExpStateCasting.instance.activeDevice?.device?.stopPlayback()
ExpStateCasting.instance.activeDevice?.device?.disconnect()
} catch (e: Throwable) {
// Ignored
}
} else {
StateCasting.instance.activeDevice?.stopCasting();
}

View file

@ -19,6 +19,7 @@ import java.net.InetAddress
import org.fcast.sender_sdk.CastingDevice as RsCastingDevice;
import org.fcast.sender_sdk.DeviceEventHandler as RsDeviceEventHandler;
import org.fcast.sender_sdk.DeviceConnectionState
import org.fcast.sender_sdk.LoadRequest
class CastingDeviceHandle {
class EventHandler : RsDeviceEventHandler {
@ -64,6 +65,10 @@ class CastingDeviceHandle {
override fun mediaEvent(event: GenericMediaEvent) {
// Unreachable
}
override fun playbackError(message: String) {
Logger.e(TAG, "Playback error: $message")
}
}
val eventHandler = EventHandler()
@ -91,17 +96,16 @@ class CastingDeviceHandle {
eventHandler.onConnectionStateChanged.subscribe { newState ->
if (newState == DeviceConnectionState.Disconnected) {
try {
Logger.i("CastingDeviceHandle", "Stopping device")
Logger.i(TAG, "Stopping device")
device.disconnect()
} catch (e: Throwable) {
Logger.e("CastingDeviceHandle", "Failed to stop device: $e")
Logger.e(TAG, "Failed to stop device: $e")
}
}
}
}
fun loadVideo(
streamType: String,
contentType: String,
contentId: String,
resumePosition: Double,
@ -109,9 +113,9 @@ class CastingDeviceHandle {
speed: Double?
) {
try {
device.loadVideo(contentType, contentId, resumePosition, speed)
device.load(LoadRequest.Video(contentType, contentId, resumePosition, speed, duration))
} catch (e: Throwable) {
Logger.e("CastingDevice", "Failed to load video: $e")
Logger.e(TAG, "Failed to load video: $e")
}
}
@ -123,11 +127,15 @@ class CastingDeviceHandle {
speed: Double?
) {
try {
device.loadContent(contentType, content, resumePosition, duration, speed)
device.load(LoadRequest.Content(contentType, content, resumePosition, duration, speed))
} catch (e: Throwable) {
Logger.e("CastingDevice", "Failed to load content: $e")
Logger.e(TAG, "Failed to load content: $e")
}
}
companion object {
private val TAG = "ExperimentalCastingDevice"
}
}
enum class CastConnectionState {

View file

@ -7,6 +7,7 @@ import android.os.Looper
import android.util.Log
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
import com.futo.platformplayer.BuildConfig
import com.futo.platformplayer.R
import com.futo.platformplayer.Settings
import com.futo.platformplayer.UIDialogs
@ -50,6 +51,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.fcast.sender_sdk.ApplicationInfo
import java.net.Inet6Address
import java.net.InetAddress
import java.net.URLDecoder
@ -110,7 +112,9 @@ class ExpStateCasting {
}
init {
org.fcast.sender_sdk.initLogger(org.fcast.sender_sdk.LogLevelFilter.DEBUG)
if (BuildConfig.DEBUG) {
org.fcast.sender_sdk.initLogger(org.fcast.sender_sdk.LogLevelFilter.DEBUG)
}
}
fun handleUrl(context: Context, url: String) {
@ -382,7 +386,13 @@ class ExpStateCasting {
}
try {
device.device.connect(device.eventHandler)
device.device.connect(
ApplicationInfo(
"grayjay android",
"${BuildConfig.VERSION_NAME}-${BuildConfig.FLAVOR}",
"Grayjay"
), device.eventHandler
)
Logger.i(TAG, "Requested manager to start device")
} catch (e: Throwable) {
Logger.w(TAG, "Failed to connect to device.");
@ -415,7 +425,7 @@ class ExpStateCasting {
val rsDeviceInfo = device.device.getDeviceInfo()
val deviceInfo = CastingDeviceInfo(
name = device.device.name(),
type = when (rsDeviceInfo.type) {
type = when (rsDeviceInfo.protocol) {
ProtocolType.CHROMECAST -> com.futo.platformplayer.casting.CastProtocolType.CHROMECAST
ProtocolType.F_CAST -> com.futo.platformplayer.casting.CastProtocolType.FCAST
},
@ -547,7 +557,6 @@ class ExpStateCasting {
val videoUrl = if (proxyStreams) url + videoPath else videoSource.getVideoUrl();
Logger.i(TAG, "Casting as singular video");
ad.loadVideo(
if (video.isLive) "LIVE" else "BUFFERED",
videoSource.container,
videoUrl,
resumePosition,
@ -559,7 +568,6 @@ class ExpStateCasting {
val audioUrl = if (proxyStreams) url + audioPath else audioSource.getAudioUrl();
Logger.i(TAG, "Casting as singular audio");
ad.loadVideo(
if (video.isLive) "LIVE" else "BUFFERED",
audioSource.container,
audioUrl,
resumePosition,
@ -579,7 +587,6 @@ class ExpStateCasting {
} else {
Logger.i(TAG, "Casting as non-proxied HLS");
ad.loadVideo(
if (video.isLive) "LIVE" else "BUFFERED",
videoSource.container,
videoSource.url,
resumePosition,
@ -600,7 +607,6 @@ class ExpStateCasting {
} else {
Logger.i(TAG, "Casting as non-proxied audio HLS");
ad.loadVideo(
if (video.isLive) "LIVE" else "BUFFERED",
audioSource.container,
audioSource.url,
resumePosition,
@ -716,7 +722,6 @@ class ExpStateCasting {
Logger.i(TAG, "Casting local video (videoUrl: $videoUrl).");
ad.loadVideo(
"BUFFERED",
videoSource.container,
videoUrl,
resumePosition,
@ -747,7 +752,6 @@ class ExpStateCasting {
Logger.i(TAG, "Casting local audio (audioUrl: $audioUrl).");
ad.loadVideo(
"BUFFERED",
audioSource.container,
audioUrl,
resumePosition,
@ -941,7 +945,6 @@ class ExpStateCasting {
"added new castLocalHls handlers (hlsPath: $hlsPath, videoPath: $videoPath, audioPath: $audioPath, subtitlePath: $subtitlePath)."
)
ad.loadVideo(
"BUFFERED",
"application/vnd.apple.mpegurl",
hlsUrl,
resumePosition,
@ -1021,7 +1024,6 @@ class ExpStateCasting {
"added new castLocalDash handlers (dashPath: $dashPath, videoPath: $videoPath, audioPath: $audioPath, subtitlePath: $subtitlePath)."
);
ad.loadVideo(
"BUFFERED",
"application/dash+xml",
dashUrl,
resumePosition,
@ -1297,7 +1299,6 @@ class ExpStateCasting {
val hackfixResumePosition =
if (ad.device.castingProtocol() == ProtocolType.CHROMECAST && !video.isLive && resumePosition == 0.0) 0.1 else resumePosition;
ad.loadVideo(
if (video.isLive) "LIVE" else "BUFFERED",
"application/vnd.apple.mpegurl",
hlsUrl,
hackfixResumePosition,
@ -1570,7 +1571,6 @@ class ExpStateCasting {
Logger.i(TAG, "added new castHls handlers (hlsPath: $hlsPath).");
ad.loadVideo(
if (video.isLive) "LIVE" else "BUFFERED",
"application/vnd.apple.mpegurl",
hlsUrl,
resumePosition,
@ -1686,7 +1686,6 @@ class ExpStateCasting {
"added new castDash handlers (dashPath: $dashPath, videoPath: $videoPath, audioPath: $audioPath)."
);
ad.loadVideo(
if (video.isLive) "LIVE" else "BUFFERED",
"application/dash+xml",
dashUrl,
resumePosition,
@ -1955,7 +1954,6 @@ class ExpStateCasting {
"added new castDash handlers (dashPath: $dashPath, videoPath: $videoPath, audioPath: $audioPath)."
);
ad.loadVideo(
if (video.isLive) "LIVE" else "BUFFERED",
"application/dash+xml",
dashUrl,
resumePosition,
@ -1971,7 +1969,7 @@ class ExpStateCasting {
deviceInfo.addresses.map { org.fcast.sender_sdk.tryIpAddrFromStr(it) } // Throws!
val rsDeviceInfo = RsDeviceInfo(
name = deviceInfo.name,
type = when (deviceInfo.type) {
protocol = when (deviceInfo.type) {
com.futo.platformplayer.casting.CastProtocolType.CHROMECAST -> ProtocolType.CHROMECAST
com.futo.platformplayer.casting.CastProtocolType.FCAST -> ProtocolType.F_CAST
else -> throw IllegalArgumentException()

View file

@ -74,7 +74,8 @@ class DeviceViewHolder : ViewHolder {
if (dev.handle.device.isReady()) {
// NOTE: we assume experimental casting is used
try {
ExpStateCasting.instance.activeDevice?.device?.stopCasting()
ExpStateCasting.instance.activeDevice?.device?.stopPlayback()
ExpStateCasting.instance.activeDevice?.device?.disconnect()
} catch (e: Throwable) {
//Ignored
}