Skip to content

Commit

Permalink
Improve media source id handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxr1998 authored and nielsvanvelzen committed Dec 27, 2022
1 parent ba88249 commit a0ea262
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import org.jellyfin.sdk.api.operations.VideosApi
import org.jellyfin.sdk.model.api.DeviceProfile
import org.jellyfin.sdk.model.api.MediaStream
import org.jellyfin.sdk.model.api.PlayMethod
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
import org.json.JSONArray
import org.json.JSONObject
import org.koin.core.component.KoinComponent
Expand Down Expand Up @@ -85,7 +86,9 @@ class ExternalPlayer(
@JavascriptInterface
fun initPlayer(args: String) {
val playOptions = PlayOptions.fromJson(JSONObject(args))
val itemId = playOptions?.run { mediaSourceId ?: ids.firstOrNull() }
val itemId = playOptions?.run {
ids.firstOrNull() ?: mediaSourceId?.toUUIDOrNull() // fallback if ids is empty
}
if (playOptions == null || itemId == null) {
context.toast(R.string.player_error_invalid_play_options)
return
Expand All @@ -94,6 +97,7 @@ class ExternalPlayer(
coroutinesScope.launch {
mediaSourceResolver.resolveMediaSource(
itemId = itemId,
mediaSourceId = playOptions.mediaSourceId,
deviceProfile = externalPlayerProfile,
startTimeTicks = playOptions.startPositionTicks,
audioStreamIndex = playOptions.audioStreamIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import java.util.UUID

@Parcelize
data class PlayOptions(
val mediaSourceId: UUID?,
val ids: List<UUID>,
val mediaSourceId: String?,
val startIndex: Int,
val startPositionTicks: Long?,
val audioStreamIndex: Int?,
Expand All @@ -22,14 +22,14 @@ data class PlayOptions(
companion object {
fun fromJson(json: JSONObject): PlayOptions? = try {
PlayOptions(
mediaSourceId = json.optString("mediaSourceId").toUUIDOrNull(),
ids = json.optJSONArray("ids")?.let { array ->
ArrayList<UUID>().apply {
for (i in 0 until array.size) {
array.getString(i).toUUIDOrNull()?.let(this::add)
}
}
} ?: emptyList(),
mediaSourceId = json.optString("mediaSourceId"),
startIndex = json.optInt("startIndex"),
startPositionTicks = json.optLong("startPositionTicks").takeIf { it > 0 },
audioStreamIndex = json.optString("audioStreamIndex").toIntOrNull(),
Expand Down
17 changes: 14 additions & 3 deletions app/src/main/java/org/jellyfin/mobile/player/queue/QueueManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.jellyfin.sdk.api.operations.VideosApi
import org.jellyfin.sdk.model.api.MediaProtocol
import org.jellyfin.sdk.model.api.MediaStream
import org.jellyfin.sdk.model.api.PlayMethod
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
import org.koin.core.component.inject
Expand Down Expand Up @@ -57,9 +58,13 @@ class QueueManager(
*/
suspend fun startPlayback(playOptions: PlayOptions, playWhenReady: Boolean): PlayerException? {
if (playOptions != currentPlayOptions) {
val itemId = playOptions.run { mediaSourceId ?: ids[playOptions.startIndex] }
val itemId = playOptions.run {
ids.getOrNull(startIndex) ?: mediaSourceId?.toUUIDOrNull() // fallback if ids is empty
} ?: return PlayerException.InvalidPlayOptions()

mediaSourceResolver.resolveMediaSource(
itemId = itemId,
mediaSourceId = playOptions.mediaSourceId,
deviceProfile = deviceProfile,
maxStreamingBitrate = playOptions.maxBitrate,
startTimeTicks = playOptions.startPositionTicks,
Expand Down Expand Up @@ -124,7 +129,10 @@ class QueueManager(
}
is QueueItem.Stub -> {
val previousId = previous.ids.lastOrNull() ?: return false
val jellyfinMediaSource = mediaSourceResolver.resolveMediaSource(previousId, deviceProfile).getOrNull() ?: return false
val jellyfinMediaSource = mediaSourceResolver.resolveMediaSource(
itemId = previousId,
deviceProfile = deviceProfile,
).getOrNull() ?: return false

val previousPrevious = QueueItem.Stub(previous.ids.dropLast(1))
createQueueItem(jellyfinMediaSource, previousPrevious, current).play()
Expand All @@ -141,7 +149,10 @@ class QueueManager(
}
is QueueItem.Stub -> {
val nextId = next.ids.firstOrNull() ?: return false
val jellyfinMediaSource = mediaSourceResolver.resolveMediaSource(nextId, deviceProfile).getOrNull() ?: return false
val jellyfinMediaSource = mediaSourceResolver.resolveMediaSource(
itemId = nextId,
deviceProfile = deviceProfile,
).getOrNull() ?: return false

val nextNext = QueueItem.Stub(next.ids.drop(1))
createQueueItem(jellyfinMediaSource, current, nextNext).play()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class MediaSourceResolver(private val apiClient: ApiClient) {
@Suppress("ReturnCount")
suspend fun resolveMediaSource(
itemId: UUID,
mediaSourceId: String? = null,
deviceProfile: DeviceProfile,
maxStreamingBitrate: Int? = null,
startTimeTicks: Long? = null,
Expand All @@ -36,7 +37,7 @@ class MediaSourceResolver(private val apiClient: ApiClient) {
// We need to remove the dashes so that the server can find the correct media source.
// And if we didn't pass the mediaSourceId, our stream indices would silently get ignored.
// https://github.com/jellyfin/jellyfin/blob/9a35fd673203cfaf0098138b2768750f4818b3ab/Jellyfin.Api/Helpers/MediaInfoHelper.cs#L196-L201
mediaSourceId = itemId.toString().replace("-", ""),
mediaSourceId = mediaSourceId ?: itemId.toString().replace("-", ""),
deviceProfile = deviceProfile,
maxStreamingBitrate = maxStreamingBitrate ?: deviceProfile.maxStreamingBitrate,
startTimeTicks = startTimeTicks,
Expand Down

0 comments on commit a0ea262

Please sign in to comment.