Skip to content

Commit de116e3

Browse files
committed
Android Auto: Added Albums, Podcasts, Radio, fixed initial loading, play mode and shuffle. Closes #70
1 parent b80608d commit de116e3

1 file changed

Lines changed: 98 additions & 5 deletions

File tree

  • composeApp/src/androidMain/kotlin/io/music_assistant/client/auto

composeApp/src/androidMain/kotlin/io/music_assistant/client/auto/AutoLibrary.kt

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import io.music_assistant.client.data.model.server.MediaType
2020
import io.music_assistant.client.data.model.server.QueueOption
2121
import io.music_assistant.client.data.model.server.SearchResult
2222
import io.music_assistant.client.data.model.server.ServerMediaItem
23+
import io.music_assistant.client.utils.DataConnectionState
2324
import io.music_assistant.client.utils.SessionState
2425
import io.music_assistant.client.utils.resultAs
2526
import kotlinx.coroutines.CoroutineScope
@@ -29,6 +30,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
2930
import kotlinx.coroutines.flow.debounce
3031
import kotlinx.coroutines.flow.filter
3132
import kotlinx.coroutines.flow.filterNotNull
33+
import kotlinx.coroutines.flow.first
34+
import kotlinx.coroutines.flow.mapNotNull
3235
import kotlinx.coroutines.flow.update
3336
import kotlinx.coroutines.launch
3437

@@ -57,7 +60,9 @@ class AutoLibrary(
5760
MediaType.ARTIST,
5861
MediaType.ALBUM,
5962
MediaType.TRACK,
60-
MediaType.PLAYLIST
63+
MediaType.PLAYLIST,
64+
MediaType.PODCAST,
65+
MediaType.RADIO
6166
),
6267
libraryOnly = false
6368
)
@@ -84,14 +89,22 @@ class AutoLibrary(
8489
result.sendResult(
8590
listOf(
8691
rootTabItem("Artists", MediaIds.TAB_ARTISTS),
87-
rootTabItem("Playlists", MediaIds.TAB_PLAYLISTS)
92+
rootTabItem("Albums", MediaIds.TAB_ALBUMS),
93+
rootTabItem("Playlists", MediaIds.TAB_PLAYLISTS),
94+
rootTabItem("Podcasts", MediaIds.TAB_PODCASTS),
95+
rootTabItem("Radio", MediaIds.TAB_RADIO)
8896
)
8997
)
9098
}
9199

