Modernize code after media3 1.1.0 update

This commit is contained in:
birdbird 2023-07-24 21:08:01 +00:00
parent acbaae9f14
commit 0492b0fa6f
5 changed files with 62 additions and 74 deletions

View File

@ -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

View File

@ -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<MediaPlayerManager>()
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<LibraryResult<ImmutableList<MediaItem>>> {
@ -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<MediaItem>.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)

View File

@ -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)

View File

@ -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,

View File

@ -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)
}