diff --git a/application/resources/src/main/res/values/strings.xml b/application/resources/src/main/res/values/strings.xml
index 0f652fdae..30d835665 100644
--- a/application/resources/src/main/res/values/strings.xml
+++ b/application/resources/src/main/res/values/strings.xml
@@ -85,6 +85,11 @@
Albums
Tracks
+
+ - 1 Saved Bookmark
+ - %d Saved Bookmarks
+
+
- 1 album
- %d albums
diff --git a/application/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt b/application/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt
index c18c8e082..2e82ef82b 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 f23027c3e..6dc34dcce 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
private val callbacks = mutableListOf()
- private val subtitleMessage = ArrayDeque(1)
+ private val subtitleMessage = ArrayDeque>(1)
private lateinit var cbActor: SendChannel
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@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().apply { value = null } }