From 58e08f5ea33eb2c1d5893bd50ad5933f6441e032 Mon Sep 17 00:00:00 2001 From: Marcus Hanestad Date: Thu, 28 Aug 2025 10:37:14 +0200 Subject: [PATCH] casting: add helper functions for dispatching to active backend --- .../dialogs/ConnectedCastingDialog.kt | 55 +--- .../experimental_casting/CastingDevice.kt | 17 +- .../experimental_casting/StateCasting.kt | 12 - .../StateCastingDispatcher.kt | 134 ++++++++++ .../mainactivity/main/VideoDetailView.kt | 245 +++++------------- .../platformplayer/views/casting/CastView.kt | 66 ++--- 6 files changed, 236 insertions(+), 293 deletions(-) create mode 100644 app/src/main/java/com/futo/platformplayer/experimental_casting/StateCastingDispatcher.kt diff --git a/app/src/main/java/com/futo/platformplayer/dialogs/ConnectedCastingDialog.kt b/app/src/main/java/com/futo/platformplayer/dialogs/ConnectedCastingDialog.kt index 08590914..f9466487 100644 --- a/app/src/main/java/com/futo/platformplayer/dialogs/ConnectedCastingDialog.kt +++ b/app/src/main/java/com/futo/platformplayer/dialogs/ConnectedCastingDialog.kt @@ -21,6 +21,7 @@ import com.futo.platformplayer.casting.ChromecastCastingDevice import com.futo.platformplayer.casting.FCastCastingDevice import com.futo.platformplayer.casting.StateCasting import com.futo.platformplayer.experimental_casting.ExpStateCasting +import com.futo.platformplayer.experimental_casting.StateCastingDispatcher import com.futo.platformplayer.fragment.mainactivity.main.VideoDetailFragment import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.states.StateApp @@ -74,30 +75,18 @@ class ConnectedCastingDialog(context: Context?) : AlertDialog(context) { _buttonPlay = findViewById(R.id.button_play); _buttonPlay.setOnClickListener { - if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.activeDevice?.device?.resumePlayback() - } else { - StateCasting.instance.activeDevice?.resumeVideo() - } + StateCastingDispatcher.resumeVideo() } _buttonPause = findViewById(R.id.button_pause); _buttonPause.setOnClickListener { - if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.activeDevice?.device?.pausePlayback() - } else { - StateCasting.instance.activeDevice?.pauseVideo() - } + StateCastingDispatcher.pauseVideo() } _buttonStop = findViewById(R.id.button_stop); _buttonStop.setOnClickListener { (ownerActivity as MainActivity?)?.getFragment()?.closeVideoDetails() - if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.activeDevice?.device?.stopPlayback() - } else { - StateCasting.instance.activeDevice?.stopVideo() - } + StateCastingDispatcher.stopVideo() } _buttonNext = findViewById(R.id.button_next); @@ -125,21 +114,7 @@ class ConnectedCastingDialog(context: Context?) : AlertDialog(context) { return@OnChangeListener } - if (Settings.instance.casting.experimentalCasting) { - val activeDevice = ExpStateCasting.instance.activeDevice ?: return@OnChangeListener; - try { - activeDevice.device.seek(value.toDouble()); - } catch (e: Throwable) { - Logger.e(TAG, "Failed to seek.", e); - } - } else { - val activeDevice = StateCasting.instance.activeDevice ?: return@OnChangeListener; - try { - activeDevice.seekVideo(value.toDouble()); - } catch (e: Throwable) { - Logger.e(TAG, "Failed to seek.", e); - } - } + StateCastingDispatcher.videoSeekTo(value.toDouble()) }); //TODO: Check if volume slider is properly hidden in all cases @@ -148,25 +123,7 @@ class ConnectedCastingDialog(context: Context?) : AlertDialog(context) { return@OnChangeListener } - if (Settings.instance.casting.experimentalCasting) { - val activeDevice = ExpStateCasting.instance.activeDevice ?: return@OnChangeListener; - if (activeDevice.device.supportsFeature(DeviceFeature.SET_VOLUME)) { - try { - activeDevice.device.changeVolume(value.toDouble()); - } catch (e: Throwable) { - Logger.e(TAG, "Failed to change volume.", e); - } - } - } else { - val activeDevice = StateCasting.instance.activeDevice ?: return@OnChangeListener; - if (activeDevice.canSetVolume) { - try { - activeDevice.changeVolume(value.toDouble()); - } catch (e: Throwable) { - Logger.e(TAG, "Failed to change volume.", e); - } - } - } + StateCastingDispatcher.changeVolume(value.toDouble()) }); setLoading(false); diff --git a/app/src/main/java/com/futo/platformplayer/experimental_casting/CastingDevice.kt b/app/src/main/java/com/futo/platformplayer/experimental_casting/CastingDevice.kt index cc495e80..151a968f 100644 --- a/app/src/main/java/com/futo/platformplayer/experimental_casting/CastingDevice.kt +++ b/app/src/main/java/com/futo/platformplayer/experimental_casting/CastingDevice.kt @@ -110,12 +110,17 @@ class CastingDeviceHandle { contentType: String, contentId: String, resumePosition: Double, - duration: Double, speed: Double?, metadata: Metadata? = null ) { try { - device.load(LoadRequest.Video(contentType, contentId, resumePosition, speed, duration, metadata)) + device.load(LoadRequest.Video( + contentType = contentType, + url = contentId, + resumePosition = resumePosition, + speed = speed, + metadata = metadata + )) } catch (e: Throwable) { Logger.e(TAG, "Failed to load video: $e") } @@ -125,11 +130,15 @@ class CastingDeviceHandle { contentType: String, content: String, resumePosition: Double, - duration: Double, speed: Double? ) { try { - device.load(LoadRequest.Content(contentType, content, resumePosition, duration, speed)) + device.load(LoadRequest.Content( + contentType =contentType, + content = content, + resumePosition = resumePosition, + speed = speed + )) } catch (e: Throwable) { Logger.e(TAG, "Failed to load content: $e") } diff --git a/app/src/main/java/com/futo/platformplayer/experimental_casting/StateCasting.kt b/app/src/main/java/com/futo/platformplayer/experimental_casting/StateCasting.kt index 04f09198..d2020370 100644 --- a/app/src/main/java/com/futo/platformplayer/experimental_casting/StateCasting.kt +++ b/app/src/main/java/com/futo/platformplayer/experimental_casting/StateCasting.kt @@ -569,7 +569,6 @@ class ExpStateCasting { videoSource.container, videoUrl, resumePosition, - video.duration.toDouble(), speed, metadataFromVideo(video) ) @@ -581,7 +580,6 @@ class ExpStateCasting { audioSource.container, audioUrl, resumePosition, - video.duration.toDouble(), speed, metadataFromVideo(video) ); @@ -601,7 +599,6 @@ class ExpStateCasting { videoSource.container, videoSource.url, resumePosition, - video.duration.toDouble(), speed, metadataFromVideo(video) ); @@ -622,7 +619,6 @@ class ExpStateCasting { audioSource.container, audioSource.url, resumePosition, - video.duration.toDouble(), speed, metadataFromVideo(video) ); @@ -738,7 +734,6 @@ class ExpStateCasting { videoSource.container, videoUrl, resumePosition, - video.duration.toDouble(), speed, metadataFromVideo(video) ); @@ -769,7 +764,6 @@ class ExpStateCasting { audioSource.container, audioUrl, resumePosition, - video.duration.toDouble(), speed, metadataFromVideo(video) ); @@ -963,7 +957,6 @@ class ExpStateCasting { "application/vnd.apple.mpegurl", hlsUrl, resumePosition, - video.duration.toDouble(), speed, metadataFromVideo(video) ) @@ -1043,7 +1036,6 @@ class ExpStateCasting { "application/dash+xml", dashUrl, resumePosition, - video.duration.toDouble(), speed, metadataFromVideo(video) ); @@ -1139,7 +1131,6 @@ class ExpStateCasting { "application/dash+xml", content, resumePosition, - video.duration.toDouble(), speed ); @@ -1319,7 +1310,6 @@ class ExpStateCasting { "application/vnd.apple.mpegurl", hlsUrl, hackfixResumePosition, - video.duration.toDouble(), speed, metadataFromVideo(video) ); @@ -1487,7 +1477,6 @@ class ExpStateCasting { "application/dash+xml", dashUrl, resumePosition, - video.duration.toDouble(), speed, metadataFromVideo(video) ); @@ -1756,7 +1745,6 @@ class ExpStateCasting { "application/dash+xml", dashUrl, resumePosition, - video.duration.toDouble(), speed, metadataFromVideo(video) ); diff --git a/app/src/main/java/com/futo/platformplayer/experimental_casting/StateCastingDispatcher.kt b/app/src/main/java/com/futo/platformplayer/experimental_casting/StateCastingDispatcher.kt new file mode 100644 index 00000000..dc73056e --- /dev/null +++ b/app/src/main/java/com/futo/platformplayer/experimental_casting/StateCastingDispatcher.kt @@ -0,0 +1,134 @@ +package com.futo.platformplayer.experimental_casting + +import com.futo.platformplayer.Settings +import com.futo.platformplayer.casting.CastConnectionState +import com.futo.platformplayer.casting.StateCasting +import com.futo.platformplayer.dialogs.ConnectedCastingDialog.Companion.TAG +import com.futo.platformplayer.logging.Logger +import org.fcast.sender_sdk.DeviceFeature + +class StateCastingDispatcher { + companion object { + fun canActiveDeviceSetSpeed(): Boolean { + return if (Settings.instance.casting.experimentalCasting) { + ExpStateCasting.instance.activeDevice?.device?.supportsFeature(DeviceFeature.SET_SPEED) == true + } else { + StateCasting.instance.activeDevice?.canSetSpeed == true + } + } + + fun getActiveDeviceSpeed(): Double? { + return if (Settings.instance.casting.experimentalCasting) { + ExpStateCasting.instance.activeDevice?.speed + } else { + StateCasting.instance.activeDevice?.speed + } + } + + fun activeDeviceSetSpeed(speed: Double) { + if (Settings.instance.casting.experimentalCasting) { + ExpStateCasting.instance.activeDevice?.device?.changeSpeed(speed) + } else { + StateCasting.instance.activeDevice?.changeSpeed(speed) + } + } + + fun resumeVideo(): Boolean { + return try { + if (Settings.instance.casting.experimentalCasting) { + ExpStateCasting.instance.resumeVideo() + } else { + StateCasting.instance.resumeVideo() + } + } catch (_: Throwable) { + false + } + } + + fun pauseVideo(): Boolean { + return try { + if (Settings.instance.casting.experimentalCasting) { + ExpStateCasting.instance.pauseVideo() + } else { + StateCasting.instance.pauseVideo() + } + } catch (_: Throwable) { + false + } + } + + fun videoSeekTo(timeSeconds: Double): Boolean { + return try { + return if (Settings.instance.casting.experimentalCasting) { + ExpStateCasting.instance.videoSeekTo(timeSeconds) + } else { + StateCasting.instance.videoSeekTo(timeSeconds) + } + } catch (_: Throwable) { + false + } + } + + fun stopVideo(): Boolean { + return try { + return if (Settings.instance.casting.experimentalCasting) { + ExpStateCasting.instance.stopVideo() + } else { + StateCasting.instance.stopVideo() + } + } catch (_: Throwable) { + false + } + } + + fun isCasting(): Boolean { + return if (Settings.instance.casting.experimentalCasting) { + ExpStateCasting.instance.isCasting + } else { + StateCasting.instance.isCasting + } + } + + fun isConnected(): Boolean { + return if (Settings.instance.casting.experimentalCasting) { + ExpStateCasting.instance.activeDevice?.connectionState == com.futo.platformplayer.experimental_casting.CastConnectionState.CONNECTED + } else { + StateCasting.instance.activeDevice?.connectionState == CastConnectionState.CONNECTED + } + } + + fun isPlaying(): Boolean { + return if (Settings.instance.casting.experimentalCasting) { + ExpStateCasting.instance.activeDevice?.isPlaying == true + } else { + StateCasting.instance.activeDevice?.isPlaying == true + } + } + + fun getExpectedCurrentTime(): Double? { + return if (Settings.instance.casting.experimentalCasting) { + ExpStateCasting.instance.activeDevice?.expectedCurrentTime + } else { + StateCasting.instance.activeDevice?.expectedCurrentTime + } + } + + fun changeVolume(volume: Double) { + try { + if (Settings.instance.casting.experimentalCasting) { + val activeDevice = + ExpStateCasting.instance.activeDevice ?: return; + if (activeDevice.device.supportsFeature(DeviceFeature.SET_VOLUME)) { + activeDevice.device.changeVolume(volume); + } + } else { + val activeDevice = + StateCasting.instance.activeDevice ?: return; + if (activeDevice.canSetVolume) { + activeDevice.changeVolume(volume); + } + } + } catch (_: Throwable) {} + } + } +} \ No newline at end of file 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 6a2c26eb..4848e748 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 @@ -99,6 +99,7 @@ import com.futo.platformplayer.engine.exceptions.ScriptReloadRequiredException import com.futo.platformplayer.engine.exceptions.ScriptUnavailableException import com.futo.platformplayer.exceptions.UnsupportedCastException import com.futo.platformplayer.experimental_casting.ExpStateCasting +import com.futo.platformplayer.experimental_casting.StateCastingDispatcher import com.futo.platformplayer.fixHtmlLinks import com.futo.platformplayer.fixHtmlWhitespace import com.futo.platformplayer.getNowDiffSeconds @@ -1217,12 +1218,8 @@ class VideoDetailView : ConstraintLayout { _onPauseCalled = true; _taskLoadVideo.cancel(); - if (Settings.instance.casting.experimentalCasting) { - if(ExpStateCasting.instance.isCasting) - return; - } else { - if(StateCasting.instance.isCasting) - return; + if (StateCastingDispatcher.isCasting()) { + return } if(allowBackground) @@ -2014,12 +2011,7 @@ class VideoDetailView : ConstraintLayout { return; } - val isCasting = if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.isCasting - } else { - StateCasting.instance.isCasting - } - if (!isCasting) { + if (!StateCastingDispatcher.isCasting()) { setCastEnabled(false); val isLimitedVersion = StatePlatform.instance.getContentClientOrNull(video.url)?.let { @@ -2303,11 +2295,7 @@ class VideoDetailView : ConstraintLayout { } val currentPlaybackRate = (if (_isCasting) { - if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.activeDevice?.speed - } else { - StateCasting.instance.activeDevice?.speed - } + StateCastingDispatcher.getActiveDeviceSpeed() } else _player.getPlaybackRate()) ?: 1.0 _overlay_quality_selector?.groupItems?.firstOrNull { it is SlideUpMenuButtonList && it.id == "playback_rate" }?.let { (it as SlideUpMenuButtonList).setSelected(currentPlaybackRate.toString()) @@ -2426,18 +2414,12 @@ class VideoDetailView : ConstraintLayout { ?.distinct() ?.toList() ?: listOf() else audioSources?.toList() ?: listOf(); - val canSetSpeed = !_isCasting || if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.activeDevice?.device?.supportsFeature(DeviceFeature.SET_SPEED) == true - } else { - StateCasting.instance.activeDevice?.canSetSpeed == true - } + val canSetSpeed = !_isCasting || StateCastingDispatcher.canActiveDeviceSetSpeed(); val currentPlaybackRate = if (_isCasting) { - if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.activeDevice?.speed - } else { - StateCasting.instance.activeDevice?.speed - } - } else _player.getPlaybackRate() + StateCastingDispatcher.getActiveDeviceSpeed() + } else { + _player.getPlaybackRate() + } val qualityPlaybackSpeedTitle = if (canSetSpeed) SlideUpMenuTitle(this.context).apply { setTitle(context.getString(R.string.playback_rate) + " (${String.format("%.2f", currentPlaybackRate)})"); } else null; _overlay_quality_selector = SlideUpMenuOverlay(this.context, _overlay_quality_container, context.getString( R.string.quality), null, true, @@ -2452,11 +2434,7 @@ class VideoDetailView : ConstraintLayout { setButtons(playbackLabels, String.format(Locale.US, format, currentPlaybackRate)); onClick.subscribe { v -> val currentPlaybackSpeed = if (_isCasting) { - if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.activeDevice?.speed - } else { - StateCasting.instance.activeDevice?.speed - } + StateCastingDispatcher.getActiveDeviceSpeed() } else _player.getPlaybackRate(); var playbackSpeedString = v; val stepSpeed = Settings.instance.playback.getPlaybackSpeedStep(); @@ -2465,26 +2443,10 @@ class VideoDetailView : ConstraintLayout { else if(v == "-") playbackSpeedString = String.format(Locale.US, "%.2f", Math.max(0.1, (currentPlaybackSpeed?.toDouble() ?: 1.0) - stepSpeed)).toString(); val newPlaybackSpeed = playbackSpeedString.toDouble(); - if (_isCasting) { - if (Settings.instance.casting.experimentalCasting) { - val ad = ExpStateCasting.instance.activeDevice ?: return@subscribe - if (!ad.device.supportsFeature(DeviceFeature.SET_SPEED)) { - return@subscribe - } - - qualityPlaybackSpeedTitle?.setTitle(context.getString(R.string.playback_rate) + " (${String.format(Locale.US, "%.2f", newPlaybackSpeed)})"); - ad.device.changeSpeed(newPlaybackSpeed) - setSelected(playbackSpeedString); - } else { - val ad = StateCasting.instance.activeDevice ?: return@subscribe - if (!ad.canSetSpeed) { - return@subscribe - } - - qualityPlaybackSpeedTitle?.setTitle(context.getString(R.string.playback_rate) + " (${String.format(Locale.US, "%.2f", newPlaybackSpeed)})"); - ad.changeSpeed(newPlaybackSpeed) - setSelected(playbackSpeedString); - } + if (_isCasting && StateCastingDispatcher.canActiveDeviceSetSpeed()) { + qualityPlaybackSpeedTitle?.setTitle(context.getString(R.string.playback_rate) + " (${String.format(Locale.US, "%.2f", newPlaybackSpeed)})"); + StateCastingDispatcher.activeDeviceSetSpeed(newPlaybackSpeed) + setSelected(playbackSpeedString); } else { qualityPlaybackSpeedTitle?.setTitle(context.getString(R.string.playback_rate) + " (${String.format(Locale.US, "%.2f", newPlaybackSpeed)})"); _player.setPlaybackRate(playbackSpeedString.toFloat()); @@ -2599,14 +2561,8 @@ class VideoDetailView : ConstraintLayout { //Handlers private fun handlePlay() { Logger.i(TAG, "handlePlay") - if (Settings.instance.casting.experimentalCasting) { - if (!ExpStateCasting.instance.resumeVideo()) { - _player.play() - } - } else { - if (!StateCasting.instance.resumeVideo()) { - _player.play(); - } + if (!StateCastingDispatcher.resumeVideo()) { + _player.play() } //TODO: This was needed because handleLowerVolume was done. @@ -2621,60 +2577,31 @@ class VideoDetailView : ConstraintLayout { private fun handlePause() { Logger.i(TAG, "handlePause") - if (Settings.instance.casting.experimentalCasting) { - if (!ExpStateCasting.instance.pauseVideo()) { - _player.pause() - } - } else { - if (!StateCasting.instance.pauseVideo()) { - _player.pause() - } + if (!StateCastingDispatcher.pauseVideo()) { + _player.pause() } } private fun handleSeek(ms: Long) { Logger.i(TAG, "handleSeek(ms=$ms)") - if (Settings.instance.casting.experimentalCasting) { - if (!ExpStateCasting.instance.videoSeekTo(ms.toDouble() / 1000.0)) { - _player.seekTo(ms) - } - } else { - if (!StateCasting.instance.videoSeekTo(ms.toDouble() / 1000.0)) { - _player.seekTo(ms) - } + if (!StateCastingDispatcher.videoSeekTo(ms.toDouble() / 1000.0)) { + _player.seekTo(ms) } } private fun handleStop() { Logger.i(TAG, "handleStop") - if (Settings.instance.casting.experimentalCasting) { - if (!ExpStateCasting.instance.stopVideo()) { - _player.stop() - } - } else { - if (!StateCasting.instance.stopVideo()) { - _player.stop() - } + if (!StateCastingDispatcher.stopVideo()) { + _player.stop() } } private fun handlePlayChanged(playing: Boolean) { Logger.i(TAG, "handlePlayChanged(playing=$playing)") - if (Settings.instance.casting.experimentalCasting) { - val ad = ExpStateCasting.instance.activeDevice; - if (ad != null) { - _cast.setIsPlaying(playing); - } else { - StatePlayer.instance.updateMediaSession( null); - StatePlayer.instance.updateMediaSessionPlaybackState(_player.exoPlayer?.getPlaybackStateCompat() ?: PlaybackStateCompat.STATE_NONE, _player.exoPlayer?.player?.currentPosition ?: 0); - } + if (StateCastingDispatcher.isCasting()) { + _cast.setIsPlaying(playing); } else { - val ad = StateCasting.instance.activeDevice; - if (ad != null) { - _cast.setIsPlaying(playing); - } else { - StatePlayer.instance.updateMediaSession( null); - StatePlayer.instance.updateMediaSessionPlaybackState(_player.exoPlayer?.getPlaybackStateCompat() ?: PlaybackStateCompat.STATE_NONE, _player.exoPlayer?.player?.currentPosition ?: 0); - } + StatePlayer.instance.updateMediaSession( null); + StatePlayer.instance.updateMediaSessionPlaybackState(_player.exoPlayer?.getPlaybackStateCompat() ?: PlaybackStateCompat.STATE_NONE, _player.exoPlayer?.player?.currentPosition ?: 0); } if(playing) { @@ -2712,26 +2639,20 @@ class VideoDetailView : ConstraintLayout { fragment.lifecycleScope.launch(Dispatchers.Main) { try { - if (Settings.instance.casting.experimentalCasting) { - val d = ExpStateCasting.instance.activeDevice; - if (d != null && d.connectionState == com.futo.platformplayer.experimental_casting.CastConnectionState.CONNECTED) - castIfAvailable( - context.contentResolver, - video, - videoSource, - _lastAudioSource, - _lastSubtitleSource, - (d.expectedCurrentTime * 1000.0).toLong(), - d.speed - ); - else if(!_player.swapSources(videoSource, _lastAudioSource, true, true, true)) - _player.hideControls(false); //TODO: Disable player? - } else { - val d = StateCasting.instance.activeDevice; - if (d != null && d.connectionState == CastConnectionState.CONNECTED) - castIfAvailable(context.contentResolver, video, videoSource, _lastAudioSource, _lastSubtitleSource, (d.expectedCurrentTime * 1000.0).toLong(), d.speed); - else if(!_player.swapSources(videoSource, _lastAudioSource, true, true, true)) - _player.hideControls(false); //TODO: Disable player? + if (StateCastingDispatcher.isConnected()) { + val expectedCurrentTime = StateCastingDispatcher.getExpectedCurrentTime() ?: 0.0 + val speed = StateCastingDispatcher.getActiveDeviceSpeed() ?: 1.0 + castIfAvailable( + context.contentResolver, + video, + videoSource, + _lastAudioSource, + _lastSubtitleSource, + (expectedCurrentTime * 1000.0).toLong(), + speed + ) + } else if(!_player.swapSources(videoSource, _lastAudioSource, true, true, true)) { + _player.hideControls(false); //TODO: Disable player? } } catch (e: Throwable) { Logger.e(TAG, "handleSelectVideoTrack failed", e) @@ -2749,34 +2670,20 @@ class VideoDetailView : ConstraintLayout { fragment.lifecycleScope.launch(Dispatchers.Main) { try { - if (Settings.instance.casting.experimentalCasting) { - val d = ExpStateCasting.instance.activeDevice; - if (d != null && d.connectionState == com.futo.platformplayer.experimental_casting.CastConnectionState.CONNECTED) - castIfAvailable( - context.contentResolver, - video, - _lastVideoSource, - audioSource, - _lastSubtitleSource, - (d.expectedCurrentTime * 1000.0).toLong(), - d.speed - ) - else if (!_player.swapSources(_lastVideoSource, audioSource, true, true, true)) - _player.hideControls(false); //TODO: Disable player? - } else { - val d = StateCasting.instance.activeDevice; - if (d != null && d.connectionState == CastConnectionState.CONNECTED) - castIfAvailable( - context.contentResolver, - video, - _lastVideoSource, - audioSource, - _lastSubtitleSource, - (d.expectedCurrentTime * 1000.0).toLong(), - d.speed - ) - else if (!_player.swapSources(_lastVideoSource, audioSource, true, true, true)) - _player.hideControls(false); //TODO: Disable player? + if (StateCastingDispatcher.isConnected()) { + val expectedCurrentTime = StateCastingDispatcher.getExpectedCurrentTime() ?: 0.0 + val speed = StateCastingDispatcher.getActiveDeviceSpeed() ?: 1.0 + castIfAvailable( + context.contentResolver, + video, + _lastVideoSource, + audioSource, + _lastSubtitleSource, + (expectedCurrentTime * 1000.0).toLong(), + speed + ) + } else if (!_player.swapSources(_lastVideoSource, audioSource, true, true, true)) { + _player.hideControls(false); //TODO: Disable player? } } catch (e: Throwable) { Logger.e(TAG, "handleSelectAudioTrack failed", e) @@ -2795,36 +2702,20 @@ class VideoDetailView : ConstraintLayout { fragment.lifecycleScope.launch(Dispatchers.Main) { try { - if (Settings.instance.casting.experimentalCasting) { - val d = ExpStateCasting.instance.activeDevice; - if (d != null && d.connectionState == com.futo.platformplayer.experimental_casting.CastConnectionState.CONNECTED) - castIfAvailable( - context.contentResolver, - video, - _lastVideoSource, - _lastAudioSource, - toSet, - (d.expectedCurrentTime * 1000.0).toLong(), - d.speed - ); - else { - _player.swapSubtitles(toSet); - } + if (StateCastingDispatcher.isConnected()) { + val expectedCurrentTime = StateCastingDispatcher.getExpectedCurrentTime() ?: 0.0 + val speed = StateCastingDispatcher.getActiveDeviceSpeed() ?: 1.0 + castIfAvailable( + context.contentResolver, + video, + _lastVideoSource, + _lastAudioSource, + toSet, + (expectedCurrentTime * 1000.0).toLong(), + speed + ) } else { - val d = StateCasting.instance.activeDevice; - if (d != null && d.connectionState == CastConnectionState.CONNECTED) - castIfAvailable( - context.contentResolver, - video, - _lastVideoSource, - _lastAudioSource, - toSet, - (d.expectedCurrentTime * 1000.0).toLong(), - d.speed - ); - else { - _player.swapSubtitles(toSet); - } + _player.swapSubtitles(toSet); } } catch (e: Throwable) { Logger.e(TAG, "handleSelectSubtitleTrack failed", e) 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 c64ccc0e..f66995d7 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 @@ -28,6 +28,7 @@ import com.futo.platformplayer.constructs.Event0 import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.constructs.Event2 import com.futo.platformplayer.experimental_casting.ExpStateCasting +import com.futo.platformplayer.experimental_casting.StateCastingDispatcher import com.futo.platformplayer.formatDuration import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.states.StateHistory @@ -142,13 +143,8 @@ class CastView : ConstraintLayout { } _gestureControlView.onSeek.subscribe { - if (Settings.instance.casting.experimentalCasting) { - val d = ExpStateCasting.instance.activeDevice ?: return@subscribe; - ExpStateCasting.instance.videoSeekTo(d.expectedCurrentTime + it / 1000); - } else { - val d = StateCasting.instance.activeDevice ?: return@subscribe; - StateCasting.instance.videoSeekTo(d.expectedCurrentTime + it / 1000); - } + val expectedCurrentTime = StateCastingDispatcher.getExpectedCurrentTime() ?: return@subscribe + StateCastingDispatcher.videoSeekTo(expectedCurrentTime + it / 1000) }; _buttonLoop.setOnClickListener { @@ -159,45 +155,25 @@ class CastView : ConstraintLayout { _timeBar.addListener(object : TimeBar.OnScrubListener { override fun onScrubStart(timeBar: TimeBar, position: Long) { - if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.videoSeekTo(position.toDouble()); - } else { - StateCasting.instance.videoSeekTo(position.toDouble()); - } + StateCastingDispatcher.videoSeekTo(position.toDouble()) } override fun onScrubMove(timeBar: TimeBar, position: Long) { - if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.videoSeekTo(position.toDouble()); - } else { - StateCasting.instance.videoSeekTo(position.toDouble()); - } + StateCastingDispatcher.videoSeekTo(position.toDouble()) } override fun onScrubStop(timeBar: TimeBar, position: Long, canceled: Boolean) { - if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.videoSeekTo(position.toDouble()); - } else { - StateCasting.instance.videoSeekTo(position.toDouble()); - } + StateCastingDispatcher.videoSeekTo(position.toDouble()) } }); _buttonMinimize.setOnClickListener { onMinimizeClick.emit(); }; _buttonSettings.setOnClickListener { onSettingsClick.emit(); }; _buttonPlay.setOnClickListener { - if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.resumeVideo() - } else { - StateCasting.instance.resumeVideo() - } + StateCastingDispatcher.resumeVideo() } _buttonPause.setOnClickListener { - if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.pauseVideo() - } else { - StateCasting.instance.pauseVideo() - } + StateCastingDispatcher.pauseVideo() } if (!isInEditMode) { @@ -311,11 +287,7 @@ class CastView : ConstraintLayout { _buttonPlay.visibility = View.VISIBLE; } - val position = if (Settings.instance.casting.experimentalCasting) { - ExpStateCasting.instance.activeDevice?.expectedCurrentTime?.times(1000.0)?.toLong() - } else { - StateCasting.instance.activeDevice?.expectedCurrentTime?.times(1000.0)?.toLong(); - } + val position = StateCastingDispatcher.getExpectedCurrentTime()?.times(1000.0)?.toLong() if(StatePlayer.instance.hasMediaSession()) { StatePlayer.instance.updateMediaSession(null); StatePlayer.instance.updateMediaSessionPlaybackState(getPlaybackStateCompat(), (position ?: 0)); @@ -379,20 +351,12 @@ class CastView : ConstraintLayout { } private fun getPlaybackStateCompat(): Int { - if (Settings.instance.casting.experimentalCasting) { - val d = ExpStateCasting.instance.activeDevice ?: return PlaybackState.STATE_NONE; - - return when(d.isPlaying) { - true -> PlaybackStateCompat.STATE_PLAYING; - else -> PlaybackStateCompat.STATE_PAUSED; - } - } else { - val d = StateCasting.instance.activeDevice ?: return PlaybackState.STATE_NONE; - - return when(d.isPlaying) { - true -> PlaybackStateCompat.STATE_PLAYING; - else -> PlaybackStateCompat.STATE_PAUSED; - } + if (!StateCastingDispatcher.isConnected()) { + return PlaybackState.STATE_NONE + } + return when(StateCastingDispatcher.isPlaying()) { + true -> PlaybackStateCompat.STATE_PLAYING; + else -> PlaybackStateCompat.STATE_PAUSED; } }