From 0492b0fa6ff234636e686cd55c92cd5d190c7e6d Mon Sep 17 00:00:00 2001 From: birdbird <6892457-tzugen@users.noreply.gitlab.com> Date: Mon, 24 Jul 2023 21:08:01 +0000 Subject: [PATCH] Modernize code after media3 1.1.0 update --- .../imageloader/ArtworkBitmapLoader.kt | 2 +- .../playback/AutoMediaBrowserCallback.kt | 96 +++++++++---------- .../ultrasonic/playback/PlaybackService.kt | 2 +- .../ultrasonic/service/JukeboxMediaPlayer.kt | 8 +- .../ultrasonic/util/MediaItemConverter.kt | 28 ++---- 5 files changed, 62 insertions(+), 74 deletions(-) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/imageloader/ArtworkBitmapLoader.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/imageloader/ArtworkBitmapLoader.kt index b7b6c15a..29bb2e16 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/imageloader/ArtworkBitmapLoader.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/imageloader/ArtworkBitmapLoader.kt @@ -11,7 +11,7 @@ import android.annotation.SuppressLint import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri -import androidx.media3.session.BitmapLoader +import androidx.media3.common.util.BitmapLoader import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListeningExecutorService import com.google.common.util.concurrent.MoreExecutors diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/AutoMediaBrowserCallback.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/AutoMediaBrowserCallback.kt index 291dc5fe..d7abb1bb 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/AutoMediaBrowserCallback.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/AutoMediaBrowserCallback.kt @@ -7,16 +7,15 @@ package org.moire.ultrasonic.playback -import android.annotation.SuppressLint import android.os.Bundle import androidx.media3.common.HeartRating import androidx.media3.common.MediaItem -import androidx.media3.common.MediaMetadata -import androidx.media3.common.MediaMetadata.FOLDER_TYPE_ALBUMS -import androidx.media3.common.MediaMetadata.FOLDER_TYPE_ARTISTS -import androidx.media3.common.MediaMetadata.FOLDER_TYPE_MIXED -import androidx.media3.common.MediaMetadata.FOLDER_TYPE_PLAYLISTS -import androidx.media3.common.MediaMetadata.FOLDER_TYPE_TITLES +import androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_ALBUMS +import androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_ARTISTS +import androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_MIXED +import androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_PLAYLISTS +import androidx.media3.common.MediaMetadata.MEDIA_TYPE_MIXED +import androidx.media3.common.MediaMetadata.MEDIA_TYPE_PLAYLIST import androidx.media3.common.Player import androidx.media3.common.Rating import androidx.media3.common.StarRating @@ -46,7 +45,6 @@ import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.domain.SearchCriteria import org.moire.ultrasonic.domain.SearchResult import org.moire.ultrasonic.domain.Track -import org.moire.ultrasonic.service.MediaPlayerManager import org.moire.ultrasonic.service.MusicServiceFactory import org.moire.ultrasonic.service.RatingManager import org.moire.ultrasonic.util.Util @@ -97,11 +95,8 @@ const val PLAY_COMMAND = "play " * MediaBrowserService implementation for e.g. Android Auto */ @Suppress("TooManyFunctions", "LargeClass", "UnusedPrivateMember") -@SuppressLint("UnsafeOptInUsageError") -class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : - MediaLibraryService.MediaLibrarySession.Callback, KoinComponent { +class AutoMediaBrowserCallback : MediaLibraryService.MediaLibrarySession.Callback, KoinComponent { - private val mediaPlayerManager by inject() private val activeServerProvider: ActiveServerProvider by inject() private val serviceJob = SupervisorJob() @@ -213,8 +208,8 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : "Root Folder", MEDIA_ROOT_ID, isPlayable = false, - folderType = FOLDER_TYPE_MIXED, - mediaType = MediaMetadata.MEDIA_TYPE_FOLDER_MIXED + isBrowsable = true, + mediaType = MEDIA_TYPE_FOLDER_MIXED ), params ) @@ -528,7 +523,7 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : ?: Futures.immediateFuture(mediaItems) } - @Suppress("ComplexMethod") + @Suppress("ReturnCount", "ComplexMethod") private fun onLoadChildren( parentId: String, ): ListenableFuture>> { @@ -598,8 +593,7 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : mediaItems.add( album.title ?: "", listOf(MEDIA_ALBUM_ITEM, album.id, album.name) - .joinToString("|"), - FOLDER_TYPE_ALBUMS + .joinToString("|") ) } @@ -691,7 +685,8 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : R.string.music_library_label, MEDIA_LIBRARY_ID, null, - folderType = FOLDER_TYPE_MIXED, + isBrowsable = true, + mediaType = MEDIA_TYPE_FOLDER_MIXED, icon = R.drawable.ic_library ) @@ -699,7 +694,8 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : R.string.main_artists_title, MEDIA_ARTIST_ID, null, - folderType = FOLDER_TYPE_ARTISTS, + isBrowsable = true, + mediaType = MEDIA_TYPE_FOLDER_ARTISTS, icon = R.drawable.ic_artist ) @@ -708,7 +704,8 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : R.string.main_albums_title, MEDIA_ALBUM_ID, null, - folderType = FOLDER_TYPE_ALBUMS, + isBrowsable = true, + mediaType = MEDIA_TYPE_FOLDER_ALBUMS, icon = R.drawable.ic_menu_browse ) @@ -716,7 +713,8 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : R.string.playlist_label, MEDIA_PLAYLIST_ID, null, - folderType = FOLDER_TYPE_PLAYLISTS, + isBrowsable = true, + mediaType = MEDIA_TYPE_FOLDER_PLAYLISTS, icon = R.drawable.ic_menu_playlists ) @@ -731,14 +729,16 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : R.string.main_songs_random, MEDIA_SONG_RANDOM_ID, R.string.main_songs_title, - folderType = FOLDER_TYPE_TITLES + isBrowsable = true, + mediaType = MEDIA_TYPE_PLAYLIST ) mediaItems.add( R.string.main_songs_starred, MEDIA_SONG_STARRED_ID, R.string.main_songs_title, - folderType = FOLDER_TYPE_TITLES + isBrowsable = true, + mediaType = MEDIA_TYPE_PLAYLIST ) // Albums @@ -752,28 +752,28 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : R.string.main_albums_recent, MEDIA_ALBUM_RECENT_ID, R.string.main_albums_title, - folderType = FOLDER_TYPE_ALBUMS + mediaType = MEDIA_TYPE_FOLDER_ALBUMS, ) mediaItems.add( R.string.main_albums_frequent, MEDIA_ALBUM_FREQUENT_ID, R.string.main_albums_title, - folderType = FOLDER_TYPE_ALBUMS + mediaType = MEDIA_TYPE_FOLDER_ALBUMS, ) mediaItems.add( R.string.main_albums_random, MEDIA_ALBUM_RANDOM_ID, R.string.main_albums_title, - folderType = FOLDER_TYPE_ALBUMS + mediaType = MEDIA_TYPE_FOLDER_ALBUMS, ) mediaItems.add( R.string.main_albums_starred, MEDIA_ALBUM_STARRED_ID, R.string.main_albums_title, - folderType = FOLDER_TYPE_ALBUMS + mediaType = MEDIA_TYPE_FOLDER_ALBUMS, ) // Other @@ -822,8 +822,7 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : index.add(currentSection) mediaItems.add( currentSection, - listOf(MEDIA_ARTIST_SECTION, currentSection).joinToString("|"), - FOLDER_TYPE_ARTISTS + listOf(MEDIA_ARTIST_SECTION, currentSection).joinToString("|") ) } } @@ -831,8 +830,7 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : artists.map { artist -> mediaItems.add( artist.name ?: "", - listOf(childMediaId, artist.id, artist.name).joinToString("|"), - FOLDER_TYPE_ARTISTS + listOf(childMediaId, artist.id, artist.name).joinToString("|") ) } } @@ -862,8 +860,7 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : mediaItems.add( album.title ?: "", listOf(MEDIA_ALBUM_ITEM, album.id, album.name) - .joinToString("|"), - FOLDER_TYPE_ALBUMS + .joinToString("|") ) } return@future LibraryResult.ofItemList(mediaItems, null) @@ -901,8 +898,7 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : if (item.isDirectory) mediaItems.add( item.title ?: "", - listOf(MEDIA_ALBUM_ITEM, item.id, item.name).joinToString("|"), - FOLDER_TYPE_TITLES + listOf(MEDIA_ALBUM_ITEM, item.id, item.name).joinToString("|") ) else if (item is Track) mediaItems.add( @@ -951,8 +947,7 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : mediaItems.add( album.title ?: "", listOf(MEDIA_ALBUM_ITEM, album.id, album.name) - .joinToString("|"), - FOLDER_TYPE_ALBUMS + .joinToString("|") ) } @@ -980,7 +975,7 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : playlist.name, listOf(MEDIA_PLAYLIST_ITEM, playlist.id, playlist.name) .joinToString("|"), - FOLDER_TYPE_PLAYLISTS + mediaType = MEDIA_TYPE_PLAYLIST, ) } return@future LibraryResult.ofItemList(mediaItems, null) @@ -1074,7 +1069,7 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : mediaItems.add( podcast.title ?: "", listOf(MEDIA_PODCAST_ITEM, podcast.id).joinToString("|"), - FOLDER_TYPE_MIXED + mediaType = MEDIA_TYPE_FOLDER_MIXED, ) } return@future LibraryResult.ofItemList(mediaItems, null) @@ -1177,7 +1172,7 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : share.name ?: "", listOf(MEDIA_SHARE_ITEM, share.id) .joinToString("|"), - FOLDER_TYPE_MIXED + mediaType = MEDIA_TYPE_FOLDER_MIXED, ) } return@future LibraryResult.ofItemList(mediaItems, null) @@ -1355,14 +1350,16 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : private fun MutableList.add( title: String, mediaId: String, - folderType: Int + mediaType: Int = MEDIA_TYPE_MIXED, + isBrowsable: Boolean = false ) { val mediaItem = buildMediaItem( title, mediaId, isPlayable = false, - folderType = folderType + isBrowsable = isBrowsable, + mediaType = mediaType ) this.add(mediaItem) @@ -1373,8 +1370,8 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : resId: Int, mediaId: String, groupNameId: Int?, - browsable: Boolean = true, - folderType: Int = FOLDER_TYPE_MIXED, + isBrowsable: Boolean = true, + mediaType: Int = MEDIA_TYPE_FOLDER_MIXED, icon: Int? = null ) { val applicationContext = UApp.applicationContext() @@ -1382,14 +1379,15 @@ class AutoMediaBrowserCallback(val libraryService: MediaLibraryService) : val mediaItem = buildMediaItem( applicationContext.getString(resId), mediaId, - isPlayable = !browsable, - folderType = folderType, + isPlayable = !isBrowsable, + isBrowsable = isBrowsable, + imageUri = if (icon != null) { + Util.getUriToDrawable(applicationContext, icon) + } else null, group = if (groupNameId != null) { applicationContext.getString(groupNameId) } else null, - imageUri = if (icon != null) { - Util.getUriToDrawable(applicationContext, icon) - } else null + mediaType = mediaType ) this.add(mediaItem) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/PlaybackService.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/PlaybackService.kt index 8ddf5f19..9ec36400 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/PlaybackService.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/PlaybackService.kt @@ -142,7 +142,7 @@ class PlaybackService : actualBackend = desiredBackend // Create browser interface - librarySessionCallback = AutoMediaBrowserCallback(this) + librarySessionCallback = AutoMediaBrowserCallback() // This will need to use the AutoCalls mediaLibrarySession = MediaLibrarySession.Builder(this, player, librarySessionCallback) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/JukeboxMediaPlayer.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/JukeboxMediaPlayer.kt index 20894ca6..fb7d3b71 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/JukeboxMediaPlayer.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/JukeboxMediaPlayer.kt @@ -82,7 +82,10 @@ class JukeboxMediaPlayer : JukeboxUnimplementedFunctions(), Player { companion object { // This is quite important, by setting the DeviceInfo the player is recognized by // Android as being a remote playback surface - val DEVICE_INFO = DeviceInfo(DeviceInfo.PLAYBACK_TYPE_REMOTE, 0, 10) + val DEVICE_INFO = DeviceInfo.Builder(DeviceInfo.PLAYBACK_TYPE_REMOTE) + .setMinVolume(0) + .setMaxVolume(10) + .build() val running = AtomicBoolean() const val MAX_GAIN = 10 } @@ -208,15 +211,12 @@ class JukeboxMediaPlayer : JukeboxUnimplementedFunctions(), Player { Player.COMMAND_GET_DEVICE_VOLUME, Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS, Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS, - Player.COMMAND_ADJUST_DEVICE_VOLUME, - Player.COMMAND_SET_DEVICE_VOLUME ) if (isPlaying) commandsBuilder.add(Player.COMMAND_STOP) if (playlist.isNotEmpty()) { commandsBuilder.addAll( Player.COMMAND_GET_CURRENT_MEDIA_ITEM, Player.COMMAND_GET_METADATA, - Player.COMMAND_GET_MEDIA_ITEMS_METADATA, Player.COMMAND_PLAY_PAUSE, Player.COMMAND_PREPARE, Player.COMMAND_SEEK_BACK, diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/MediaItemConverter.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/MediaItemConverter.kt index f7eebd3e..e05957ed 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/MediaItemConverter.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/util/MediaItemConverter.kt @@ -14,7 +14,8 @@ import androidx.core.net.toUri import androidx.media3.common.HeartRating import androidx.media3.common.MediaItem import androidx.media3.common.MediaMetadata -import androidx.media3.common.MediaMetadata.FOLDER_TYPE_NONE +import androidx.media3.common.MediaMetadata.MEDIA_TYPE_FOLDER_MIXED +import androidx.media3.common.MediaMetadata.MEDIA_TYPE_MUSIC import androidx.media3.common.StarRating import java.text.DateFormat import java.text.ParseException @@ -22,7 +23,7 @@ import java.util.Date import org.moire.ultrasonic.domain.Track import org.moire.ultrasonic.provider.AlbumArtContentProvider -// Copied from androidx.media.utils.MediaConstants in order to avoid importing a whole dependecy +// Copied from androidx.media.utils.MediaConstants in order to avoid importing a whole dependency // for a single string value private const val DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE = "android.media.browse.CONTENT_STYLE_GROUP_TITLE_HINT" @@ -76,15 +77,16 @@ fun Track.toMediaItem( title = title ?: "", mediaId = mediaId, isPlayable = !isDirectory, - folderType = if (isDirectory) MediaMetadata.FOLDER_TYPE_TITLES - else MediaMetadata.FOLDER_TYPE_NONE, + isBrowsable = isDirectory, album = album, artist = artist, genre = genre, sourceUri = uri.toUri(), imageUri = artworkUri, starred = starred, - group = null + group = null, + mediaType = if (isDirectory) MEDIA_TYPE_FOLDER_MIXED + else MEDIA_TYPE_MUSIC ) val metadataBuilder = mediaItem.mediaMetadata.buildUpon() @@ -204,14 +206,6 @@ private fun safeParseDate(created: String?): Date? { } else null } -fun MediaItem.setPin(pin: Boolean) { - this.mediaMetadata.extras?.putBoolean("pin", pin) -} - -fun MediaItem.shouldBePinned(): Boolean { - return this.mediaMetadata.extras?.getBoolean("pin") ?: false -} - /** * Build a new MediaItem from a list of attributes. * Especially useful to create folder entries in the Auto interface. @@ -222,7 +216,7 @@ fun buildMediaItem( title: String, mediaId: String, isPlayable: Boolean, - folderType: @MediaMetadata.FolderType Int, + isBrowsable: Boolean = false, album: String? = null, artist: String? = null, genre: String? = null, @@ -241,17 +235,13 @@ fun buildMediaItem( .setAlbumArtist(artist) .setGenre(genre) .setUserRating(HeartRating(starred)) - .setFolderType(folderType) + .setIsBrowsable(isBrowsable) .setIsPlayable(isPlayable) if (imageUri != null) { metadataBuilder.setArtworkUri(imageUri) } - if (folderType > FOLDER_TYPE_NONE) { - metadataBuilder.setIsBrowsable(true) - } - if (mediaType != null) { metadataBuilder.setMediaType(mediaType) }