mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Change tracks in place
This commit is contained in:
parent
5f2cf5849c
commit
3a4a22ec94
1 changed files with 161 additions and 78 deletions
|
|
@ -84,6 +84,8 @@ import org.jellyfin.sdk.model.api.BaseItemKind
|
|||
import org.jellyfin.sdk.model.api.DeviceProfile
|
||||
import org.jellyfin.sdk.model.api.MediaSegmentDto
|
||||
import org.jellyfin.sdk.model.api.MediaSegmentType
|
||||
import org.jellyfin.sdk.model.api.MediaSourceInfo
|
||||
import org.jellyfin.sdk.model.api.MediaStream
|
||||
import org.jellyfin.sdk.model.api.MediaStreamType
|
||||
import org.jellyfin.sdk.model.api.PlayMethod
|
||||
import org.jellyfin.sdk.model.api.PlaybackInfoDto
|
||||
|
|
@ -423,6 +425,56 @@ class PlaybackViewModel
|
|||
) = withContext(Dispatchers.IO) {
|
||||
val itemId = item.id
|
||||
|
||||
val currentPlayback = this@PlaybackViewModel.currentPlayback.value
|
||||
if (currentPlayback != null && currentPlayback.playMethod == PlayMethod.DIRECT_PLAY) {
|
||||
// If direct playing, can try to switch tracks without playback restarting
|
||||
// Except for external subtitles
|
||||
// TODO there's probably no reason why we can't add external subtitles?
|
||||
|
||||
val source = currentPlayback.mediaSourceInfo
|
||||
val externalSubtitleCount = source.externalSubtitlesCount
|
||||
val externalSubtitle = source.findExternalSubtitle(subtitleIndex)
|
||||
|
||||
val result =
|
||||
withContext(Dispatchers.Main) {
|
||||
applyTrackSelections(
|
||||
player,
|
||||
true,
|
||||
audioIndex,
|
||||
subtitleIndex,
|
||||
externalSubtitleCount,
|
||||
externalSubtitle != null,
|
||||
)
|
||||
}
|
||||
if (result.bothSelected) {
|
||||
Timber.d("Changes tracks audio=$audioIndex, subtitle=$subtitleIndex")
|
||||
val itemPlayback =
|
||||
currentItemPlayback.copy(
|
||||
sourceId = source.id?.toUUIDOrNull(),
|
||||
audioIndex = audioIndex ?: TrackIndex.UNSPECIFIED,
|
||||
subtitleIndex = subtitleIndex ?: TrackIndex.DISABLED,
|
||||
)
|
||||
if (userInitiated) {
|
||||
viewModelScope.launchIO {
|
||||
Timber.v("Saving user initiated item playback: %s", itemPlayback)
|
||||
val updated = itemPlaybackRepository.saveItemPlayback(itemPlayback)
|
||||
withContext(Dispatchers.Main) {
|
||||
this@PlaybackViewModel.currentItemPlayback.value = updated
|
||||
}
|
||||
}
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
this@PlaybackViewModel.currentPlayback.value =
|
||||
currentPlayback.copy(
|
||||
tracks = checkForSupport(player.currentTracks),
|
||||
)
|
||||
this@PlaybackViewModel.currentItemPlayback.value = itemPlayback
|
||||
}
|
||||
|
||||
return@withContext
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
// if (currentItemPlayback.let {
|
||||
// it.itemId == itemId &&
|
||||
|
|
@ -505,14 +557,10 @@ class PlaybackViewModel
|
|||
val decision = StreamDecision(itemId, transcodeType, mediaUrl)
|
||||
Timber.v("Playback decision: $decision")
|
||||
|
||||
val externalSubtitleCount =
|
||||
source.mediaStreams
|
||||
?.count { it.type == MediaStreamType.SUBTITLE && it.isExternal } ?: 0
|
||||
val externalSubtitleCount = source.externalSubtitlesCount
|
||||
|
||||
val externalSubtitle =
|
||||
source.mediaStreams
|
||||
?.firstOrNull { it.type == MediaStreamType.SUBTITLE && it.isExternal && it.index == subtitleIndex }
|
||||
?.let {
|
||||
source.findExternalSubtitle(subtitleIndex)?.let {
|
||||
it.deliveryUrl?.let { deliveryUrl ->
|
||||
var flags = 0
|
||||
if (it.isForced) flags = flags.or(C.SELECTION_FLAG_FORCED)
|
||||
|
|
@ -527,6 +575,7 @@ class PlaybackViewModel
|
|||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
Timber.v("externalSubtitleCount=$externalSubtitleCount, externalSubtitle=$externalSubtitle")
|
||||
|
||||
val mediaItem =
|
||||
|
|
@ -544,6 +593,7 @@ class PlaybackViewModel
|
|||
playMethod = transcodeType,
|
||||
playSessionId = response.playSessionId,
|
||||
liveStreamId = source.liveStreamId,
|
||||
mediaSourceInfo = source,
|
||||
)
|
||||
val itemPlayback =
|
||||
currentItemPlayback.copy(
|
||||
|
|
@ -580,7 +630,7 @@ class PlaybackViewModel
|
|||
|
||||
duration.value = source.runTimeTicks?.ticks
|
||||
loading.value = LoadingState.Success
|
||||
currentPlayback.value = playback
|
||||
this@PlaybackViewModel.currentPlayback.value = playback
|
||||
this@PlaybackViewModel.currentItemPlayback.value = itemPlayback
|
||||
player.setMediaItem(
|
||||
mediaItem,
|
||||
|
|
@ -1056,6 +1106,7 @@ data class CurrentPlayback(
|
|||
val playMethod: PlayMethod,
|
||||
val playSessionId: String?,
|
||||
val liveStreamId: String?,
|
||||
val mediaSourceInfo: MediaSourceInfo,
|
||||
)
|
||||
|
||||
sealed interface SubtitleSearch {
|
||||
|
|
@ -1084,8 +1135,32 @@ val Format.idAsInt: Int?
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of external subtitle streams there are
|
||||
*/
|
||||
val MediaSourceInfo.externalSubtitlesCount: Int
|
||||
get() =
|
||||
mediaStreams
|
||||
?.count { it.type == MediaStreamType.SUBTITLE && it.isExternal } ?: 0
|
||||
|
||||
/**
|
||||
* Returns the [MediaStream] for the given subtitle index iff it is external
|
||||
*/
|
||||
fun MediaSourceInfo.findExternalSubtitle(subtitleIndex: Int?): MediaStream? =
|
||||
subtitleIndex?.let {
|
||||
mediaStreams
|
||||
?.firstOrNull { it.type == MediaStreamType.SUBTITLE && it.isExternal && it.index == subtitleIndex }
|
||||
}
|
||||
|
||||
suspend fun <T> onMain(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.Main, block)
|
||||
|
||||
data class TrackSelectionResult(
|
||||
val audioSelected: Boolean,
|
||||
val subtitleSelected: Boolean,
|
||||
) {
|
||||
val bothSelected: Boolean = audioSelected && subtitleSelected
|
||||
}
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
private fun applyTrackSelections(
|
||||
player: Player,
|
||||
|
|
@ -1094,7 +1169,8 @@ private fun applyTrackSelections(
|
|||
subtitleIndex: Int?,
|
||||
externalSubtitleCount: Int,
|
||||
subtitleIsExternal: Boolean,
|
||||
) {
|
||||
): TrackSelectionResult {
|
||||
val subtitleSelected =
|
||||
if (subtitleIndex != null && subtitleIndex >= 0 && (subtitleIsExternal || supportsDirectPlay)) {
|
||||
val chosenTrack =
|
||||
if (subtitleIsExternal) {
|
||||
|
|
@ -1129,13 +1205,16 @@ private fun applyTrackSelections(
|
|||
),
|
||||
).build()
|
||||
}
|
||||
chosenTrack != null
|
||||
} else {
|
||||
player.trackSelectionParameters =
|
||||
player.trackSelectionParameters
|
||||
.buildUpon()
|
||||
.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, true)
|
||||
.build()
|
||||
true
|
||||
}
|
||||
val audioSelected =
|
||||
if (audioIndex != null && supportsDirectPlay) {
|
||||
val indexToFind =
|
||||
audioIndex - externalSubtitleCount + 1
|
||||
|
|
@ -1160,5 +1239,9 @@ private fun applyTrackSelections(
|
|||
),
|
||||
).build()
|
||||
}
|
||||
chosenTrack != null
|
||||
} else {
|
||||
audioIndex == null
|
||||
}
|
||||
return TrackSelectionResult(audioSelected, subtitleSelected)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue