mirror of
https://github.com/antebudimir/tempus.git
synced 2026-01-01 09:53:33 +00:00
feat: test: Implemented initial functional version with Android Auto support
This commit is contained in:
parent
e8c7c065e2
commit
d6cc4fc028
8 changed files with 758 additions and 160 deletions
|
|
@ -2,17 +2,19 @@ package com.cappielloantonio.tempo.service
|
|||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.MediaItem.SubtitleConfiguration
|
||||
import androidx.media3.common.MediaMetadata
|
||||
import androidx.media3.session.LibraryResult
|
||||
import androidx.media3.session.MediaLibraryService
|
||||
import com.cappielloantonio.tempo.model.SessionMediaItem
|
||||
import com.cappielloantonio.tempo.repository.AutomotiveRepository
|
||||
import com.cappielloantonio.tempo.util.MusicUtil
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.google.common.util.concurrent.Futures
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.google.common.util.concurrent.SettableFuture
|
||||
import java.lang.Exception
|
||||
|
||||
object MediaBrowserTree {
|
||||
|
||||
|
|
@ -42,6 +44,8 @@ object MediaBrowserTree {
|
|||
|
||||
// Second level LIBRARY_ID
|
||||
private const val FOLDER_ID = "[folderID]"
|
||||
private const val INDEX_ID = "[indexID]"
|
||||
private const val DIRECTORY_ID = "[directoryID]"
|
||||
private const val PLAYLIST_ID = "[playlistID]"
|
||||
|
||||
// Second level OTHER_ID
|
||||
|
|
@ -343,7 +347,7 @@ object MediaBrowserTree {
|
|||
RECENTLY_ADDED_ID -> automotiveRepository.getAlbums(id, "newest", 100)
|
||||
BEST_OF_ID -> automotiveRepository.getStarredArtists(id, true)
|
||||
MADE_FOR_YOU_ID -> automotiveRepository.getStarredArtists(id, true)
|
||||
STARRED_TRACKS_ID -> automotiveRepository.getStarredSongs(id)
|
||||
STARRED_TRACKS_ID -> automotiveRepository.starredSongs
|
||||
STARRED_ALBUMS_ID -> automotiveRepository.getStarredAlbums(id)
|
||||
STARRED_ARTISTS_ID -> automotiveRepository.getStarredArtists(id, false)
|
||||
FOLDER_ID -> automotiveRepository.getMusicFolders(id)
|
||||
|
|
@ -359,7 +363,6 @@ object MediaBrowserTree {
|
|||
id.removePrefix(
|
||||
MOST_PLAYED_ID
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -368,7 +371,6 @@ object MediaBrowserTree {
|
|||
id.removePrefix(
|
||||
LAST_PLAYED_ID
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -377,7 +379,6 @@ object MediaBrowserTree {
|
|||
id.removePrefix(
|
||||
RECENTLY_ADDED_ID
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -390,11 +391,38 @@ object MediaBrowserTree {
|
|||
}
|
||||
|
||||
if (id.startsWith(FOLDER_ID)) {
|
||||
return automotiveRepository.getIndexes(
|
||||
INDEX_ID,
|
||||
id.removePrefix(
|
||||
FOLDER_ID
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (id.startsWith(INDEX_ID)) {
|
||||
return automotiveRepository.getDirectories(
|
||||
DIRECTORY_ID,
|
||||
id.removePrefix(
|
||||
INDEX_ID
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (id.startsWith(DIRECTORY_ID)) {
|
||||
return automotiveRepository.getDirectories(
|
||||
DIRECTORY_ID,
|
||||
id.removePrefix(
|
||||
DIRECTORY_ID
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (id.startsWith(PLAYLIST_ID)) {
|
||||
|
||||
return automotiveRepository.getPlaylistSongs(
|
||||
id.removePrefix(
|
||||
PLAYLIST_ID
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (id.startsWith(PODCAST_ID)) {
|
||||
|
|
@ -410,28 +438,27 @@ object MediaBrowserTree {
|
|||
}
|
||||
}
|
||||
|
||||
fun getItem(id: String): ListenableFuture<LibraryResult<MediaItem>> {
|
||||
val mediaMetadata = MediaMetadata.Builder()
|
||||
.setTitle("Titolo")
|
||||
.setAlbumTitle("Titolo album")
|
||||
.setArtist("Artista")
|
||||
.setIsBrowsable(false)
|
||||
.setIsPlayable(true)
|
||||
.setMediaType(MediaMetadata.MEDIA_TYPE_MUSIC)
|
||||
.build()
|
||||
// https://github.com/androidx/media/issues/156
|
||||
fun getItems(mediaItems: List<MediaItem>): List<MediaItem> {
|
||||
val updatedMediaItems = ArrayList<MediaItem>()
|
||||
|
||||
val mediaItem = MediaItem.Builder()
|
||||
.setMediaId(id)
|
||||
.setMediaMetadata(mediaMetadata)
|
||||
.setUri(MusicUtil.getStreamUri(id))
|
||||
.build()
|
||||
mediaItems.forEach {
|
||||
if (it.localConfiguration?.uri != null) {
|
||||
updatedMediaItems.add(it)
|
||||
} else {
|
||||
val sessionMediaItem = automotiveRepository.getSessionMediaItem(it.mediaId)
|
||||
|
||||
return Futures.immediateFuture(LibraryResult.ofItem(mediaItem, null))
|
||||
if (sessionMediaItem != null) {
|
||||
var toAdd = automotiveRepository.getMetadatas(sessionMediaItem.timestamp!!)
|
||||
val index = toAdd.indexOfFirst { mediaItem -> mediaItem.mediaId == it.mediaId }
|
||||
|
||||
/* if (treeNodes[id]?.item != null) {
|
||||
return Futures.immediateFuture(LibraryResult.ofItem(treeNodes[id]!!.item, null))
|
||||
toAdd = toAdd.subList(index, toAdd.size)
|
||||
|
||||
updatedMediaItems.addAll(toAdd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Futures.immediateFuture(LibraryResult.ofError(LibraryResult.RESULT_ERROR_BAD_VALUE)) */
|
||||
return updatedMediaItems
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,91 +121,17 @@ open class MediaLibrarySessionCallback(
|
|||
return MediaBrowserTree.getChildren(parentId, params)
|
||||
}
|
||||
|
||||
/* override fun onGetItem(
|
||||
session: MediaLibraryService.MediaLibrarySession,
|
||||
browser: MediaSession.ControllerInfo,
|
||||
mediaId: String
|
||||
): ListenableFuture<LibraryResult<MediaItem>> {
|
||||
Log.d(TAG, "onGetItem()")
|
||||
|
||||
return MediaBrowserTree.getItem(mediaId)
|
||||
} */
|
||||
|
||||
/* override fun onAddMediaItems(
|
||||
override fun onAddMediaItems(
|
||||
mediaSession: MediaSession,
|
||||
controller: MediaSession.ControllerInfo,
|
||||
mediaItems: List<MediaItem>
|
||||
): ListenableFuture<List<MediaItem>> {
|
||||
Log.d(TAG, "onAddMediaItems()")
|
||||
|
||||
return Futures.immediateFuture(mediaItems)
|
||||
}
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
override fun onSetMediaItems(
|
||||
mediaSession: MediaSession,
|
||||
browser: MediaSession.ControllerInfo,
|
||||
mediaItems: List<MediaItem>,
|
||||
startIndex: Int,
|
||||
startPositionMs: Long
|
||||
): ListenableFuture<MediaSession.MediaItemsWithStartPosition> {
|
||||
Log.d(TAG, "onSetMediaItems()")
|
||||
|
||||
val mediaItemss: MutableList<MediaItem> = ArrayList()
|
||||
|
||||
val mediaMetadata = MediaMetadata.Builder()
|
||||
.setTitle("Titolo")
|
||||
.setAlbumTitle("Titolo album")
|
||||
.setArtist("Artista")
|
||||
.setIsBrowsable(false)
|
||||
.setIsPlayable(true)
|
||||
.setMediaType(MediaMetadata.MEDIA_TYPE_MUSIC)
|
||||
.build()
|
||||
|
||||
val mediaItem = MediaItem.Builder()
|
||||
.setMediaId(mediaItems.get(0).mediaId)
|
||||
.setMediaMetadata(mediaMetadata)
|
||||
.setUri(MusicUtil.getStreamUri(mediaItems.get(0).mediaId))
|
||||
.build()
|
||||
|
||||
mediaItemss.add(mediaItem)
|
||||
|
||||
return Futures.immediateFuture(
|
||||
MediaSession.MediaItemsWithStartPosition(
|
||||
mediaItemss, 0, 0
|
||||
)
|
||||
return super.onAddMediaItems(
|
||||
mediaSession,
|
||||
controller,
|
||||
MediaBrowserTree.getItems(mediaItems)
|
||||
)
|
||||
} */
|
||||
|
||||
/* @OptIn(UnstableApi::class) // MediaSession.MediaItemsWithStartPosition
|
||||
private fun maybeExpandSingleItemToPlaylist(
|
||||
mediaItem: MediaItem, startIndex: Int, startPositionMs: Long
|
||||
): MediaSession.MediaItemsWithStartPosition? {
|
||||
var playlist = listOf<MediaItem>()
|
||||
var indexInPlaylist = startIndex
|
||||
|
||||
MediaBrowserTree.getItem(mediaItem.mediaId)?.apply {
|
||||
if (mediaMetadata.isBrowsable == true) {
|
||||
playlist = MediaBrowserTree.getChildren(mediaId)
|
||||
} else if (requestMetadata.searchQuery == null) {
|
||||
MediaBrowserTree.getParentId(mediaId)?.let {
|
||||
playlist = MediaBrowserTree.getChildren(it).map { mediaItem ->
|
||||
if (mediaItem.mediaId == mediaId) MediaBrowserTree.expandItem(mediaItem)!! else mediaItem
|
||||
}
|
||||
|
||||
indexInPlaylist = MediaBrowserTree.getIndexInMediaItems(mediaId, playlist)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (playlist.isNotEmpty()) {
|
||||
return MediaSession.MediaItemsWithStartPosition(
|
||||
playlist, indexInPlaylist, startPositionMs
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
} */
|
||||
}
|
||||
|
||||
/* override fun onSearch(
|
||||
session: MediaLibraryService.MediaLibrarySession,
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
|
|||
if (this::castPlayer.isInitialized) castPlayer.release()
|
||||
player.release()
|
||||
mediaLibrarySession.release()
|
||||
automotiveRepository.deleteMetadata()
|
||||
clearListener()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue