From 715c60dc6eb44aa428350cede7472f3c641d847e Mon Sep 17 00:00:00 2001 From: Koen J Date: Wed, 4 Jun 2025 12:13:18 +0200 Subject: [PATCH] Fixed Chromecast position not updating on Grayjay side. Fixed Chromecast not reconnecting properly. Fixed AirPlay/Chromecast position not being reflected in history. --- .../com/futo/platformplayer/casting/CastingDevice.kt | 2 +- .../platformplayer/casting/ChomecastCastingDevice.kt | 10 +++++++++- .../fragment/mainactivity/main/VideoDetailView.kt | 9 +++++++++ .../futo/platformplayer/views/casting/CastView.kt | 12 +++++++++--- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/futo/platformplayer/casting/CastingDevice.kt b/app/src/main/java/com/futo/platformplayer/casting/CastingDevice.kt index c6e046ef..69f74747 100644 --- a/app/src/main/java/com/futo/platformplayer/casting/CastingDevice.kt +++ b/app/src/main/java/com/futo/platformplayer/casting/CastingDevice.kt @@ -108,7 +108,7 @@ abstract class CastingDevice { val expectedCurrentTime: Double get() { - val diff = (System.currentTimeMillis() - lastTimeChangeTime_ms).toDouble() / 1000.0; + val diff = if (isPlaying) ((System.currentTimeMillis() - lastTimeChangeTime_ms).toDouble() / 1000.0) else 0.0; return time + diff; }; var connectionState: CastConnectionState = CastConnectionState.DISCONNECTED 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 0c3d4662..3d362efd 100644 --- a/app/src/main/java/com/futo/platformplayer/casting/ChomecastCastingDevice.kt +++ b/app/src/main/java/com/futo/platformplayer/casting/ChomecastCastingDevice.kt @@ -344,6 +344,10 @@ class ChromecastCastingDevice : CastingDevice { //Connection loop while (_scopeIO?.isActive == true) { + _sessionId = null; + _launchRetries = 0 + _mediaSessionId = null; + Logger.i(TAG, "Connecting to Chromecast."); connectionState = CastConnectionState.CONNECTING; @@ -499,6 +503,10 @@ class ChromecastCastingDevice : CastingDevice { } } catch (e: Throwable) { Logger.w(TAG, "Failed to send channel message (sourceId: $sourceId, destinationId: $destinationId, namespace: $namespace, json: $json)", e); + _socket?.close(); + Logger.i(TAG, "Socket disconnected."); + + connectionState = CastConnectionState.CONNECTING; } } @@ -600,7 +608,7 @@ class ChromecastCastingDevice : CastingDevice { } isPlaying = playerState == "PLAYING"; - if (isPlaying) { + if (isPlaying || playerState == "PAUSED") { setTime(currentTime); } diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt index 9c34dfac..50e3a730 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt @@ -647,6 +647,15 @@ class VideoDetailView : ConstraintLayout { _timeBar.setDuration(video?.duration ?: 0); } }; + + _cast.onTimeJobTimeChanged_s.subscribe { + if (_isCasting) { + setLastPositionMilliseconds((it * 1000.0).toLong(), true); + _timeBar.setPosition(it); + _timeBar.setBufferedPosition(0); + _timeBar.setDuration(video?.duration ?: 0); + } + } } _playerProgress.player = _player.exoPlayer?.player; diff --git a/app/src/main/java/com/futo/platformplayer/views/casting/CastView.kt b/app/src/main/java/com/futo/platformplayer/views/casting/CastView.kt index 91631f1e..fff853a8 100644 --- a/app/src/main/java/com/futo/platformplayer/views/casting/CastView.kt +++ b/app/src/main/java/com/futo/platformplayer/views/casting/CastView.kt @@ -21,10 +21,13 @@ import com.futo.platformplayer.R import com.futo.platformplayer.api.media.models.chapters.IChapter import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails import com.futo.platformplayer.casting.AirPlayCastingDevice +import com.futo.platformplayer.casting.ChromecastCastingDevice import com.futo.platformplayer.casting.StateCasting import com.futo.platformplayer.constructs.Event0 +import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.constructs.Event2 import com.futo.platformplayer.formatDuration +import com.futo.platformplayer.states.StateHistory import com.futo.platformplayer.states.StatePlayer import com.futo.platformplayer.views.behavior.GestureControlView import kotlinx.coroutines.CoroutineScope @@ -61,6 +64,7 @@ class CastView : ConstraintLayout { val onSettingsClick = Event0(); val onPrevious = Event0(); val onNext = Event0(); + val onTimeJobTimeChanged_s = Event1() @OptIn(UnstableApi::class) constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { @@ -185,11 +189,11 @@ class CastView : ConstraintLayout { } fun setIsPlaying(isPlaying: Boolean) { - _updateTimeJob?.cancel(); + stopTimeJob() if(isPlaying) { val d = StateCasting.instance.activeDevice; - if (d is AirPlayCastingDevice) { + if (d is AirPlayCastingDevice || d is ChromecastCastingDevice) { _updateTimeJob = _scope.launch { while (true) { val device = StateCasting.instance.activeDevice; @@ -198,7 +202,9 @@ class CastView : ConstraintLayout { } delay(1000); - setTime((device.expectedCurrentTime * 1000.0).toLong()); + val time_ms = (device.expectedCurrentTime * 1000.0).toLong() + setTime(time_ms); + onTimeJobTimeChanged_s.emit(device.expectedCurrentTime.toLong()) } } }