Fixed Chromecast position not updating on Grayjay side. Fixed Chromecast not reconnecting properly. Fixed AirPlay/Chromecast position not being reflected in history.

This commit is contained in:
Koen J 2025-06-04 12:13:18 +02:00
commit 715c60dc6e
4 changed files with 28 additions and 5 deletions

View file

@ -108,7 +108,7 @@ abstract class CastingDevice {
val expectedCurrentTime: Double val expectedCurrentTime: Double
get() { 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; return time + diff;
}; };
var connectionState: CastConnectionState = CastConnectionState.DISCONNECTED var connectionState: CastConnectionState = CastConnectionState.DISCONNECTED

View file

@ -344,6 +344,10 @@ class ChromecastCastingDevice : CastingDevice {
//Connection loop //Connection loop
while (_scopeIO?.isActive == true) { while (_scopeIO?.isActive == true) {
_sessionId = null;
_launchRetries = 0
_mediaSessionId = null;
Logger.i(TAG, "Connecting to Chromecast."); Logger.i(TAG, "Connecting to Chromecast.");
connectionState = CastConnectionState.CONNECTING; connectionState = CastConnectionState.CONNECTING;
@ -499,6 +503,10 @@ class ChromecastCastingDevice : CastingDevice {
} }
} catch (e: Throwable) { } catch (e: Throwable) {
Logger.w(TAG, "Failed to send channel message (sourceId: $sourceId, destinationId: $destinationId, namespace: $namespace, json: $json)", e); 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"; isPlaying = playerState == "PLAYING";
if (isPlaying) { if (isPlaying || playerState == "PAUSED") {
setTime(currentTime); setTime(currentTime);
} }

View file

@ -647,6 +647,15 @@ class VideoDetailView : ConstraintLayout {
_timeBar.setDuration(video?.duration ?: 0); _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; _playerProgress.player = _player.exoPlayer?.player;

View file

@ -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.chapters.IChapter
import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails
import com.futo.platformplayer.casting.AirPlayCastingDevice import com.futo.platformplayer.casting.AirPlayCastingDevice
import com.futo.platformplayer.casting.ChromecastCastingDevice
import com.futo.platformplayer.casting.StateCasting import com.futo.platformplayer.casting.StateCasting
import com.futo.platformplayer.constructs.Event0 import com.futo.platformplayer.constructs.Event0
import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.constructs.Event2 import com.futo.platformplayer.constructs.Event2
import com.futo.platformplayer.formatDuration import com.futo.platformplayer.formatDuration
import com.futo.platformplayer.states.StateHistory
import com.futo.platformplayer.states.StatePlayer import com.futo.platformplayer.states.StatePlayer
import com.futo.platformplayer.views.behavior.GestureControlView import com.futo.platformplayer.views.behavior.GestureControlView
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -61,6 +64,7 @@ class CastView : ConstraintLayout {
val onSettingsClick = Event0(); val onSettingsClick = Event0();
val onPrevious = Event0(); val onPrevious = Event0();
val onNext = Event0(); val onNext = Event0();
val onTimeJobTimeChanged_s = Event1<Long>()
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
@ -185,11 +189,11 @@ class CastView : ConstraintLayout {
} }
fun setIsPlaying(isPlaying: Boolean) { fun setIsPlaying(isPlaying: Boolean) {
_updateTimeJob?.cancel(); stopTimeJob()
if(isPlaying) { if(isPlaying) {
val d = StateCasting.instance.activeDevice; val d = StateCasting.instance.activeDevice;
if (d is AirPlayCastingDevice) { if (d is AirPlayCastingDevice || d is ChromecastCastingDevice) {
_updateTimeJob = _scope.launch { _updateTimeJob = _scope.launch {
while (true) { while (true) {
val device = StateCasting.instance.activeDevice; val device = StateCasting.instance.activeDevice;
@ -198,7 +202,9 @@ class CastView : ConstraintLayout {
} }
delay(1000); 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())
} }
} }
} }