Skip to content

Commit

Permalink
Expand MediaItems in session demo instead of just replacing them
Browse files Browse the repository at this point in the history
When MediaItems are added from the controller, we currently completely
replace the item with the one from our database, overriding any
potential additional information the controller may have set.

Also forward the onAddMediaItems/onSetMediaItems callbacks to common
helper methods instead of redirecting them through super methods

#minor-release
Issue: #706
PiperOrigin-RevId: 573799351
  • Loading branch information
tonihei authored and copybara-github committed Oct 16, 2023
1 parent 37c86f3 commit 00425db
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class PlayableFolderActivity : AppCompatActivity() {
browser.shuffleModeEnabled = true
browser.prepare()
browser.play()
browser?.sessionActivity?.send()
browser.sessionActivity?.send()
}

findViewById<Button>(R.id.play_button).setOnClickListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ import androidx.media3.session.CommandButton
import androidx.media3.session.LibraryResult
import androidx.media3.session.MediaLibraryService
import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSession.MediaItemsWithStartPosition
import androidx.media3.session.SessionCommand
import androidx.media3.session.SessionResult
import com.google.common.collect.ImmutableList
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture

/** A [MediaLibraryService.MediaLibrarySession.Callback] implementation. */
open class DemoMediaLibrarySessionCallback(private val context: Context) :
open class DemoMediaLibrarySessionCallback(context: Context) :
MediaLibraryService.MediaLibrarySession.Callback {

init {
Expand Down Expand Up @@ -155,14 +156,7 @@ open class DemoMediaLibrarySessionCallback(private val context: Context) :
controller: MediaSession.ControllerInfo,
mediaItems: List<MediaItem>
): ListenableFuture<List<MediaItem>> {
val playlist = mutableListOf<MediaItem>()
mediaItems.forEach { mediaItem ->
when (mediaItem.requestMetadata.searchQuery) {
null -> MediaItemTree.getItem(mediaItem.mediaId)?.let { playlist.add(it) }
else -> playlist.addAll(MediaItemTree.search(mediaItem.requestMetadata.searchQuery!!))
}
}
return Futures.immediateFuture(playlist)
return Futures.immediateFuture(resolveMediaItems(mediaItems))
}

@OptIn(UnstableApi::class) // MediaSession.MediaItemsWithStartPosition
Expand All @@ -172,34 +166,57 @@ open class DemoMediaLibrarySessionCallback(private val context: Context) :
mediaItems: List<MediaItem>,
startIndex: Int,
startPositionMs: Long
): ListenableFuture<MediaSession.MediaItemsWithStartPosition> {
): ListenableFuture<MediaItemsWithStartPosition> {
if (mediaItems.size == 1) {
// Try to expand a single item to a playlist.
val mediaId = mediaItems.first().mediaId
val mediaItem = MediaItemTree.getItem(mediaId)
val playlist = mutableListOf<MediaItem>()
var indexInPlaylist = startIndex
mediaItem?.apply {
if (mediaMetadata.isBrowsable == true) {
// Get children browsable item.
playlist.addAll(MediaItemTree.getChildren(mediaId))
} else if (requestMetadata.searchQuery == null) {
// Try to get the parent and its children.
MediaItemTree.getParentId(mediaId)?.let {
playlist.addAll(MediaItemTree.getChildren(it))
indexInPlaylist = MediaItemTree.getIndexInMediaItems(mediaId, playlist)
}
}
maybeExpandSingleItemToPlaylist(mediaItems.first(), startIndex, startPositionMs)?.also {
return Futures.immediateFuture(it)
}
}
return Futures.immediateFuture(
MediaItemsWithStartPosition(resolveMediaItems(mediaItems), startIndex, startPositionMs)
)
}

private fun resolveMediaItems(mediaItems: List<MediaItem>): List<MediaItem> {
val playlist = mutableListOf<MediaItem>()
mediaItems.forEach { mediaItem ->
if (mediaItem.mediaId.isNotEmpty()) {
MediaItemTree.expandItem(mediaItem)?.let { playlist.add(it) }
} else if (mediaItem.requestMetadata.searchQuery != null) {
playlist.addAll(MediaItemTree.search(mediaItem.requestMetadata.searchQuery!!))
}
if (playlist.isNotEmpty()) {
// Return the expanded playlist to be set on the player of the session.
return Futures.immediateFuture(
MediaSession.MediaItemsWithStartPosition(playlist, indexInPlaylist, startPositionMs)
)
}
return playlist
}

@OptIn(UnstableApi::class) // MediaSession.MediaItemsWithStartPosition
private fun maybeExpandSingleItemToPlaylist(
mediaItem: MediaItem,
startIndex: Int,
startPositionMs: Long
): MediaItemsWithStartPosition? {
var playlist = listOf<MediaItem>()
var indexInPlaylist = startIndex
MediaItemTree.getItem(mediaItem.mediaId)?.apply {
if (mediaMetadata.isBrowsable == true) {
// Get children browsable item.
playlist = MediaItemTree.getChildren(mediaId)
} else if (requestMetadata.searchQuery == null) {
// Try to get the parent and its children.
MediaItemTree.getParentId(mediaId)?.let {
playlist =
MediaItemTree.getChildren(it).map { mediaItem ->
if (mediaItem.mediaId == mediaId) MediaItemTree.expandItem(mediaItem)!! else mediaItem
}
indexInPlaylist = MediaItemTree.getIndexInMediaItems(mediaId, playlist)
}
}
}
// Let super serve the request if item isn't expanded.
return super.onSetMediaItems(mediaSession, browser, mediaItems, startIndex, startPositionMs)
if (playlist.isNotEmpty()) {
return MediaItemsWithStartPosition(playlist, indexInPlaylist, startPositionMs)
}
return null
}

override fun onSearch(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ package androidx.media3.demo.session

import android.content.res.AssetManager
import android.net.Uri
import androidx.annotation.OptIn
import androidx.media3.common.MediaItem
import androidx.media3.common.MediaItem.SubtitleConfiguration
import androidx.media3.common.MediaMetadata
import androidx.media3.common.util.UnstableApi
import com.google.common.collect.ImmutableList
import java.io.BufferedReader
import java.lang.StringBuilder
Expand Down Expand Up @@ -275,6 +277,18 @@ object MediaItemTree {
return treeNodes[id]?.item
}

fun expandItem(item: MediaItem): MediaItem? {
val treeItem = getItem(item.mediaId) ?: return null
@OptIn(UnstableApi::class) // MediaMetadata.populate
val metadata = treeItem.mediaMetadata.buildUpon().populate(item.mediaMetadata).build()
return item
.buildUpon()
.setMediaMetadata(metadata)
.setSubtitleConfigurations(treeItem.localConfiguration?.subtitleConfigurations ?: listOf())
.setUri(treeItem.localConfiguration?.uri)
.build()
}

/**
* Returns the media ID of the parent of the given media ID, or null if the media ID wasn't found.
*
Expand Down Expand Up @@ -342,19 +356,6 @@ object MediaItemTree {
return treeNodes[id]?.getChildren() ?: listOf()
}

fun getRandomItem(): MediaItem {
var curRoot = getRootItem()
while (curRoot.mediaMetadata.isBrowsable == true) {
val children = getChildren(curRoot.mediaId)
curRoot = children.random()
}
return curRoot
}

fun getItemFromTitle(title: String): MediaItem? {
return titleMap[title]?.item
}

private fun normalizeSearchText(text: CharSequence?): String {
if (text.isNullOrEmpty() || text.trim().length == 1) {
return ""
Expand Down

0 comments on commit 00425db

Please sign in to comment.