diff --git a/app/src/main/java/com/futo/platformplayer/api/media/models/playback/IPlaybackTracker.kt b/app/src/main/java/com/futo/platformplayer/api/media/models/playback/IPlaybackTracker.kt index 59527d66..7c85249c 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/models/playback/IPlaybackTracker.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/models/playback/IPlaybackTracker.kt @@ -7,4 +7,5 @@ interface IPlaybackTracker { fun onInit(seconds: Double); fun onProgress(seconds: Double, isPlaying: Boolean); + fun onConcluded(); } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaybackTracker.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaybackTracker.kt index efb032cb..e5ee7b68 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaybackTracker.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaybackTracker.kt @@ -17,6 +17,8 @@ class JSPlaybackTracker: IPlaybackTracker { private var _lastRequest: Long = Long.MIN_VALUE; + private val _hasOnConcluded: Boolean; + override var nextRequest: Int = 1000 private set; @@ -26,6 +28,7 @@ class JSPlaybackTracker: IPlaybackTracker { throw ScriptImplementationException(config, "Missing onProgress on PlaybackTracker"); if(!obj.has("nextRequest")) throw ScriptImplementationException(config, "Missing nextRequest on PlaybackTracker"); + _hasOnConcluded = obj.has("onConcluded"); this._config = config; this._obj = obj; @@ -59,6 +62,16 @@ class JSPlaybackTracker: IPlaybackTracker { } } } + override fun onConcluded() { + warnIfMainThread("JSPlaybackTracker.onConcluded"); + if(_hasOnConcluded) { + synchronized(_obj) { + Logger.i("JSPlaybackTracker", "onConcluded"); + _obj.invokeVoid("onConcluded", -1); + } + } + } + override fun shouldUpdate(): Boolean = (_lastRequest < 0 || (System.currentTimeMillis() - _lastRequest) > nextRequest); } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt index 666bd2f5..bbac4acf 100644 --- a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt +++ b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt @@ -191,6 +191,8 @@ class PackageHttp: V8Package { @Transient private val _client: ManagedHttpClient; + val parentConfig: IV8PluginConfig get() = _package._config; + @Transient private val _defaultHeaders = mutableMapOf(); @Transient @@ -431,7 +433,7 @@ class PackageHttp: V8Package { val hasClosed = socketObj.has("closed"); val hasFailure = socketObj.has("failure"); - //socketObj.setWeak(); //We have to manage this lifecycle + socketObj.setWeak(); //We have to manage this lifecycle _listeners = socketObj; _socket = _packageClient.logExceptions { @@ -440,8 +442,14 @@ class PackageHttp: V8Package { override fun open() { Logger.i(TAG, "Websocket opened: " + _url); _isOpen = true; - if(hasOpen) - _listeners?.invokeVoid("open", arrayOf()); + if(hasOpen) { + try { + _listeners?.invokeVoid("open", arrayOf()); + } + catch(ex: Throwable){ + Logger.e(TAG, "Socket for [${_packageClient.parentConfig.name}] open failed: " + ex.message, ex); + } + } } override fun message(msg: String) { if(hasMessage) { @@ -453,18 +461,37 @@ class PackageHttp: V8Package { } override fun closing(code: Int, reason: String) { if(hasClosing) - _listeners?.invokeVoid("closing", code, reason); + { + try { + _listeners?.invokeVoid("closing", code, reason); + } + catch(ex: Throwable){ + Logger.e(TAG, "Socket for [${_packageClient.parentConfig.name}] closing failed: " + ex.message, ex); + } + } } override fun closed(code: Int, reason: String) { _isOpen = false; - if(hasClosed) - _listeners?.invokeVoid("closed", code, reason); + if(hasClosed) { + try { + _listeners?.invokeVoid("closed", code, reason); + } + catch(ex: Throwable){ + Logger.e(TAG, "Socket for [${_packageClient.parentConfig.name}] closed failed: " + ex.message, ex); + } + } } override fun failure(exception: Throwable) { _isOpen = false; Logger.e(TAG, "Websocket failure: ${exception.message} (${_url})", exception); - if(hasFailure) - _listeners?.invokeVoid("failure", exception.message); + if(hasFailure) { + try { + _listeners?.invokeVoid("failure", exception.message); + } + catch(ex: Throwable){ + Logger.e(TAG, "Socket for [${_packageClient.parentConfig.name}] closed failed: " + ex.message, ex); + } + } } }); }; @@ -474,6 +501,16 @@ class PackageHttp: V8Package { fun send(msg: String) { _socket?.send(msg); } + + @V8Function + fun close() { + _socket?.close(1000, ""); + } + @V8Function + fun close(code: Int?, reason: String?) { + _socket?.close(code ?: 1000, reason ?: ""); + _listeners?.close() + } } data class RequestDescriptor( 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 6d0901e3..07ba3e7f 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 @@ -690,7 +690,7 @@ class VideoDetailView : ConstraintLayout { _lastAudioSource = null; _lastSubtitleSource = null; video = null; - _playbackTracker = null; + cleanupPlaybackTracker(); Logger.i(TAG, "Keep screen on unset onClose") fragment.activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); }; @@ -1033,7 +1033,7 @@ class VideoDetailView : ConstraintLayout { _searchVideo = null; video = null; - _playbackTracker = null; + cleanupPlaybackTracker(); _url = url; _videoResumePositionMilliseconds = resumeSeconds * 1000; _rating.visibility = View.GONE; @@ -1071,7 +1071,7 @@ class VideoDetailView : ConstraintLayout { } this.video = null; - this._playbackTracker = null; + cleanupPlaybackTracker(); _searchVideo = video; _videoResumePositionMilliseconds = resumeSeconds * 1000; setLastPositionMilliseconds(_videoResumePositionMilliseconds, false); @@ -1206,7 +1206,7 @@ class VideoDetailView : ConstraintLayout { } this.videoLocal = videoLocal; this.video = video; - this._playbackTracker = null; + cleanupPlaybackTracker(); if(video is JSVideoDetails) { val me = this; @@ -1522,6 +1522,22 @@ class VideoDetailView : ConstraintLayout { } } + fun cleanupPlaybackTracker(){ + val tracker = _playbackTracker; + if(tracker != null) { + _playbackTracker = null; + fragment.lifecycleScope.launch(Dispatchers.IO) { + Logger.i(TAG, "Cleaning up old playback tracker"); + try { + tracker.onConcluded(); + } + catch(ex: Throwable) { + Logger.e(TAG, "Failed to cleanup playback tracker", ex); + } + } + } + } + //Source Loads private fun loadCurrentVideo(resumePositionMs: Long = 0) { _didStop = false; @@ -2016,7 +2032,7 @@ class VideoDetailView : ConstraintLayout { private fun fetchVideo() { Logger.i(TAG, "fetchVideo") video = null; - _playbackTracker = null; + cleanupPlaybackTracker(); val url = _url; if (url != null && url.isNotBlank()) { diff --git a/app/src/stable/assets/sources/bilibili b/app/src/stable/assets/sources/bilibili index 59d2200f..611f692c 160000 --- a/app/src/stable/assets/sources/bilibili +++ b/app/src/stable/assets/sources/bilibili @@ -1 +1 @@ -Subproject commit 59d2200f9220f2add3c4b7eccc314306503493a3 +Subproject commit 611f692ced94bac637907b105170a4143580281a diff --git a/app/src/unstable/assets/sources/bilibili b/app/src/unstable/assets/sources/bilibili index 59d2200f..611f692c 160000 --- a/app/src/unstable/assets/sources/bilibili +++ b/app/src/unstable/assets/sources/bilibili @@ -1 +1 @@ -Subproject commit 59d2200f9220f2add3c4b7eccc314306503493a3 +Subproject commit 611f692ced94bac637907b105170a4143580281a