mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Add option to play item forcing transcoding (#153)
Closes #97 Adds an option to force an item to play by transcoding. This can be useful in the few cases where the device reports that it supports direct play for a file, but it really doesn't. Also rearranges the "More" dialog list to move picking audio & subtitle track near the top.
This commit is contained in:
parent
2840fa3f2a
commit
a0b9ac7673
5 changed files with 85 additions and 47 deletions
|
|
@ -65,53 +65,7 @@ fun buildMoreDialogItems(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
add(
|
|
||||||
DialogItem(
|
|
||||||
text = if (watched) R.string.mark_unwatched else R.string.mark_watched,
|
|
||||||
iconStringRes = if (watched) R.string.fa_eye else R.string.fa_eye_slash,
|
|
||||||
) {
|
|
||||||
onClickWatch.invoke(!watched)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
add(
|
|
||||||
DialogItem(
|
|
||||||
text = if (favorite) R.string.remove_favorite else R.string.add_favorite,
|
|
||||||
iconStringRes = R.string.fa_heart,
|
|
||||||
iconColor = if (favorite) Color.Red else Color.Unspecified,
|
|
||||||
) {
|
|
||||||
onClickFavorite.invoke(!favorite)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
series?.let {
|
|
||||||
add(
|
|
||||||
DialogItem(
|
|
||||||
context.getString(R.string.go_to_series),
|
|
||||||
Icons.AutoMirrored.Filled.ArrowForward,
|
|
||||||
) {
|
|
||||||
navigateTo(
|
|
||||||
Destination.MediaItem(
|
|
||||||
series.id,
|
|
||||||
BaseItemKind.SERIES,
|
|
||||||
series,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
item.data.mediaSources?.letNotEmpty { sources ->
|
item.data.mediaSources?.letNotEmpty { sources ->
|
||||||
if (sources.size > 1) {
|
|
||||||
add(
|
|
||||||
DialogItem(
|
|
||||||
context.getString(
|
|
||||||
R.string.choose_stream,
|
|
||||||
context.getString(R.string.version),
|
|
||||||
),
|
|
||||||
R.string.fa_file_video,
|
|
||||||
) {
|
|
||||||
onChooseVersion.invoke()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val source =
|
val source =
|
||||||
sourceId?.let { sources.firstOrNull { it.id?.toUUIDOrNull() == sourceId } }
|
sourceId?.let { sources.firstOrNull { it.id?.toUUIDOrNull() == sourceId } }
|
||||||
?: sources.firstOrNull()
|
?: sources.firstOrNull()
|
||||||
|
|
@ -145,8 +99,69 @@ fun buildMoreDialogItems(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (sources.size > 1) {
|
||||||
|
add(
|
||||||
|
DialogItem(
|
||||||
|
context.getString(
|
||||||
|
R.string.choose_stream,
|
||||||
|
context.getString(R.string.version),
|
||||||
|
),
|
||||||
|
R.string.fa_file_video,
|
||||||
|
) {
|
||||||
|
onChooseVersion.invoke()
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
add(
|
||||||
|
DialogItem(
|
||||||
|
text = if (watched) R.string.mark_unwatched else R.string.mark_watched,
|
||||||
|
iconStringRes = if (watched) R.string.fa_eye else R.string.fa_eye_slash,
|
||||||
|
) {
|
||||||
|
onClickWatch.invoke(!watched)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
add(
|
||||||
|
DialogItem(
|
||||||
|
text = if (favorite) R.string.remove_favorite else R.string.add_favorite,
|
||||||
|
iconStringRes = R.string.fa_heart,
|
||||||
|
iconColor = if (favorite) Color.Red else Color.Unspecified,
|
||||||
|
) {
|
||||||
|
onClickFavorite.invoke(!favorite)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
series?.let {
|
||||||
|
add(
|
||||||
|
DialogItem(
|
||||||
|
context.getString(R.string.go_to_series),
|
||||||
|
Icons.AutoMirrored.Filled.ArrowForward,
|
||||||
|
) {
|
||||||
|
navigateTo(
|
||||||
|
Destination.MediaItem(
|
||||||
|
series.id,
|
||||||
|
BaseItemKind.SERIES,
|
||||||
|
series,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(
|
||||||
|
DialogItem(
|
||||||
|
context.getString(R.string.play_with_transcoding),
|
||||||
|
Icons.Default.PlayArrow,
|
||||||
|
) {
|
||||||
|
navigateTo(
|
||||||
|
Destination.Playback(
|
||||||
|
item.id,
|
||||||
|
item.resumeMs ?: 0L,
|
||||||
|
item,
|
||||||
|
forceTranscoding = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun buildMoreDialogItemsForHome(
|
fun buildMoreDialogItemsForHome(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ sealed class Destination(
|
||||||
val startIndex: Int? = null,
|
val startIndex: Int? = null,
|
||||||
val shuffle: Boolean = false,
|
val shuffle: Boolean = false,
|
||||||
val itemPlayback: ItemPlayback? = null,
|
val itemPlayback: ItemPlayback? = null,
|
||||||
|
val forceTranscoding: Boolean = false,
|
||||||
) : Destination(true) {
|
) : Destination(true) {
|
||||||
override fun toString(): String = "Playback(itemId=$itemId, positionMs=$positionMs)"
|
override fun toString(): String = "Playback(itemId=$itemId, positionMs=$positionMs)"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,11 @@ class PlaybackViewModel
|
||||||
destination.startIndex,
|
destination.startIndex,
|
||||||
destination.shuffle,
|
destination.shuffle,
|
||||||
)
|
)
|
||||||
|
if (playlist.items.isEmpty()) {
|
||||||
|
showToast(context, "Playlist is empty", Toast.LENGTH_SHORT)
|
||||||
|
navigationManager.goBack()
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
this@PlaybackViewModel.playlist.value = playlist
|
this@PlaybackViewModel.playlist.value = playlist
|
||||||
}
|
}
|
||||||
|
|
@ -218,7 +223,13 @@ class PlaybackViewModel
|
||||||
queriedItem
|
queriedItem
|
||||||
}
|
}
|
||||||
|
|
||||||
val played = play(base, destination.positionMs, destination.itemPlayback)
|
val played =
|
||||||
|
play(
|
||||||
|
base,
|
||||||
|
destination.positionMs,
|
||||||
|
destination.itemPlayback,
|
||||||
|
destination.forceTranscoding,
|
||||||
|
)
|
||||||
if (!played) {
|
if (!played) {
|
||||||
playUpNextUp()
|
playUpNextUp()
|
||||||
}
|
}
|
||||||
|
|
@ -238,6 +249,7 @@ class PlaybackViewModel
|
||||||
base: BaseItemDto,
|
base: BaseItemDto,
|
||||||
positionMs: Long,
|
positionMs: Long,
|
||||||
itemPlayback: ItemPlayback? = null,
|
itemPlayback: ItemPlayback? = null,
|
||||||
|
forceTranscoding: Boolean = false,
|
||||||
): Boolean =
|
): Boolean =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
Timber.i("Playing ${base.id}")
|
Timber.i("Playing ${base.id}")
|
||||||
|
|
@ -369,6 +381,8 @@ class PlaybackViewModel
|
||||||
subtitleIndex,
|
subtitleIndex,
|
||||||
if (positionMs > 0) positionMs else C.TIME_UNSET,
|
if (positionMs > 0) positionMs else C.TIME_UNSET,
|
||||||
itemPlayback != null, // If it was passed in, then it was not queried from the database
|
itemPlayback != null, // If it was passed in, then it was not queried from the database
|
||||||
|
enableDirectPlay = !forceTranscoding,
|
||||||
|
enableDirectStream = !forceTranscoding,
|
||||||
)
|
)
|
||||||
player.prepare()
|
player.prepare()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,13 @@ class SwitchUserViewModel
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
viewModelScope.launchIO {
|
viewModelScope.launchIO {
|
||||||
|
quickConnectJob?.cancel()
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
users.value = listOf()
|
||||||
|
serverStatus.value = mapOf()
|
||||||
|
serverQuickConnect.value = mapOf()
|
||||||
|
}
|
||||||
|
|
||||||
val allServers =
|
val allServers =
|
||||||
serverDao
|
serverDao
|
||||||
.getServers()
|
.getServers()
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,7 @@
|
||||||
<string name="video">Video</string>
|
<string name="video">Video</string>
|
||||||
<string name="watch_live">Watch live</string>
|
<string name="watch_live">Watch live</string>
|
||||||
<string name="years_old">%1$d years old</string>
|
<string name="years_old">%1$d years old</string>
|
||||||
|
<string name="play_with_transcoding">Play with transcoding</string>
|
||||||
|
|
||||||
<plurals name="downloads">
|
<plurals name="downloads">
|
||||||
<item quantity="zero">%d downloads</item>
|
<item quantity="zero">%d downloads</item>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue