[Android] Rework notification mechanism to send updates for specific paths

Robert Stone git at videolan.org
Thu Apr 24 07:23:39 UTC 2025


vlc-android | branch: master | Robert Stone <rhstone at gmail.com> | Mon Apr 21 23:29:47 2025 -0700| [e53f458157ae307089bb433bd36ece113a0a1f42] | committer: Nicolas Pomepuy

Rework notification mechanism to send updates for specific paths

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

 .../vlc/gui/preferences/PreferencesAudioUITest.kt  |  1 -
 .../java/org/videolan/tools/KotlinExtensions.kt    |  4 +-
 .../src/org/videolan/vlc/MediaBrowserCallback.kt   | 75 +++++++++++-----------
 .../src/org/videolan/vlc/PlaybackService.kt        | 14 ++--
 4 files changed, 51 insertions(+), 43 deletions(-)

diff --git a/application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesAudioUITest.kt b/application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesAudioUITest.kt
index 20fa8aae75..10528cadd5 100644
--- a/application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesAudioUITest.kt
+++ b/application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesAudioUITest.kt
@@ -7,7 +7,6 @@ import androidx.test.filters.SdkSuppress
 import org.junit.Rule
 import org.junit.Test
 import org.videolan.tools.KEY_AOUT
-import org.videolan.tools.KEY_PLAYBACK_SPEED_PERSIST
 import org.videolan.tools.RESUME_PLAYBACK
 import org.videolan.vlc.PreferenceMatchers.withKey
 import org.videolan.vlc.R
diff --git a/application/tools/src/main/java/org/videolan/tools/KotlinExtensions.kt b/application/tools/src/main/java/org/videolan/tools/KotlinExtensions.kt
index 5d33b962c2..bec9598c1d 100644
--- a/application/tools/src/main/java/org/videolan/tools/KotlinExtensions.kt
+++ b/application/tools/src/main/java/org/videolan/tools/KotlinExtensions.kt
@@ -80,9 +80,9 @@ val Int.px: Int get() = (this / Resources.getSystem().displayMetrics.density).to
 fun Boolean.toInt() = if (this) 1 else 0
 
 @OptIn(ObsoleteCoroutinesApi::class)
-fun CoroutineScope.conflatedActor(time: Long = 2000L, action: suspend () -> Unit) = actor<Unit>(capacity = Channel.CONFLATED) {
+fun <T> CoroutineScope.conflatedActor(time: Long = 2000L, action: suspend (T) -> Unit) = actor<T>(capacity = Channel.CONFLATED) {
     for (evt in channel) {
-        action()
+        action(evt)
         if (time > 0L) delay(time)
     }
 }
diff --git a/application/vlc-android/src/org/videolan/vlc/MediaBrowserCallback.kt b/application/vlc-android/src/org/videolan/vlc/MediaBrowserCallback.kt
index 95e8fa9c6b..aad3af1593 100644
--- a/application/vlc-android/src/org/videolan/vlc/MediaBrowserCallback.kt
+++ b/application/vlc-android/src/org/videolan/vlc/MediaBrowserCallback.kt
@@ -30,8 +30,7 @@ import org.videolan.tools.conflatedActor
  * @see org.videolan.vlc.viewmodels.ICallBackHandler
  */
 interface IMediaBrowserCallback {
-    fun registerHistoryCallback(callback: () -> Unit)
-    fun registerMediaCallback(callback: () -> Unit)
+    fun registerCallback(callback: (BrowserUpdate) -> Unit)
     fun removeCallbacks()
 }
 
@@ -47,33 +46,24 @@ class MediaBrowserCallback(private val playbackService: PlaybackService) : IMedi
         Medialibrary.HistoryCb {
 
     private val medialibrary = Medialibrary.getInstance()
-    private lateinit var historyActor: SendChannel<Unit>
-    private lateinit var refreshActor: SendChannel<Unit>
+    private lateinit var refreshActor: SendChannel<BrowserUpdate>
 
-    override fun registerHistoryCallback(callback: () -> Unit) {
-        historyActor = playbackService.lifecycleScope.conflatedActor { callback() }
-        medialibrary.addHistoryCb(this)
-    }
-
-    override fun onHistoryModified() {
-        historyActor.trySend(Unit)
-    }
-
-    override fun registerMediaCallback(callback: () -> Unit) {
-        refreshActor = playbackService.lifecycleScope.conflatedActor { callback() }
+    override fun registerCallback(callback: (BrowserUpdate) -> Unit) {
+        refreshActor = playbackService.lifecycleScope.conflatedActor { callback(it) }
         medialibrary.addMediaCb(this)
         medialibrary.addArtistsCb(this)
         medialibrary.addAlbumsCb(this)
         medialibrary.addGenreCb(this)
         medialibrary.addPlaylistCb(this)
+        medialibrary.addHistoryCb(this)
     }
 
     override fun onMediaAdded() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.MEDIA))
     }
 
     override fun onMediaDeleted(id: LongArray?) {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.MEDIA))
     }
 
     override fun onMediaModified() {
@@ -81,59 +71,63 @@ class MediaBrowserCallback(private val playbackService: PlaybackService) : IMedi
     }
 
     override fun onMediaConvertedToExternal(id: LongArray?) {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.MEDIA))
     }
 
     override fun onArtistsAdded() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.ARTIST))
     }
 
     override fun onArtistsModified() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.ARTIST))
     }
 
     override fun onArtistsDeleted() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.ARTIST))
     }
 
     override fun onAlbumsAdded() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.ALBUM))
     }
 
     override fun onAlbumsModified() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.ALBUM))
     }
 
     override fun onAlbumsDeleted() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.ALBUM))
     }
 
     override fun onGenresAdded() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.GENRE))
     }
 
     override fun onGenresModified() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.GENRE))
     }
 
     override fun onGenresDeleted() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.GENRE))
     }
 
     override fun onPlaylistsAdded() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.PLAYLIST))
     }
 
     override fun onPlaylistsModified() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.PLAYLIST))
     }
 
     override fun onPlaylistsDeleted() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.PLAYLIST))