92100
MediaIds.TAB_ARTISTS -> {
93101
result.detach()
94102
scope.launch {
103+
// Block until authenticated, then proceed.
104+
apiClient.sessionState
105+
.mapNotNull { it as? SessionState.Connected }
106+
.mapNotNull { it.dataConnectionState as? DataConnectionState.Authenticated }
107+
.first()
95108
result.sendResult(
96109
apiClient.sendRequest(Request.Artist.listLibrary())
97110
.resultAs<List<ServerMediaItem>>()
@@ -106,9 +119,36 @@ class AutoLibrary(
106119
}
107120
}
108121

122+
MediaIds.TAB_ALBUMS -> {
123+
result.detach()
124+
scope.launch {
125+
// Block until authenticated, then proceed.
126+
apiClient.sessionState
127+
.mapNotNull { it as? SessionState.Connected }
128+
.mapNotNull { it.dataConnectionState as? DataConnectionState.Authenticated }
129+
.first()
130+
result.sendResult(
131+
apiClient.sendRequest(Request.Album.listLibrary())
132+
.resultAs<List<ServerMediaItem>>()
133+
?.toAppMediaItemList()
134+
?.map {
135+
it.toAutoMediaItem(
136+
baseUrl,
137+
true,
138+
defaultIconUri
139+
)
140+
})
141+
}
142+
}
143+
109144
MediaIds.TAB_PLAYLISTS -> {
110145
result.detach()
111146
scope.launch {
147+
// Block until authenticated, then proceed.
148+
apiClient.sessionState
149+
.mapNotNull { it as? SessionState.Connected }
150+
.mapNotNull { it.dataConnectionState as? DataConnectionState.Authenticated }
151+
.first()
112152
result.sendResult(
113153
apiClient.sendRequest(Request.Playlist.listLibrary())
114154
.resultAs<List<ServerMediaItem>>()
@@ -123,6 +163,52 @@ class AutoLibrary(
123163
}
124164
}
125165

166+
MediaIds.TAB_PODCASTS -> {
167+
result.detach()
168+
scope.launch {
169+
// Block until authenticated, then proceed.
170+
apiClient.sessionState
171+
.mapNotNull { it as? SessionState.Connected }
172+
.mapNotNull { it.dataConnectionState as? DataConnectionState.Authenticated }
173+
.first()
174+
result.sendResult(
175+
apiClient.sendRequest(Request.Podcast.listLibrary())
176+
.resultAs<List<ServerMediaItem>>()
177+
?.toAppMediaItemList()
178+
?.map {
179+
it.toAutoMediaItem(
180+
baseUrl,
181+
true,
182+
defaultIconUri
183+
)
184+
})
185+
}
186+
}
187+
188+
MediaIds.TAB_RADIO -> {
189+
result.detach()
190+
scope.launch {
191+
// Block until authenticated, then proceed.
192+
apiClient.sessionState
193+
.mapNotNull { it as? SessionState.Connected }
194+
.mapNotNull { it.dataConnectionState as? DataConnectionState.Authenticated }
195+
.first()
196+
result.sendResult(
197+
apiClient.sendRequest(Request.RadioStation.listLibrary())
198+
.resultAs<List<ServerMediaItem>>()
199+
?.toAppMediaItemList()
200+
?.map {
201+
it.toAutoMediaItem(
202+
baseUrl,
203+
true,
204+
defaultIconUri
205+
)
206+
})
207+
}
208+
}
209+
210+
211+
126212
else -> {
127213
val parts = id.split("__")
128214
if (parts.size != 4) {
@@ -134,6 +220,8 @@ class AutoLibrary(
134220
val requestAndCategory = when (parentType) {
135221
MediaType.ARTIST -> Request.Artist.getAlbums(parts[0], parts[3])
136222
MediaType.ALBUM -> Request.Album.getTracks(parts[0], parts[3])
223+
MediaType.PLAYLIST -> Request.Playlist.getTracks(parts[0], parts[3])
224+
MediaType.PODCAST -> Request.Podcast.getEpisodes(parts[0], parts[3])
137225
else -> {
138226
result.sendResult(null)
139227
return
@@ -213,7 +301,7 @@ class AutoLibrary(
213301
queueOrPlayerId = queueId,
214302
option = extras?.getString(
215303
MediaIds.QUEUE_OPTION_KEY,
216-
QueueOption.PLAY.name
304+
QueueOption.REPLACE.name
217305
)?.let { QueueOption.valueOf(it) },
218306
radioMode = false
219307
)
@@ -235,7 +323,10 @@ class AutoLibrary(
235323
internal object MediaIds {
236324
const val ROOT = "auto_lib_root"
237325
const val TAB_ARTISTS = "auto_lib_artists"
326+
const val TAB_ALBUMS = "auto_lib_albums"
238327
const val TAB_PLAYLISTS = "auto_lib_playlists"
328+
const val TAB_PODCASTS = "auto_lib_podcasts"
329+
const val TAB_RADIO = "auto_lib_radio"
239330
const val QUEUE_OPTION_KEY = "auto_queue_option"
240331
}
241332

@@ -247,7 +338,9 @@ private fun SearchResult.toAutoMediaItems(
247338
tracks to "Tracks",
248339
albums to "Albums",
249340
artists to "Artists",
250-
playlists to "Playlists"
341+
playlists to "Playlists",
342+
podcasts to "Podcasts",
343+
radios to "Radio stations"
251344
).forEach { (items, category) ->
252345
addAll(items.mapNotNull { it.toAutoMediaItem(serverUrl, true, defaultIconUri, category) })
253346
}
@@ -277,7 +370,7 @@ private fun AppMediaItem.toAutoMediaItem(
277370
}
278371

279372
private fun MediaType.isBrowsableInAuto(): Boolean = this in setOf(
280-
MediaType.ARTIST, MediaType.ALBUM
373+
MediaType.ARTIST, MediaType.ALBUM, MediaType.PODCAST, MediaType.PLAYLIST
281374
)
282375

283376
fun @receiver:DrawableRes Int.toUri(context: Context): Uri = Uri.parse(

0 commit comments

Comments
 (0)