[Android] Cycle through subtitle messages under Android Auto

Robert Stone git at videolan.org
Wed Nov 20 06:47:53 UTC 2024


vlc-android | branch: master | Robert Stone <rhstone at gmail.com> | Wed Aug  7 21:56:07 2024 -0700| [264fe69be73954b711eb55e10b5b3e1b57d6d2b1] | committer: Duncan McNamara

Cycle through subtitle messages under Android Auto

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

 .../resources/src/main/res/values/strings.xml      |  5 ++++
 .../src/org/videolan/vlc/MediaSessionCallback.kt   |  9 ++++---
 .../src/org/videolan/vlc/PlaybackService.kt        | 30 ++++++++++++++++++----
 3 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/application/resources/src/main/res/values/strings.xml b/application/resources/src/main/res/values/strings.xml
index 0f652fdae2..30d8356659 100644
--- a/application/resources/src/main/res/values/strings.xml
+++ b/application/resources/src/main/res/values/strings.xml
@@ -85,6 +85,11 @@
     <string name="albums">Albums</string>
     <string name="tracks">Tracks</string>
 
+    <plurals name="saved_bookmarks_quantity">
+        <item quantity="one">1 Saved Bookmark</item>
+        <item quantity="other">%d Saved Bookmarks</item>
+    </plurals>
+
     <plurals name="albums_quantity">
         <item quantity="one">1 album</item>
         <item quantity="other">%d albums</item>
diff --git a/application/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt b/application/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt
index c18c8e082f..2e82ef82be 100644
--- a/application/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt
+++ b/application/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt
@@ -181,7 +181,8 @@ internal class MediaSessionCallback(private val playbackService: PlaybackService
                         val bookmark = it.addBookmark(playbackService.getTime())
                         val bookmarkName = context.getString(R.string.bookmark_default_name, Tools.millisToString(playbackService.getTime()))
                         bookmark?.setName(bookmarkName)
-                        playbackService.displayPlaybackMessage(R.string.saved, bookmarkName)
+                        playbackService.displaySubtitleMessage(context.getString(R.string.saved, bookmarkName),
+                                context.resources.getQuantityString(R.plurals.saved_bookmarks_quantity, it.bookmarks.size, it.bookmarks.size))
                     }
                 }
             }
@@ -306,8 +307,10 @@ internal class MediaSessionCallback(private val playbackService: PlaybackService
     }
 
     private fun checkForSeekFailure(forward: Boolean) {
-        if (playbackService.playlistManager.player.lastPosition == 0.0f && (forward || playbackService.getTime() > 0))
-            playbackService.displayPlaybackMessage(R.string.unseekable_stream)
+        if (playbackService.playlistManager.player.lastPosition == 0.0f && (forward || playbackService.getTime() > 0)) {
+            val context = playbackService.applicationContext
+            playbackService.displaySubtitleMessage(context.getString(R.string.unseekable_stream))
+        }
     }
 
     override fun onPlayFromUri(uri: Uri?, extras: Bundle?) = playbackService.loadUri(uri)
diff --git a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
index f23027c3e2..6dc34dcced 100644
--- a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
+++ b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
@@ -211,7 +211,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner, CoroutineSc
     private lateinit var artworkMap: MutableMap<String, Uri>
 
     private val callbacks = mutableListOf<Callback>()
-    private val subtitleMessage = ArrayDeque<String>(1)
+    private val subtitleMessage = ArrayDeque<Pair<String,Long>>(1)
     private lateinit var cbActor: SendChannel<CbAction>
     var detectHeadset = true
     var headsetInserted = false
@@ -1136,7 +1136,8 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner, CoroutineSc
         val length = length
         lastLength = length
         val chapterTitle = if (lastChaptersCount > 0) getCurrentChapter() else null
-        val displayMsg = subtitleMessage.poll()
+        val displayMsg = getSubtitleMessage()
+        displayMsg?.let { scheduler.scheduleAction(UPDATE_META, 5_000L) }
         val bob = withContext(Dispatchers.Default) {
             val carMode = isCarMode()
             val title = media.nowPlaying ?: media.title
@@ -1322,6 +1323,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner, CoroutineSc
     }
 
     fun notifyTrackChanged() {
+        subtitleMessage.clear()
         updateMetadata()
         updateWidget()
         broadcastMetadata()
@@ -1557,12 +1559,28 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner, CoroutineSc
         mediaSession.setPlaybackState(playbackState)
     }
 
-    fun displayPlaybackMessage(@StringRes resId: Int, vararg formatArgs: String) {
-        val ctx = this at PlaybackService
-        subtitleMessage.push(ctx.getString(resId, *formatArgs))
+    fun displaySubtitleMessage(vararg messages: String) {
+        var endTime = System.currentTimeMillis()
+        subtitleMessage.clear()
+        messages.forEach { msg ->
+            endTime += 5000L
+            msg?.let { subtitleMessage.addLast(Pair(it, endTime)) }
+        }
         updateMetadata()
     }
 
+    private fun getSubtitleMessage(): String? {
+        return subtitleMessage.peek()?.let {
+            when {
+                System.currentTimeMillis() > it.second -> {
+                    subtitleMessage.poll()
+                    subtitleMessage.peek()?.first
+                }
+                else -> it.first
+            }
+        }
+    }
+
     @MainThread
     fun load(media: MediaWrapper, position: Int = 0) = load(listOf(media), position)
 
@@ -1824,6 +1842,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner, CoroutineSc
                 currentToast = Toast.makeText(applicationContext, text, duration)
                 currentToast?.show()
             }
+            UPDATE_META -> updateMetadata()
             END_MEDIASESSION -> if (::mediaSession.isInitialized) mediaSession.isActive = false
         }
     }
@@ -1946,6 +1965,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner, CoroutineSc
 
         private const val SHOW_TOAST = "show_toast"
         private const val END_MEDIASESSION = "end_mediasession"
+        private const val UPDATE_META = "update_meta"
 
         val playerSleepTime by lazy(LazyThreadSafetyMode.NONE) { MutableLiveData<Calendar?>().apply { value = null } }
 



More information about the Android mailing list