+    }
+
+    override fun onHistoryModified() {
+        refreshActor.trySend(BrowserUpdate(UpdateType.HISTORY))
     }
 
     fun onShuffleChanged() {
-        refreshActor.trySend(Unit)
+        refreshActor.trySend(BrowserUpdate(UpdateType.SHUFFLE))
     }
 
     override fun removeCallbacks() {
@@ -143,11 +137,20 @@ class MediaBrowserCallback(private val playbackService: PlaybackService) : IMedi
             medialibrary.removeAlbumsCb(this)
             medialibrary.removeGenreCb(this)
             medialibrary.removePlaylistCb(this)
-            refreshActor.close()
-        }
-        if (::historyActor.isInitialized) {
             medialibrary.removeHistoryCb(this)
-            historyActor.close()
+            refreshActor.close()
         }
     }
-}
\ No newline at end of file
+}
+
+enum class UpdateType {
+    MEDIA,
+    ARTIST,
+    ALBUM,
+    GENRE,
+    PLAYLIST,
+    HISTORY,
+    SHUFFLE;
+}
+
+class BrowserUpdate(val updateType: UpdateType)
\ No newline at end of file
diff --git a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
index 56b6944f92..60b1412db2 100644
--- a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
+++ b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
@@ -741,10 +741,16 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner, CoroutineSc
         artworkMap = HashMap<String, Uri>()
 
         browserCallback = MediaBrowserCallback(this)
-        browserCallback.registerMediaCallback { if (lastParentId.isNotEmpty()) notifyChildrenChanged(lastParentId) }
-        browserCallback.registerHistoryCallback {
-            when (lastParentId) {
-                MediaSessionBrowser.ID_HOME, MediaSessionBrowser.ID_HISTORY -> notifyChildrenChanged(lastParentId)
+        browserCallback.registerCallback {
+            notifyChildrenChanged(MediaSessionBrowser.ID_HOME)
+            when (it.updateType) {
+                UpdateType.MEDIA -> notifyChildrenChanged(MediaSessionBrowser.ID_LAST_ADDED)
+                UpdateType.ARTIST -> notifyChildrenChanged(MediaSessionBrowser.ID_ARTIST)
+                UpdateType.ALBUM -> notifyChildrenChanged(MediaSessionBrowser.ID_ALBUM)
+                UpdateType.GENRE -> notifyChildrenChanged(MediaSessionBrowser.ID_GENRE)
+                UpdateType.PLAYLIST -> notifyChildrenChanged(MediaSessionBrowser.ID_PLAYLIST)
+                UpdateType.HISTORY -> notifyChildrenChanged(MediaSessionBrowser.ID_HISTORY)
+                UpdateType.SHUFFLE -> notifyChildrenChanged(lastParentId)
             }
         }
 



More information about the Android mailing list