[Android] Confine mediaplayer events in a Channel for safety

Geoffrey Métais git at videolan.org
Tue May 15 16:42:20 CEST 2018


vlc-android | branch: master | Geoffrey Métais <geoffrey.metais at gmail.com> | Tue May 15 16:39:25 2018 +0200| [e947b9b8c7496b1ee137f390c0a1594871612cd8] | committer: Geoffrey Métais

Confine mediaplayer events in a Channel for safety

> https://code.videolan.org/videolan/vlc-android/commit/e947b9b8c7496b1ee137f390c0a1594871612cd8
---

 .../src/org/videolan/vlc/media/PlayerController.kt | 45 ++++++++++------
 .../src/org/videolan/vlc/media/PlaylistManager.kt  | 60 +++++++++++-----------
 2 files changed, 58 insertions(+), 47 deletions(-)

diff --git a/vlc-android/src/org/videolan/vlc/media/PlayerController.kt b/vlc-android/src/org/videolan/vlc/media/PlayerController.kt
index 97fcb4b73..42264be3c 100644
--- a/vlc-android/src/org/videolan/vlc/media/PlayerController.kt
+++ b/vlc-android/src/org/videolan/vlc/media/PlayerController.kt
@@ -7,6 +7,8 @@ import android.support.v4.media.session.PlaybackStateCompat
 import android.widget.Toast
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.android.UI
+import kotlinx.coroutines.experimental.channels.Channel
+import kotlinx.coroutines.experimental.channels.actor
 import org.videolan.libvlc.*
 import org.videolan.medialibrary.media.MediaWrapper
 import org.videolan.vlc.BuildConfig
@@ -65,8 +67,8 @@ class PlayerController : IVLCVout.Callback, MediaPlayer.EventListener {
         it.release()
     }
 
-    private var mediaplayerEventListener: MediaPlayer.EventListener? = null
-    internal fun startPlayback(media: Media, listener: MediaPlayer.EventListener) {
+    private var mediaplayerEventListener: MediaPLayerEventListener? = null
+    internal fun startPlayback(media: Media, listener: MediaPLayerEventListener) {
         mediaplayerEventListener = listener
         seekable = true
         pausable = true
@@ -274,24 +276,29 @@ class PlayerController : IVLCVout.Callback, MediaPlayer.EventListener {
     }
 
     private var lastTime = 0L
-    override fun onEvent(event: MediaPlayer.Event?) {
-        if (event === null) return
-        when(event.type) {
-            MediaPlayer.Event.Playing -> playbackState = PlaybackStateCompat.STATE_PLAYING
-            MediaPlayer.Event.Paused -> playbackState = PlaybackStateCompat.STATE_PAUSED
-            MediaPlayer.Event.EncounteredError -> setPlaybackStopped()
-            MediaPlayer.Event.PausableChanged -> pausable = event.pausable
-            MediaPlayer.Event.SeekableChanged -> seekable = event.seekable
-            MediaPlayer.Event.LengthChanged -> length = event.lengthChanged
-            MediaPlayer.Event.TimeChanged -> {
-                val time = event.timeChanged
-                if (time - lastTime > 950L) {
-                    currentTime.value = time
-                    lastTime = time
+    private val eventActor = actor<MediaPlayer.Event>(UI, Channel.UNLIMITED) {
+        for (event in channel) {
+            when (event.type) {
+                MediaPlayer.Event.Playing -> playbackState = PlaybackStateCompat.STATE_PLAYING
+                MediaPlayer.Event.Paused -> playbackState = PlaybackStateCompat.STATE_PAUSED
+                MediaPlayer.Event.EncounteredError -> setPlaybackStopped()
+                MediaPlayer.Event.PausableChanged -> pausable = event.pausable
+                MediaPlayer.Event.SeekableChanged -> seekable = event.seekable
+                MediaPlayer.Event.LengthChanged -> length = event.lengthChanged
+                MediaPlayer.Event.TimeChanged -> {
+                    val time = event.timeChanged
+                    if (time - lastTime > 950L) {
+                        currentTime.value = time
+                        lastTime = time
+                    }
                 }
             }
+            mediaplayerEventListener?.onEvent(event)
         }
-        mediaplayerEventListener?.onEvent(event)
+    }
+
+    override fun onEvent(event: MediaPlayer.Event?) {
+        if (event != null) eventActor.offer(event)
     }
 
     private fun setPlaybackStopped() {
@@ -307,4 +314,8 @@ class PlayerController : IVLCVout.Callback, MediaPlayer.EventListener {
 //            Toast.makeText(VLCApplication.getAppContext(), VLCApplication.getAppContext().getString(R.string.feedback_player_crashed), Toast.LENGTH_LONG).show()
 //        }
 //    }
+}
+
+internal interface MediaPLayerEventListener {
+    suspend fun onEvent(event: MediaPlayer.Event)
 }
\ No newline at end of file
diff --git a/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt b/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt
index e7e02b9ae..6523f3bc3 100644
--- a/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt
+++ b/vlc-android/src/org/videolan/vlc/media/PlaylistManager.kt
@@ -660,42 +660,42 @@ class PlaylistManager(val service: PlaybackService) : MediaWrapperList.EventList
         }
     }
 
-    private val mediaplayerEventListener = MediaPlayer.EventListener { event ->
-        when (event.type) {
-            MediaPlayer.Event.Playing -> {
-                medialibrary.pauseBackgroundOperations()
-                videoBackground = false
-                val mw = medialibrary.findMedia(getCurrentMedia())
-                if (newMedia) {
-                    loadMediaMeta(mw)
-                    if (mw.type == MediaWrapper.TYPE_STREAM) medialibrary.addToHistory(mw.location, mw.title)
-                    saveMediaList()
-                    savePosition(true)
-                    saveCurrentMedia()
-                    newMedia = false
-                    if (player.hasRenderer|| !player.isVideoPlaying()) showAudioPlayer.value = true
-                }
-            }
-            MediaPlayer.Event.Paused -> medialibrary.resumeBackgroundOperations()
-            MediaPlayer.Event.EndReached -> {
-                if (currentIndex != nextIndex) {
-                    saveMediaMeta()
-                    if (isBenchmark) player.setPreviousStats()
-                    if (nextIndex == -1) savePosition(true)
+    private val mediaplayerEventListener = object : MediaPLayerEventListener {
+        override suspend fun onEvent(event: MediaPlayer.Event) {
+            when (event.type) {
+                MediaPlayer.Event.Playing -> {
+                    medialibrary.pauseBackgroundOperations()
+                    videoBackground = false
+                    val mw = withContext(VLCIO) { medialibrary.findMedia(getCurrentMedia()) }
+                    if (newMedia) {
+                        loadMediaMeta(mw)
+                        if (mw.type == MediaWrapper.TYPE_STREAM) medialibrary.addToHistory(mw.location, mw.title)
+                        saveMediaList()
+                        savePosition(true)
+                        saveCurrentMedia()
+                        newMedia = false
+                        if (player.hasRenderer || !player.isVideoPlaying()) showAudioPlayer.value = true
+                    }
                 }
-                launch(UI, CoroutineStart.UNDISPATCHED) {
+                MediaPlayer.Event.Paused -> medialibrary.resumeBackgroundOperations()
+                MediaPlayer.Event.EndReached -> {
+                    if (currentIndex != nextIndex) {
+                        saveMediaMeta()
+                        if (isBenchmark) player.setPreviousStats()
+                        if (nextIndex == -1) savePosition(true)
+                    }
                     determinePrevAndNextIndices(true)
                     next()
                 }
+                MediaPlayer.Event.EncounteredError -> {
+                    service.showToast(service.getString(
+                            R.string.invalid_location,
+                            getCurrentMedia()?.getLocation() ?: ""), Toast.LENGTH_SHORT)
+                    if (currentIndex != nextIndex) next() else stop(true)
+                }
             }
-            MediaPlayer.Event.EncounteredError -> {
-                service.showToast(service.getString(
-                        R.string.invalid_location,
-                        getCurrentMedia()?.getLocation() ?: ""), Toast.LENGTH_SHORT)
-                if (currentIndex != nextIndex) next() else stop(true)
-            }
+            service.onMediaPlayerEvent(event)
         }
-        service.onMediaPlayerEvent(event)
     }
 
     private fun isAudioList() = !player.canSwitchToVideo() && mediaList.isAudioList



More information about the Android mailing list