mirror of
https://gitlab.com/ultrasonic/ultrasonic.git
synced 2025-05-02 16:41:33 +03:00
working version
This commit is contained in:
parent
3853fce818
commit
793c4a6ca7
@ -18,7 +18,7 @@ class AlbumListModel(application: Application) : GenericListModel(application) {
|
|||||||
|
|
||||||
fun getAlbumList(
|
fun getAlbumList(
|
||||||
refresh: Boolean,
|
refresh: Boolean,
|
||||||
swipe: SwipeRefreshLayout,
|
swipe: SwipeRefreshLayout?,
|
||||||
args: Bundle
|
args: Bundle
|
||||||
): LiveData<List<MusicDirectory.Entry>> {
|
): LiveData<List<MusicDirectory.Entry>> {
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ import org.moire.ultrasonic.service.MusicService
|
|||||||
* Provides ViewModel which contains the list of available Artists
|
* Provides ViewModel which contains the list of available Artists
|
||||||
*/
|
*/
|
||||||
class ArtistListModel(application: Application) : GenericListModel(application) {
|
class ArtistListModel(application: Application) : GenericListModel(application) {
|
||||||
private val artists: MutableLiveData<List<Artist>> = MutableLiveData()
|
val artists: MutableLiveData<List<Artist>> = MutableLiveData()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves all available Artists in a LiveData
|
* Retrieves all available Artists in a LiveData
|
||||||
*/
|
*/
|
||||||
fun getItems(refresh: Boolean, swipe: SwipeRefreshLayout): LiveData<List<Artist>> {
|
fun getItems(refresh: Boolean, swipe: SwipeRefreshLayout?): LiveData<List<Artist>> {
|
||||||
backgroundLoadFromServer(refresh, swipe)
|
backgroundLoadFromServer(refresh, swipe)
|
||||||
return artists
|
return artists
|
||||||
}
|
}
|
||||||
|
@ -66,20 +66,24 @@ open class GenericListModel(application: Application) :
|
|||||||
*/
|
*/
|
||||||
fun backgroundLoadFromServer(
|
fun backgroundLoadFromServer(
|
||||||
refresh: Boolean,
|
refresh: Boolean,
|
||||||
swipe: SwipeRefreshLayout,
|
swipe: SwipeRefreshLayout?,
|
||||||
bundle: Bundle = Bundle()
|
bundle: Bundle = Bundle()
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
swipe.isRefreshing = true
|
if (swipe != null) {
|
||||||
|
swipe.isRefreshing = true
|
||||||
|
}
|
||||||
loadFromServer(refresh, swipe, bundle)
|
loadFromServer(refresh, swipe, bundle)
|
||||||
swipe.isRefreshing = false
|
if (swipe != null) {
|
||||||
|
swipe.isRefreshing = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls the load() function with error handling
|
* Calls the load() function with error handling
|
||||||
*/
|
*/
|
||||||
suspend fun loadFromServer(refresh: Boolean, swipe: SwipeRefreshLayout, bundle: Bundle) =
|
suspend fun loadFromServer(refresh: Boolean, swipe: SwipeRefreshLayout?, bundle: Bundle) =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val musicService = MusicServiceFactory.getMusicService()
|
val musicService = MusicServiceFactory.getMusicService()
|
||||||
val isOffline = ActiveServerProvider.isOffline()
|
val isOffline = ActiveServerProvider.isOffline()
|
||||||
@ -88,7 +92,9 @@ open class GenericListModel(application: Application) :
|
|||||||
try {
|
try {
|
||||||
load(isOffline, useId3Tags, musicService, refresh, bundle)
|
load(isOffline, useId3Tags, musicService, refresh, bundle)
|
||||||
} catch (all: Exception) {
|
} catch (all: Exception) {
|
||||||
handleException(all, swipe.context)
|
if (swipe != null) {
|
||||||
|
handleException(all, swipe.context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,8 +61,8 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
|
|||||||
private val localMediaPlayer by inject<LocalMediaPlayer>()
|
private val localMediaPlayer by inject<LocalMediaPlayer>()
|
||||||
private val nowPlayingEventDistributor by inject<NowPlayingEventDistributor>()
|
private val nowPlayingEventDistributor by inject<NowPlayingEventDistributor>()
|
||||||
private val mediaPlayerLifecycleSupport by inject<MediaPlayerLifecycleSupport>()
|
private val mediaPlayerLifecycleSupport by inject<MediaPlayerLifecycleSupport>()
|
||||||
private val autoMediaBrowser: AndroidAutoMediaBrowser = AndroidAutoMediaBrowser()
|
|
||||||
|
|
||||||
|
private var autoMediaBrowser: AndroidAutoMediaBrowser? = null
|
||||||
private var mediaSession: MediaSessionCompat? = null
|
private var mediaSession: MediaSessionCompat? = null
|
||||||
private var isInForeground = false
|
private var isInForeground = false
|
||||||
private var notificationBuilder: NotificationCompat.Builder? = null
|
private var notificationBuilder: NotificationCompat.Builder? = null
|
||||||
@ -73,6 +73,7 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
|
|||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
|
autoMediaBrowser = AndroidAutoMediaBrowser(application)
|
||||||
updateMediaSession(null, PlayerState.IDLE)
|
updateMediaSession(null, PlayerState.IDLE)
|
||||||
|
|
||||||
downloader.onCreate()
|
downloader.onCreate()
|
||||||
@ -140,14 +141,14 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
|
|||||||
clientUid: Int,
|
clientUid: Int,
|
||||||
rootHints: Bundle?
|
rootHints: Bundle?
|
||||||
): MediaBrowserServiceCompat.BrowserRoot {
|
): MediaBrowserServiceCompat.BrowserRoot {
|
||||||
return autoMediaBrowser.getRoot(clientPackageName, clientUid, rootHints)
|
return autoMediaBrowser!!.getRoot(clientPackageName, clientUid, rootHints)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLoadChildren(
|
override fun onLoadChildren(
|
||||||
parentMediaId: String,
|
parentMediaId: String,
|
||||||
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
||||||
) {
|
) {
|
||||||
autoMediaBrowser.loadChildren(parentMediaId, result)
|
autoMediaBrowser!!.loadChildren(parentMediaId, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@ -832,12 +833,20 @@ class MediaPlayerService : MediaBrowserServiceCompat() {
|
|||||||
override fun onPlayFromMediaId(mediaId: String?, extras: Bundle?) {
|
override fun onPlayFromMediaId(mediaId: String?, extras: Bundle?) {
|
||||||
super.onPlayFromMediaId(mediaId, extras)
|
super.onPlayFromMediaId(mediaId, extras)
|
||||||
|
|
||||||
val item: MusicDirectory.Entry? = autoMediaBrowser.getMusicDirectoryEntry(extras)
|
val result = autoMediaBrowser!!.getBundleData(extras)
|
||||||
if (item != null) {
|
if (result != null) {
|
||||||
|
val mediaId = result.first
|
||||||
|
val directoryList = result.second
|
||||||
|
|
||||||
resetPlayback()
|
resetPlayback()
|
||||||
val songs: MutableList<MusicDirectory.Entry> = mutableListOf()
|
val songs: MutableList<MusicDirectory.Entry> = mutableListOf()
|
||||||
songs.add(item)
|
var found = false
|
||||||
|
for (item in directoryList) {
|
||||||
|
if (found || item.id == mediaId) {
|
||||||
|
found = true
|
||||||
|
songs.add(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
downloader.download(songs, false, false, false, true)
|
downloader.download(songs, false, false, false, true)
|
||||||
|
|
||||||
getPendingIntentForMediaAction(
|
getPendingIntentForMediaAction(
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package org.moire.ultrasonic.util
|
package org.moire.ultrasonic.util
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.media.MediaBrowserCompat
|
import android.support.v4.media.MediaBrowserCompat
|
||||||
import android.support.v4.media.MediaDescriptionCompat
|
import android.support.v4.media.MediaDescriptionCompat
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
import androidx.media.MediaBrowserServiceCompat
|
import androidx.media.MediaBrowserServiceCompat
|
||||||
import androidx.media.utils.MediaConstants
|
import androidx.media.utils.MediaConstants
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
@ -12,28 +15,124 @@ import java.io.ObjectOutputStream
|
|||||||
import java.util.concurrent.ExecutorService
|
import java.util.concurrent.ExecutorService
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import org.moire.ultrasonic.api.subsonic.models.AlbumListType
|
import org.moire.ultrasonic.api.subsonic.models.AlbumListType
|
||||||
import org.moire.ultrasonic.domain.Genre
|
import org.moire.ultrasonic.domain.Artist
|
||||||
import org.moire.ultrasonic.domain.MusicDirectory
|
import org.moire.ultrasonic.domain.MusicDirectory
|
||||||
|
import org.moire.ultrasonic.fragment.AlbumListModel
|
||||||
|
import org.moire.ultrasonic.fragment.ArtistListModel
|
||||||
import org.moire.ultrasonic.service.MusicServiceFactory
|
import org.moire.ultrasonic.service.MusicServiceFactory
|
||||||
|
|
||||||
class AndroidAutoMediaBrowser() {
|
class AndroidAutoMediaBrowser(application: Application) {
|
||||||
|
|
||||||
|
val albumListModel: AlbumListModel = AlbumListModel(application)
|
||||||
|
val artistListModel: ArtistListModel = ArtistListModel(application)
|
||||||
|
|
||||||
val executorService: ExecutorService = Executors.newFixedThreadPool(4)
|
val executorService: ExecutorService = Executors.newFixedThreadPool(4)
|
||||||
var maximumRootChildLimit: Int = 4
|
var maximumRootChildLimit: Int = 4
|
||||||
|
|
||||||
private val MEDIA_BROWSER_ROOT_ID = "_Ultrasonice_mb_root_"
|
private val MEDIA_BROWSER_ROOT_ID = "_Ultrasonice_mb_root_"
|
||||||
|
|
||||||
private val MEDIA_BROWSER_GENRE_LIST_ROOT = "_Ultrasonic_mb_genre_list_root_"
|
|
||||||
private val MEDIA_BROWSER_RECENT_LIST_ROOT = "_Ultrasonic_mb_recent_list_root_"
|
private val MEDIA_BROWSER_RECENT_LIST_ROOT = "_Ultrasonic_mb_recent_list_root_"
|
||||||
private val MEDIA_BROWSER_ALBUM_LIST_ROOT = "_Ultrasonic_mb_album_list_root_"
|
private val MEDIA_BROWSER_ALBUM_LIST_ROOT = "_Ultrasonic_mb_album_list_root_"
|
||||||
private val MEDIA_BROWSER_ARTIST_LIST_ROOT = "_Ultrasonic_mb_rtist_list_root_"
|
private val MEDIA_BROWSER_ARTIST_LIST_ROOT = "_Ultrasonic_mb_rtist_list_root_"
|
||||||
|
|
||||||
private val MEDIA_BROWSER_GENRE_PREFIX = "_Ultrasonic_mb_genre_prefix_"
|
|
||||||
private val MEDIA_BROWSER_RECENT_PREFIX = "_Ultrasonic_mb_recent_prefix_"
|
private val MEDIA_BROWSER_RECENT_PREFIX = "_Ultrasonic_mb_recent_prefix_"
|
||||||
private val MEDIA_BROWSER_ALBUM_PREFIX = "_Ultrasonic_mb_album_prefix_"
|
private val MEDIA_BROWSER_ALBUM_PREFIX = "_Ultrasonic_mb_album_prefix_"
|
||||||
private val MEDIA_BROWSER_ARTIST_PREFIX = "_Ultrasonic_mb_artist_prefix_"
|
private val MEDIA_BROWSER_ARTIST_PREFIX = "_Ultrasonic_mb_artist_prefix_"
|
||||||
|
|
||||||
private val MEDIA_BROWSER_EXTRA_ENTRY_BYTES = "_Ultrasonic_mb_extra_entry_bytes_"
|
private val MEDIA_BROWSER_EXTRA_ALBUM_LIST = "_Ultrasonic_mb_extra_album_list_"
|
||||||
|
private val MEDIA_BROWSER_EXTRA_MEDIA_ID = "_Ultrasonic_mb_extra_media_id_"
|
||||||
|
|
||||||
|
class AlbumListObserver(
|
||||||
|
val idPrefix: String,
|
||||||
|
val result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>,
|
||||||
|
data: LiveData<List<MusicDirectory.Entry>>
|
||||||
|
) :
|
||||||
|
Observer<List<MusicDirectory.Entry>> {
|
||||||
|
|
||||||
|
private var liveData: LiveData<List<MusicDirectory.Entry>>? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
// Order is very important here. When observerForever is called onChanged
|
||||||
|
// will immediately be called with any past data updates. We don't care
|
||||||
|
// about those. So by having it called *before* liveData is set will
|
||||||
|
// signal to onChanged to ignore the first input
|
||||||
|
data.observeForever(this)
|
||||||
|
liveData = data
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onChanged(albumList: List<MusicDirectory.Entry>?) {
|
||||||
|
if (liveData == null) {
|
||||||
|
// See comment in the initializer
|
||||||
|
return
|
||||||
|
}
|
||||||
|
liveData!!.removeObserver(this)
|
||||||
|
if (albumList == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
||||||
|
for (item in albumList) {
|
||||||
|
val entryBuilder: MediaDescriptionCompat.Builder =
|
||||||
|
MediaDescriptionCompat.Builder()
|
||||||
|
entryBuilder
|
||||||
|
.setTitle(item.title)
|
||||||
|
.setMediaId(idPrefix + item.id)
|
||||||
|
mediaItems.add(
|
||||||
|
MediaBrowserCompat.MediaItem(
|
||||||
|
entryBuilder.build(),
|
||||||
|
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.sendResult(mediaItems)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ArtistListObserver(
|
||||||
|
val idPrefix: String,
|
||||||
|
val result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>,
|
||||||
|
data: LiveData<List<Artist>>
|
||||||
|
) :
|
||||||
|
Observer<List<Artist>> {
|
||||||
|
|
||||||
|
private var liveData: LiveData<List<Artist>>? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
// Order is very important here. When observerForever is called onChanged
|
||||||
|
// will immediately be called with any past data updates. We don't care
|
||||||
|
// about those. So by having it called *before* liveData is set will
|
||||||
|
// signal to onChanged to ignore the first input
|
||||||
|
data.observeForever(this)
|
||||||
|
liveData = data
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onChanged(artistList: List<Artist>?) {
|
||||||
|
if (liveData == null) {
|
||||||
|
// See comment in the initializer
|
||||||
|
return
|
||||||
|
}
|
||||||
|
liveData!!.removeObserver(this)
|
||||||
|
if (artistList == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
||||||
|
for (item in artistList) {
|
||||||
|
val entryBuilder: MediaDescriptionCompat.Builder =
|
||||||
|
MediaDescriptionCompat.Builder()
|
||||||
|
entryBuilder
|
||||||
|
.setTitle(item.name)
|
||||||
|
.setMediaId(idPrefix + item.id)
|
||||||
|
mediaItems.add(
|
||||||
|
MediaBrowserCompat.MediaItem(
|
||||||
|
entryBuilder.build(),
|
||||||
|
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.sendResult(mediaItems)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getRoot(
|
fun getRoot(
|
||||||
clientPackageName: String,
|
clientPackageName: String,
|
||||||
@ -65,14 +164,6 @@ class AndroidAutoMediaBrowser() {
|
|||||||
// Build the MediaItem objects for the top level,
|
// Build the MediaItem objects for the top level,
|
||||||
// and put them in the mediaItems list...
|
// and put them in the mediaItems list...
|
||||||
|
|
||||||
var genreList: MediaDescriptionCompat.Builder = MediaDescriptionCompat.Builder()
|
|
||||||
genreList.setTitle("Genre").setMediaId(MEDIA_BROWSER_GENRE_LIST_ROOT)
|
|
||||||
mediaItems.add(
|
|
||||||
MediaBrowserCompat.MediaItem(
|
|
||||||
genreList.build(),
|
|
||||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
var recentList: MediaDescriptionCompat.Builder = MediaDescriptionCompat.Builder()
|
var recentList: MediaDescriptionCompat.Builder = MediaDescriptionCompat.Builder()
|
||||||
recentList.setTitle("Recent").setMediaId(MEDIA_BROWSER_RECENT_LIST_ROOT)
|
recentList.setTitle("Recent").setMediaId(MEDIA_BROWSER_RECENT_LIST_ROOT)
|
||||||
mediaItems.add(
|
mediaItems.add(
|
||||||
@ -97,9 +188,6 @@ class AndroidAutoMediaBrowser() {
|
|||||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else if (MEDIA_BROWSER_GENRE_LIST_ROOT == parentMediaId) {
|
|
||||||
fetchGenres(result)
|
|
||||||
return
|
|
||||||
} else if (MEDIA_BROWSER_RECENT_LIST_ROOT == parentMediaId) {
|
} else if (MEDIA_BROWSER_RECENT_LIST_ROOT == parentMediaId) {
|
||||||
fetchAlbumList(AlbumListType.RECENT, MEDIA_BROWSER_RECENT_PREFIX, result)
|
fetchAlbumList(AlbumListType.RECENT, MEDIA_BROWSER_RECENT_PREFIX, result)
|
||||||
return
|
return
|
||||||
@ -107,43 +195,19 @@ class AndroidAutoMediaBrowser() {
|
|||||||
fetchAlbumList(AlbumListType.SORTED_BY_NAME, MEDIA_BROWSER_ALBUM_PREFIX, result)
|
fetchAlbumList(AlbumListType.SORTED_BY_NAME, MEDIA_BROWSER_ALBUM_PREFIX, result)
|
||||||
return
|
return
|
||||||
} else if (MEDIA_BROWSER_ARTIST_LIST_ROOT == parentMediaId) {
|
} else if (MEDIA_BROWSER_ARTIST_LIST_ROOT == parentMediaId) {
|
||||||
fetchAlbumList(AlbumListType.SORTED_BY_ARTIST, MEDIA_BROWSER_ARTIST_PREFIX, result)
|
fetchArtistList(MEDIA_BROWSER_ARTIST_PREFIX, result)
|
||||||
|
return
|
||||||
|
} else if (parentMediaId.startsWith(MEDIA_BROWSER_RECENT_PREFIX)) {
|
||||||
|
fetchTrackList(parentMediaId.substring(MEDIA_BROWSER_RECENT_PREFIX.length), result)
|
||||||
return
|
return
|
||||||
} else if (parentMediaId.startsWith(MEDIA_BROWSER_ALBUM_PREFIX)) {
|
} else if (parentMediaId.startsWith(MEDIA_BROWSER_ALBUM_PREFIX)) {
|
||||||
executorService.execute {
|
fetchTrackList(parentMediaId.substring(MEDIA_BROWSER_ALBUM_PREFIX.length), result)
|
||||||
val musicService = MusicServiceFactory.getMusicService()
|
return
|
||||||
val id = parentMediaId.substring(MEDIA_BROWSER_ALBUM_PREFIX.length)
|
} else if (parentMediaId.startsWith(MEDIA_BROWSER_ARTIST_PREFIX)) {
|
||||||
|
fetchArtistAlbumList(
|
||||||
val albumDirectory = musicService.getAlbum(
|
parentMediaId.substring(MEDIA_BROWSER_ARTIST_PREFIX.length),
|
||||||
id, "", false
|
result
|
||||||
)
|
)
|
||||||
for (item in albumDirectory.getAllChild()) {
|
|
||||||
val extras = Bundle()
|
|
||||||
|
|
||||||
// Note that Bundle supports putSerializable and MusicDirectory.Entry
|
|
||||||
// implements Serializable, but when I try to use it the app crashes
|
|
||||||
val byteArrayOutputStream = ByteArrayOutputStream()
|
|
||||||
val objectOutputStream = ObjectOutputStream(byteArrayOutputStream)
|
|
||||||
objectOutputStream.writeObject(item)
|
|
||||||
objectOutputStream.close()
|
|
||||||
extras.putByteArray(
|
|
||||||
MEDIA_BROWSER_EXTRA_ENTRY_BYTES,
|
|
||||||
byteArrayOutputStream.toByteArray()
|
|
||||||
)
|
|
||||||
|
|
||||||
val entryBuilder: MediaDescriptionCompat.Builder =
|
|
||||||
MediaDescriptionCompat.Builder()
|
|
||||||
entryBuilder.setTitle(item.title).setMediaId(item.id).setExtras(extras)
|
|
||||||
mediaItems.add(
|
|
||||||
MediaBrowserCompat.MediaItem(
|
|
||||||
entryBuilder.build(),
|
|
||||||
MediaBrowserCompat.MediaItem.FLAG_PLAYABLE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
result.sendResult(mediaItems)
|
|
||||||
}
|
|
||||||
result.detach()
|
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
// Examine the passed parentMediaId to see which submenu we're at,
|
// Examine the passed parentMediaId to see which submenu we're at,
|
||||||
@ -152,39 +216,67 @@ class AndroidAutoMediaBrowser() {
|
|||||||
result.sendResult(mediaItems)
|
result.sendResult(mediaItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMusicDirectoryEntry(bundle: Bundle?): MusicDirectory.Entry? {
|
fun getBundleData(bundle: Bundle?): Pair<String, List<MusicDirectory.Entry>>? {
|
||||||
if (bundle == null) {
|
if (bundle == null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bundle.containsKey(MEDIA_BROWSER_EXTRA_ENTRY_BYTES)) {
|
if (!bundle.containsKey(MEDIA_BROWSER_EXTRA_ALBUM_LIST) ||
|
||||||
|
!bundle.containsKey(MEDIA_BROWSER_EXTRA_MEDIA_ID)
|
||||||
|
) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val bytes = bundle.getByteArray(MEDIA_BROWSER_EXTRA_ENTRY_BYTES)
|
val bytes = bundle.getByteArray(MEDIA_BROWSER_EXTRA_ALBUM_LIST)
|
||||||
val byteArrayInputStream = ByteArrayInputStream(bytes)
|
val byteArrayInputStream = ByteArrayInputStream(bytes)
|
||||||
val objectInputStream = ObjectInputStream(byteArrayInputStream)
|
val objectInputStream = ObjectInputStream(byteArrayInputStream)
|
||||||
return objectInputStream.readObject() as MusicDirectory.Entry
|
return Pair(
|
||||||
|
bundle.getString(MEDIA_BROWSER_EXTRA_MEDIA_ID),
|
||||||
|
objectInputStream.readObject() as List<MusicDirectory.Entry>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fetchAlbumList(
|
private fun fetchAlbumList(
|
||||||
type: AlbumListType,
|
type: AlbumListType,
|
||||||
idPrefix: String,
|
idPrefix: String,
|
||||||
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
||||||
|
) {
|
||||||
|
AlbumListObserver(
|
||||||
|
idPrefix, result,
|
||||||
|
albumListModel.albumList
|
||||||
|
)
|
||||||
|
|
||||||
|
val args: Bundle = Bundle()
|
||||||
|
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type.toString())
|
||||||
|
albumListModel.getAlbumList(false, null, args)
|
||||||
|
result.detach()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetchArtistList(
|
||||||
|
idPrefix: String,
|
||||||
|
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
||||||
|
) {
|
||||||
|
ArtistListObserver(idPrefix, result, artistListModel.artists)
|
||||||
|
|
||||||
|
artistListModel.getItems(false, null)
|
||||||
|
result.detach()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetchArtistAlbumList(
|
||||||
|
id: String,
|
||||||
|
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
||||||
) {
|
) {
|
||||||
executorService.execute {
|
executorService.execute {
|
||||||
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
|
||||||
val musicService = MusicServiceFactory.getMusicService()
|
val musicService = MusicServiceFactory.getMusicService()
|
||||||
|
|
||||||
val musicDirectory: MusicDirectory = musicService.getAlbumList2(
|
val musicDirectory = musicService.getMusicDirectory(
|
||||||
type.toString(), 500, 0, null
|
id, "", false
|
||||||
)
|
)
|
||||||
|
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
||||||
|
|
||||||
for (item in musicDirectory.getAllChild()) {
|
for (item in musicDirectory.getAllChild()) {
|
||||||
var entryBuilder: MediaDescriptionCompat.Builder =
|
val entryBuilder: MediaDescriptionCompat.Builder =
|
||||||
MediaDescriptionCompat.Builder()
|
MediaDescriptionCompat.Builder()
|
||||||
entryBuilder
|
entryBuilder.setTitle(item.title).setMediaId(MEDIA_BROWSER_ALBUM_PREFIX + item.id)
|
||||||
.setTitle(item.title)
|
|
||||||
.setMediaId(idPrefix + item.id)
|
|
||||||
mediaItems.add(
|
mediaItems.add(
|
||||||
MediaBrowserCompat.MediaItem(
|
MediaBrowserCompat.MediaItem(
|
||||||
entryBuilder.build(),
|
entryBuilder.build(),
|
||||||
@ -197,26 +289,48 @@ class AndroidAutoMediaBrowser() {
|
|||||||
result.detach()
|
result.detach()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fetchGenres(result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>) {
|
private fun fetchTrackList(
|
||||||
|
id: String,
|
||||||
|
result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>
|
||||||
|
) {
|
||||||
executorService.execute {
|
executorService.execute {
|
||||||
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
|
||||||
val musicService = MusicServiceFactory.getMusicService()
|
val musicService = MusicServiceFactory.getMusicService()
|
||||||
|
|
||||||
val genreList: List<Genre>? = musicService.getGenres(false)
|
val albumDirectory = musicService.getAlbum(
|
||||||
if (genreList != null) {
|
id, "", false
|
||||||
for (genre in genreList) {
|
)
|
||||||
var entryBuilder: MediaDescriptionCompat.Builder =
|
|
||||||
MediaDescriptionCompat.Builder()
|
// The idea here is that we want to attach the full album list to every song,
|
||||||
entryBuilder
|
// as well as the id of the specific song. This way if someone chooses to play a song
|
||||||
.setTitle(genre.name)
|
// we can add the song and all subsequent songs in the album
|
||||||
.setMediaId(MEDIA_BROWSER_GENRE_PREFIX + genre.index)
|
val byteArrayOutputStream = ByteArrayOutputStream()
|
||||||
mediaItems.add(
|
val objectOutputStream = ObjectOutputStream(byteArrayOutputStream)
|
||||||
MediaBrowserCompat.MediaItem(
|
objectOutputStream.writeObject(albumDirectory.getAllChild())
|
||||||
entryBuilder.build(),
|
objectOutputStream.close()
|
||||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
val songList = byteArrayOutputStream.toByteArray()
|
||||||
)
|
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
||||||
|
|
||||||
|
for (item in albumDirectory.getAllChild()) {
|
||||||
|
val extras = Bundle()
|
||||||
|
|
||||||
|
extras.putByteArray(
|
||||||
|
MEDIA_BROWSER_EXTRA_ALBUM_LIST,
|
||||||
|
songList
|
||||||
|
)
|
||||||
|
extras.putString(
|
||||||
|
MEDIA_BROWSER_EXTRA_MEDIA_ID,
|
||||||
|
item.id
|
||||||
|
)
|
||||||
|
|
||||||
|
val entryBuilder: MediaDescriptionCompat.Builder =
|
||||||
|
MediaDescriptionCompat.Builder()
|
||||||
|
entryBuilder.setTitle(item.title).setMediaId(item.id).setExtras(extras)
|
||||||
|
mediaItems.add(
|
||||||
|
MediaBrowserCompat.MediaItem(
|
||||||
|
entryBuilder.build(),
|
||||||
|
MediaBrowserCompat.MediaItem.FLAG_PLAYABLE
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
result.sendResult(mediaItems)
|
result.sendResult(mediaItems)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user