[Android] Android Auto: 'Shuffle all' option

Geoffrey Métais git at videolan.org
Wed Mar 13 11:12:03 CET 2019


vlc-android | branch: 3.1.x | Geoffrey Métais <geoffrey.metais at gmail.com> | Fri Mar  8 15:24:23 2019 +0100| [248a9a9a61a818c594f973f80908387c2699f9d0] | committer: Geoffrey Métais

Android Auto: 'Shuffle all' option

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

 vlc-android/res/values/strings.xml                 |  1 +
 .../src/org/videolan/vlc/MediaSessionCallback.kt   | 40 +++++++++++++++++-----
 .../src/org/videolan/vlc/PlaybackService.kt        |  7 ++--
 .../org/videolan/vlc/media/BrowserProvider.java    |  9 ++++-
 4 files changed, 44 insertions(+), 13 deletions(-)

diff --git a/vlc-android/res/values/strings.xml b/vlc-android/res/values/strings.xml
index a2c11455b..0828ab585 100644
--- a/vlc-android/res/values/strings.xml
+++ b/vlc-android/res/values/strings.xml
@@ -121,6 +121,7 @@
     <string name="validation">Are you sure?</string>
 
     <string name="cover_art">Cover art</string>
+    <string name="shuffle_all_title">Shuffle all</string>
     <string name="shuffle_title">Shuffle mode</string>
     <string name="shuffle">Shuffle Off</string>
     <string name="shuffle_on">Shuffle On</string>
diff --git a/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt b/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt
index a00721e25..b9be20f97 100644
--- a/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt
+++ b/vlc-android/src/org/videolan/vlc/MediaSessionCallback.kt
@@ -13,6 +13,8 @@ import org.videolan.medialibrary.media.MediaWrapper
 import org.videolan.vlc.extensions.ExtensionsManager
 import org.videolan.vlc.media.BrowserProvider
 import org.videolan.vlc.util.*
+import java.util.*
+import kotlin.math.min
 
 @Suppress("unused")
 private const val TAG = "VLC/MediaSessionCallback"
@@ -51,19 +53,39 @@ internal class MediaSessionCallback(private val playbackService: PlaybackService
     }
 
     override fun onPlayFromMediaId(mediaId: String, extras: Bundle?) {
-        when {
-            mediaId.startsWith(BrowserProvider.ALBUM_PREFIX) -> playbackService.load(playbackService.medialibrary.getAlbum(java.lang.Long.parseLong(mediaId.split("_".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]))!!.tracks, 0)
-            mediaId.startsWith(BrowserProvider.PLAYLIST_PREFIX) -> playbackService.load(playbackService.medialibrary.getPlaylist(java.lang.Long.parseLong(mediaId.split("_".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]))!!.tracks, 0)
-            mediaId.startsWith(ExtensionsManager.EXTENSION_PREFIX) -> onPlayFromUri(Uri.parse(mediaId.replace(ExtensionsManager.EXTENSION_PREFIX + "_" + mediaId.split("_".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1] + "_", "")), null)
-            else -> try {
-                playbackService.medialibrary.getMedia(mediaId.toLong())?.let { playbackService.load(it) }
-            } catch (e: NumberFormatException) {
-                playbackService.loadLocation(mediaId)
+        AppScope.launch {
+            val context = playbackService.applicationContext
+            val ml = playbackService.medialibrary
+            when {
+                mediaId == BrowserProvider.ID_SHUFFLE_ALL -> {
+                    val count = context.getFromMl { ml.audioCount }
+                    val tracks = withContext(Dispatchers.IO) { ml.audio }
+                    playbackService.load(tracks, Random().nextInt(min(count, MEDIALIBRARY_PAGE_SIZE)))
+                    if (!playbackService.isShuffling) playbackService.shuffle()
+                }
+                mediaId.startsWith(BrowserProvider.ALBUM_PREFIX) -> {
+                    val tracks = context.getFromMl { getAlbum(mediaId.extractId())?.tracks }
+                    tracks?.let { playbackService.load(it, 0) }
+                }
+                mediaId.startsWith(BrowserProvider.PLAYLIST_PREFIX) -> {
+                    val tracks = context.getFromMl { getPlaylist(mediaId.extractId())?.tracks }
+                    tracks?.let { playbackService.load(it, 0) }
+                }
+                mediaId.startsWith(ExtensionsManager.EXTENSION_PREFIX) -> {
+                    val id = mediaId.replace(ExtensionsManager.EXTENSION_PREFIX + "_" + mediaId.split("_".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1] + "_", "")
+                    onPlayFromUri(Uri.parse(id), null)
+                }
+                else -> try {
+                    context.getFromMl { getMedia(mediaId.toLong()) }?.let { playbackService.load(it) }
+                } catch (e: NumberFormatException) {
+                    playbackService.loadLocation(mediaId)
+                }
             }
         }
-
     }
 
+    private fun String.extractId() = split("_".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1].toLong()
+
     override fun onPlayFromUri(uri: Uri?, extras: Bundle?) = playbackService.loadUri(uri)
 
     override fun onPlayFromSearch(query: String?, extras: Bundle?) {
diff --git a/vlc-android/src/org/videolan/vlc/PlaybackService.kt b/vlc-android/src/org/videolan/vlc/PlaybackService.kt
index e36eb6208..afa721319 100644
--- a/vlc-android/src/org/videolan/vlc/PlaybackService.kt
+++ b/vlc-android/src/org/videolan/vlc/PlaybackService.kt
@@ -1249,9 +1249,10 @@ class PlaybackService : MediaBrowserServiceCompat(), CoroutineScope, LifecycleOw
 
     override fun onLoadChildren(parentId: String, result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>) {
         result.detach()
-        if (!medialibrary.isInitiated || libraryReceiver != null)
-            registerMedialibrary(Runnable { sendResults(result, parentId) })
-        else sendResults(result, parentId)
+        launch {
+            getFromMl { isStarted }
+            sendResults(result, parentId)
+        }
     }
 
     private fun sendResults(result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>, parentId: String) {
diff --git a/vlc-android/src/org/videolan/vlc/media/BrowserProvider.java b/vlc-android/src/org/videolan/vlc/media/BrowserProvider.java
index 5ec1293f3..721fecec5 100644
--- a/vlc-android/src/org/videolan/vlc/media/BrowserProvider.java
+++ b/vlc-android/src/org/videolan/vlc/media/BrowserProvider.java
@@ -74,6 +74,7 @@ public class BrowserProvider implements ExtensionManagerService.ExtensionManager
     private static final String ID_PLAYLISTS = "ID_PLAYLISTS";
     private static final String ID_HISTORY = "ID_HISTORY";
     private static final String ID_LAST_ADDED = "ID_RECENT";
+    public static final String ID_SHUFFLE_ALL = "ID_SHUFFLE_ALL";
     public static final String ALBUM_PREFIX = "album";
     private static final String ARTIST_PREFIX = "artist";
     private static final String GENRE_PREFIX = "genre";
@@ -160,6 +161,12 @@ public class BrowserProvider implements ExtensionManagerService.ExtensionManager
                         }
                     }
                     if (BASE_DRAWABLE_URI == null) BASE_DRAWABLE_URI = "android.resource://"+context.getPackageName()+"/drawable/";
+                    //Shuffle
+                    item = new MediaDescriptionCompat.Builder()
+                            .setMediaId(ID_SHUFFLE_ALL)
+                            .setTitle(res.getString(R.string.shuffle_all_title))
+                            .setIconUri(Uri.parse(BASE_DRAWABLE_URI + "ic_auto_audio_normal"));
+                    results.add(new MediaBrowserCompat.MediaItem(item.build(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE));
                     //Last added
                     item = new MediaDescriptionCompat.Builder()
                             .setMediaId(ID_LAST_ADDED)
@@ -237,7 +244,7 @@ public class BrowserProvider implements ExtensionManagerService.ExtensionManager
             if (list != null) {
                 MediaDescriptionCompat.Builder item = new MediaDescriptionCompat.Builder();
                 for (MediaLibraryItem libraryItem : list) {
-                    if (libraryItem == null || (libraryItem.getItemType() == MediaLibraryItem.TYPE_MEDIA && ((MediaWrapper) libraryItem).getType() != MediaWrapper.TYPE_AUDIO))
+                    if (libraryItem.getItemType() == MediaLibraryItem.TYPE_MEDIA && ((MediaWrapper) libraryItem).getType() != MediaWrapper.TYPE_AUDIO)
                         continue;
                     Bitmap cover = AudioUtil.readCoverBitmap(Uri.decode(libraryItem.getArtworkMrl()), 256);
                     if (cover == null) cover = DEFAULT_AUDIO_COVER;



More information about the Android mailing list