diff --git a/app/src/main/java/org/oxycblt/auxio/AuxioService.kt b/app/src/main/java/org/oxycblt/auxio/AuxioService.kt index 09d6fd379..9c9ddd595 100644 --- a/app/src/main/java/org/oxycblt/auxio/AuxioService.kt +++ b/app/src/main/java/org/oxycblt/auxio/AuxioService.kt @@ -30,6 +30,7 @@ import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.app.ServiceCompat import androidx.media.MediaBrowserServiceCompat +import androidx.media.utils.MediaConstants import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject import org.oxycblt.auxio.music.service.MusicServiceFragment @@ -83,7 +84,12 @@ class AuxioService : clientPackageName: String, clientUid: Int, rootHints: Bundle? - ): BrowserRoot = musicFragment.getRoot() + ): BrowserRoot { + val maximumRootChildLimit = + rootHints?.getInt( + MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT, 4) ?: 4 + return musicFragment.getRoot(maximumRootChildLimit) + } override fun onLoadItem(itemId: String, result: Result) { musicFragment.getItem(itemId, result) diff --git a/app/src/main/java/org/oxycblt/auxio/music/service/Category.kt b/app/src/main/java/org/oxycblt/auxio/music/service/Category.kt new file mode 100644 index 000000000..c2babde29 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/service/Category.kt @@ -0,0 +1,94 @@ +package org.oxycblt.auxio.music.service + +import org.oxycblt.auxio.R + +sealed interface Category { + val id: String + val nameRes: Int + val bitmapRes: Int? + + data class Root(val amount: Int) : Category { + override val id = "root/$amount" + override val nameRes = R.string.info_app_name + override val bitmapRes = null + + companion object { + const val ID_PREFIX = "root" + + fun fromString(str: String): Root? { + val split = str.split("/", limit = 2) + if (split.size != 2) { + return null + } + val limit = split[1].toIntOrNull() ?: return null + return Root(limit) + } + } + } + + data class More(val remainder: Int) : Category { + override val id = "more/$remainder" + override val nameRes = R.string.lbl_more + override val bitmapRes = null + + companion object { + const val ID_PREFIX = "more" + + fun fromString(str: String): More? { + val split = str.split("/", limit = 2) + if (split.size != 2) { + return null + } + val remainder = split[1].toIntOrNull() ?: return null + return More(remainder) + } + } + } + + data object Songs : Category { + override val id = "songs" + override val nameRes = R.string.lbl_songs + override val bitmapRes = R.drawable.ic_song_bitmap_24 + } + + data object Albums : Category { + override val id = "albums" + override val nameRes = R.string.lbl_albums + override val bitmapRes = R.drawable.ic_album_bitmap_24 + } + + data object Artists : Category { + override val id = "artists" + override val nameRes = R.string.lbl_artists + override val bitmapRes = R.drawable.ic_artist_bitmap_24 + } + + data object Genres : Category { + override val id = "genres" + override val nameRes = R.string.lbl_genres + override val bitmapRes = R.drawable.ic_genre_bitmap_24 + } + + data object Playlists : Category { + override val id = "playlists" + override val nameRes = R.string.lbl_playlists + override val bitmapRes = R.drawable.ic_playlist_bitmap_24 + } + + companion object { + val MUSIC = arrayOf(Songs, Albums, Artists, Genres, Playlists) + val DEVICE_MUSIC = arrayOf(Songs, Albums, Artists, Genres) + val USER_MUSIC = arrayOf(Playlists) + fun fromString(str: String): Category? = + when { + str.startsWith(Root.ID_PREFIX) -> Root.fromString(str) + str.startsWith(More.ID_PREFIX) -> More.fromString(str) + str == Songs.id -> Songs + str == Albums.id -> Albums + str == Artists.id -> Artists + str == Genres.id -> Genres + str == Playlists.id -> Playlists + else -> null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt b/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt index e0354ba3a..b04afbc23 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt @@ -23,7 +23,6 @@ import android.graphics.BitmapFactory import android.os.Bundle import android.support.v4.media.MediaBrowserCompat.MediaItem import android.support.v4.media.MediaDescriptionCompat -import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.media.utils.MediaConstants import org.oxycblt.auxio.BuildConfig @@ -38,22 +37,6 @@ import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.util.getPlural -enum class Category(val id: String, @StringRes val nameRes: Int, @DrawableRes val bitmapRes: Int?) { - ROOT("root", R.string.info_app_name, null), - MORE("more", R.string.lbl_more, R.drawable.ic_more_24), - SONGS("songs", R.string.lbl_songs, R.drawable.ic_song_bitmap_24), - ALBUMS("albums", R.string.lbl_albums, R.drawable.ic_album_bitmap_24), - ARTISTS("artists", R.string.lbl_artists, R.drawable.ic_artist_bitmap_24), - GENRES("genres", R.string.lbl_genres, R.drawable.ic_genre_bitmap_24), - PLAYLISTS("playlists", R.string.lbl_playlists, R.drawable.ic_playlist_bitmap_24); - - companion object { - val DEVICE_MUSIC = listOf(ROOT, SONGS, ALBUMS, ARTISTS, GENRES) - val USER_MUSIC = listOf(ROOT, PLAYLISTS) - val IMPORTANT = listOf(SONGS, ALBUMS, ARTISTS, GENRES, PLAYLISTS) - } -} - sealed interface MediaSessionUID { data class CategoryItem(val category: Category) : MediaSessionUID { override fun toString() = "$ID_CATEGORY:$category" @@ -78,17 +61,7 @@ sealed interface MediaSessionUID { } return when (parts[0]) { ID_CATEGORY -> - CategoryItem( - when (parts[1]) { - Category.ROOT.id -> Category.ROOT - Category.MORE.id -> Category.MORE - Category.SONGS.id -> Category.SONGS - Category.ALBUMS.id -> Category.ALBUMS - Category.ARTISTS.id -> Category.ARTISTS - Category.GENRES.id -> Category.GENRES - Category.PLAYLISTS.id -> Category.PLAYLISTS - else -> return null - }) + CategoryItem(Category.fromString(parts[1]) ?: return null) ID_ITEM -> { val uids = parts[1].split(">", limit = 2) if (uids.size == 1) { @@ -113,7 +86,6 @@ fun header(@StringRes nameRes: Int): Sugar = { } fun Category.toMediaItem(context: Context): MediaItem { - // TODO: Make custom overflow menu for compat val extras = Bundle().apply { putInt( @@ -126,8 +98,8 @@ fun Category.toMediaItem(context: Context): MediaItem { .setMediaId(mediaSessionUID.toString()) .setTitle(context.getString(nameRes)) .setExtras(extras) - if (bitmapRes != null) { - val bitmap = BitmapFactory.decodeResource(context.resources, bitmapRes) + bitmapRes?.let { res -> + val bitmap = BitmapFactory.decodeResource(context.resources, res) description.setIconBitmap(bitmap) } return MediaItem(description.build(), MediaItem.FLAG_BROWSABLE) diff --git a/app/src/main/java/org/oxycblt/auxio/music/service/MusicBrowser.kt b/app/src/main/java/org/oxycblt/auxio/music/service/MusicBrowser.kt index a2008b0cc..576454204 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/service/MusicBrowser.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/service/MusicBrowser.kt @@ -172,27 +172,7 @@ constructor( ): List? { return when (val mediaSessionUID = MediaSessionUID.fromString(id)) { is MediaSessionUID.CategoryItem -> { - when (mediaSessionUID.category) { - Category.ROOT -> Category.IMPORTANT.map { it.toMediaItem(context) } - Category.MORE -> TODO() - Category.SONGS -> - listSettings.songSort.songs(deviceLibrary.songs).map { - it.toMediaItem(context, null) - } - Category.ALBUMS -> - listSettings.albumSort.albums(deviceLibrary.albums).map { - it.toMediaItem(context) - } - Category.ARTISTS -> - listSettings.artistSort.artists(deviceLibrary.artists).map { - it.toMediaItem(context) - } - Category.GENRES -> - listSettings.genreSort.genres(deviceLibrary.genres).map { - it.toMediaItem(context) - } - Category.PLAYLISTS -> userLibrary.playlists.map { it.toMediaItem(context) } - } + getCategoryMediaItems(mediaSessionUID.category, deviceLibrary, userLibrary) } is MediaSessionUID.SingleItem -> { getChildMediaItems(mediaSessionUID.uid) @@ -206,6 +186,38 @@ constructor( } } + private fun getCategoryMediaItems(category: Category, deviceLibrary: DeviceLibrary, userLibrary: UserLibrary) = + when (category) { + is Category.Root -> { + val base = Category.MUSIC.take(category.amount) + if (base.size < Category.MUSIC.size) { + base + Category.More(Category.MUSIC.size - base.size) + } else { + base + }.map { it.toMediaItem(context) } + } + is Category.More -> Category.MUSIC.takeLast(category.remainder).map { + it.toMediaItem(context) + } + is Category.Songs -> + listSettings.songSort.songs(deviceLibrary.songs).map { + it.toMediaItem(context, null) + } + is Category.Albums -> + listSettings.albumSort.albums(deviceLibrary.albums).map { + it.toMediaItem(context) + } + is Category.Artists -> + listSettings.artistSort.artists(deviceLibrary.artists).map { + it.toMediaItem(context) + } + is Category.Genres -> + listSettings.genreSort.genres(deviceLibrary.genres).map { + it.toMediaItem(context) + } + is Category.Playlists -> userLibrary.playlists.map { it.toMediaItem(context) } + } + private fun getChildMediaItems(uid: Music.UID): List? { return when (val item = musicRepository.find(uid)) { is Album -> { diff --git a/app/src/main/java/org/oxycblt/auxio/music/service/MusicServiceFragment.kt b/app/src/main/java/org/oxycblt/auxio/music/service/MusicServiceFragment.kt index eb37dd0ec..8d439b2c4 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/service/MusicServiceFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/service/MusicServiceFragment.kt @@ -76,7 +76,8 @@ constructor( indexer.createNotification(post) } - fun getRoot() = BrowserRoot(Category.ROOT.id, null) + fun getRoot(maxItems: Int) = + BrowserRoot(MediaSessionUID.CategoryItem(Category.Root(maxItems)).toString(), null) fun getItem(mediaId: String, result: Result) = result.dispatch { musicBrowser.getItem(mediaId) }