From 3de5cd92aef5a702562c3554476113592e560f1a Mon Sep 17 00:00:00 2001 From: Marcus Hanestad Date: Thu, 4 Sep 2025 13:08:40 +0200 Subject: [PATCH] casting: log exceptions from playback controls --- .../casting/ExpCastingDevice.kt | 68 ++++++------------- .../platformplayer/casting/StateCasting.kt | 40 +++++++++-- .../dialogs/ConnectedCastingDialog.kt | 24 +++---- .../mainactivity/main/VideoDetailView.kt | 9 +-- .../views/adapters/DeviceViewHolder.kt | 9 ++- .../platformplayer/views/casting/CastView.kt | 47 +++++-------- 6 files changed, 94 insertions(+), 103 deletions(-) diff --git a/app/src/main/java/com/futo/platformplayer/casting/ExpCastingDevice.kt b/app/src/main/java/com/futo/platformplayer/casting/ExpCastingDevice.kt index b017fe88..cda02ebf 100644 --- a/app/src/main/java/com/futo/platformplayer/casting/ExpCastingDevice.kt +++ b/app/src/main/java/com/futo/platformplayer/casting/ExpCastingDevice.kt @@ -128,33 +128,15 @@ class ExpCastingDevice(val device: RsCastingDevice) : CastingDevice() { override val onSpeedChanged: Event1 get() = eventHandler.onSpeedChanged - override fun resumePlayback() = try { - device.resumePlayback() - } catch (_: Throwable) { - } - - override fun pausePlayback() = try { - device.pausePlayback() - } catch (_: Throwable) { - } - - override fun stopPlayback() = try { - device.stopPlayback() - } catch (_: Throwable) { - } - - override fun seekTo(timeSeconds: Double) = try { - device.seek(timeSeconds) - } catch (_: Throwable) { - } - + override fun resumePlayback() = device.resumePlayback() + override fun pausePlayback() = device.pausePlayback() + override fun stopPlayback() = device.stopPlayback() + override fun seekTo(timeSeconds: Double) = device.seek(timeSeconds) override fun changeVolume(newVolume: Double) { device.changeVolume(newVolume) volume = newVolume } - override fun changeSpeed(speed: Double) = device.changeSpeed(speed) - override fun connect() = device.connect( ApplicationInfo( "Grayjay Android", @@ -192,19 +174,16 @@ class ExpCastingDevice(val device: RsCastingDevice) : CastingDevice() { duration: Double, speed: Double?, metadata: Metadata? - ) = try { - device.load( - LoadRequest.Video( - contentType = contentType, - url = contentId, - resumePosition = resumePosition, - speed = speed, - volume = volume, - metadata = metadata - ) + ) = device.load( + LoadRequest.Video( + contentType = contentType, + url = contentId, + resumePosition = resumePosition, + speed = speed, + volume = volume, + metadata = metadata ) - } catch (_: Throwable) { - } + ) override fun loadContent( contentType: String, @@ -213,19 +192,16 @@ class ExpCastingDevice(val device: RsCastingDevice) : CastingDevice() { duration: Double, speed: Double?, metadata: Metadata? - ) = try { - device.load( - LoadRequest.Content( - contentType = contentType, - content = content, - resumePosition = resumePosition, - speed = speed, - volume = volume, - metadata = metadata, - ) + ) = device.load( + LoadRequest.Content( + contentType = contentType, + content = content, + resumePosition = resumePosition, + speed = speed, + volume = volume, + metadata = metadata, ) - } catch (_: Throwable) { - } + ) override var connectionState = CastConnectionState.DISCONNECTED override val protocolType: CastProtocolType 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 69477dcb..e3b9ef5e 100644 --- a/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt +++ b/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt @@ -45,6 +45,8 @@ import com.futo.platformplayer.states.StateApp import com.futo.platformplayer.stores.CastingDeviceInfoStorage import com.futo.platformplayer.stores.FragmentedStorage import com.futo.platformplayer.toUrlAddress +import com.futo.platformplayer.views.casting.CastView +import com.futo.platformplayer.views.casting.CastView.Companion import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -238,6 +240,7 @@ abstract class StateCasting { ) } + @Throws suspend fun castIfAvailable(contentResolver: ContentResolver, video: IPlatformVideoDetails, videoSource: IVideoSource?, audioSource: IAudioSource?, subtitleSource: ISubtitleSource?, ms: Long = -1, speed: Double?, onLoadingEstimate: ((Int) -> Unit)? = null, onLoading: ((Boolean) -> Unit)? = null): Boolean { return withContext(Dispatchers.IO) { val ad = activeDevice ?: return@withContext false; @@ -348,7 +351,9 @@ abstract class StateCasting { val ad = activeDevice ?: return false; try { ad.resumePlayback(); - } catch (_: Throwable) { + } catch (e: Throwable) { + Logger.e(TAG, "Failed to resume playback: $e") + return false } return true; } @@ -357,7 +362,9 @@ abstract class StateCasting { val ad = activeDevice ?: return false; try { ad.pausePlayback(); - } catch (_: Throwable) { + } catch (e: Throwable) { + Logger.e(TAG, "Failed to pause playback: $e") + return false } return true; } @@ -366,7 +373,9 @@ abstract class StateCasting { val ad = activeDevice ?: return false; try { ad.stopPlayback(); - } catch (_: Throwable) { + } catch (e: Throwable) { + Logger.e(TAG, "Failed to stop playback: $e") + return false } return true; } @@ -375,11 +384,34 @@ abstract class StateCasting { val ad = activeDevice ?: return false; try { ad.seekTo(timeSeconds); - } catch (_: Throwable) { + } catch (e: Throwable) { + Logger.e(TAG, "Failed to seek: $e") + return false } return true; } + fun changeVolume(volume: Double): Boolean { + val ad = activeDevice ?: return false; + try { + ad.changeVolume(volume); + } catch (e: Throwable) { + Logger.e(TAG, "Failed to change volume: $e") + return false + } + return true; + } + + fun changeSpeed(speed: Double): Boolean { + val ad = activeDevice ?: return false; + try { + ad.changeSpeed(speed); + } catch (e: Throwable) { + Logger.e(TAG, "Failed to change speed: $e") + return false + } + return true; + } private fun castLocalVideo(video: IPlatformVideoDetails, videoSource: LocalVideoSource, resumePosition: Double, speed: Double?) : List { val ad = activeDevice ?: return listOf(); 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 1597cc2c..cea969a9 100644 --- a/app/src/main/java/com/futo/platformplayer/dialogs/ConnectedCastingDialog.kt +++ b/app/src/main/java/com/futo/platformplayer/dialogs/ConnectedCastingDialog.kt @@ -74,24 +74,18 @@ class ConnectedCastingDialog(context: Context?) : AlertDialog(context) { _buttonPlay = findViewById(R.id.button_play); _buttonPlay.setOnClickListener { - try { - StateCasting.instance.activeDevice?.resumePlayback() - } catch (_: Throwable) {} + StateCasting.instance.resumeVideo() } _buttonPause = findViewById(R.id.button_pause); _buttonPause.setOnClickListener { - try { - StateCasting.instance.activeDevice?.pausePlayback() - } catch (_: Throwable) {} + StateCasting.instance.pauseVideo() } _buttonStop = findViewById(R.id.button_stop); _buttonStop.setOnClickListener { (ownerActivity as MainActivity?)?.getFragment()?.closeVideoDetails() - try { - StateCasting.instance.activeDevice?.stopPlayback() - } catch (_: Throwable) {} + StateCasting.instance.stopVideo() } _buttonNext = findViewById(R.id.button_next); @@ -103,7 +97,9 @@ class ConnectedCastingDialog(context: Context?) : AlertDialog(context) { _buttonDisconnect.setOnClickListener { try { StateCasting.instance.activeDevice?.disconnect() - } catch (_: Throwable) {} + } catch (e: Throwable) { + Logger.e(TAG, "Active device failed to disconnect: $e") + } dismiss(); }; @@ -112,9 +108,7 @@ class ConnectedCastingDialog(context: Context?) : AlertDialog(context) { return@OnChangeListener } - try { - StateCasting.instance.activeDevice?.seekTo(value.toDouble()) - } catch (_: Throwable) {} + StateCasting.instance.videoSeekTo(value.toDouble()) }); //TODO: Check if volume slider is properly hidden in all cases @@ -123,9 +117,7 @@ class ConnectedCastingDialog(context: Context?) : AlertDialog(context) { return@OnChangeListener } - try { - StateCasting.instance.activeDevice?.changeVolume(value.toDouble()) - } catch (_: Throwable) {} + StateCasting.instance.changeVolume(value.toDouble()) }); setLoading(false); 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 07f83b17..1481916e 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 @@ -577,10 +577,7 @@ class VideoDetailView : ConstraintLayout { if(chapter?.type == ChapterType.SKIPPABLE) { _layoutSkip.visibility = VISIBLE; } else if(chapter?.type == ChapterType.SKIP || chapter?.type == ChapterType.SKIPONCE) { - val ad = StateCasting.instance.activeDevice - if (ad != null) { - ad.seekTo(chapter.timeEnd) - } else { + if (!StateCasting.instance.videoSeekTo(chapter.timeEnd)) { _player.seekTo((chapter.timeEnd * 1000).toLong()); } @@ -2383,9 +2380,7 @@ class VideoDetailView : ConstraintLayout { val newPlaybackSpeed = playbackSpeedString.toDouble(); if (_isCasting && StateCasting.instance.activeDevice?.canSetSpeed() ?: false) { qualityPlaybackSpeedTitle?.setTitle(context.getString(R.string.playback_rate) + " (${String.format(Locale.US, "%.2f", newPlaybackSpeed)})"); - try { - StateCasting.instance.activeDevice?.changeSpeed(newPlaybackSpeed) - } catch (_: Throwable) {} + StateCasting.instance.changeSpeed(newPlaybackSpeed) setSelected(playbackSpeedString); } else { qualityPlaybackSpeedTitle?.setTitle(context.getString(R.string.playback_rate) + " (${String.format(Locale.US, "%.2f", newPlaybackSpeed)})"); diff --git a/app/src/main/java/com/futo/platformplayer/views/adapters/DeviceViewHolder.kt b/app/src/main/java/com/futo/platformplayer/views/adapters/DeviceViewHolder.kt index 4a260fe1..c99af145 100644 --- a/app/src/main/java/com/futo/platformplayer/views/adapters/DeviceViewHolder.kt +++ b/app/src/main/java/com/futo/platformplayer/views/adapters/DeviceViewHolder.kt @@ -16,6 +16,7 @@ import com.futo.platformplayer.casting.CastProtocolType import com.futo.platformplayer.casting.CastingDevice import com.futo.platformplayer.casting.StateCasting import com.futo.platformplayer.constructs.Event1 +import com.futo.platformplayer.logging.Logger class DeviceViewHolder : ViewHolder { private val _layoutDevice: FrameLayout; @@ -63,7 +64,9 @@ class DeviceViewHolder : ViewHolder { UIDialogs.toast(it, "Device not ready, may be offline") } } - } catch (_: Throwable) { } + } catch (e: Throwable) { + Logger.e(TAG, "Failed to connect: $e") + } } } @@ -142,4 +145,8 @@ class DeviceViewHolder : ViewHolder { device = d; } + + companion object { + private val TAG = "DeviceViewHolder" + } } \ No newline at end of file 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 f09b4689..7e31d326 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 @@ -27,6 +27,7 @@ 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.logging.Logger import com.futo.platformplayer.states.StatePlayer import com.futo.platformplayer.views.TargetTapLoaderView import com.futo.platformplayer.views.behavior.GestureControlView @@ -96,17 +97,13 @@ class CastView : ConstraintLayout { val d = StateCasting.instance.activeDevice ?: return@subscribe _speedHoldWasPlaying = d.isPlaying _speedHoldPrevRate = d.speed - if (d.canSetSpeed()) { - try { - d.changeSpeed(Settings.instance.playback.getHoldPlaybackSpeed()) - } catch (e: Throwable) { - // Ignored - } - } try { + if (d.canSetSpeed()) { + d.changeSpeed(Settings.instance.playback.getHoldPlaybackSpeed()) + } d.resumePlayback() } catch (e: Throwable) { - // Ignored + Logger.e(TAG, "$e") } } _gestureControlView.onSpeedHoldEnd.subscribe { @@ -117,16 +114,14 @@ class CastView : ConstraintLayout { } d.changeSpeed(_speedHoldPrevRate) } catch (e: Throwable) { - // Ignored + Logger.e(TAG, "$e") } } _gestureControlView.onSeek.subscribe { - try { - val d = StateCasting.instance.activeDevice ?: return@subscribe - val expectedCurrentTime = d.expectedCurrentTime - d.seekTo(expectedCurrentTime + it / 1000) - } catch (_: Throwable) { } + val d = StateCasting.instance.activeDevice ?: return@subscribe + val expectedCurrentTime = d.expectedCurrentTime + StateCasting.instance.videoSeekTo(expectedCurrentTime + it / 1000) }; _buttonLoop.setOnClickListener { @@ -137,35 +132,25 @@ class CastView : ConstraintLayout { _timeBar.addListener(object : TimeBar.OnScrubListener { override fun onScrubStart(timeBar: TimeBar, position: Long) { - try { - StateCasting.instance.activeDevice?.seekTo(position.toDouble()) - } catch (_: Throwable) { } + StateCasting.instance.videoSeekTo(position.toDouble()) } override fun onScrubMove(timeBar: TimeBar, position: Long) { - try { - StateCasting.instance.activeDevice?.seekTo(position.toDouble()) - } catch (_: Throwable) { } + StateCasting.instance.videoSeekTo(position.toDouble()) } override fun onScrubStop(timeBar: TimeBar, position: Long, canceled: Boolean) { - try { - StateCasting.instance.activeDevice?.seekTo(position.toDouble()) - } catch (_: Throwable) { } + StateCasting.instance.videoSeekTo(position.toDouble()) } }); _buttonMinimize.setOnClickListener { onMinimizeClick.emit(); }; _buttonSettings.setOnClickListener { onSettingsClick.emit(); }; _buttonPlay.setOnClickListener { - try { - StateCasting.instance.activeDevice?.resumePlayback() - } catch (_: Throwable) { } + StateCasting.instance.resumeVideo() } _buttonPause.setOnClickListener { - try { - StateCasting.instance.activeDevice?.pausePlayback() - } catch (_: Throwable) { } + StateCasting.instance.pauseVideo() } if (!isInEditMode) { @@ -350,4 +335,8 @@ class CastView : ConstraintLayout { _loaderGame.visibility = View.VISIBLE _loaderGame.startLoader(expectedDurationMs.toLong()) } + + companion object { + private val TAG = "CastView"; + } } \ No newline at end of file